diff options
author | Jonathan White <support@dmapps.us> | 2019-10-14 16:31:23 +0300 |
---|---|---|
committer | Jonathan White <support@dmapps.us> | 2019-10-21 01:56:41 +0300 |
commit | 744b4abce801440ff4e143fb2bb416b3d7a91e07 (patch) | |
tree | 6d0f520feb41501f173536dc32a1b5d7ab0d494a /src/gui | |
parent | 6b746913e4cd96dc6d539486c539de86a39f5d28 (diff) |
Move FileWatcher into Database class
* Fix #3506
* Fix #2389
* Fix #2536
* Fix #2230
Every database that has been opened now watch's it's own file. This allows the database class to manage file changes and detect fail conditions during saving. Additionally, all stakeholders of the database can listen for the database file changed notification and respond accordingly.
Performed significant cleanup of the autoreload code within DatabaseWidget. Fixed several issues with handling changes due to merging, not merging, and other scenarios while reloading.
Prevent database saves to the same file if there are changes on disk that have not been merged with the open database.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/DatabaseTabWidget.cpp | 5 | ||||
-rw-r--r-- | src/gui/DatabaseWidget.cpp | 41 | ||||
-rw-r--r-- | src/gui/DatabaseWidget.h | 6 |
3 files changed, 10 insertions, 42 deletions
diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 8e7096a1c..4c8458e52 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -200,11 +200,14 @@ void DatabaseTabWidget::addDatabaseTab(DatabaseWidget* dbWidget, bool inBackgrou setCurrentIndex(index); } - connect(dbWidget, SIGNAL(databaseFilePathChanged(QString, QString)), SLOT(updateTabName())); connect(dbWidget, SIGNAL(requestOpenDatabase(QString, bool, QString, QString)), SLOT(addDatabaseTab(QString, bool, QString, QString))); + connect(dbWidget, SIGNAL(databaseFilePathChanged(QString, QString)), SLOT(updateTabName())); connect(dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseTabFromSender())); + connect(dbWidget, + SIGNAL(databaseReplaced(const QSharedPointer<Database>&, const QSharedPointer<Database>&)), + SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseModified()), SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseSaved()), SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseUnlocked()), SLOT(updateTabName())); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index bc6d2b507..ef76bd82d 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -94,7 +94,6 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent) , m_opVaultOpenWidget(new OpVaultOpenWidget(this)) , m_groupView(new GroupView(m_db.data(), m_mainSplitter)) , m_saveAttempts(0) - , m_fileWatcher(new DelayingFileWatcher(this)) { m_messageWidget->setHidden(true); @@ -199,7 +198,6 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent) connect(m_keepass1OpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); connect(m_opVaultOpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); connect(m_csvImportWizard, SIGNAL(importFinished(bool)), SLOT(csvImportFinished(bool))); - connect(m_fileWatcher.data(), SIGNAL(fileChanged()), this, SLOT(reloadDatabaseFile())); connect(this, SIGNAL(currentChanged(int)), SLOT(emitCurrentModeChanged())); // clang-format on @@ -895,6 +893,7 @@ void DatabaseWidget::connectDatabaseSignals() connect(m_db.data(), SIGNAL(databaseModified()), SIGNAL(databaseModified())); connect(m_db.data(), SIGNAL(databaseModified()), SLOT(onDatabaseModified())); connect(m_db.data(), SIGNAL(databaseSaved()), SIGNAL(databaseSaved())); + connect(m_db.data(), SIGNAL(databaseFileChanged()), this, SLOT(reloadDatabaseFile())); } void DatabaseWidget::loadDatabase(bool accepted) @@ -908,14 +907,12 @@ void DatabaseWidget::loadDatabase(bool accepted) if (accepted) { replaceDatabase(openWidget->database()); switchToMainView(); - m_fileWatcher->restart(); m_saveAttempts = 0; emit databaseUnlocked(); if (config()->get("MinimizeAfterUnlock").toBool()) { window()->showMinimized(); } } else { - m_fileWatcher->stop(); if (m_databaseOpenWidget->database()) { m_databaseOpenWidget->database().reset(); } @@ -1063,7 +1060,6 @@ void DatabaseWidget::switchToOpenDatabase() void DatabaseWidget::switchToOpenDatabase(const QString& filePath) { - updateFilePath(filePath); m_databaseOpenWidget->load(filePath); setCurrentWidget(m_databaseOpenWidget); } @@ -1091,14 +1087,12 @@ void DatabaseWidget::csvImportFinished(bool accepted) void DatabaseWidget::switchToImportKeepass1(const QString& filePath) { - updateFilePath(filePath); m_keepass1OpenWidget->load(filePath); setCurrentWidget(m_keepass1OpenWidget); } void DatabaseWidget::switchToImportOpVault(const QString& fileName) { - updateFilePath(fileName); m_opVaultOpenWidget->load(fileName); setCurrentWidget(m_opVaultOpenWidget); } @@ -1384,21 +1378,6 @@ bool DatabaseWidget::lock() return true; } -void DatabaseWidget::updateFilePath(const QString& filePath) -{ - m_fileWatcher->start(filePath); - m_db->setFilePath(filePath); -} - -void DatabaseWidget::blockAutoReload(bool block) -{ - if (block) { - m_fileWatcher->ignoreFileChanges(); - } else { - m_fileWatcher->observeFileChanges(true); - } -} - void DatabaseWidget::reloadDatabaseFile() { if (!m_db || isLocked()) { @@ -1417,22 +1396,20 @@ void DatabaseWidget::reloadDatabaseFile() if (result == MessageBox::No) { // Notify everyone the database does not match the file m_db->markAsModified(); - // Rewatch the database file - m_fileWatcher->restart(); return; } } QString error; auto db = QSharedPointer<Database>::create(m_db->filePath()); - if (db->open(database()->key(), &error, true)) { + if (db->open(database()->key(), &error)) { if (m_db->isModified()) { // Ask if we want to merge changes into new database auto result = MessageBox::question( this, tr("Merge Request"), tr("The database file has changed and you have unsaved changes.\nDo you want to merge your changes?"), - MessageBox::Merge | MessageBox::Cancel, + MessageBox::Merge | MessageBox::Discard, MessageBox::Merge); if (result == MessageBox::Merge) { @@ -1442,11 +1419,9 @@ void DatabaseWidget::reloadDatabaseFile() } } - QUuid groupBeforeReload; + QUuid groupBeforeReload = m_db->rootGroup()->uuid(); if (m_groupView && m_groupView->currentGroup()) { groupBeforeReload = m_groupView->currentGroup()->uuid(); - } else { - groupBeforeReload = m_db->rootGroup()->uuid(); } QUuid entryBeforeReload; @@ -1454,19 +1429,15 @@ void DatabaseWidget::reloadDatabaseFile() entryBeforeReload = m_entryView->currentEntry()->uuid(); } - bool isReadOnly = m_db->isReadOnly(); replaceDatabase(db); - m_db->setReadOnly(isReadOnly); restoreGroupEntryFocus(groupBeforeReload, entryBeforeReload); + m_blockAutoSave = false; } else { showMessage(tr("Could not open the new database file while attempting to autoreload.\nError: %1").arg(error), MessageWidget::Error); // Mark db as modified since existing data may differ from file or file was deleted m_db->markAsModified(); } - - // Rewatch the database file - m_fileWatcher->restart(); } int DatabaseWidget::numberOfSelectedEntries() const @@ -1604,7 +1575,6 @@ bool DatabaseWidget::save() } // Prevent recursions and infinite save loops - blockAutoReload(true); m_blockAutoSave = true; ++m_saveAttempts; @@ -1612,7 +1582,6 @@ bool DatabaseWidget::save() bool useAtomicSaves = config()->get("UseAtomicSaves", true).toBool(); QString errorMessage; bool ok = m_db->save(&errorMessage, useAtomicSaves, config()->get("BackupBeforeSave").toBool()); - blockAutoReload(false); if (ok) { m_saveAttempts = 0; diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 7f5e8099d..5a163a312 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -35,7 +35,7 @@ class KeePass1OpenWidget; class OpVaultOpenWidget; class DatabaseSettingsDialog; class Database; -class DelayingFileWatcher; +class FileWatcher; class EditEntryWidget; class EditGroupWidget; class Entry; @@ -108,8 +108,6 @@ public: bool currentEntryHasNotes(); bool currentEntryHasTotp(); - void blockAutoReload(bool block = true); - QByteArray entryViewState() const; bool setEntryViewState(const QByteArray& state) const; QList<int> mainSplitterSizes() const; @@ -210,7 +208,6 @@ protected: void showEvent(QShowEvent* event) override; private slots: - void updateFilePath(const QString& filePath); void entryActivationSignalReceived(Entry* entry, EntryModel::ModelColumn column); void switchBackToEntryEdit(); void switchToHistoryView(Entry* entry); @@ -273,7 +270,6 @@ private: bool m_searchLimitGroup; // Autoreload - QPointer<DelayingFileWatcher> m_fileWatcher; bool m_blockAutoSave; }; |