Add auto-save delay per database (#9100)

Add a new propery autosaveDelay in Metadata of the db.
The property is saved in customData to not affect database structure as this setting is unique to keepasxc.
The propery sets delay to wait since last modification before saving.

Co-authored-by: jNullj <jNullj@users.noreply.github.com>
This commit is contained in:
jNullj 2023-07-08 15:49:03 +03:00 committed by GitHub
parent a0874a0d6d
commit 35baeaff79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 272 additions and 6 deletions

View file

@ -1470,7 +1470,10 @@ void TestGui::testDatabaseSettings()
auto* dbSettingsStackedWidget = dbSettingsDialog->findChild<QStackedWidget*>("stackedWidget");
auto* transformRoundsSpinBox = dbSettingsDialog->findChild<QSpinBox*>("transformRoundsSpinBox");
auto advancedToggle = dbSettingsDialog->findChild<QCheckBox*>("advancedSettingsToggle");
auto* autosaveDelayCheckBox = dbSettingsDialog->findChild<QCheckBox*>("autosaveDelayCheckBox");
auto* autosaveDelaySpinBox = dbSettingsDialog->findChild<QSpinBox*>("autosaveDelaySpinBox");
auto* dbSettingsButtonBox = dbSettingsDialog->findChild<QDialogButtonBox*>("buttonBox");
int autosaveDelayTestValue = 2;
advancedToggle->setChecked(true);
QApplication::processEvents();
@ -1503,7 +1506,115 @@ void TestGui::testDatabaseSettings()
QCOMPARE(historyMaxSizeCheckBox->isChecked(), false);
QTest::mouseClick(dbSettingsButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton);
// Test loading default values and setting autosaveDelay
triggerAction("actionDatabaseSettings");
QVERIFY(autosaveDelayCheckBox->isChecked() == false);
autosaveDelayCheckBox->toggle();
autosaveDelaySpinBox->setValue(autosaveDelayTestValue);
QTest::mouseClick(dbSettingsButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
QTRY_COMPARE(m_db->metadata()->autosaveDelayMin(), autosaveDelayTestValue);
checkSaveDatabase();
// Test loading autosaveDelay non-default values
triggerAction("actionDatabaseSettings");
QTRY_COMPARE(autosaveDelayCheckBox->isChecked(), true);
QTRY_COMPARE(autosaveDelaySpinBox->value(), autosaveDelayTestValue);
QTest::mouseClick(dbSettingsButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton);
// test autosave delay
// 1 init
config()->set(Config::AutoSaveAfterEveryChange, true);
QSignalSpy writeDbSignalSpy(m_db.data(), &Database::databaseSaved);
// 2 create new entries
// 2.a) Click the new entry button and set the title
auto* entryNewAction = m_mainWindow->findChild<QAction*>("actionEntryNew");
QVERIFY(entryNewAction->isEnabled());
auto* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
QVERIFY(toolBar);
QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction);
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
QVERIFY(editEntryWidget);
auto* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
QVERIFY(titleEdit);
QTest::keyClicks(titleEdit, "Test autosaveDelay 1");
// 2.b) Save changes
editEntryWidget->setCurrentPage(0);
auto* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
// 2.c) Make sure file was not modified yet
Tools::wait(150); // due to modify timer
QTRY_COMPARE(writeDbSignalSpy.count(), 0);
// 2.d) Create second entry to test delay timer reset
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QTest::keyClicks(titleEdit, "Test autosaveDelay 2");
// 2.e) Save changes
editEntryWidget->setCurrentPage(0);
editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
// 3 Double check both true negative and true positive
// 3.a) Test unmodified prior to delay timeout
Tools::wait(150); // due to modify timer
QTRY_COMPARE(writeDbSignalSpy.count(), 0);
// 3.b) Test modification time after expected
m_dbWidget->triggerAutosaveTimer();
QTRY_COMPARE(writeDbSignalSpy.count(), 1);
// 4 Test no delay when disabled autosave or autosaveDelay
// 4.a) create new entry
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QTest::keyClicks(titleEdit, "Test autosaveDelay 3");
// 4.b) Save changes
editEntryWidget->setCurrentPage(0);
editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
// 4.c) Start timer
Tools::wait(150); // due to modify timer
// 4.d) Disable autosave
config()->set(Config::AutoSaveAfterEveryChange, false);
// 4.e) Make sure changes are not saved
m_dbWidget->triggerAutosaveTimer();
QTRY_COMPARE(writeDbSignalSpy.count(), 1);
// 4.f) Repeat for autosaveDelay
config()->set(Config::AutoSaveAfterEveryChange, true);
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QTest::keyClicks(titleEdit, "Test autosaveDelay 4");
editEntryWidget->setCurrentPage(0);
editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
Tools::wait(150); // due to modify timer
m_db->metadata()->setAutosaveDelayMin(0);
// 4.g) Make sure changes are not saved
m_dbWidget->triggerAutosaveTimer();
QTRY_COMPARE(writeDbSignalSpy.count(), 1);
// 5 Cleanup
config()->set(Config::AutoSaveAfterEveryChange, false);
}
void TestGui::testKeePass1Import()