2011-04-06 13:48:02 +04:00
/*
* Copyright ( C ) by Duncan Mac - Vicar P . < duncan @ kde . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*/
2014-07-11 02:31:24 +04:00
# include "folderwizard.h"
# include "folderman.h"
2014-11-10 01:25:57 +03:00
# include "configfile.h"
2014-07-11 02:31:24 +04:00
# include "theme.h"
# include "networkjobs.h"
# include "account.h"
2014-08-15 18:26:38 +04:00
# include "selectivesyncdialog.h"
2015-04-28 12:29:35 +03:00
# include "accountstate.h"
2015-03-10 14:14:14 +03:00
# include "creds/abstractcredentials.h"
2017-05-09 15:24:11 +03:00
# include "wizard/owncloudwizard.h"
2017-09-01 19:11:43 +03:00
# include "common/asserts.h"
2012-05-21 18:48:49 +04:00
2011-04-05 20:31:14 +04:00
# include <QDesktopServices>
2013-07-22 20:07:44 +04:00
# include <QDir>
2011-04-05 20:31:14 +04:00
# include <QFileDialog>
# include <QFileInfo>
2013-08-01 20:22:13 +04:00
# include <QFileIconProvider>
2013-07-22 20:07:44 +04:00
# include <QInputDialog>
2011-04-05 20:31:14 +04:00
# include <QUrl>
# include <QValidator>
# include <QWizardPage>
2013-08-06 23:50:06 +04:00
# include <QTreeWidget>
2014-08-15 18:26:38 +04:00
# include <QVBoxLayout>
2017-11-21 18:13:06 +03:00
# include <QEvent>
2018-01-15 19:30:33 +03:00
# include <QCheckBox>
2020-10-21 13:31:21 +03:00
# include <QMessageBox>
2011-10-06 18:55:28 +04:00
2020-08-13 14:00:56 +03:00
# include <cstdlib>
2011-09-26 15:12:00 +04:00
2014-11-10 00:34:07 +03:00
namespace OCC {
2011-04-05 13:10:44 +04:00
2013-11-26 05:02:56 +04:00
QString FormatWarningsWizardPage : : formatWarnings ( const QStringList & warnings ) const
{
QString ret ;
if ( warnings . count ( ) = = 1 ) {
2015-02-06 00:00:13 +03:00
ret = tr ( " <b>Warning:</b> %1 " ) . arg ( warnings . first ( ) ) ;
2013-11-26 05:02:56 +04:00
} else if ( warnings . count ( ) > 1 ) {
2015-02-06 00:00:13 +03:00
ret = tr ( " <b>Warning:</b> " ) + " <ul> " ;
2013-11-26 05:02:56 +04:00
Q_FOREACH ( QString warning , warnings ) {
ret + = QString : : fromLatin1 ( " <li>%1</li> " ) . arg ( warning ) ;
}
ret + = " </ul> " ;
}
return ret ;
}
2016-11-29 12:39:20 +03:00
FolderWizardLocalPath : : FolderWizardLocalPath ( const AccountPtr & account )
2016-09-30 15:08:00 +03:00
: FormatWarningsWizardPage ( )
, _account ( account )
2011-04-05 20:31:14 +04:00
{
_ui . setupUi ( this ) ;
2012-08-17 19:13:17 +04:00
registerField ( QLatin1String ( " sourceFolder* " ) , _ui . localFolderLineEdit ) ;
2017-09-20 11:14:48 +03:00
connect ( _ui . localFolderChooseBtn , & QAbstractButton : : clicked , this , & FolderWizardLocalPath : : slotChooseLocalFolder ) ;
2014-01-14 20:40:42 +04:00
_ui . localFolderChooseBtn - > setToolTip ( tr ( " Click to select a local folder to sync. " ) ) ;
2018-07-16 13:46:03 +03:00
QUrl serverUrl = _account - > url ( ) ;
serverUrl . setUserName ( _account - > credentials ( ) - > user ( ) ) ;
2017-02-23 16:54:17 +03:00
QString defaultPath = QDir : : homePath ( ) + QLatin1Char ( ' / ' ) + Theme : : instance ( ) - > appName ( ) ;
2023-03-24 14:29:41 +03:00
defaultPath = FolderMan : : instance ( ) - > findGoodPathForNewSyncFolder ( defaultPath , serverUrl , FolderMan : : GoodPathStrategy : : AllowOnlyNewPath ) ;
2013-06-11 20:18:38 +04:00
_ui . localFolderLineEdit - > setText ( QDir : : toNativeSeparators ( defaultPath ) ) ;
2014-01-14 20:40:42 +04:00
_ui . localFolderLineEdit - > setToolTip ( tr ( " Enter the path to the local folder. " ) ) ;
2013-11-26 05:02:56 +04:00
_ui . warnLabel - > setTextFormat ( Qt : : RichText ) ;
2011-10-11 17:39:25 +04:00
_ui . warnLabel - > hide ( ) ;
2022-02-15 15:53:39 +03:00
changeStyle ( ) ;
2011-04-05 20:31:14 +04:00
}
2020-05-25 22:33:24 +03:00
FolderWizardLocalPath : : ~ FolderWizardLocalPath ( ) = default ;
2011-04-05 20:31:14 +04:00
2014-01-14 20:40:42 +04:00
void FolderWizardLocalPath : : initializePage ( )
2011-10-26 15:59:06 +04:00
{
_ui . warnLabel - > hide ( ) ;
}
2014-01-14 20:40:42 +04:00
void FolderWizardLocalPath : : cleanupPage ( )
2011-10-26 15:59:06 +04:00
{
_ui . warnLabel - > hide ( ) ;
}
2014-01-14 20:40:42 +04:00
bool FolderWizardLocalPath : : isComplete ( ) const
2011-04-05 20:31:14 +04:00
{
2016-09-30 15:08:00 +03:00
QUrl serverUrl = _account - > url ( ) ;
serverUrl . setUserName ( _account - > credentials ( ) - > user ( ) ) ;
2022-09-08 13:00:13 +03:00
const auto errorStr = FolderMan : : instance ( ) - > checkPathValidityForNewFolder (
QDir : : fromNativeSeparators ( _ui . localFolderLineEdit - > text ( ) ) , serverUrl ) . second ;
2016-09-30 15:08:00 +03:00
2015-07-13 15:35:19 +03:00
bool isOk = errorStr . isEmpty ( ) ;
QStringList warnStrings ;
if ( ! isOk ) {
warnStrings < < errorStr ;
2011-10-11 16:23:32 +04:00
}
2013-11-26 05:02:56 +04:00
_ui . warnLabel - > setWordWrap ( true ) ;
2011-10-11 17:39:25 +04:00
if ( isOk ) {
_ui . warnLabel - > hide ( ) ;
2020-09-18 14:42:42 +03:00
_ui . warnLabel - > clear ( ) ;
2011-10-11 17:39:25 +04:00
} else {
_ui . warnLabel - > show ( ) ;
2013-11-26 05:02:56 +04:00
QString warnings = formatWarnings ( warnStrings ) ;
_ui . warnLabel - > setText ( warnings ) ;
2011-10-11 16:23:32 +04:00
}
return isOk ;
2011-04-05 20:31:14 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardLocalPath : : slotChooseLocalFolder ( )
2011-04-05 20:31:14 +04:00
{
2017-12-08 15:02:05 +03:00
QString sf = QStandardPaths : : writableLocation ( QStandardPaths : : HomeLocation ) ;
2014-01-14 20:40:42 +04:00
QDir d ( sf ) ;
// open the first entry of the home dir. Otherwise the dir picker comes
// up with the closed home dir icon, stupid Qt default...
QStringList dirs = d . entryList ( QDir : : Dirs | QDir : : NoDotAndDotDot | QDir : : NoSymLinks ,
QDir : : DirsFirst | QDir : : Name ) ;
if ( dirs . count ( ) > 0 )
sf + = " / " + dirs . at ( 0 ) ; // Take the first dir in home dir.
2011-04-05 20:31:14 +04:00
QString dir = QFileDialog : : getExistingDirectory ( this ,
tr ( " Select the source folder " ) ,
2014-01-14 20:40:42 +04:00
sf ) ;
2011-04-05 20:31:14 +04:00
if ( ! dir . isEmpty ( ) ) {
2014-01-14 20:40:42 +04:00
// set the last directory component name as alias
2013-06-11 20:18:38 +04:00
_ui . localFolderLineEdit - > setText ( QDir : : toNativeSeparators ( dir ) ) ;
2011-04-05 20:31:14 +04:00
}
emit completeChanged ( ) ;
}
2022-02-15 15:53:39 +03:00
void FolderWizardLocalPath : : changeEvent ( QEvent * e )
{
switch ( e - > type ( ) ) {
case QEvent : : StyleChange :
case QEvent : : PaletteChange :
case QEvent : : ThemeChange :
// Notify the other widgets (Dark-/Light-Mode switching)
changeStyle ( ) ;
break ;
default :
break ;
}
FormatWarningsWizardPage : : changeEvent ( e ) ;
}
void FolderWizardLocalPath : : changeStyle ( )
{
const auto warnYellow = Theme : : isDarkColor ( QGuiApplication : : palette ( ) . base ( ) . color ( ) ) ? QColor ( 63 , 63 , 0 ) : QColor ( 255 , 255 , 192 ) ;
auto modifiedPalette = _ui . warnLabel - > palette ( ) ;
modifiedPalette . setColor ( QPalette : : Window , warnYellow ) ;
_ui . warnLabel - > setPalette ( modifiedPalette ) ;
}
2011-10-11 16:23:32 +04:00
// =================================================================================
2016-11-29 12:39:20 +03:00
FolderWizardRemotePath : : FolderWizardRemotePath ( const AccountPtr & account )
2013-11-26 05:02:56 +04:00
: FormatWarningsWizardPage ( )
2015-01-28 12:38:54 +03:00
, _account ( account )
2011-04-05 20:31:14 +04:00
{
_ui . setupUi ( this ) ;
2011-10-26 15:59:06 +04:00
_ui . warnFrame - > hide ( ) ;
2011-04-06 12:40:15 +04:00
2014-10-10 18:56:05 +04:00
_ui . folderTreeWidget - > setSortingEnabled ( true ) ;
_ui . folderTreeWidget - > sortByColumn ( 0 , Qt : : AscendingOrder ) ;
2017-09-20 11:14:48 +03:00
connect ( _ui . addFolderButton , & QAbstractButton : : clicked , this , & FolderWizardRemotePath : : slotAddRemoteFolder ) ;
connect ( _ui . refreshButton , & QAbstractButton : : clicked , this , & FolderWizardRemotePath : : slotRefreshFolders ) ;
connect ( _ui . folderTreeWidget , & QTreeWidget : : itemExpanded , this , & FolderWizardRemotePath : : slotItemExpanded ) ;
connect ( _ui . folderTreeWidget , & QTreeWidget : : currentItemChanged , this , & FolderWizardRemotePath : : slotCurrentItemChanged ) ;
connect ( _ui . folderEntry , & QLineEdit : : textEdited , this , & FolderWizardRemotePath : : slotFolderEntryEdited ) ;
2013-10-23 16:48:44 +04:00
2015-03-12 17:59:59 +03:00
_lscolTimer . setInterval ( 500 ) ;
_lscolTimer . setSingleShot ( true ) ;
2017-09-20 11:14:48 +03:00
connect ( & _lscolTimer , & QTimer : : timeout , this , & FolderWizardRemotePath : : slotLsColFolderEntry ) ;
2015-03-23 18:28:42 +03:00
_ui . folderTreeWidget - > header ( ) - > setSectionResizeMode ( 0 , QHeaderView : : ResizeToContents ) ;
// Make sure that there will be a scrollbar when the contents is too wide
_ui . folderTreeWidget - > header ( ) - > setStretchLastSection ( false ) ;
2011-04-05 20:31:14 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : slotAddRemoteFolder ( )
2011-10-06 18:55:28 +04:00
{
2013-08-06 23:50:06 +04:00
QTreeWidgetItem * current = _ui . folderTreeWidget - > currentItem ( ) ;
QString parent ( ' / ' ) ;
if ( current ) {
parent = current - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
}
2020-05-18 21:54:23 +03:00
auto * dlg = new QInputDialog ( this ) ;
2013-08-06 23:50:06 +04:00
2014-12-04 12:47:26 +03:00
dlg - > setWindowTitle ( tr ( " Create Remote Folder " ) ) ;
2021-07-28 22:35:13 +03:00
dlg - > setLabelText ( tr ( " Enter the name of the new folder to be created below \" %1 \" : " )
2014-12-04 12:47:26 +03:00
. arg ( parent ) ) ;
2013-07-22 20:07:44 +04:00
dlg - > open ( this , SLOT ( slotCreateRemoteFolder ( QString ) ) ) ;
dlg - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2011-10-06 18:55:28 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : slotCreateRemoteFolder ( const QString & folder )
2011-10-06 18:55:28 +04:00
{
2012-04-14 21:08:53 +04:00
if ( folder . isEmpty ( ) )
return ;
2013-10-23 16:48:44 +04:00
2014-12-04 12:47:26 +03:00
QTreeWidgetItem * current = _ui . folderTreeWidget - > currentItem ( ) ;
QString fullPath ;
if ( current ) {
fullPath = current - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
}
fullPath + = " / " + folder ;
2020-05-18 21:54:23 +03:00
auto * job = new MkColJob ( _account , fullPath , this ) ;
2013-10-23 16:48:44 +04:00
/* check the owncloud configuration file and query the ownCloud */
2021-02-17 16:30:26 +03:00
connect ( job , & MkColJob : : finishedWithoutError ,
2017-09-20 12:48:13 +03:00
this , & FolderWizardRemotePath : : slotCreateRemoteFolderFinished ) ;
2017-09-20 11:14:48 +03:00
connect ( job , & AbstractNetworkJob : : networkError , this , & FolderWizardRemotePath : : slotHandleMkdirNetworkError ) ;
2013-11-14 22:20:09 +04:00
job - > start ( ) ;
2011-10-26 15:59:06 +04:00
}
2021-02-17 16:30:26 +03:00
void FolderWizardRemotePath : : slotCreateRemoteFolderFinished ( )
2011-10-26 15:59:06 +04:00
{
2021-02-17 16:30:26 +03:00
qCDebug ( lcWizard ) < < " webdav mkdir request finished " ;
showWarn ( tr ( " Folder was successfully created on %1. " ) . arg ( Theme : : instance ( ) - > appNameGUI ( ) ) ) ;
slotRefreshFolders ( ) ;
2022-09-30 22:36:58 +03:00
_ui . folderEntry - > setText ( dynamic_cast < MkColJob * > ( sender ( ) ) - > path ( ) ) ;
2021-02-17 16:30:26 +03:00
slotLsColFolderEntry ( ) ;
2013-10-23 16:48:44 +04:00
}
2015-08-21 12:46:38 +03:00
void FolderWizardRemotePath : : slotHandleMkdirNetworkError ( QNetworkReply * reply )
2013-10-23 16:48:44 +04:00
{
2017-03-30 14:46:20 +03:00
qCWarning ( lcWizard ) < < " webdav mkdir request failed: " < < reply - > error ( ) ;
2017-03-23 17:53:22 +03:00
if ( ! _account - > credentials ( ) - > stillValid ( reply ) ) {
2015-03-10 14:14:14 +03:00
showWarn ( tr ( " Authentication failed accessing %1 " ) . arg ( Theme : : instance ( ) - > appNameGUI ( ) ) ) ;
} else {
showWarn ( tr ( " Failed to create the folder on %1. Please check manually. " )
. arg ( Theme : : instance ( ) - > appNameGUI ( ) ) ) ;
}
2011-10-26 15:59:06 +04:00
}
2011-10-06 18:55:28 +04:00
2020-09-18 14:42:42 +03:00
void FolderWizardRemotePath : : slotHandleLsColNetworkError ( QNetworkReply * reply )
2015-08-21 12:46:38 +03:00
{
2020-09-18 14:42:42 +03:00
// Ignore 404s, otherwise users will get annoyed by error popups
// when not typing fast enough. It's still clear that a given path
// was not found, because the 'Next' button is disabled and no entry
// is selected in the tree view.
int httpCode = reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) . toInt ( ) ;
if ( httpCode = = 404 ) {
showWarn ( QString ( ) ) ; // hides the warning pane
return ;
}
2017-07-28 11:13:07 +03:00
auto job = qobject_cast < LsColJob * > ( sender ( ) ) ;
ASSERT ( job ) ;
2015-08-21 12:46:38 +03:00
showWarn ( tr ( " Failed to list a folder. Error: %1 " )
2017-03-23 17:53:22 +03:00
. arg ( job - > errorStringParsingBody ( ) ) ) ;
2015-08-21 12:46:38 +03:00
}
2013-08-06 23:50:06 +04:00
static QTreeWidgetItem * findFirstChild ( QTreeWidgetItem * parent , const QString & text )
{
for ( int i = 0 ; i < parent - > childCount ( ) ; + + i ) {
QTreeWidgetItem * child = parent - > child ( i ) ;
if ( child - > text ( 0 ) = = text ) {
return child ;
}
}
2018-11-11 12:56:22 +03:00
return nullptr ;
2013-08-06 23:50:06 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : recursiveInsert ( QTreeWidgetItem * parent , QStringList pathTrail , QString path )
2013-08-06 23:50:06 +04:00
{
2015-03-12 17:59:59 +03:00
if ( pathTrail . isEmpty ( ) )
return ;
const QString parentPath = parent - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
const QString folderName = pathTrail . first ( ) ;
QString folderPath ;
if ( parentPath = = QLatin1String ( " / " ) ) {
folderPath = folderName ;
2013-08-06 23:50:06 +04:00
} else {
2015-03-12 17:59:59 +03:00
folderPath = parentPath + " / " + folderName ;
}
QTreeWidgetItem * item = findFirstChild ( parent , folderName ) ;
if ( ! item ) {
item = new QTreeWidgetItem ( parent ) ;
QFileIconProvider prov ;
QIcon folderIcon = prov . icon ( QFileIconProvider : : Folder ) ;
item - > setIcon ( 0 , folderIcon ) ;
item - > setText ( 0 , folderName ) ;
item - > setData ( 0 , Qt : : UserRole , folderPath ) ;
item - > setToolTip ( 0 , folderPath ) ;
item - > setChildIndicatorPolicy ( QTreeWidgetItem : : ShowIndicator ) ;
}
pathTrail . removeFirst ( ) ;
recursiveInsert ( item , pathTrail , path ) ;
}
bool FolderWizardRemotePath : : selectByPath ( QString path )
{
if ( path . startsWith ( QLatin1Char ( ' / ' ) ) ) {
path = path . mid ( 1 ) ;
}
if ( path . endsWith ( QLatin1Char ( ' / ' ) ) ) {
path . chop ( 1 ) ;
}
2013-08-06 23:50:06 +04:00
2015-03-12 17:59:59 +03:00
QTreeWidgetItem * it = _ui . folderTreeWidget - > topLevelItem ( 0 ) ;
if ( ! path . isEmpty ( ) ) {
const QStringList pathTrail = path . split ( QLatin1Char ( ' / ' ) ) ;
foreach ( const QString & path , pathTrail ) {
if ( ! it ) {
return false ;
}
it = findFirstChild ( it , path ) ;
}
}
if ( ! it ) {
return false ;
2013-08-06 23:50:06 +04:00
}
2015-03-12 17:59:59 +03:00
_ui . folderTreeWidget - > setCurrentItem ( it ) ;
2016-04-27 11:37:17 +03:00
_ui . folderTreeWidget - > scrollToItem ( it ) ;
2015-03-12 17:59:59 +03:00
return true ;
2013-08-06 23:50:06 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : slotUpdateDirectories ( const QStringList & list )
2013-07-22 20:07:44 +04:00
{
2015-01-28 12:38:54 +03:00
QString webdavFolder = QUrl ( _account - > davUrl ( ) ) . path ( ) ;
2013-08-06 23:50:06 +04:00
QTreeWidgetItem * root = _ui . folderTreeWidget - > topLevelItem ( 0 ) ;
if ( ! root ) {
root = new QTreeWidgetItem ( _ui . folderTreeWidget ) ;
2013-09-16 00:46:32 +04:00
root - > setText ( 0 , Theme : : instance ( ) - > appNameGUI ( ) ) ;
root - > setIcon ( 0 , Theme : : instance ( ) - > applicationIcon ( ) ) ;
2013-08-06 23:50:06 +04:00
root - > setToolTip ( 0 , tr ( " Choose this to sync the entire account " ) ) ;
root - > setData ( 0 , Qt : : UserRole , " / " ) ;
}
2016-04-28 10:21:42 +03:00
QStringList sortedList = list ;
2016-05-19 16:36:46 +03:00
Utility : : sortFilenames ( sortedList ) ;
2016-04-28 10:21:42 +03:00
foreach ( QString path , sortedList ) {
2013-08-05 16:28:05 +04:00
path . remove ( webdavFolder ) ;
2020-06-30 19:18:06 +03:00
// Don't allow to select subfolders of encrypted subfolders
2020-12-08 17:36:17 +03:00
const auto isAnyAncestorEncrypted = std : : any_of ( std : : cbegin ( _encryptedPaths ) , std : : cend ( _encryptedPaths ) , [ = ] ( const QString & encryptedPath ) {
return path . size ( ) > encryptedPath . size ( ) & & path . startsWith ( encryptedPath ) ;
} ) ;
if ( isAnyAncestorEncrypted ) {
2020-06-30 19:18:06 +03:00
continue ;
}
2013-08-06 23:50:06 +04:00
QStringList paths = path . split ( ' / ' ) ;
if ( paths . last ( ) . isEmpty ( ) )
paths . removeLast ( ) ;
recursiveInsert ( root , paths , path ) ;
2013-07-22 20:07:44 +04:00
}
2013-08-06 23:50:06 +04:00
root - > setExpanded ( true ) ;
2013-07-22 20:07:44 +04:00
}
2020-12-08 17:36:17 +03:00
void FolderWizardRemotePath : : slotGatherEncryptedPaths ( const QString & path , const QMap < QString , QString > & properties )
{
const auto it = properties . find ( " is-encrypted " ) ;
if ( it = = properties . cend ( ) | | * it ! = QStringLiteral ( " 1 " ) ) {
return ;
}
const auto webdavFolder = QUrl ( _account - > davUrl ( ) ) . path ( ) ;
Q_ASSERT ( path . startsWith ( webdavFolder ) ) ;
_encryptedPaths < < path . mid ( webdavFolder . size ( ) ) ;
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : slotRefreshFolders ( )
2013-07-22 20:07:44 +04:00
{
2020-12-08 17:36:17 +03:00
_encryptedPaths . clear ( ) ;
2015-08-21 12:46:38 +03:00
runLsColJob ( " / " ) ;
2013-08-06 23:50:06 +04:00
_ui . folderTreeWidget - > clear ( ) ;
2015-03-12 17:59:59 +03:00
_ui . folderEntry - > clear ( ) ;
2013-08-06 23:50:06 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : slotItemExpanded ( QTreeWidgetItem * item )
2013-08-06 23:50:06 +04:00
{
2013-10-23 16:48:44 +04:00
QString dir = item - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
2015-08-21 12:46:38 +03:00
runLsColJob ( dir ) ;
2013-07-22 20:07:44 +04:00
}
2015-03-12 17:59:59 +03:00
void FolderWizardRemotePath : : slotCurrentItemChanged ( QTreeWidgetItem * item )
{
if ( item ) {
QString dir = item - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
2020-06-30 19:18:06 +03:00
// We don't want to allow creating subfolders in encrypted folders outside of the sync logic
2020-12-08 17:36:17 +03:00
const auto encrypted = _encryptedPaths . contains ( dir ) ;
2020-06-30 19:18:06 +03:00
_ui . addFolderButton - > setEnabled ( ! encrypted ) ;
2015-03-12 17:59:59 +03:00
if ( ! dir . startsWith ( QLatin1Char ( ' / ' ) ) ) {
dir . prepend ( QLatin1Char ( ' / ' ) ) ;
}
_ui . folderEntry - > setText ( dir ) ;
}
emit completeChanged ( ) ;
}
void FolderWizardRemotePath : : slotFolderEntryEdited ( const QString & text )
{
if ( selectByPath ( text ) ) {
_lscolTimer . stop ( ) ;
return ;
}
2020-05-18 21:39:16 +03:00
_ui . folderTreeWidget - > setCurrentItem ( nullptr ) ;
2015-03-12 17:59:59 +03:00
_lscolTimer . start ( ) ; // avoid sending a request on each keystroke
}
void FolderWizardRemotePath : : slotLsColFolderEntry ( )
{
QString path = _ui . folderEntry - > text ( ) ;
if ( path . startsWith ( QLatin1Char ( ' / ' ) ) )
path = path . mid ( 1 ) ;
2015-08-21 12:46:38 +03:00
LsColJob * job = runLsColJob ( path ) ;
2016-04-27 11:37:17 +03:00
// No error handling, no updating, we do this manually
// because of extra logic in the typed-path case.
2020-05-18 21:39:16 +03:00
disconnect ( job , nullptr , this , nullptr ) ;
2017-09-20 11:14:48 +03:00
connect ( job , & LsColJob : : finishedWithError ,
2020-09-18 14:42:42 +03:00
this , & FolderWizardRemotePath : : slotHandleLsColNetworkError ) ;
2017-09-20 11:14:48 +03:00
connect ( job , & LsColJob : : directoryListingSubfolders ,
this , & FolderWizardRemotePath : : slotTypedPathFound ) ;
2015-03-12 17:59:59 +03:00
}
void FolderWizardRemotePath : : slotTypedPathFound ( const QStringList & subpaths )
{
slotUpdateDirectories ( subpaths ) ;
selectByPath ( _ui . folderEntry - > text ( ) ) ;
}
2015-08-21 12:46:38 +03:00
LsColJob * FolderWizardRemotePath : : runLsColJob ( const QString & path )
{
2020-05-18 21:54:23 +03:00
auto * job = new LsColJob ( _account , path , this ) ;
2020-12-08 17:36:17 +03:00
auto props = QList < QByteArray > ( ) < < " resourcetype " ;
if ( _account - > capabilities ( ) . clientSideEncryptionAvailable ( ) ) {
props < < " http://nextcloud.org/ns:is-encrypted " ;
}
job - > setProperties ( props ) ;
2017-09-20 11:14:48 +03:00
connect ( job , & LsColJob : : directoryListingSubfolders ,
this , & FolderWizardRemotePath : : slotUpdateDirectories ) ;
connect ( job , & LsColJob : : finishedWithError ,
this , & FolderWizardRemotePath : : slotHandleLsColNetworkError ) ;
2020-12-08 17:36:17 +03:00
connect ( job , & LsColJob : : directoryListingIterated ,
this , & FolderWizardRemotePath : : slotGatherEncryptedPaths ) ;
2015-08-21 12:46:38 +03:00
job - > start ( ) ;
return job ;
}
2020-05-25 22:33:24 +03:00
FolderWizardRemotePath : : ~ FolderWizardRemotePath ( ) = default ;
2011-04-05 20:31:14 +04:00
2014-01-14 20:40:42 +04:00
bool FolderWizardRemotePath : : isComplete ( ) const
2011-04-05 20:31:14 +04:00
{
2013-08-06 23:50:06 +04:00
if ( ! _ui . folderTreeWidget - > currentItem ( ) )
2013-07-22 20:07:44 +04:00
return false ;
2013-11-26 05:02:56 +04:00
QStringList warnStrings ;
2013-08-06 23:50:06 +04:00
QString dir = _ui . folderTreeWidget - > currentItem ( ) - > data ( 0 , Qt : : UserRole ) . toString ( ) ;
2013-11-26 05:02:56 +04:00
if ( ! dir . startsWith ( QLatin1Char ( ' / ' ) ) ) {
dir . prepend ( QLatin1Char ( ' / ' ) ) ;
}
2013-07-23 01:14:41 +04:00
wizard ( ) - > setProperty ( " targetPath " , dir ) ;
2014-06-13 01:17:13 +04:00
Folder : : Map map = FolderMan : : instance ( ) - > map ( ) ;
2013-09-11 01:37:52 +04:00
Folder : : Map : : const_iterator i = map . constBegin ( ) ;
for ( i = map . constBegin ( ) ; i ! = map . constEnd ( ) ; i + + ) {
2020-05-18 21:54:23 +03:00
auto * f = static_cast < Folder * > ( i . value ( ) ) ;
2015-04-28 12:29:35 +03:00
if ( f - > accountState ( ) - > account ( ) ! = _account ) {
continue ;
}
2019-01-25 09:46:16 +03:00
QString curDir = f - > remotePathTrailingSlash ( ) ;
2013-11-26 05:02:56 +04:00
if ( QDir : : cleanPath ( dir ) = = QDir : : cleanPath ( curDir ) ) {
warnStrings . append ( tr ( " This folder is already being synced. " ) ) ;
2019-01-25 09:46:16 +03:00
} else if ( dir . startsWith ( curDir ) ) {
2017-02-23 16:54:17 +03:00
warnStrings . append ( tr ( " You are already syncing <i>%1</i>, which is a parent folder of <i>%2</i>. " ) . arg ( Utility : : escape ( curDir ) , Utility : : escape ( dir ) ) ) ;
2020-11-27 12:03:32 +03:00
} else if ( curDir . startsWith ( dir ) ) {
warnStrings . append ( tr ( " You are already syncing <i>%1</i>, which is a subfolder of <i>%2</i>. " ) . arg ( Utility : : escape ( curDir ) , Utility : : escape ( dir ) ) ) ;
2013-09-11 01:37:52 +04:00
}
2011-04-05 20:31:14 +04:00
}
2013-11-26 05:02:56 +04:00
showWarn ( formatWarnings ( warnStrings ) ) ;
2017-09-14 16:09:21 +03:00
return true ;
2011-04-05 20:31:14 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : cleanupPage ( )
2011-10-26 15:59:06 +04:00
{
2012-03-16 17:43:37 +04:00
showWarn ( ) ;
2011-10-26 15:59:06 +04:00
}
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : initializePage ( )
2011-04-05 20:31:14 +04:00
{
2012-03-16 17:43:37 +04:00
showWarn ( ) ;
2013-10-23 16:48:44 +04:00
slotRefreshFolders ( ) ;
2011-10-06 12:54:54 +04:00
}
2011-10-05 19:49:03 +04:00
2014-01-14 20:40:42 +04:00
void FolderWizardRemotePath : : showWarn ( const QString & msg ) const
2011-10-06 12:54:54 +04:00
{
2011-10-19 13:53:12 +04:00
if ( msg . isEmpty ( ) ) {
2011-10-26 15:59:06 +04:00
_ui . warnFrame - > hide ( ) ;
2012-03-16 17:43:37 +04:00
2011-10-19 13:53:12 +04:00
} else {
2011-10-26 15:59:06 +04:00
_ui . warnFrame - > show ( ) ;
2011-10-19 13:53:12 +04:00
_ui . warnLabel - > setText ( msg ) ;
}
2011-10-12 17:14:39 +04:00
}
2011-10-19 13:53:12 +04:00
// ====================================================================================
2016-11-29 12:39:20 +03:00
FolderWizardSelectiveSync : : FolderWizardSelectiveSync ( const AccountPtr & account )
2014-08-15 18:26:38 +04:00
{
2020-05-18 21:54:23 +03:00
auto * layout = new QVBoxLayout ( this ) ;
2017-01-03 17:33:06 +03:00
_selectiveSync = new SelectiveSyncWidget ( account , this ) ;
layout - > addWidget ( _selectiveSync ) ;
2018-04-05 14:35:25 +03:00
2018-11-13 13:46:26 +03:00
if ( Theme : : instance ( ) - > showVirtualFilesOption ( ) & & bestAvailableVfsMode ( ) ! = Vfs : : Off ) {
2020-12-16 23:09:40 +03:00
_virtualFilesCheckBox = new QCheckBox ( tr ( " Use virtual files instead of downloading content immediately %1 " ) . arg ( bestAvailableVfsMode ( ) = = Vfs : : WindowsCfApi ? QString ( ) : tr ( " (experimental) " ) ) ) ;
2018-05-18 09:29:40 +03:00
connect ( _virtualFilesCheckBox , & QCheckBox : : clicked , this , & FolderWizardSelectiveSync : : virtualFilesCheckboxClicked ) ;
2018-09-16 13:25:44 +03:00
connect ( _virtualFilesCheckBox , & QCheckBox : : stateChanged , this , [ this ] ( int state ) {
_selectiveSync - > setEnabled ( state = = Qt : : Unchecked ) ;
} ) ;
2020-09-17 12:16:12 +03:00
_virtualFilesCheckBox - > setChecked ( bestAvailableVfsMode ( ) = = Vfs : : WindowsCfApi ) ;
2018-05-18 09:29:40 +03:00
layout - > addWidget ( _virtualFilesCheckBox ) ;
2018-04-05 14:35:25 +03:00
}
2014-08-15 18:26:38 +04:00
}
2020-05-25 22:33:24 +03:00
FolderWizardSelectiveSync : : ~ FolderWizardSelectiveSync ( ) = default ;
2014-08-15 18:26:38 +04:00
void FolderWizardSelectiveSync : : initializePage ( )
{
QString targetPath = wizard ( ) - > property ( " targetPath " ) . toString ( ) ;
if ( targetPath . startsWith ( ' / ' ) ) {
targetPath = targetPath . mid ( 1 ) ;
}
2016-05-17 11:49:57 +03:00
QString alias = QFileInfo ( targetPath ) . fileName ( ) ;
if ( alias . isEmpty ( ) )
alias = Theme : : instance ( ) - > appName ( ) ;
2017-01-04 16:28:11 +03:00
QStringList initialBlacklist ;
if ( Theme : : instance ( ) - > wizardSelectiveSyncDefaultNothing ( ) ) {
initialBlacklist = QStringList ( " / " ) ;
}
_selectiveSync - > setFolderInfo ( targetPath , alias , initialBlacklist ) ;
2021-05-07 20:02:03 +03:00
if ( _virtualFilesCheckBox ) {
// TODO: remove when UX decision is made
if ( Utility : : isPathWindowsDrivePartitionRoot ( wizard ( ) - > field ( QStringLiteral ( " sourceFolder " ) ) . toString ( ) ) ) {
_virtualFilesCheckBox - > setChecked ( false ) ;
_virtualFilesCheckBox - > setEnabled ( false ) ;
_virtualFilesCheckBox - > setText ( tr ( " Virtual files are not supported for Windows partition roots as local folder. Please choose a valid subfolder under drive letter. " ) ) ;
} else {
_virtualFilesCheckBox - > setChecked ( bestAvailableVfsMode ( ) = = Vfs : : WindowsCfApi ) ;
_virtualFilesCheckBox - > setEnabled ( true ) ;
_virtualFilesCheckBox - > setText ( tr ( " Use virtual files instead of downloading content immediately %1 " ) . arg ( bestAvailableVfsMode ( ) = = Vfs : : WindowsCfApi ? QString ( ) : tr ( " (experimental) " ) ) ) ;
2021-11-04 13:20:16 +03:00
if ( Theme : : instance ( ) - > enforceVirtualFilesSyncFolder ( ) ) {
_virtualFilesCheckBox - > setChecked ( true ) ;
_virtualFilesCheckBox - > setDisabled ( true ) ;
}
2021-05-07 20:02:03 +03:00
}
//
}
2014-08-15 18:26:38 +04:00
QWizardPage : : initializePage ( ) ;
}
bool FolderWizardSelectiveSync : : validatePage ( )
{
2020-10-21 13:31:21 +03:00
const bool useVirtualFiles = _virtualFilesCheckBox & & _virtualFilesCheckBox - > isChecked ( ) ;
if ( useVirtualFiles ) {
const auto availability = Vfs : : checkAvailability ( wizard ( ) - > field ( QStringLiteral ( " sourceFolder " ) ) . toString ( ) ) ;
if ( ! availability ) {
auto msg = new QMessageBox ( QMessageBox : : Warning , tr ( " Virtual files are not available for the selected folder " ) , availability . error ( ) , QMessageBox : : Ok , this ) ;
msg - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
msg - > open ( ) ;
return false ;
}
}
2018-09-16 13:25:44 +03:00
wizard ( ) - > setProperty ( " selectiveSyncBlackList " , useVirtualFiles ? QVariant ( ) : QVariant ( _selectiveSync - > createBlackList ( ) ) ) ;
wizard ( ) - > setProperty ( " useVirtualFiles " , QVariant ( useVirtualFiles ) ) ;
2014-08-15 18:26:38 +04:00
return true ;
}
void FolderWizardSelectiveSync : : cleanupPage ( )
{
QString targetPath = wizard ( ) - > property ( " targetPath " ) . toString ( ) ;
2016-05-17 11:49:57 +03:00
QString alias = QFileInfo ( targetPath ) . fileName ( ) ;
if ( alias . isEmpty ( ) )
alias = Theme : : instance ( ) - > appName ( ) ;
2017-01-03 17:33:06 +03:00
_selectiveSync - > setFolderInfo ( targetPath , alias ) ;
2014-08-15 18:26:38 +04:00
QWizardPage : : cleanupPage ( ) ;
}
2018-05-18 09:29:40 +03:00
void FolderWizardSelectiveSync : : virtualFilesCheckboxClicked ( )
2018-04-03 18:30:17 +03:00
{
// The click has already had an effect on the box, so if it's
// checked it was newly activated.
2018-05-18 09:29:40 +03:00
if ( _virtualFilesCheckBox - > isChecked ( ) ) {
2020-11-27 11:58:57 +03:00
OwncloudWizard : : askExperimentalVirtualFilesFeature ( this , [ this ] ( bool enable ) {
2018-04-03 18:30:17 +03:00
if ( ! enable )
2018-05-18 09:29:40 +03:00
_virtualFilesCheckBox - > setChecked ( false ) ;
2018-04-03 18:30:17 +03:00
} ) ;
}
}
2014-08-15 18:26:38 +04:00
// ====================================================================================
2011-04-05 20:31:14 +04:00
/**
* Folder wizard itself
*/
2015-01-28 12:38:54 +03:00
FolderWizard : : FolderWizard ( AccountPtr account , QWidget * parent )
2011-10-11 16:23:32 +04:00
: QWizard ( parent )
2016-09-30 15:08:00 +03:00
, _folderWizardSourcePage ( new FolderWizardLocalPath ( account ) )
2015-01-28 12:38:54 +03:00
, _folderWizardSelectiveSyncPage ( new FolderWizardSelectiveSync ( account ) )
2011-04-05 13:10:44 +04:00
{
2013-11-13 23:12:56 +04:00
setWindowFlags ( windowFlags ( ) & ~ Qt : : WindowContextHelpButtonHint ) ;
2013-07-04 21:59:40 +04:00
setPage ( Page_Source , _folderWizardSourcePage ) ;
2017-11-21 18:13:06 +03:00
_folderWizardSourcePage - > installEventFilter ( this ) ;
2013-04-08 16:50:26 +04:00
if ( ! Theme : : instance ( ) - > singleSyncFolder ( ) ) {
2015-01-28 12:38:54 +03:00
_folderWizardTargetPage = new FolderWizardRemotePath ( account ) ;
2013-04-08 16:50:26 +04:00
setPage ( Page_Target , _folderWizardTargetPage ) ;
2017-11-21 18:13:06 +03:00
_folderWizardTargetPage - > installEventFilter ( this ) ;
2013-04-08 16:50:26 +04:00
}
2014-08-15 18:26:38 +04:00
setPage ( Page_SelectiveSync , _folderWizardSelectiveSyncPage ) ;
2013-04-08 16:50:26 +04:00
2015-10-27 14:12:21 +03:00
setWindowTitle ( tr ( " Add Folder Sync Connection " ) ) ;
2013-08-09 02:27:06 +04:00
setOptions ( QWizard : : CancelButtonOnLeft ) ;
2015-10-27 14:12:21 +03:00
setButtonText ( QWizard : : FinishButton , tr ( " Add Sync Connection " ) ) ;
2011-04-05 13:10:44 +04:00
}
2020-05-25 22:33:24 +03:00
FolderWizard : : ~ FolderWizard ( ) = default ;
2013-04-08 16:50:26 +04:00
2017-11-21 18:13:06 +03:00
bool FolderWizard : : eventFilter ( QObject * watched , QEvent * event )
{
if ( event - > type ( ) = = QEvent : : LayoutRequest ) {
// Workaround QTBUG-3396: forces QWizardPrivate::updateLayout()
QTimer : : singleShot ( 0 , this , [ this ] { setTitleFormat ( titleFormat ( ) ) ; } ) ;
}
return QWizard : : eventFilter ( watched , event ) ;
}
void FolderWizard : : resizeEvent ( QResizeEvent * event )
{
QWizard : : resizeEvent ( event ) ;
// workaround for QTBUG-22819: when the error label word wrap, the minimum height is not adjusted
2018-01-09 13:41:39 +03:00
if ( auto page = currentPage ( ) ) {
int hfw = page - > heightForWidth ( page - > width ( ) ) ;
if ( page - > height ( ) < hfw ) {
page - > setMinimumSize ( page - > minimumSizeHint ( ) . width ( ) , hfw ) ;
setTitleFormat ( titleFormat ( ) ) ; // And another workaround for QTBUG-3396
}
2017-11-21 18:13:06 +03:00
}
}
2011-10-11 16:23:32 +04:00
2011-09-26 15:12:00 +04:00
} // end namespace