diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59ada8766..3d3d3f5f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,7 +40,6 @@ set(keepassx_SOURCES autotype/test/AutoTypeTestInterface.h core/AutoTypeAssociations.cpp core/Config.cpp - core/FileSystemWatcher.cpp core/Database.cpp core/DatabaseIcons.cpp core/Endian.cpp diff --git a/src/core/FileSystemWatcher.cpp b/src/core/FileSystemWatcher.cpp deleted file mode 100644 index 93b4f6f3f..000000000 --- a/src/core/FileSystemWatcher.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * 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 or (at your option) - * version 3 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "FileSystemWatcher.h" -#include -#include -#include - -FileSystemWatcher::FileSystemWatcher (): QFileSystemWatcher ( ) -{ - connect(this,SIGNAL( fileChanged ( const QString & )), - this,SLOT( fileChangedSlot ( const QString & ))); - connect(this,SIGNAL( directoryChanged ( const QString & )), - this,SLOT( directoryChangedSlot ( const QString & ))); -} - -void FileSystemWatcher::watchFile(const QString &file) -{ - _file=file; - if (!files().isEmpty()) - removePaths(files()); - if (!directories().isEmpty()) - removePaths(directories()); - QFileInfo fileInfo(file); - if (fileInfo.exists()) - addPath(file); - QString filePath=fileInfo.absoluteDir().path(); - QFileInfo filePathInfo(filePath); - if (filePathInfo.exists()) - addPath(filePath); -} - -void FileSystemWatcher::stopWatching() -{ - watchFile( QString() ); -} - -void FileSystemWatcher::fileChangedSlot ( const QString & ) -{ - QFileInfo fileInfo(_file); - if ( fileInfo.exists() ) - fileChanged(); -} - -void FileSystemWatcher::directoryChangedSlot ( const QString & ) -{ - if (!files().contains(_file)) - { - QFileInfo fileInfo(_file); - if ( fileInfo.exists() ) - { - addPath(_file); - fileChanged(); - } - } -} - -FileSystemWatcher::~FileSystemWatcher() -{ -} - diff --git a/src/core/FileSystemWatcher.h b/src/core/FileSystemWatcher.h deleted file mode 100644 index 4721a98b7..000000000 --- a/src/core/FileSystemWatcher.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * 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 or (at your option) - * version 3 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef FILE_SYSTEM_WATCHER_H -#define FILE_SYSTEM_WATCHER_H -#include -#include -#include - - -class FileSystemWatcher : public QFileSystemWatcher -{ - Q_OBJECT ; - -public: - FileSystemWatcher (); - void watchFile( const QString & ); - void stopWatching(); - - virtual ~FileSystemWatcher(); - -private: - QString _file; - -private Q_SLOTS: - void directoryChangedSlot ( const QString & ); - void fileChangedSlot ( const QString & ); -Q_SIGNALS: - void fileChanged(); -}; - -#endif - diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 8915e5c06..f9b635af0 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "autotype/AutoType.h" @@ -157,8 +156,12 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_databaseOpenMergeWidget, SIGNAL(editFinished(bool)), SLOT(mergeDatabase(bool))); connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool))); + connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(onWatchedFileChanged())); + connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile())); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); + m_fileWatchTimer.setSingleShot(true); + m_searchCaseSensitive = false; m_searchCurrentGroup = false; @@ -662,11 +665,10 @@ void DatabaseWidget::openDatabase(bool accepted) m_databaseOpenWidget = nullptr; delete m_keepass1OpenWidget; m_keepass1OpenWidget = nullptr; - if (config()->get("AutoReloadOnChange").toBool() ) - m_file_watcher.watchFile( m_filename ); + m_fileWatcher.addPath(m_filename); } else { - m_file_watcher.stopWatching(); + m_fileWatcher.removePath(m_filename); if (m_databaseOpenWidget->database()) { delete m_databaseOpenWidget->database(); } @@ -939,29 +941,52 @@ void DatabaseWidget::updateFilename(const QString& fileName) m_filename = fileName; } -void DatabaseWidget::databaseModifedExternally() +void DatabaseWidget::onWatchedFileChanged() { - if ( database() == Q_NULLPTR ) + if (m_fileWatchTimer.isActive()) return; - if ( ! config()->get("AutoReloadOnChange").toBool() ) + m_fileWatchTimer.start(500); +} + +void DatabaseWidget::reloadDatabaseFile() +{ + if (m_db == nullptr) return; + // TODO: Also check if db is currently modified before reloading + if (! config()->get("AutoReloadOnChange").toBool()) { + // Ask if we want to reload the db + QMessageBox::StandardButton mb = MessageBox::question(this, tr("Reload database file"), + tr("The database file has changed. Do you want to load the changes?"), + QMessageBox::Yes | QMessageBox::No); + + if (mb == QMessageBox::No) { + // TODO: taint database + + // Rewatch the database file + m_fileWatcher.addPath(m_filename); + return; + } + } + KeePass2Reader reader; QFile file(m_filename); - if (!file.open(QIODevice::ReadOnly)) { - // TODO: error message - return; + if (file.open(QIODevice::ReadOnly)) { + Database* db = reader.readDatabase(&file, database()->key()); + if (db != nullptr) { + replaceDatabase(db); + } + else { + // TODO: error message for failure to read the new db + } } - Database* db = reader.readDatabase(&file, database()->key() ); - if ( db ) - { - Database* oldDb = m_db; - m_db = db; - m_groupView->changeDatabase(m_db); - Q_EMIT databaseChanged(m_db); - delete oldDb; + else { + // TODO: error message for failure to open db file } + + // Rewatch the database file + m_fileWatcher.addPath(m_filename); } int DatabaseWidget::numberOfSelectedEntries() const diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 57211c05f..11b5d3963 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -20,11 +20,12 @@ #include #include +#include +#include #include "core/Uuid.h" #include "gui/entry/EntryModel.h" -#include "core/FileSystemWatcher.h" class ChangeMasterKeyWidget; class DatabaseOpenWidget; @@ -42,6 +43,7 @@ class QMenu; class QSplitter; class QLabel; class UnlockDatabaseWidget; +class QFileSystemWatcher; class DatabaseWidget : public QStackedWidget { @@ -149,10 +151,12 @@ private Q_SLOTS: void updateMasterKey(bool accepted); void openDatabase(bool accepted); void mergeDatabase(bool accepted); - void databaseModifedExternally(); void unlockDatabase(bool accepted); void emitCurrentModeChanged(); void clearLastGroup(Group* group); + // Database autoreload slots + void onWatchedFileChanged(); + void reloadDatabaseFile(); private: void setClipboardTextAndMinimize(const QString& text); @@ -186,7 +190,8 @@ private: bool m_searchCaseSensitive; bool m_searchCurrentGroup; - FileSystemWatcher m_file_watcher; + QFileSystemWatcher m_fileWatcher; + QTimer m_fileWatchTimer; }; #endif // KEEPASSX_DATABASEWIDGET_H diff --git a/src/gui/SettingsWidgetGeneral.ui b/src/gui/SettingsWidgetGeneral.ui index 843e16fec..223e2b9af 100644 --- a/src/gui/SettingsWidgetGeneral.ui +++ b/src/gui/SettingsWidgetGeneral.ui @@ -7,7 +7,7 @@ 0 0 684 - 394 + 430 @@ -103,14 +103,7 @@ - - - - Show a system tray icon - - - - + QLayout::SetMaximumSize @@ -149,7 +142,7 @@ - + QLayout::SetMaximumSize @@ -179,7 +172,7 @@ - + QLayout::SetMaximumSize @@ -209,6 +202,13 @@ + + + + Show a system tray icon + + + diff --git a/tests/data/NewDatabase.kdbx b/tests/data/NewDatabase.kdbx index 4e77724c7..f45929de2 100644 Binary files a/tests/data/NewDatabase.kdbx and b/tests/data/NewDatabase.kdbx differ