Skip to content

Commit

Permalink
Merge PR keepassx#56: Automatic reload on DB changes
Browse files Browse the repository at this point in the history
  • Loading branch information
nandhp committed Oct 12, 2015
1 parent 6e45cf0 commit 496e1f7
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Expand Up @@ -40,6 +40,8 @@ set(keepassx_SOURCES
autotype/test/AutoTypeTestInterface.h
core/AutoTypeAssociations.cpp
core/Config.cpp
core/FileSystemWatcher.cpp
core/FileSystemWatcher.h
core/Database.cpp
core/DatabaseIcons.cpp
core/Endian.cpp
Expand Down
1 change: 1 addition & 0 deletions src/core/Config.cpp
Expand Up @@ -92,6 +92,7 @@ void Config::init(const QString& fileName)
m_defaults.insert("RememberLastKeyFiles", true);
m_defaults.insert("OpenPreviousDatabasesOnStartup", true);
m_defaults.insert("AutoSaveAfterEveryChange", false);
m_defaults.insert("AutoReloadOnChange", true);
m_defaults.insert("AutoSaveOnExit", false);
m_defaults.insert("ShowToolbar", true);
m_defaults.insert("MinimizeOnCopy", false);
Expand Down
6 changes: 6 additions & 0 deletions src/core/Database.cpp
Expand Up @@ -315,3 +315,9 @@ void Database::startModifiedTimer()
}
m_timer->start(150);
}

const CompositeKey & Database::key() const
{
return m_data.key;
}

1 change: 1 addition & 0 deletions src/core/Database.h
Expand Up @@ -88,6 +88,7 @@ class Database : public QObject
QByteArray transformSeed() const;
quint64 transformRounds() const;
QByteArray transformedMasterKey() const;
const CompositeKey & key() const;

void setCipher(const Uuid& cipher);
void setCompressionAlgo(Database::CompressionAlgorithm algo);
Expand Down
75 changes: 75 additions & 0 deletions src/core/FileSystemWatcher.cpp
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "FileSystemWatcher.h"
#include <QFile>
#include <QDir>
#include <QFileInfo>

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()
{
}

47 changes: 47 additions & 0 deletions src/core/FileSystemWatcher.h
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/

#ifndef FILE_SYSTEM_WATCHER_H
#define FILE_SYSTEM_WATCHER_H
#include <QFileSystemWatcher>
#include <QString>
#include <QObject>


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

32 changes: 32 additions & 0 deletions src/gui/DatabaseWidget.cpp
Expand Up @@ -22,10 +22,12 @@
#include <QDesktopServices>
#include <QHBoxLayout>
#include <QLabel>
#include <QFile>
#include <QLineEdit>
#include <QSplitter>
#include <QTimer>
#include <QProcess>
//#include <QtDebug>

#include "autotype/AutoType.h"
#include "core/Config.h"
Expand All @@ -34,6 +36,7 @@
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/Tools.h"
#include "format/KeePass2Reader.h"
#include "gui/ChangeMasterKeyWidget.h"
#include "gui/Clipboard.h"
#include "gui/DatabaseOpenWidget.h"
Expand Down Expand Up @@ -163,6 +166,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
connect(m_searchUi->searchEdit, SIGNAL(returnPressed()), m_entryView, SLOT(setFocus()));
connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(search()));
connect(closeAction, SIGNAL(triggered()), this, SLOT(closeSearch()));
connect( &m_file_watcher, SIGNAL( fileChanged() ), this, SLOT( databaseModifedExternally() ) );

setCurrentWidget(m_mainWidget);
}
Expand Down Expand Up @@ -639,8 +643,11 @@ 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 );
}
else {
m_file_watcher.stopWatching();
if (m_databaseOpenWidget->database()) {
delete m_databaseOpenWidget->database();
}
Expand Down Expand Up @@ -913,6 +920,31 @@ void DatabaseWidget::updateFilename(const QString& fileName)
m_filename = fileName;
}

void DatabaseWidget::databaseModifedExternally()
{
if ( database() == Q_NULLPTR )
return;

if ( ! config()->get("AutoReloadOnChange").toBool() )
return;

KeePass2Reader reader;
QFile file(m_filename);
if (!file.open(QIODevice::ReadOnly)) {
// TODO: error message
return;
}
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;
}
}

int DatabaseWidget::numberOfSelectedEntries() const
{
return m_entryView->numberOfSelectedEntries();
Expand Down
3 changes: 3 additions & 0 deletions src/gui/DatabaseWidget.h
Expand Up @@ -24,6 +24,7 @@
#include "core/Uuid.h"

#include "gui/entry/EntryModel.h"
#include "core/FileSystemWatcher.h"

class ChangeMasterKeyWidget;
class DatabaseOpenWidget;
Expand Down Expand Up @@ -137,6 +138,7 @@ private Q_SLOTS:
void emitEntryContextMenuRequested(const QPoint& pos);
void updateMasterKey(bool accepted);
void openDatabase(bool accepted);
void databaseModifedExternally();
void unlockDatabase(bool accepted);
void emitCurrentModeChanged();
void clearLastGroup(Group* group);
Expand Down Expand Up @@ -173,6 +175,7 @@ private Q_SLOTS:
QTimer* m_searchTimer;
QString m_filename;
Uuid m_groupBeforeLock;
FileSystemWatcher m_file_watcher;
};

#endif // KEEPASSX_DATABASEWIDGET_H
2 changes: 2 additions & 0 deletions src/gui/SettingsWidget.cpp
Expand Up @@ -73,6 +73,7 @@ void SettingsWidget::loadSettings()
config()->get("OpenPreviousDatabasesOnStartup").toBool());
m_generalUi->autoSaveAfterEveryChangeCheckBox->setChecked(config()->get("AutoSaveAfterEveryChange").toBool());
m_generalUi->autoSaveOnExitCheckBox->setChecked(config()->get("AutoSaveOnExit").toBool());
m_generalUi->autoReloadOnChangeCheckBox->setChecked(config()->get("AutoReloadOnChange").toBool());
m_generalUi->minimizeOnCopyCheckBox->setChecked(config()->get("MinimizeOnCopy").toBool());
m_generalUi->useGroupIconOnEntryCreationCheckBox->setChecked(config()->get("UseGroupIconOnEntryCreation").toBool());
m_generalUi->autoTypeEntryTitleMatchCheckBox->setChecked(config()->get("AutoTypeEntryTitleMatch").toBool());
Expand Down Expand Up @@ -120,6 +121,7 @@ void SettingsWidget::saveSettings()
config()->set("AutoSaveAfterEveryChange",
m_generalUi->autoSaveAfterEveryChangeCheckBox->isChecked());
config()->set("AutoSaveOnExit", m_generalUi->autoSaveOnExitCheckBox->isChecked());
config()->set("AutoReloadOnChange", m_generalUi->autoReloadOnChangeCheckBox->isChecked());
config()->set("MinimizeOnCopy", m_generalUi->minimizeOnCopyCheckBox->isChecked());
config()->set("UseGroupIconOnEntryCreation",
m_generalUi->useGroupIconOnEntryCreationCheckBox->isChecked());
Expand Down
9 changes: 8 additions & 1 deletion src/gui/SettingsWidgetGeneral.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>456</width>
<height>313</height>
<height>338</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
Expand Down Expand Up @@ -113,6 +113,13 @@
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="autoReloadOnChangeCheckBox">
<property name="text">
<string>Automatically reload when the database is externally modified</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
Expand Down

0 comments on commit 496e1f7

Please sign in to comment.