Skip to content

Commit 4b05aed

Browse files
authored
Collection of work to improve efficiency of app (#12081)
* example cases for enhancing handling of previous "assert" conditions * started collecting migration related code to a single function in FolderMan named migrateFolderDefinition improved loading from config to only save the extracted FolderDefintions if they were migrated started prepping for deeper cuts related to Folder::saveToSettings, plus overhaul of impl and uses of FolderMan::addFolderFromFolderWizardResult and addFolderFromWizard * fix for failing unit tests. Hopefully fixes squish tests too. * many changes to give FolderDefinition a clear public interface with accessors, all members are now private, FolderMan has been removed as friend refactored addFolderInternal -> moved the small amount of actual folder adding code out and renamed it connectFolder. Also refactored unloadFolder -> moved some parts to removeFolderSync (formerly removeFolder which was easily confused with internal remove operations) and renamed it to disconnectFolder to match connectFolder activity. put an end to the extra careful handling of "unexpected" Vfs modes - basically now if the mode isn't among our legit set, it just assumes VfsMode = off added loads of todo's and other notes for next steps * BAH! I didn't commit these = failing build :( * first stab at consolidating all code paths to use addFolder * woops - missed this small but important change before last merge * corrected "ok" param logic for SyncJournalDb::getSelectiveSyncList ok param originally took a pointer to bool which makes no sense since it's a simple flag value, and most importantly not allowed to be nullptr. It should therefore be a ref. * added many Refactoring todo's Refactored the auto-loading of spaces/ocis folders on adding account. Moved the bulk of the activity to FolderMan where it belongs. saving is still wonky and done in the folder sometimes but now I should be able to finally finish this persistence task now that loading spaces/folders from account is in the FolderMan. * fixed the saving on adding folders - finally! need to validate the auto-save on changing pause or vfs mode as I think we will still get too many saves when enabling/disabling vfs in the Folder but otherwise it's in good shape now last steps are to relocate the removeFromSettings operations from Folder to FolderMan * saves are now updated - all folder persistence is managed by FolderMan now there are a couple of wonky bits but they should be ironed out in future when we convert direct calls from Gui to FolderMan to signals requesting xyz change I have to do one more pass comparing functionality in AddFolderFromWizared to AddFolder, will tidy up and finally rename AddFolderFromWizard to something more sensible * this is as done as I can get it for now. main todo is to discuss some points with Erik to funny finish this. * updated some comments + removed handling for legacy folder config groups (they were already migrated/eliminated in 5.0) * home stretch. Erik and I worked out the strategy for scheduling folders for sync and calling setSyncEnabled(false/true) depending on activity *in* the FolderMan, so there is not some third party making the decisions. Unfortunately I was not able to fully eliminate calls to FolderMan::setSycnEnabled and make it private as it is still used in the SpaceMigration routine. That needs deep review/refactoring so I'm leaving it alone for now. Also refactored adding account folders from config one last time. It's now renamed addFoldersFromConfigByAccount and does just that. * worked out the final open questions with Erik so this is "done" in terms of planned intent. I still have to debug/fix the squish test failure on ocis * found an error from last refactoring of FolderMan::setupFoldersFromConfig - all better now. Also fixed broken connections that trigger saving a folder to config after change in pause or vfs mode at runtime * addressed Erik's requested review changes * this should fix the current squish test failures - revisit once qa issue #12136 is resolved * removed tests for obsolete/no longer supported folder migrations
1 parent 3d1a2d5 commit 4b05aed

30 files changed

+898
-781
lines changed

src/cmd/cmd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QSet<QString> &newLis
9191

9292
bool ok;
9393

94-
const auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
94+
const auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, ok);
9595
if (ok) {
9696
const auto changes = (oldBlackListSet - newListSet) + (newListSet - oldBlackListSet);
9797
for (const auto &it : changes) {

src/common/restartmanager.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ RestartManager::RestartManager(std::function<int(int, char **)> &&main)
3232
: _main(main)
3333
{
3434
Q_ASSERT(!_instance);
35-
_instance = this;
35+
if (!_instance)
36+
_instance = this;
3637
}
3738

3839
RestartManager::~RestartManager()
@@ -59,6 +60,9 @@ int RestartManager::exec(int argc, char **argv) const
5960
void RestartManager::requestRestart()
6061
{
6162
Q_ASSERT(_instance);
63+
if (!_instance)
64+
return;
65+
6266
qCInfo(lcRestart) << "Restarting application with PID" << QCoreApplication::applicationPid();
6367

6468
QString pathToLaunch = QCoreApplication::applicationFilePath();

src/common/syncjournaldb.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,32 +1705,31 @@ void SyncJournalDb::setErrorBlacklistEntry(const SyncJournalErrorBlacklistRecord
17051705
query->exec();
17061706
}
17071707

1708-
QSet<QString> SyncJournalDb::getSelectiveSyncList(SyncJournalDb::SelectiveSyncListType type, bool *ok)
1708+
QSet<QString> SyncJournalDb::getSelectiveSyncList(SyncJournalDb::SelectiveSyncListType type, bool &ok)
17091709
{
17101710
QSet<QString> result;
1711-
OC_ASSERT(ok);
17121711

17131712
QMutexLocker locker(&_mutex);
17141713
if (!checkConnect()) {
1715-
*ok = false;
1714+
ok = false;
17161715
return result;
17171716
}
17181717

17191718
const auto query = _queryManager.get(PreparedSqlQueryManager::GetSelectiveSyncListQuery, QByteArrayLiteral("SELECT path FROM selectivesync WHERE type=?1"), _db);
17201719
if (!query) {
1721-
*ok = false;
1720+
ok = false;
17221721
return result;
17231722
}
17241723

17251724
query->bindValue(1, int(type));
17261725
if (!query->exec()) {
1727-
*ok = false;
1726+
ok = false;
17281727
return result;
17291728
}
17301729
while (true) {
17311730
auto next = query->next();
17321731
if (!next.ok) {
1733-
*ok = false;
1732+
ok = false;
17341733
return result;
17351734
}
17361735
if (!next.hasData)
@@ -1742,7 +1741,7 @@ QSet<QString> SyncJournalDb::getSelectiveSyncList(SyncJournalDb::SelectiveSyncLi
17421741
}
17431742
result.insert(entry);
17441743
}
1745-
*ok = true;
1744+
ok = true;
17461745

17471746
return result;
17481747
}

src/common/syncjournaldb.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,11 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
168168
};
169169
Q_ENUM(SelectiveSyncListType)
170170

171-
/* return the specified list from the database */
172-
QSet<QString> getSelectiveSyncList(SelectiveSyncListType type, bool *ok);
171+
/* return the specified list from the database
172+
* ok param holds value indicating "success" of the operation. If the sync list cannot be retrieved ok will be false
173+
*/
174+
QSet<QString> getSelectiveSyncList(SelectiveSyncListType type, bool &ok);
175+
173176
/* Write the selective sync list (remove all other entries of that list */
174177
void setSelectiveSyncList(SelectiveSyncListType type, const QSet<QString> &list);
175178

src/common/vfs.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,17 @@ QString Vfs::underlyingFileName(const QString &fileName) const
4747

4848
Vfs::~Vfs() = default;
4949

50-
Optional<Vfs::Mode> Vfs::modeFromString(const QString &str)
50+
Vfs::Mode Vfs::modeFromString(const QString &str)
5151
{
5252
// Note: Strings are used for config and must be stable
5353
// keep in sync with: QString Utility::enumToString(Vfs::Mode mode)
54-
if (str == QLatin1String("off")) {
55-
return Off;
56-
} else if (str == QLatin1String("suffix")) {
54+
// which is defined BELOW
55+
if (str == QLatin1String("suffix")) {
5756
return WithSuffix;
5857
} else if (str == QLatin1String("wincfapi")) {
5958
return WindowsCfApi;
6059
}
61-
return {};
60+
return Off;
6261
}
6362

6463
template <>
@@ -72,9 +71,9 @@ QString Utility::enumToString(Vfs::Mode mode)
7271
case Vfs::Mode::WindowsCfApi:
7372
return QStringLiteral("wincfapi");
7473
case Vfs::Mode::Off:
74+
default:
7575
return QStringLiteral("off");
7676
}
77-
Q_UNREACHABLE();
7877
}
7978

8079
Result<void, QString> Vfs::checkAvailability(const QString &path, Vfs::Mode mode)
@@ -242,7 +241,8 @@ Vfs::Mode OCC::VfsPluginManager::bestAvailableVfsMode() const
242241
} else if (isVfsPluginAvailable(Vfs::Off)) {
243242
return Vfs::Off;
244243
}
245-
Q_UNREACHABLE();
244+
245+
return Vfs::Off;
246246
}
247247

248248
std::unique_ptr<Vfs> OCC::VfsPluginManager::createVfsFromPlugin(Vfs::Mode mode) const

src/common/vfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class OCSYNC_EXPORT Vfs : public QObject
123123
};
124124
Q_ENUM(ConvertToPlaceholderResult)
125125

126-
static Optional<Mode> modeFromString(const QString &str);
126+
static Mode modeFromString(const QString &str);
127127

128128
static Result<void, QString> checkAvailability(const QString &path, OCC::Vfs::Mode mode);
129129

src/gui/accountmanager.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ void AccountManager::saveAccount(Account *account, bool saveCredentials)
239239
}
240240

241241
// HACK: Save http_user also as user
242+
// Refactoring todo: is this still valid? I don't find uses of httpUserC() aside from this instance
242243
if (account->_settingsMap.contains(httpUserC()))
243244
settings->setValue(userC(), account->_settingsMap.value(httpUserC()));
244245
}
@@ -429,7 +430,7 @@ AccountStatePtr AccountManager::addAccountState(std::unique_ptr<AccountState> &&
429430
// this slot can't be connected until the account state exists because saveAccount uses the state
430431
connect(rawAccount, &Account::wantsAccountSaved, this, [rawAccount, this] {
431432
// persis the account, not the credentials, we don't know whether they are ready yet
432-
// Refactor todo: how about we make those two completely different saves? then we can ditch this lambda
433+
// Refactoring todo: how about we make those two completely different saves? then we can ditch this lambda
433434
saveAccount(rawAccount, false);
434435
});
435436

src/gui/accountsettings.cpp

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ namespace OCC {
5555

5656
Q_LOGGING_CATEGORY(lcAccountSettings, "gui.account.settings", QtInfoMsg)
5757

58+
// Refactoring todo: devise a correct handling of null account state in this ctr.
59+
// also move all this connect stuff to a "connect" method.
60+
// also ditch the lambdas which should actually be functions (private if necessary)
61+
// Also refactoring todo: split the controller behavior out into a controller. A widget should NOT contain
62+
// business or controller logic!
5863
AccountSettings::AccountSettings(const AccountStatePtr &accountState, QWidget *parent)
5964
: QWidget(parent)
6065
, ui(new Ui::AccountSettings)
@@ -67,9 +72,6 @@ AccountSettings::AccountSettings(const AccountStatePtr &accountState, QWidget *p
6772
// the QPointer properly, but as a stopgap to catch null states asap before they trickle down into other areas:
6873
Q_ASSERT(_accountState);
6974

70-
// Refactor todo: devise a correct handling of null account state in this ctr.
71-
// also move all this connect stuff to a "connect" method.
72-
// also ditch the lambdas which should actually be functions (private if necessary)
7375

7476
_model = new FolderStatusModel(this);
7577

@@ -93,6 +95,9 @@ AccountSettings::AccountSettings(const AccountStatePtr &accountState, QWidget *p
9395
connect(_accountState.data(), &AccountState::stateChanged, this, &AccountSettings::slotAccountStateChanged);
9496
slotAccountStateChanged();
9597

98+
// Refactoring todo: eval why this is created/destructed each time the user invokes the manageAccount button.
99+
// normal impl creates actions as members of either gui, or better, a controller, and controller updates action states
100+
// in line with updates it receives.
96101
connect(ui->manageAccountButton, &QToolButton::clicked, this, [this] {
97102
QMenu *menu = new QMenu(this);
98103
menu->setAttribute(Qt::WA_DeleteOnClose);
@@ -194,7 +199,7 @@ void AccountSettings::slotCustomContextMenuRequested(Folder *folder)
194199
}
195200

196201
// Add an action to open the folder on the server in a webbrowser:
197-
// Refactor todo: why are we using the folder accountState AND the local member? shouldn't the folder have the same account state
202+
// Refactoring todo: why are we using the folder accountState AND the local member? shouldn't the folder have the same account state
198203
// as this settings panel?!
199204
if (folder->accountState()->account()->capabilities().privateLinkPropertyAvailable()) {
200205
QString path = folder->remotePathTrailingSlash();
@@ -274,7 +279,7 @@ void AccountSettings::showSelectiveSyncDialog(Folder *folder)
274279
selectiveSync->setDavUrl(folder->webDavUrl());
275280
bool ok;
276281
selectiveSync->setFolderInfo(
277-
folder->remotePath(), folder->displayName(), folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok));
282+
folder->remotePath(), folder->displayName(), folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, ok));
278283
Q_ASSERT(ok);
279284

280285
auto *modalWidget = new AccountModalWidget(tr("Choose what to sync"), selectiveSync, this);
@@ -292,15 +297,12 @@ void AccountSettings::slotAddFolder()
292297
return;
293298
}
294299

295-
FolderMan::instance()->setSyncEnabled(false); // do not start more syncs.
296-
297300
FolderWizard *folderWizard = new FolderWizard(_accountState, this);
298301
folderWizard->setAttribute(Qt::WA_DeleteOnClose);
299302

300303
connect(folderWizard, &QDialog::accepted, this, &AccountSettings::slotFolderWizardAccepted);
301304
connect(folderWizard, &QDialog::rejected, this, [] {
302305
qCInfo(lcAccountSettings) << "Folder wizard cancelled";
303-
FolderMan::instance()->setSyncEnabled(true);
304306
});
305307

306308
addModalLegacyDialog(folderWizard, AccountSettings::ModalWidgetSizePolicy::Expanding);
@@ -314,20 +316,21 @@ void AccountSettings::slotFolderWizardAccepted()
314316
}
315317

316318
FolderWizard *folderWizard = qobject_cast<FolderWizard *>(sender());
317-
qCInfo(lcAccountSettings) << "Folder wizard completed";
318-
319-
const auto config = folderWizard->result();
319+
if (!folderWizard)
320+
return;
320321

321-
auto folder = FolderMan::instance()->addFolderFromFolderWizardResult(_accountState, config);
322+
qCInfo(lcAccountSettings) << "Folder wizard completed";
322323

323-
if (!config.selectiveSyncBlackList.isEmpty() && OC_ENSURE(folder && !config.useVirtualFiles)) {
324-
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, config.selectiveSyncBlackList);
324+
auto config = folderWizard->result();
325325

326-
// The user already accepted the selective sync dialog. everything is in the white list
327-
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, {QLatin1String("/")});
326+
// The gui should not allow users to selectively choose any sync lists if vfs is enabled, but this kind of check was
327+
// originally in play here so...keep it just in case.
328+
if (config.useVirtualFiles && !config.selectiveSyncBlackList.empty()) {
329+
config.selectiveSyncBlackList.clear();
328330
}
329-
FolderMan::instance()->setSyncEnabled(true);
330-
FolderMan::instance()->scheduleAllFolders();
331+
332+
// Refactoring todo: turn this into a signal/requestAddFolder
333+
FolderMan::instance()->addFolderFromGui(_accountState, config);
331334
}
332335

333336
void AccountSettings::slotRemoveCurrentFolder(Folder *folder)
@@ -345,7 +348,15 @@ void AccountSettings::slotRemoveCurrentFolder(Folder *folder)
345348
messageBox->addButton(tr("Cancel"), QMessageBox::NoRole);
346349
connect(messageBox, &QMessageBox::finished, this, [messageBox, yesButton, folder, this] {
347350
if (messageBox->clickedButton() == yesButton) {
348-
FolderMan::instance()->removeFolder(folder);
351+
// Refactoring todo: this should just emit a signal to request removing the folder - let the FolderMan do the right stuff
352+
FolderMan::instance()->removeFolderSettings(folder);
353+
FolderMan::instance()->removeFolderSync(folder);
354+
// Refactoring todo: I don't understand why this is called when a folder is removed as the slot seems to be more
355+
// geared to loading/adding newly discovered spaces *when the spaces manager notifies something has changed*
356+
// instead we seem to "conveniently" recycle the meaning of the handler to cover other changes as well.
357+
// also, I *really* don't understand why we are using a single shot timer to "schedule" this in the main event
358+
// loop when we are already in the main event loop aren't we (ie we are IN a gui slot already)? I am seeing this
359+
// a lot and so far have no explanation as to what the reason or intent is.
349360
QTimer::singleShot(0, this, &AccountSettings::slotSpacesUpdated);
350361
}
351362
});
@@ -362,9 +373,6 @@ void AccountSettings::slotEnableVfsCurrentFolder(Folder *folder)
362373

363374
// Change the folder vfs mode and load the plugin
364375
folder->setVirtualFilesEnabled(true);
365-
366-
// don't schedule the folder, it might not be ready yet.
367-
// it will schedule its self once set up
368376
}
369377
}
370378

@@ -599,18 +607,24 @@ void AccountSettings::slotSpacesUpdated()
599607
}
600608

601609
// Check if we should add new spaces automagically, or only signal that there are unsynced spaces.
610+
// Refactoring todo answer to above: we should not be loading spaces in any gui. Instead I would expect that the gui merely updates
611+
// it's view/state in response to new or removed spaces. The clue is that the main actor here is FolderMan - connect FolderMan to whoever
612+
// emits the newly discovered spaces (or whatever this is) and let it deal with it.
613+
// A wrinkle here is that this slot is called in several places in the gui, apparently just to trigger refresh or similar? Not good!
602614
if (Theme::instance()->syncNewlyDiscoveredSpaces()) {
615+
// Refactoring todo: why is this scheduled for "later" on the main event loop? aren't we already there?
616+
// where does this slot run if not on the main thread?
617+
// what needs to be processed "before" this loading routine that requires scheduling it for later?
618+
// if anything we should consider running the loading routines in a worker thread to avoid *blocking* the main
619+
// event loop.
603620
QTimer::singleShot(0, this, [this, unsycnedSpaces]() {
604-
// Refactor todo: I see zero reason to make a copy of the member. Just use the member!
605-
auto accountStatePtr = _accountState;
606-
607621
for (GraphApi::Space *newSpace : unsycnedSpaces) {
608622
// TODO: Problem: when a space is manually removed, this will re-add it!
609623
qCInfo(lcAccountSettings) << "Adding sync connection for newly discovered space" << newSpace->displayName();
610624

611625
const QString localDir(_accountState->account()->defaultSyncRoot());
612626
const QString folderName = FolderMan::instance()->findGoodPathForNewSyncFolder(
613-
localDir, newSpace->displayName(), FolderMan::NewFolderType::SpacesFolder, accountStatePtr->account()->uuid());
627+
localDir, newSpace->displayName(), FolderMan::NewFolderType::SpacesFolder, _accountState->account()->uuid());
614628

615629
FolderMan::SyncConnectionDescription fwr;
616630
fwr.davUrl = QUrl(newSpace->drive().getRoot().getWebDavUrl());
@@ -619,7 +633,7 @@ void AccountSettings::slotSpacesUpdated()
619633
fwr.displayName = newSpace->displayName();
620634
fwr.useVirtualFiles = Utility::isWindows() ? Theme::instance()->showVirtualFilesOption() : false;
621635
fwr.priority = newSpace->priority();
622-
FolderMan::instance()->addFolderFromFolderWizardResult(accountStatePtr, fwr);
636+
FolderMan::instance()->addFolderFromGui(_accountState, fwr);
623637
}
624638

625639
_unsyncedSpaces = 0;

src/gui/accountstate.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,16 @@ bool AccountState::isSettingUp() const
633633
return _settingUp;
634634
}
635635

636+
// Refactoring todo: We currently call this from owncloudgui to set the val true then false at a later point
637+
// actual consumer is in the AccountSettings gui - it shows a spinny from the time it's set to
638+
// true to when it switches to false. IMO this does NOT belong in the AccountState if it can't
639+
// manage the value itself. It needs to go elsewhere, ideally the owncloudgui can just call
640+
// into the account settings directly as any good controller would
636641
void AccountState::setSettingUp(bool settingUp)
637642
{
638643
if (_settingUp != settingUp) {
639644
_settingUp = settingUp;
645+
// for goodness sake, just send the new value
640646
Q_EMIT isSettingUpChanged();
641647
}
642648
}

src/gui/application.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ Application::Application(Platform *platform, const QString &displayLanguage, boo
103103

104104
connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &ownCloudGui::slotShowShareDialog);
105105

106+
// Refactoring example: this is oversimplified and really belongs in a dedicated app builder impl but the idea is illustrated:
107+
// don't handling everything "locally" -> request that the best entity for the job do it. Then make the proper connections between
108+
// requestor and responsible handler in a clearly defined, central location (eg an app builder, but for now, this will do)
109+
connect(_gui, &ownCloudGui::requestSetUpSyncFoldersForAccount, FolderMan::instance(), &FolderMan::setUpInitialSyncFolders);
110+
106111
#ifdef WITH_AUTO_UPDATER
107112
// Update checks
108113
UpdaterScheduler *updaterScheduler = new UpdaterScheduler(this, this);

0 commit comments

Comments
 (0)