From 6d569a86f9f7d86bc8672a7f9364cc4c525c26c0 Mon Sep 17 00:00:00 2001 From: Bernhard Rieder Date: Mon, 9 Oct 2017 13:26:24 +0200 Subject: [PATCH 01/79] added autoopen functionality (#477) --- src/gui/DatabaseTabWidget.cpp | 41 ++++++++++++++++++++++++++++++++++- src/gui/DatabaseWidget.cpp | 15 ++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index df0e1a1d..b443aba1 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -129,7 +129,13 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, while (i.hasNext()) { i.next(); if (i.value().canonicalFilePath == canonicalFilePath) { - setCurrentIndex(databaseIndex(i.key())); + if (pw.isEmpty() && keyFile.isEmpty()) { + setCurrentIndex(databaseIndex(i.key())); + } else { + if (!i.key()->hasKey()) { + i.value().dbWidget->switchToOpenDatabase(canonicalFilePath, pw, keyFile); + } + } return; } } @@ -607,6 +613,39 @@ void DatabaseTabWidget::updateTabNameFromDbWidgetSender() DatabaseWidget* dbWidget = static_cast(sender()); updateTabName(databaseFromDatabaseWidget(dbWidget)); + + Database* db = dbWidget->database(); + Group *autoload = db->rootGroup()->findChildByName("AutoOpen"); + if (autoload) + { + const DatabaseManagerStruct& dbStruct = m_dbList.value(db); + QFileInfo dbpath(dbStruct.canonicalFilePath); + QDir dbFolder(dbpath.canonicalPath()); + + for (auto entry : autoload->entries()) { + + if (entry->url().isEmpty() || entry->password().isEmpty()) + continue; + + QFileInfo filepath; + if (entry->url().startsWith("file:/")) { + QUrl url(entry->url()); + filepath.setFile(url.toLocalFile()); + } + else { + filepath.setFile(entry->url()); + if (filepath.isRelative()) { + filepath.setFile(dbFolder, entry->url()); + } + } + + if (!filepath.isFile()) + continue; + + openDatabase(filepath.canonicalFilePath(), entry->password(), ""); + + } + } } int DatabaseTabWidget::databaseIndex(Database* db) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 3a39bddc..e5693e4f 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -897,8 +897,13 @@ void DatabaseWidget::switchToDatabaseSettings() void DatabaseWidget::switchToOpenDatabase(const QString& fileName) { updateFilename(fileName); - m_databaseOpenWidget->load(fileName); - setCurrentWidget(m_databaseOpenWidget); + if (m_databaseOpenWidget) { + m_databaseOpenWidget->load(fileName); + setCurrentWidget(m_databaseOpenWidget); + } else if (m_unlockDatabaseWidget) { + m_unlockDatabaseWidget->load(fileName); + setCurrentWidget(m_unlockDatabaseWidget); + } } void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString& password, @@ -906,7 +911,11 @@ void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString { updateFilename(fileName); switchToOpenDatabase(fileName); - m_databaseOpenWidget->enterKey(password, keyFile); + if (m_databaseOpenWidget) { + m_databaseOpenWidget->enterKey(password, keyFile); + } else if (m_unlockDatabaseWidget) { + m_unlockDatabaseWidget->enterKey(password, keyFile); + } } void DatabaseWidget::switchToImportCsv(const QString& fileName) From 0fc8c37f23d0fa1ee64f718c92afc20c9ff037c9 Mon Sep 17 00:00:00 2001 From: Bernhard Rieder Date: Thu, 12 Oct 2017 23:30:51 +0200 Subject: [PATCH 02/79] changed file:/ to file:// --- src/gui/DatabaseTabWidget.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index b443aba1..67edd130 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -90,12 +90,12 @@ void DatabaseTabWidget::newDatabase() Database* db = new Database(); db->rootGroup()->setName(tr("Root")); dbStruct.dbWidget = new DatabaseWidget(db, this); - + CompositeKey emptyKey; db->setKey(emptyKey); insertDatabase(db, dbStruct); - + if (!saveDatabaseAs(db)) { closeDatabase(db); return; @@ -616,19 +616,16 @@ void DatabaseTabWidget::updateTabNameFromDbWidgetSender() Database* db = dbWidget->database(); Group *autoload = db->rootGroup()->findChildByName("AutoOpen"); - if (autoload) - { + if (autoload) { const DatabaseManagerStruct& dbStruct = m_dbList.value(db); QFileInfo dbpath(dbStruct.canonicalFilePath); QDir dbFolder(dbpath.canonicalPath()); - for (auto entry : autoload->entries()) { - - if (entry->url().isEmpty() || entry->password().isEmpty()) + if (entry->url().isEmpty() || entry->password().isEmpty()) { continue; - + } QFileInfo filepath; - if (entry->url().startsWith("file:/")) { + if (entry->url().startsWith("file://")) { QUrl url(entry->url()); filepath.setFile(url.toLocalFile()); } @@ -639,11 +636,11 @@ void DatabaseTabWidget::updateTabNameFromDbWidgetSender() } } - if (!filepath.isFile()) + if (!filepath.isFile()) { continue; + } openDatabase(filepath.canonicalFilePath(), entry->password(), ""); - } } } From 4e7f2c6a4fe920ec4301b110258f894fc9ea87bf Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 28 Oct 2017 09:23:45 -0400 Subject: [PATCH 03/79] Fix apply button not saving new entries --- src/gui/entry/EditEntryWidget.cpp | 4 ++- src/gui/entry/EditEntryWidget.h | 1 + tests/gui/TestGui.cpp | 58 ++++++++++++++++++++++++++++--- tests/gui/TestGui.h | 1 + 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 809ac95e..5a058bda 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -278,6 +278,7 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q m_database = database; m_create = create; m_history = history; + m_saved = false; if (history) { setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history"))); @@ -438,6 +439,7 @@ void EditEntryWidget::saveEntry() } updateEntryData(m_entry); + m_saved = true; if (!m_create) { m_entry->endUpdate(); @@ -510,7 +512,7 @@ void EditEntryWidget::cancel() clear(); - emit editFinished(false); + emit editFinished(m_saved); } void EditEntryWidget::clear() diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index 2888d43a..628f8f8e 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -121,6 +121,7 @@ private: bool m_create; bool m_history; + bool m_saved; const QScopedPointer m_mainUi; const QScopedPointer m_advancedUi; const QScopedPointer m_autoTypeUi; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 75ce3cc5..6805e105 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -332,15 +332,27 @@ void TestGui::testAddEntry() QTest::keyClicks(passwordRepeatEdit, "something 2"); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); - // Add entry "something 3" + // Add entry "something 3" using the apply button then click ok QTest::mouseClick(entryNewWidget, Qt::LeftButton); QTest::keyClicks(titleEdit, "something 3"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + // Add entry "something 4" using the apply button then click cancel + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "something 4"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton); + + // Add entry "something 5" but click cancel button (does NOT add entry) + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "something 5"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton); + QApplication::processEvents(); - // Confirm that 4 entries now exist - QTRY_COMPARE(entryView->model()->rowCount(), 4); + // Confirm that 5 entries now exist + QTRY_COMPARE(entryView->model()->rowCount(), 5); } void TestGui::testPasswordEntryEntropy() @@ -513,7 +525,7 @@ void TestGui::testTotp() void TestGui::testSearch() { // Add canned entries for consistent testing - testAddEntry(); + Q_UNUSED(addCannedEntries()); QToolBar* toolBar = m_mainWindow->findChild("toolBar"); @@ -629,7 +641,7 @@ void TestGui::testSearch() void TestGui::testDeleteEntry() { // Add canned entries for consistent testing - testAddEntry(); + Q_UNUSED(addCannedEntries()); GroupView* groupView = m_dbWidget->findChild("groupView"); EntryView* entryView = m_dbWidget->findChild("entryView"); @@ -905,6 +917,42 @@ void TestGui::cleanupTestCase() delete m_mainWindow; } +int TestGui::addCannedEntries() +{ + int entries_added = 0; + + // Find buttons + QToolBar* toolBar = m_mainWindow->findChild("toolBar"); + QWidget* entryNewWidget = toolBar->widgetForAction(m_mainWindow->findChild("actionEntryNew")); + EditEntryWidget* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); + QLineEdit* titleEdit = editEntryWidget->findChild("titleEdit"); + QLineEdit* passwordEdit = editEntryWidget->findChild("passwordEdit"); + QLineEdit* passwordRepeatEdit = editEntryWidget->findChild("passwordRepeatEdit"); + + // Add entry "test" and confirm added + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "test"); + QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + ++entries_added; + + // Add entry "something 2" + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "something 2"); + QTest::keyClicks(passwordEdit, "something 2"); + QTest::keyClicks(passwordRepeatEdit, "something 2"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + ++entries_added; + + // Add entry "something 3" + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "something 3"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + ++entries_added; + + return entries_added; +} + void TestGui::checkDatabase(QString dbFileName) { if (dbFileName.isEmpty()) diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 904e5f21..352dbf21 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -61,6 +61,7 @@ private slots: void testDatabaseLocking(); private: + int addCannedEntries(); void checkDatabase(QString dbFileName = ""); void triggerAction(const QString& name); void dragAndDropGroup(const QModelIndex& sourceIndex, const QModelIndex& targetIndex, int row, From ffe344ce901b37c0b118398be1a1db0862f3357d Mon Sep 17 00:00:00 2001 From: frostasm Date: Sun, 29 Oct 2017 11:18:48 +0200 Subject: [PATCH 04/79] Save the geometry of main window only if the window is visible --- src/gui/MainWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index c82ea175..ccc5fb11 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -727,7 +727,9 @@ void MainWindow::changeEvent(QEvent* event) void MainWindow::saveWindowInformation() { - config()->set("GUI/MainWindowGeometry", saveGeometry()); + if (isVisible()) { + config()->set("GUI/MainWindowGeometry", saveGeometry()); + } } bool MainWindow::saveLastDatabases() @@ -858,6 +860,7 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason) void MainWindow::hideWindow() { + saveWindowInformation(); #ifndef Q_OS_MAC setWindowState(windowState() | Qt::WindowMinimized); #endif From 6bbd42bfd194c93639ba246b92ae08dbee277e79 Mon Sep 17 00:00:00 2001 From: frostasm Date: Sat, 28 Oct 2017 18:37:05 +0300 Subject: [PATCH 05/79] Allow to change the height of the preview panel (#1135) --- src/gui/DetailsWidget.ui | 322 ++++++++++++++++++--------------------- 1 file changed, 147 insertions(+), 175 deletions(-) diff --git a/src/gui/DetailsWidget.ui b/src/gui/DetailsWidget.ui index fb31409f..8fbafe34 100644 --- a/src/gui/DetailsWidget.ui +++ b/src/gui/DetailsWidget.ui @@ -6,22 +6,10 @@ 0 0 - 630 + 600 200 - - - 0 - 0 - - - - - 16777215 - 200 - - @@ -36,12 +24,6 @@ 0 - - - 20 - 16777215 - - @@ -166,85 +148,19 @@ - - - 0 - 0 - - 0 - + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + - - - - - - - 0 - 0 - - - - PointingHandCursor - - - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Expiration - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - URL - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - @@ -267,6 +183,102 @@ + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + URL + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Expiration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + @@ -291,41 +303,11 @@ - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - 0 - 0 - - - - - + + @@ -347,7 +329,30 @@ - + + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + @@ -357,7 +362,7 @@ - + @@ -379,7 +384,7 @@ - + @@ -389,7 +394,7 @@ - + @@ -411,15 +416,18 @@ - - + + - Qt::Vertical + Qt::Horizontal + + + QSizePolicy::Fixed 20 - 40 + 20 @@ -434,27 +442,9 @@ Attributes - - + + - - - 0 - 1 - - - - - 0 - 80 - - - - - 16777215 - 80 - - Qt::ClickFocus @@ -469,27 +459,9 @@ Notes - - + + - - - 0 - 1 - - - - - 0 - 80 - - - - - 16777215 - 80 - - Qt::ClickFocus @@ -504,8 +476,8 @@ Autotype - - + + QFrame::Sunken From 8b00d0580bd4028a20124113d2bc2be3f3153f1e Mon Sep 17 00:00:00 2001 From: frostasm Date: Sat, 28 Oct 2017 21:14:45 +0300 Subject: [PATCH 06/79] Synchronize the height of the preview panel for all open databases --- src/gui/DatabaseWidget.cpp | 39 ++++++++++++++++++----------- src/gui/DatabaseWidget.h | 11 +++++--- src/gui/DatabaseWidgetStateSync.cpp | 20 ++++++++++----- src/gui/DatabaseWidgetStateSync.h | 3 ++- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 6571668c..ec51312c 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -73,15 +73,15 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) QLayout* layout = new QHBoxLayout(); mainLayout->addWidget(m_messageWidget); mainLayout->addLayout(layout); - m_splitter = new QSplitter(m_mainWidget); - m_splitter->setChildrenCollapsible(false); + m_mainSplitter = new QSplitter(m_mainWidget); + m_mainSplitter->setChildrenCollapsible(false); m_detailSplitter = new QSplitter(m_mainWidget); m_detailSplitter->setOrientation(Qt::Vertical); m_detailSplitter->setChildrenCollapsible(true); - QWidget* rightHandSideWidget = new QWidget(m_splitter); + QWidget* rightHandSideWidget = new QWidget(m_mainSplitter); - m_groupView = new GroupView(db, m_splitter); + m_groupView = new GroupView(db, m_mainSplitter); m_groupView->setObjectName("groupView"); m_groupView->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_groupView, SIGNAL(customContextMenuRequested(QPoint)), @@ -122,13 +122,13 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) setTabOrder(m_entryView, m_groupView); - m_splitter->addWidget(m_groupView); - m_splitter->addWidget(rightHandSideWidget); + m_mainSplitter->addWidget(m_groupView); + m_mainSplitter->addWidget(rightHandSideWidget); - m_splitter->setStretchFactor(0, 30); - m_splitter->setStretchFactor(1, 70); + m_mainSplitter->setStretchFactor(0, 30); + m_mainSplitter->setStretchFactor(1, 70); - layout->addWidget(m_splitter); + layout->addWidget(m_mainSplitter); m_mainWidget->setLayout(mainLayout); m_editEntryWidget = new EditEntryWidget(); @@ -168,7 +168,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) addWidget(m_keepass1OpenWidget); addWidget(m_unlockDatabaseWidget); - connect(m_splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged())); + connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged())); + connect(m_detailSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(detailSplitterSizesChanged())); connect(m_entryView->header(), SIGNAL(sectionResized(int,int,int)), SIGNAL(entryColumnSizesChanged())); connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(onGroupChanged(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged())); @@ -251,14 +252,24 @@ bool DatabaseWidget::isEditWidgetModified() const } } -QList DatabaseWidget::splitterSizes() const +QList DatabaseWidget::mainSplitterSizes() const { - return m_splitter->sizes(); + return m_mainSplitter->sizes(); } -void DatabaseWidget::setSplitterSizes(const QList& sizes) +void DatabaseWidget::setMainSplitterSizes(const QList& sizes) { - m_splitter->setSizes(sizes); + m_mainSplitter->setSizes(sizes); +} + +QList DatabaseWidget::detailSplitterSizes() const +{ + return m_detailSplitter->sizes(); +} + +void DatabaseWidget::setDetailSplitterSizes(const QList &sizes) +{ + m_detailSplitter->setSizes(sizes); } QList DatabaseWidget::entryHeaderViewSizes() const diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 404adb52..21507759 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -88,8 +88,10 @@ public: bool isGroupSelected() const; bool isInEditMode() const; bool isEditWidgetModified() const; - QList splitterSizes() const; - void setSplitterSizes(const QList& sizes); + QList mainSplitterSizes() const; + void setMainSplitterSizes(const QList& sizes); + QList detailSplitterSizes() const; + void setDetailSplitterSizes(const QList& sizes); QList entryHeaderViewSizes() const; void setEntryViewHeaderSizes(const QList& sizes); void clearAllWidgets(); @@ -123,7 +125,8 @@ signals: void listModeActivated(); void searchModeAboutToActivate(); void searchModeActivated(); - void splitterSizesChanged(); + void mainSplitterSizesChanged(); + void detailSplitterSizesChanged(); void entryColumnSizesChanged(); void updateSearch(QString text); @@ -214,7 +217,7 @@ private: KeePass1OpenWidget* m_keepass1OpenWidget; UnlockDatabaseWidget* m_unlockDatabaseWidget; UnlockDatabaseDialog* m_unlockDatabaseDialog; - QSplitter* m_splitter; + QSplitter* m_mainSplitter; QSplitter* m_detailSplitter; GroupView* m_groupView; EntryView* m_entryView; diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index 1510d844..9b5492b0 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -25,14 +25,16 @@ DatabaseWidgetStateSync::DatabaseWidgetStateSync(QObject* parent) , m_activeDbWidget(nullptr) , m_blockUpdates(false) { - m_splitterSizes = variantToIntList(config()->get("GUI/SplitterState")); + m_mainSplitterSizes = variantToIntList(config()->get("GUI/SplitterState")); + m_detailSplitterSizes = variantToIntList(config()->get("GUI/DetailSplitterState")); m_columnSizesList = variantToIntList(config()->get("GUI/EntryListColumnSizes")); m_columnSizesSearch = variantToIntList(config()->get("GUI/EntrySearchColumnSizes")); } DatabaseWidgetStateSync::~DatabaseWidgetStateSync() { - config()->set("GUI/SplitterState", intListToVariant(m_splitterSizes)); + config()->set("GUI/SplitterState", intListToVariant(m_mainSplitterSizes)); + config()->set("GUI/DetailSplitterState", intListToVariant(m_detailSplitterSizes)); config()->set("GUI/EntryListColumnSizes", intListToVariant(m_columnSizesList)); config()->set("GUI/EntrySearchColumnSizes", intListToVariant(m_columnSizesSearch)); } @@ -48,8 +50,11 @@ void DatabaseWidgetStateSync::setActive(DatabaseWidget* dbWidget) if (m_activeDbWidget) { m_blockUpdates = true; - if (!m_splitterSizes.isEmpty()) - m_activeDbWidget->setSplitterSizes(m_splitterSizes); + if (!m_mainSplitterSizes.isEmpty()) + m_activeDbWidget->setMainSplitterSizes(m_mainSplitterSizes); + + if (!m_detailSplitterSizes.isEmpty()) + m_activeDbWidget->setDetailSplitterSizes(m_detailSplitterSizes); if (m_activeDbWidget->isInSearchMode()) restoreSearchView(); @@ -58,7 +63,9 @@ void DatabaseWidgetStateSync::setActive(DatabaseWidget* dbWidget) m_blockUpdates = false; - connect(m_activeDbWidget, SIGNAL(splitterSizesChanged()), + connect(m_activeDbWidget, SIGNAL(mainSplitterSizesChanged()), + SLOT(updateSplitterSizes())); + connect(m_activeDbWidget, SIGNAL(detailSplitterSizesChanged()), SLOT(updateSplitterSizes())); connect(m_activeDbWidget, SIGNAL(entryColumnSizesChanged()), SLOT(updateColumnSizes())); @@ -102,7 +109,8 @@ void DatabaseWidgetStateSync::updateSplitterSizes() return; } - m_splitterSizes = m_activeDbWidget->splitterSizes(); + m_mainSplitterSizes = m_activeDbWidget->mainSplitterSizes(); + m_detailSplitterSizes = m_activeDbWidget->detailSplitterSizes(); } void DatabaseWidgetStateSync::updateColumnSizes() diff --git a/src/gui/DatabaseWidgetStateSync.h b/src/gui/DatabaseWidgetStateSync.h index 96ecd104..79a8ded3 100644 --- a/src/gui/DatabaseWidgetStateSync.h +++ b/src/gui/DatabaseWidgetStateSync.h @@ -46,7 +46,8 @@ private: DatabaseWidget* m_activeDbWidget; bool m_blockUpdates; - QList m_splitterSizes; + QList m_mainSplitterSizes; + QList m_detailSplitterSizes; QList m_columnSizesList; QList m_columnSizesSearch; }; From afaa0a3493c78d47fd4aad14c4c3fff5292b5afe Mon Sep 17 00:00:00 2001 From: frostasm Date: Thu, 2 Nov 2017 20:47:54 +0200 Subject: [PATCH 07/79] Fix formatting brackets in DatabaseWidgetStateSync::setActive function --- src/gui/DatabaseWidgetStateSync.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index 9b5492b0..57a3dcf8 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -50,16 +50,19 @@ void DatabaseWidgetStateSync::setActive(DatabaseWidget* dbWidget) if (m_activeDbWidget) { m_blockUpdates = true; - if (!m_mainSplitterSizes.isEmpty()) + if (!m_mainSplitterSizes.isEmpty()) { m_activeDbWidget->setMainSplitterSizes(m_mainSplitterSizes); + } - if (!m_detailSplitterSizes.isEmpty()) + if (!m_detailSplitterSizes.isEmpty()) { m_activeDbWidget->setDetailSplitterSizes(m_detailSplitterSizes); + } - if (m_activeDbWidget->isInSearchMode()) + if (m_activeDbWidget->isInSearchMode()) { restoreSearchView(); - else + } else { restoreListView(); + } m_blockUpdates = false; From c3c67f18b8752b3304bcd057efac43ade31c89fb Mon Sep 17 00:00:00 2001 From: thez3ro Date: Sun, 29 Oct 2017 15:04:46 +0100 Subject: [PATCH 08/79] add test for DB creation --- src/gui/DatabaseWidget.cpp | 19 +++++++++++--- src/gui/DatabaseWidget.h | 3 +++ src/gui/csvImport/CsvImportWizard.cpp | 23 ++++------------ src/gui/csvImport/CsvImportWizard.h | 6 ++--- tests/gui/TestGui.cpp | 38 +++++++++++++++++++++++++++ tests/gui/TestGui.h | 1 + 6 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index ec51312c..63420158 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -63,6 +63,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) , m_newGroup(nullptr) , m_newEntry(nullptr) , m_newParent(nullptr) + , m_importingCsv(false) { m_mainWidget = new QWidget(this); @@ -137,13 +138,14 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_editGroupWidget = new EditGroupWidget(); m_editGroupWidget->setObjectName("editGroupWidget"); m_changeMasterKeyWidget = new ChangeMasterKeyWidget(); + m_changeMasterKeyWidget->setObjectName("changeMasterKeyWidget"); m_changeMasterKeyWidget->headlineLabel()->setText(tr("Change master key")); - m_csvImportWizard = new CsvImportWizard(); - m_csvImportWizard->setObjectName("csvImportWizard"); QFont headlineLabelFont = m_changeMasterKeyWidget->headlineLabel()->font(); headlineLabelFont.setBold(true); headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2); m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont); + m_csvImportWizard = new CsvImportWizard(); + m_csvImportWizard->setObjectName("csvImportWizard"); m_databaseSettingsWidget = new DatabaseSettingsWidget(); m_databaseSettingsWidget->setObjectName("databaseSettingsWidget"); m_databaseOpenWidget = new DatabaseOpenWidget(); @@ -782,6 +784,12 @@ void DatabaseWidget::switchToGroupEdit(Group* group, bool create) void DatabaseWidget::updateMasterKey(bool accepted) { + if (m_importingCsv) { + setCurrentWidget(m_csvImportWizard); + m_csvImportWizard->keyFinished(accepted, m_changeMasterKeyWidget->newMasterKey()); + return; + } + if (accepted) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool result = m_db->setKey(m_changeMasterKeyWidget->newMasterKey()); @@ -915,6 +923,7 @@ void DatabaseWidget::switchToMasterKeyChange(bool disableCancel) m_changeMasterKeyWidget->clearForms(); m_changeMasterKeyWidget->setCancelEnabled(!disableCancel); setCurrentWidget(m_changeMasterKeyWidget); + m_importingCsv = false; } void DatabaseWidget::switchToDatabaseSettings() @@ -941,9 +950,11 @@ void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString void DatabaseWidget::switchToImportCsv(const QString& fileName) { updateFilename(fileName); - switchToMasterKeyChange(); m_csvImportWizard->load(fileName, m_db); - setCurrentWidget(m_csvImportWizard); + m_changeMasterKeyWidget->clearForms(); + m_changeMasterKeyWidget->setCancelEnabled(false); + setCurrentWidget(m_changeMasterKeyWidget); + m_importingCsv = true; } void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName) diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 21507759..e9428a70 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -236,6 +236,9 @@ private: bool m_searchCaseSensitive; bool m_searchLimitGroup; + // CSV import state + bool m_importingCsv; + // Autoreload QFileSystemWatcher m_fileWatcher; QTimer m_fileWatchTimer; diff --git a/src/gui/csvImport/CsvImportWizard.cpp b/src/gui/csvImport/CsvImportWizard.cpp index eb4b2123..e9a8f498 100644 --- a/src/gui/csvImport/CsvImportWizard.cpp +++ b/src/gui/csvImport/CsvImportWizard.cpp @@ -28,19 +28,9 @@ CsvImportWizard::CsvImportWizard(QWidget *parent) : DialogyWidget(parent) { m_layout = new QGridLayout(this); - m_pages = new QStackedWidget(parent); - m_layout->addWidget(m_pages, 0, 0); + m_layout->addWidget(m_parse = new CsvImportWidget(this), 0, 0); - m_pages->addWidget(key = new ChangeMasterKeyWidget(m_pages)); - m_pages->addWidget(parse = new CsvImportWidget(m_pages)); - key->headlineLabel()->setText(tr("Import CSV file")); - QFont headLineFont = key->headlineLabel()->font(); - headLineFont.setBold(true); - headLineFont.setPointSize(headLineFont.pointSize() + 2); - key->headlineLabel()->setFont(headLineFont); - - connect(key, SIGNAL(editFinished(bool)), this, SLOT(keyFinished(bool))); - connect(parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool))); + connect(m_parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool))); } CsvImportWizard::~CsvImportWizard() @@ -49,21 +39,18 @@ CsvImportWizard::~CsvImportWizard() void CsvImportWizard::load(const QString& filename, Database* database) { m_db = database; - parse->load(filename, database); - key->clearForms(); + m_parse->load(filename, database); } -void CsvImportWizard::keyFinished(bool accepted) +void CsvImportWizard::keyFinished(bool accepted, CompositeKey key) { if (!accepted) { emit importFinished(false); return; } - m_pages->setCurrentIndex(m_pages->currentIndex()+1); - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - bool result = m_db->setKey(key->newMasterKey()); + bool result = m_db->setKey(key); QApplication::restoreOverrideCursor(); if (!result) { diff --git a/src/gui/csvImport/CsvImportWizard.h b/src/gui/csvImport/CsvImportWizard.h index 317018d9..b6414c0c 100644 --- a/src/gui/csvImport/CsvImportWizard.h +++ b/src/gui/csvImport/CsvImportWizard.h @@ -38,19 +38,17 @@ public: explicit CsvImportWizard(QWidget *parent = nullptr); ~CsvImportWizard(); void load(const QString& filename, Database *database); + void keyFinished(bool accepted, CompositeKey key); signals: void importFinished(bool accepted); private slots: - void keyFinished(bool accepted); void parseFinished(bool accepted); private: Database* m_db; - CsvImportWidget* parse; - ChangeMasterKeyWidget* key; - QStackedWidget *m_pages; + CsvImportWidget* m_parse; QGridLayout *m_layout; }; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 75ce3cc5..8c066c93 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -49,6 +49,7 @@ #include "gui/DatabaseTabWidget.h" #include "gui/DatabaseWidget.h" #include "gui/CloneDialog.h" +#include "gui/PasswordEdit.h" #include "gui/TotpDialog.h" #include "gui/SetupTotpDialog.h" #include "gui/FileDialog.h" @@ -119,6 +120,43 @@ void TestGui::cleanup() m_dbWidget = nullptr; } +void TestGui::testCreateDatabase() +{ + fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewTestDatabase.kdbx")); + triggerAction("actionDatabaseNew"); + + DatabaseWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); + + QWidget* databaseNewWidget = dbWidget->findChild("changeMasterKeyWidget"); + QList databaseNewWidgets = dbWidget->findChildren("changeMasterKeyWidget"); + PasswordEdit* editPassword = databaseNewWidget->findChild("enterPasswordEdit"); + QVERIFY(editPassword->isVisible()); + + QLineEdit* editPasswordRepeat = databaseNewWidget->findChild("repeatPasswordEdit"); + QVERIFY(editPasswordRepeat->isVisible()); + + m_tabWidget->currentDatabaseWidget()->setCurrentWidget(databaseNewWidget); + + QTest::keyClicks(editPassword, "test"); + QTest::keyClicks(editPasswordRepeat, "test"); + QTest::keyClick(editPasswordRepeat, Qt::Key_Enter); + + QTRY_VERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).contains("*")); + + m_db = m_tabWidget->currentDatabaseWidget()->database(); + + // there is a new empty db + QCOMPARE(m_db->rootGroup()->children().size(), 0); + + // clean + MessageBox::setNextAnswer(QMessageBox::No); + triggerAction("actionDatabaseClose"); + Tools::wait(100); + + QFile dbfile(QString(KEEPASSX_TEST_DATA_DIR).append("/NewTestDatabase.kdbx")); + dbfile.remove(); +} + void TestGui::testMergeDatabase() { // It is safe to ignore the warning this line produces diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 904e5f21..9929b4e7 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -40,6 +40,7 @@ private slots: void cleanup(); void cleanupTestCase(); + void testCreateDatabase(); void testMergeDatabase(); void testAutoreloadDatabase(); void testTabs(); From d6e8e1be6e1371f9dad6b83c1fa698ac77f218af Mon Sep 17 00:00:00 2001 From: thez3ro Date: Thu, 2 Nov 2017 19:58:45 +0100 Subject: [PATCH 09/79] use QTemporaryFile when creating a database for guitest --- tests/gui/TestGui.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 8c066c93..ffa10b7d 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -122,7 +122,12 @@ void TestGui::cleanup() void TestGui::testCreateDatabase() { - fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewTestDatabase.kdbx")); + QTemporaryFile tmpFile; + QVERIFY(tmpFile.open()); + QString tmpFileName = tmpFile.fileName(); + tmpFile.remove(); + + fileDialog()->setNextFileName(tmpFileName); triggerAction("actionDatabaseNew"); DatabaseWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); @@ -148,13 +153,10 @@ void TestGui::testCreateDatabase() // there is a new empty db QCOMPARE(m_db->rootGroup()->children().size(), 0); - // clean + // close the new database MessageBox::setNextAnswer(QMessageBox::No); triggerAction("actionDatabaseClose"); Tools::wait(100); - - QFile dbfile(QString(KEEPASSX_TEST_DATA_DIR).append("/NewTestDatabase.kdbx")); - dbfile.remove(); } void TestGui::testMergeDatabase() From 78408cf54ba817f0fb666ce69a701ac10fdf41b0 Mon Sep 17 00:00:00 2001 From: Yen Chi Hsuan Date: Mon, 6 Nov 2017 16:05:39 +0800 Subject: [PATCH 10/79] COPYING: remove a duplicated entry Already in line 46~48 :) --- COPYING | 4 ---- 1 file changed, 4 deletions(-) diff --git a/COPYING b/COPYING index e12f4534..a6bf0cf4 100644 --- a/COPYING +++ b/COPYING @@ -55,10 +55,6 @@ Files: cmake/GenerateProductVersion.cmake Copyright: 2015 halex2005 License: MIT -Files: cmake/CodeCoverage.cmake -Copyright: 2012 - 2015, Lars Bilke -License: BSD-3-clause - Files: share/icons/application/*/apps/keepassxc.png share/icons/application/scalable/apps/keepassxc.svgz share/icons/application/*/apps/keepassxc-dark.png From 4853014a61f01427ec9cb59c46371c5619e74653 Mon Sep 17 00:00:00 2001 From: AsavarTzeth Date: Thu, 26 Oct 2017 13:00:50 +0200 Subject: [PATCH 11/79] Fix id and appdata validation failures (#1131) According to the AppStream specification org.keepassxc is not a valid id. The product name is missing. This results in failures if one tries to validate the file and makes it unusable where validation is enforced. Additionally it seems specification don't allow the `` tag with component type desktop-application. I am not sure this tag is strictly necessary. In any case validation tests require this to be removed. Fixing both of these issues ensure the AppStream appdata is compliant and works anywhere passing validations is a requirement. Also provide some other fixes and improvements to the appdata. Minor validation failures: - Fix missing captions for screenshots (`appstreamcli`) - Fix descriptions cannot start with `