mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
parent
c8fc25ea5c
commit
e591dbcf10
7
COPYING
7
COPYING
@ -155,6 +155,7 @@ Files: share/icons/application/scalable/actions/application-exit.svg
|
||||
share/icons/application/scalable/actions/database-lock-all.svg
|
||||
share/icons/application/scalable/actions/database-merge.svg
|
||||
share/icons/application/scalable/actions/database-search.svg
|
||||
share/icons/application/scalable/actions/database-settings.svg
|
||||
share/icons/application/scalable/actions/dialog-close.svg
|
||||
share/icons/application/scalable/actions/dialog-ok.svg
|
||||
share/icons/application/scalable/actions/document-close.svg
|
||||
@ -243,9 +244,9 @@ Files: share/icons/application/scalable/actions/application-exit.svg
|
||||
share/icons/application/scalable/actions/lock-open-alert.svg
|
||||
share/icons/application/scalable/actions/lock-open.svg
|
||||
share/icons/application/scalable/actions/lock.svg
|
||||
Copyright: 2019 Austin Andrews <http://templarian.com/>
|
||||
License: SIL OPEN FONT LICENSE Version 1.1
|
||||
Comment: Taken from Material Design icon set (https://github.com/templarian/MaterialDesign/)
|
||||
Copyright: 2023 Pictogrammers <https://pictogrammers.com/docs/general/about/>
|
||||
License: Apache-2.0
|
||||
Comment: Some icons are modified to fit KeePassXC design (https://pictogrammers.com/library/mdi/)
|
||||
|
||||
Files: src/streams/qtiocompressor.*
|
||||
src/streams/QtIOCompressor
|
||||
|
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 14C9.58 14 7.3 13.4 6 12.45V9.64C7.47 10.47 9.61 11 12 11S16.53 10.47 18 9.64V12.08C18.33 12.03 18.66 12 19 12C19.34 12 19.67 12.03 20 12.08V7C20 4.79 16.42 3 12 3S4 4.79 4 7V17C4 19.21 7.59 21 12 21C12.1 21 12.2 21 12.29 21C12.11 20.36 12 19.69 12 19C8.13 19 6 17.5 6 17V14.77C7.61 15.55 9.72 16 12 16C12.24 16 12.47 16 12.7 15.97C13.1 15.14 13.65 14.41 14.32 13.81C13.58 13.93 12.8 14 12 14M12 5C15.87 5 18 6.5 18 7S15.87 9 12 9 6 7.5 6 7 8.13 5 12 5M22.7 19.6V18.6L23.8 17.8C23.9 17.7 24 17.6 23.9 17.5L22.9 15.8C22.9 15.7 22.7 15.7 22.6 15.7L21.4 16.2C21.1 16 20.8 15.8 20.5 15.7L20.3 14.4C20.3 14.3 20.2 14.2 20.1 14.2H18.1C17.9 14.2 17.8 14.3 17.8 14.4L17.6 15.7C17.3 15.9 17.1 16 16.8 16.2L15.6 15.7C15.5 15.7 15.4 15.7 15.3 15.8L14.3 17.5C14.3 17.6 14.3 17.7 14.4 17.8L15.5 18.6V19.6L14.4 20.4C14.3 20.5 14.2 20.6 14.3 20.7L15.3 22.4C15.4 22.5 15.5 22.5 15.6 22.5L16.8 22C17 22.2 17.3 22.4 17.6 22.5L17.8 23.8C17.9 23.9 18 24 18.1 24H20.1C20.2 24 20.3 23.9 20.3 23.8L20.5 22.5C20.8 22.3 21 22.2 21.3 22L22.5 22.4C22.6 22.4 22.7 22.4 22.8 22.3L23.8 20.6C23.9 20.5 23.9 20.4 23.8 20.4L22.7 19.6M19 20.5C18.2 20.5 17.5 19.8 17.5 19S18.2 17.5 19 17.5 20.5 18.2 20.5 19 19.8 20.5 19 20.5Z" /></svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -1 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="mdi-close-circle-outline" width="24" height="24" viewBox="0 0 24 24"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M14.59,8L12,10.59L9.41,8L8,9.41L10.59,12L8,14.59L9.41,16L12,13.41L14.59,16L16,14.59L13.41,12L16,9.41L14.59,8Z" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M16,10V17A1,1 0 0,1 15,18H9A1,1 0 0,1 8,17V10H16M13.5,6L14.5,7H17V9H7V7H9.5L10.5,6H13.5Z" /></svg>
|
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 309 B |
@ -1 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="mdi-lightbulb-on-outline" width="24" height="24" viewBox="0 0 24 24"><path d="M20,11H23V13H20V11M1,11H4V13H1V11M13,1V4H11V1H13M4.92,3.5L7.05,5.64L5.63,7.05L3.5,4.93L4.92,3.5M16.95,5.63L19.07,3.5L20.5,4.93L18.37,7.05L16.95,5.63M12,6A6,6 0 0,1 18,12C18,14.22 16.79,16.16 15,17.2V19A1,1 0 0,1 14,20H10A1,1 0 0,1 9,19V17.2C7.21,16.16 6,14.22 6,12A6,6 0 0,1 12,6M14,21V22A1,1 0 0,1 13,23H11A1,1 0 0,1 10,22V21H14M11,18H13V15.87C14.73,15.43 16,13.86 16,12A4,4 0 0,0 12,8A4,4 0 0,0 8,12C8,13.86 9.27,15.43 11,15.87V18Z" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 16V4H8V16M22 16C22 17.1 21.1 18 20 18H8C6.9 18 6 17.1 6 16V4C6 2.9 6.9 2 8 2H20C21.1 2 22 2.9 22 4M16 20V22H4C2.9 22 2 21.1 2 20V7H4V20M16 11H18V14H16M13 6H15V14H13M10 8H12V14H10Z" /></svg>
|
Before Width: | Height: | Size: 758 B After Width: | Height: | Size: 262 B |
@ -20,6 +20,7 @@
|
||||
<file>application/scalable/actions/database-lock-all.svg</file>
|
||||
<file>application/scalable/actions/database-merge.svg</file>
|
||||
<file>application/scalable/actions/database-search.svg</file>
|
||||
<file>application/scalable/actions/database-settings.svg</file>
|
||||
<file>application/scalable/actions/dialog-close.svg</file>
|
||||
<file>application/scalable/actions/dialog-ok.svg</file>
|
||||
<file>application/scalable/actions/document-close.svg</file>
|
||||
|
@ -1689,6 +1689,10 @@ Are you sure you want to continue with this file?.</source>
|
||||
<source>Remote Sync</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Database Settings: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DatabaseSettingsWidgetBrowser</name>
|
||||
|
@ -543,7 +543,7 @@ namespace FdoSecrets
|
||||
}
|
||||
// switch selected to current
|
||||
m_databases->setCurrentWidget(dbWidget);
|
||||
m_databases->showDatabaseSettings();
|
||||
m_databases->showDatabaseSettings(true);
|
||||
|
||||
// open settings (switch from app settings to m_dbTabs)
|
||||
m_plugin->emitRequestSwitchToDatabases();
|
||||
|
@ -537,21 +537,29 @@ bool DatabaseTabWidget::warnOnExport()
|
||||
return ans == MessageBox::Yes;
|
||||
}
|
||||
|
||||
void DatabaseTabWidget::showDatabaseReports(bool state)
|
||||
{
|
||||
if (state) {
|
||||
currentDatabaseWidget()->switchToDatabaseReports();
|
||||
} else {
|
||||
currentDatabaseWidget()->switchToMainView();
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseTabWidget::showDatabaseSettings(bool state)
|
||||
{
|
||||
if (state) {
|
||||
currentDatabaseWidget()->switchToDatabaseSettings();
|
||||
} else {
|
||||
currentDatabaseWidget()->switchToMainView();
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseTabWidget::showDatabaseSecurity()
|
||||
{
|
||||
currentDatabaseWidget()->switchToDatabaseSecurity();
|
||||
}
|
||||
|
||||
void DatabaseTabWidget::showDatabaseReports()
|
||||
{
|
||||
currentDatabaseWidget()->switchToDatabaseReports();
|
||||
}
|
||||
|
||||
void DatabaseTabWidget::showDatabaseSettings()
|
||||
{
|
||||
currentDatabaseWidget()->switchToDatabaseSettings();
|
||||
}
|
||||
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
void DatabaseTabWidget::showPasskeys()
|
||||
{
|
||||
|
@ -82,9 +82,9 @@ public slots:
|
||||
void unlockAnyDatabaseInDialog(DatabaseOpenDialog::Intent intent);
|
||||
void relockPendingDatabase();
|
||||
|
||||
void showDatabaseReports(bool state);
|
||||
void showDatabaseSettings(bool state);
|
||||
void showDatabaseSecurity();
|
||||
void showDatabaseReports();
|
||||
void showDatabaseSettings();
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
void showPasskeys();
|
||||
void importPasskey();
|
||||
|
@ -265,15 +265,26 @@ QSharedPointer<Database> DatabaseWidget::database() const
|
||||
|
||||
DatabaseWidget::Mode DatabaseWidget::currentMode() const
|
||||
{
|
||||
if (currentWidget() == nullptr) {
|
||||
return Mode::None;
|
||||
} else if (currentWidget() == m_mainWidget) {
|
||||
return Mode::ViewMode;
|
||||
} else if (currentWidget() == m_databaseOpenWidget) {
|
||||
return Mode::LockedMode;
|
||||
auto mode = Mode::None;
|
||||
auto widget = currentWidget();
|
||||
if (widget == m_mainWidget) {
|
||||
mode = Mode::ViewMode;
|
||||
} else if (widget == m_databaseOpenWidget) {
|
||||
mode = Mode::LockedMode;
|
||||
} else if (widget == m_reportsDialog) {
|
||||
mode = Mode::ReportsMode;
|
||||
} else if (widget == m_databaseSettingDialog) {
|
||||
mode = Mode::DatabaseSettingsMode;
|
||||
} else if (widget == m_editEntryWidget) {
|
||||
mode = Mode::EditEntryMode;
|
||||
} else if (widget == m_editGroupWidget) {
|
||||
mode = Mode::EditGroupMode;
|
||||
} else {
|
||||
return Mode::EditMode;
|
||||
// We are missing a condition if we reach here
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
bool DatabaseWidget::isLocked() const
|
||||
@ -1014,7 +1025,7 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
|
||||
}
|
||||
}
|
||||
|
||||
Entry* DatabaseWidget::currentSelectedEntry()
|
||||
Entry* DatabaseWidget::currentSelectedEntry() const
|
||||
{
|
||||
if (currentWidget() == m_editEntryWidget) {
|
||||
return m_editEntryWidget->currentEntry();
|
||||
@ -1516,15 +1527,19 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod
|
||||
|
||||
void DatabaseWidget::switchToDatabaseReports()
|
||||
{
|
||||
if (currentMode() != Mode::ReportsMode) {
|
||||
m_reportsDialog->load(m_db);
|
||||
setCurrentWidget(m_reportsDialog);
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseWidget::switchToDatabaseSettings()
|
||||
{
|
||||
if (currentMode() != Mode::DatabaseSettingsMode) {
|
||||
m_databaseSettingDialog->load(m_db);
|
||||
setCurrentWidget(m_databaseSettingDialog);
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseWidget::switchToOpenDatabase()
|
||||
{
|
||||
@ -1865,16 +1880,13 @@ void DatabaseWidget::onEntryChanged(Entry* entry)
|
||||
|
||||
bool DatabaseWidget::canCloneCurrentGroup() const
|
||||
{
|
||||
bool isRootGroup = m_db->rootGroup() == m_groupView->currentGroup();
|
||||
// bool isRecycleBin = isRecycleBinSelected();
|
||||
|
||||
return !isRootGroup;
|
||||
auto currentGroup = m_groupView->currentGroup();
|
||||
return currentGroup != m_db->rootGroup() && currentGroup != m_db->metadata()->recycleBin();
|
||||
}
|
||||
|
||||
bool DatabaseWidget::canDeleteCurrentGroup() const
|
||||
{
|
||||
bool isRootGroup = m_db->rootGroup() == m_groupView->currentGroup();
|
||||
return !isRootGroup;
|
||||
return currentGroup() != m_db->rootGroup();
|
||||
}
|
||||
|
||||
Group* DatabaseWidget::currentGroup() const
|
||||
@ -2483,7 +2495,9 @@ void DatabaseWidget::hideMessage()
|
||||
|
||||
bool DatabaseWidget::isRecycleBinSelected() const
|
||||
{
|
||||
return m_groupView->currentGroup() && m_groupView->currentGroup() == m_db->metadata()->recycleBin();
|
||||
auto group = currentGroup();
|
||||
auto entry = currentSelectedEntry();
|
||||
return (group && group->isRecycled()) || (entry && entry->isRecycled());
|
||||
}
|
||||
|
||||
void DatabaseWidget::emptyRecycleBin()
|
||||
|
@ -64,8 +64,11 @@ public:
|
||||
{
|
||||
None,
|
||||
ViewMode,
|
||||
EditMode,
|
||||
LockedMode
|
||||
EditEntryMode,
|
||||
EditGroupMode,
|
||||
LockedMode,
|
||||
ReportsMode,
|
||||
DatabaseSettingsMode
|
||||
};
|
||||
|
||||
explicit DatabaseWidget(QSharedPointer<Database> db, QWidget* parent = nullptr);
|
||||
@ -106,7 +109,7 @@ public:
|
||||
QStringList customEntryAttributes() const;
|
||||
bool isEditWidgetModified() const;
|
||||
void clearAllWidgets();
|
||||
Entry* currentSelectedEntry();
|
||||
Entry* currentSelectedEntry() const;
|
||||
bool currentEntryHasTitle();
|
||||
bool currentEntryHasUsername();
|
||||
bool currentEntryHasPassword();
|
||||
|
@ -31,6 +31,7 @@ EditWidget::EditWidget(QWidget* parent)
|
||||
setModified(false);
|
||||
|
||||
m_ui->messageWidget->setHidden(true);
|
||||
m_ui->headerLabel->setHidden(true);
|
||||
|
||||
QFont headerLabelFont = m_ui->headerLabel->font();
|
||||
headerLabelFont.setBold(true);
|
||||
@ -118,6 +119,7 @@ void EditWidget::setCurrentPage(int index)
|
||||
|
||||
void EditWidget::setHeadline(const QString& text)
|
||||
{
|
||||
m_ui->headerLabel->setHidden(text.isEmpty());
|
||||
m_ui->headerLabel->setText(text);
|
||||
}
|
||||
|
||||
|
@ -127,6 +127,8 @@ MainWindow::MainWindow()
|
||||
|
||||
m_entryContextMenu = new QMenu(this);
|
||||
m_entryContextMenu->setSeparatorsCollapsible(true);
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryRestore);
|
||||
m_entryContextMenu->addSeparator();
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryCopyUsername);
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryCopyPassword);
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryCopyURL);
|
||||
@ -154,8 +156,6 @@ MainWindow::MainWindow()
|
||||
m_entryContextMenu->addSeparator();
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryAddToAgent);
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryRemoveFromAgent);
|
||||
m_entryContextMenu->addSeparator();
|
||||
m_entryContextMenu->addAction(m_ui->actionEntryRestore);
|
||||
|
||||
m_entryNewContextMenu = new QMenu(this);
|
||||
m_entryNewContextMenu->addAction(m_ui->actionEntryNew);
|
||||
@ -346,8 +346,10 @@ MainWindow::MainWindow()
|
||||
m_ui->actionDatabaseSaveBackup->setIcon(icons()->icon("document-save-copy"));
|
||||
m_ui->actionDatabaseClose->setIcon(icons()->icon("document-close"));
|
||||
m_ui->actionReports->setIcon(icons()->icon("reports"));
|
||||
m_ui->actionDatabaseSettings->setIcon(icons()->icon("document-edit"));
|
||||
m_ui->actionDatabaseSettings->setIcon(icons()->icon("database-settings"));
|
||||
m_ui->actionDatabaseSecurity->setIcon(icons()->icon("database-change-key"));
|
||||
m_ui->actionPasskeys->setIcon(icons()->icon("passkey"));
|
||||
m_ui->actionImportPasskey->setIcon(icons()->icon("document-import"));
|
||||
m_ui->actionLockDatabase->setIcon(icons()->icon("database-lock"));
|
||||
m_ui->actionLockDatabaseToolbar->setIcon(icons()->icon("database-lock"));
|
||||
m_ui->actionLockAllDatabases->setIcon(icons()->icon("database-lock-all"));
|
||||
@ -357,6 +359,12 @@ MainWindow::MainWindow()
|
||||
m_ui->actionImport->setIcon(icons()->icon("document-import"));
|
||||
m_ui->menuExport->setIcon(icons()->icon("document-export"));
|
||||
|
||||
#ifndef WITH_XC_BROWSER_PASSKEYS
|
||||
m_ui->actionPasskeys->setVisible(false);
|
||||
m_ui->actionImportPasskey->setVisible(false);
|
||||
m_ui->actionEntryImportPasskey->setVisible(false);
|
||||
#endif
|
||||
|
||||
m_ui->actionEntryNew->setIcon(icons()->icon("entry-new"));
|
||||
m_ui->actionEntryClone->setIcon(icons()->icon("entry-clone"));
|
||||
m_ui->actionEntryEdit->setIcon(icons()->icon("entry-edit"));
|
||||
@ -381,6 +389,7 @@ MainWindow::MainWindow()
|
||||
m_ui->actionEntryCopyPasswordTotp->setIcon(icons()->icon("totp-copy-password"));
|
||||
m_ui->actionEntryTotpQRCode->setIcon(icons()->icon("qrcode"));
|
||||
m_ui->actionEntrySetupTotp->setIcon(icons()->icon("totp-edit"));
|
||||
m_ui->actionEntryImportPasskey->setIcon(icons()->icon("document-import"));
|
||||
m_ui->actionEntryAddToAgent->setIcon(icons()->icon("utilities-terminal"));
|
||||
m_ui->actionEntryRemoveFromAgent->setIcon(icons()->icon("utilities-terminal"));
|
||||
m_ui->menuTags->setIcon(icons()->icon("tag-multiple"));
|
||||
@ -415,11 +424,10 @@ MainWindow::MainWindow()
|
||||
m_ui->actionEntryRemovePasskey->setIcon(icons()->icon("document-close"));
|
||||
#endif
|
||||
|
||||
m_actionMultiplexer.connect(
|
||||
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
|
||||
m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(setMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(entrySelectionChanged()), this, SLOT(setMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(databaseNonDataChanged()), this, SLOT(setMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(updateMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(updateMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(entrySelectionChanged()), this, SLOT(updateMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(databaseNonDataChanged()), this, SLOT(updateMenuActionState()));
|
||||
m_actionMultiplexer.connect(SIGNAL(groupContextMenuRequested(QPoint)), this, SLOT(showGroupContextMenu(QPoint)));
|
||||
m_actionMultiplexer.connect(SIGNAL(entryContextMenuRequested(QPoint)), this, SLOT(showEntryContextMenu(QPoint)));
|
||||
m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(updateEntryCountLabel()));
|
||||
@ -438,11 +446,11 @@ MainWindow::MainWindow()
|
||||
connect(m_ui->tabWidget, SIGNAL(tabNameChanged()), SLOT(updateWindowTitle()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateWindowTitle()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(databaseTabChanged(int)));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(setMenuActionState()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateMenuActionState()));
|
||||
connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*)));
|
||||
connect(m_ui->tabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*)));
|
||||
connect(m_ui->tabWidget, SIGNAL(tabVisibilityChanged(bool)), SLOT(updateToolbarSeparatorVisibility()));
|
||||
connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(setMenuActionState()));
|
||||
connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(updateMenuActionState()));
|
||||
connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(updateWindowTitle()));
|
||||
connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(updateToolbarSeparatorVisibility()));
|
||||
connect(m_ui->settingsWidget, SIGNAL(accepted()), SLOT(applySettingsChanges()));
|
||||
@ -457,9 +465,9 @@ MainWindow::MainWindow()
|
||||
connect(m_ui->actionDatabaseSaveBackup, SIGNAL(triggered()), m_ui->tabWidget, SLOT(saveDatabaseBackup()));
|
||||
connect(m_ui->actionDatabaseClose, SIGNAL(triggered()), m_ui->tabWidget, SLOT(closeCurrentDatabaseTab()));
|
||||
connect(m_ui->actionDatabaseMerge, SIGNAL(triggered()), m_ui->tabWidget, SLOT(mergeDatabase()));
|
||||
connect(m_ui->actionDatabaseSettings, SIGNAL(toggled(bool)), m_ui->tabWidget, SLOT(showDatabaseSettings(bool)));
|
||||
connect(m_ui->actionDatabaseSecurity, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseSecurity()));
|
||||
connect(m_ui->actionReports, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseReports()));
|
||||
connect(m_ui->actionDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseSettings()));
|
||||
connect(m_ui->actionReports, SIGNAL(toggled(bool)), m_ui->tabWidget, SLOT(showDatabaseReports(bool)));
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
connect(m_ui->actionPasskeys, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showPasskeys()));
|
||||
connect(m_ui->actionImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskey()));
|
||||
@ -668,7 +676,7 @@ MainWindow::MainWindow()
|
||||
statusBar()->addPermanentWidget(m_statusBarLabel);
|
||||
|
||||
restoreConfigState();
|
||||
setMenuActionState();
|
||||
updateMenuActionState();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@ -844,251 +852,149 @@ void MainWindow::openDatabase(const QString& filePath, const QString& password,
|
||||
m_ui->tabWidget->addDatabaseTab(filePath, false, password, keyfile);
|
||||
}
|
||||
|
||||
void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
||||
void MainWindow::updateMenuActionState()
|
||||
{
|
||||
// MainWindow State
|
||||
int currentIndex = m_ui->stackedWidget->currentIndex();
|
||||
bool hasLockableDatabase = m_ui->tabWidget->hasLockableDatabases();
|
||||
bool inAppSettings = (currentIndex == SettingsScreen);
|
||||
bool inPasswordGenerator = (currentIndex == PasswordGeneratorScreen);
|
||||
|
||||
bool inDatabaseTabWidget = (currentIndex == DatabaseTabScreen);
|
||||
bool inWelcomeWidget = (currentIndex == WelcomeScreen);
|
||||
bool inDatabaseTabWidgetOrWelcomeWidget = inDatabaseTabWidget || inWelcomeWidget;
|
||||
auto dbWidget = (currentIndex == DatabaseTabScreen ? m_ui->tabWidget->currentDatabaseWidget() : nullptr);
|
||||
auto dbMode = (dbWidget ? dbWidget->currentMode() : DatabaseWidget::Mode::None);
|
||||
|
||||
m_ui->actionDatabaseClose->setEnabled(true);
|
||||
m_ui->actionDatabaseMerge->setEnabled(inDatabaseTabWidget);
|
||||
m_ui->menuRemoteSync->setEnabled(inDatabaseTabWidget);
|
||||
m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget);
|
||||
m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget);
|
||||
m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget);
|
||||
m_ui->actionImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget);
|
||||
m_ui->actionLockDatabase->setEnabled(m_ui->tabWidget->hasLockableDatabases());
|
||||
m_ui->actionLockDatabaseToolbar->setEnabled(m_ui->tabWidget->hasLockableDatabases());
|
||||
m_ui->actionLockAllDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases());
|
||||
// Database State
|
||||
bool databaseUnlocked = (dbWidget && !dbWidget->isLocked());
|
||||
bool inDatabase = (dbMode == DatabaseWidget::Mode::ViewMode);
|
||||
bool inDatabaseSettings = (dbMode == DatabaseWidget::Mode::DatabaseSettingsMode);
|
||||
bool inReports = (dbMode == DatabaseWidget::Mode::ReportsMode);
|
||||
bool editingEntry = (dbMode == DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
if (inDatabaseTabWidget && m_ui->tabWidget->currentIndex() != -1) {
|
||||
DatabaseWidget* dbWidget = m_ui->tabWidget->currentDatabaseWidget();
|
||||
Q_ASSERT(dbWidget);
|
||||
// Synchronize toggle buttons
|
||||
m_ui->actionDatabaseSettings->blockSignals(true);
|
||||
m_ui->actionPasswordGenerator->blockSignals(true);
|
||||
m_ui->actionReports->blockSignals(true);
|
||||
m_ui->actionSettings->blockSignals(true);
|
||||
|
||||
if (mode == DatabaseWidget::Mode::None) {
|
||||
mode = dbWidget->currentMode();
|
||||
}
|
||||
m_ui->actionDatabaseSettings->setChecked(inDatabaseSettings);
|
||||
m_ui->actionPasswordGenerator->setChecked(inPasswordGenerator);
|
||||
m_ui->actionReports->setChecked(inReports);
|
||||
m_ui->actionSettings->setChecked(inAppSettings);
|
||||
|
||||
switch (mode) {
|
||||
case DatabaseWidget::Mode::ViewMode: {
|
||||
bool singleEntrySelected = dbWidget->numberOfSelectedEntries() == 1;
|
||||
bool entriesSelected = dbWidget->numberOfSelectedEntries() > 0;
|
||||
bool groupSelected = dbWidget->isGroupSelected();
|
||||
bool currentGroupHasChildren = dbWidget->currentGroup()->hasChildren();
|
||||
bool currentGroupHasEntries = !dbWidget->currentGroup()->entries().isEmpty();
|
||||
bool recycleBinSelected = dbWidget->isRecycleBinSelected();
|
||||
bool sorted = dbWidget->isSorted();
|
||||
int entryIndex = dbWidget->currentEntryIndex();
|
||||
int numEntries = dbWidget->currentGroup()->entries().size();
|
||||
m_ui->actionDatabaseSettings->blockSignals(false);
|
||||
m_ui->actionPasswordGenerator->blockSignals(false);
|
||||
m_ui->actionReports->blockSignals(false);
|
||||
m_ui->actionSettings->blockSignals(false);
|
||||
|
||||
m_ui->actionEntryNew->setEnabled(true);
|
||||
m_ui->actionEntryClone->setEnabled(singleEntrySelected);
|
||||
// Entry State
|
||||
bool singleEntrySelected = (inDatabase && dbWidget->numberOfSelectedEntries() == 1);
|
||||
bool singleEntryOrEditing = (singleEntrySelected || editingEntry);
|
||||
bool multiEntrySelected = (inDatabase && dbWidget->numberOfSelectedEntries() > 0);
|
||||
|
||||
// Group State
|
||||
bool groupSelected = (inDatabase && dbWidget->isGroupSelected());
|
||||
bool groupHasChildren = (groupSelected && dbWidget->currentGroup()->hasChildren());
|
||||
bool groupHasEntries = (groupSelected && !dbWidget->currentGroup()->entries().isEmpty());
|
||||
bool inRecycleBin = (inDatabase && dbWidget->isRecycleBinSelected());
|
||||
|
||||
bool entryViewSorted = (inDatabase && dbWidget->isSorted());
|
||||
bool entryViewAtTop = (inDatabase && dbWidget->currentEntryIndex() == 0);
|
||||
bool entryViewAtBottom =
|
||||
(groupSelected && dbWidget->currentEntryIndex() == dbWidget->currentGroup()->entries().size() - 1);
|
||||
|
||||
m_ui->actionEntryNew->setEnabled(inDatabase && !inRecycleBin);
|
||||
m_ui->actionEntryClone->setEnabled(singleEntrySelected && !inRecycleBin);
|
||||
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryDelete->setEnabled(entriesSelected);
|
||||
m_ui->actionEntryRestore->setVisible(entriesSelected && recycleBinSelected);
|
||||
m_ui->actionEntryRestore->setEnabled(entriesSelected && recycleBinSelected);
|
||||
m_ui->actionEntryDelete->setEnabled(multiEntrySelected);
|
||||
m_ui->actionEntryRestore->setVisible(multiEntrySelected && inRecycleBin);
|
||||
m_ui->actionEntryRestore->setEnabled(multiEntrySelected && inRecycleBin);
|
||||
if (dbWidget) {
|
||||
m_ui->actionEntryRestore->setText(tr("Restore Entry(s)", "", dbWidget->numberOfSelectedEntries()));
|
||||
m_ui->actionEntryRestore->setToolTip(tr("Restore Entry(s)", "", dbWidget->numberOfSelectedEntries()));
|
||||
m_ui->actionEntryMoveUp->setVisible(!sorted);
|
||||
m_ui->actionEntryMoveDown->setVisible(!sorted);
|
||||
m_ui->actionEntryMoveUp->setEnabled(singleEntrySelected && !sorted && entryIndex > 0);
|
||||
m_ui->actionEntryMoveDown->setEnabled(singleEntrySelected && !sorted && entryIndex >= 0
|
||||
&& entryIndex < numEntries - 1);
|
||||
m_ui->actionEntryCopyTitle->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTitle());
|
||||
m_ui->actionEntryCopyUsername->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername());
|
||||
}
|
||||
m_ui->actionEntryMoveUp->setVisible(inDatabase && !entryViewSorted);
|
||||
m_ui->actionEntryMoveDown->setVisible(inDatabase && !entryViewSorted);
|
||||
m_ui->actionEntryMoveUp->setEnabled(singleEntrySelected && !entryViewSorted && !entryViewAtTop);
|
||||
m_ui->actionEntryMoveDown->setEnabled(singleEntrySelected && !entryViewSorted && !entryViewAtBottom);
|
||||
m_ui->actionEntryCopyTitle->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasTitle());
|
||||
m_ui->actionEntryCopyUsername->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasUsername());
|
||||
// NOTE: Copy password is enabled even if the selected entry's password is blank to prevent Ctrl+C
|
||||
// from copying information from the currently selected cell in the entry view table.
|
||||
m_ui->actionEntryCopyPassword->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryCopyURL->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl());
|
||||
m_ui->actionEntryCopyNotes->setEnabled(singleEntrySelected && dbWidget->currentEntryHasNotes());
|
||||
m_ui->menuEntryCopyAttribute->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryCopyPassword->setEnabled(singleEntryOrEditing);
|
||||
m_ui->actionEntryCopyURL->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasUrl());
|
||||
m_ui->actionEntryCopyNotes->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasNotes());
|
||||
m_ui->menuEntryCopyAttribute->setEnabled(singleEntryOrEditing);
|
||||
m_ui->menuEntryTotp->setEnabled(singleEntrySelected);
|
||||
m_ui->menuTags->setEnabled(entriesSelected);
|
||||
m_ui->menuTags->setEnabled(multiEntrySelected);
|
||||
m_ui->actionEntryAutoType->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
|
||||
m_ui->actionEntryAutoType->menu()->setEnabled(singleEntrySelected
|
||||
&& dbWidget->currentEntryHasAutoTypeEnabled());
|
||||
m_ui->actionEntryAutoTypeSequence->setText(
|
||||
singleEntrySelected ? dbWidget->currentSelectedEntry()->effectiveAutoTypeSequence()
|
||||
m_ui->actionEntryAutoType->menu()->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
|
||||
m_ui->actionEntryAutoTypeSequence->setText(singleEntrySelected
|
||||
? dbWidget->currentSelectedEntry()->effectiveAutoTypeSequence()
|
||||
: Group::RootAutoTypeSequence);
|
||||
m_ui->actionEntryAutoTypeSequence->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryAutoTypeUsername->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername());
|
||||
m_ui->actionEntryAutoTypeUsernameEnter->setEnabled(singleEntrySelected
|
||||
&& dbWidget->currentEntryHasUsername());
|
||||
m_ui->actionEntryAutoTypeUsernameEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername());
|
||||
m_ui->actionEntryAutoTypePassword->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword());
|
||||
m_ui->actionEntryAutoTypePasswordEnter->setEnabled(singleEntrySelected
|
||||
&& dbWidget->currentEntryHasPassword());
|
||||
m_ui->actionEntryAutoTypePasswordEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword());
|
||||
m_ui->actionEntryAutoTypeTOTP->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntryAutoTypeTOTP->setVisible(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntryOpenUrl->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl());
|
||||
m_ui->actionEntryOpenUrl->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasUrl());
|
||||
m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntryCopyTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntryCopyPasswordTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntrySetupTotp->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryTotpQRCode->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
|
||||
m_ui->actionEntryDownloadIcon->setEnabled((entriesSelected && !singleEntrySelected)
|
||||
m_ui->actionEntryDownloadIcon->setEnabled((multiEntrySelected && !singleEntrySelected)
|
||||
|| (singleEntrySelected && dbWidget->currentEntryHasUrl()));
|
||||
m_ui->actionGroupNew->setEnabled(groupSelected);
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
m_ui->actionEntryImportPasskey->setVisible(singleEntrySelected);
|
||||
m_ui->actionEntryImportPasskey->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryRemovePasskey->setVisible(singleEntrySelected && dbWidget->currentEntryHasPasskey());
|
||||
m_ui->actionEntryRemovePasskey->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPasskey());
|
||||
#endif
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
bool hasSSHKey = singleEntrySelected && sshAgent()->isEnabled() && dbWidget->currentEntryHasSshKey();
|
||||
m_ui->actionEntryAddToAgent->setVisible(hasSSHKey);
|
||||
m_ui->actionEntryAddToAgent->setEnabled(hasSSHKey);
|
||||
m_ui->actionEntryRemoveFromAgent->setVisible(hasSSHKey);
|
||||
m_ui->actionEntryRemoveFromAgent->setEnabled(hasSSHKey);
|
||||
#endif
|
||||
|
||||
m_ui->actionGroupNew->setEnabled(groupSelected && !inRecycleBin);
|
||||
m_ui->actionGroupEdit->setEnabled(groupSelected);
|
||||
m_ui->actionGroupClone->setEnabled(groupSelected && dbWidget->canCloneCurrentGroup());
|
||||
m_ui->actionGroupDelete->setEnabled(groupSelected && dbWidget->canDeleteCurrentGroup());
|
||||
m_ui->actionGroupSortAsc->setEnabled(groupSelected && currentGroupHasChildren);
|
||||
m_ui->actionGroupSortDesc->setEnabled(groupSelected && currentGroupHasChildren);
|
||||
m_ui->actionGroupEmptyRecycleBin->setVisible(recycleBinSelected);
|
||||
m_ui->actionGroupEmptyRecycleBin->setEnabled(recycleBinSelected);
|
||||
m_ui->actionGroupSortAsc->setVisible(groupHasChildren);
|
||||
m_ui->actionGroupSortAsc->setEnabled(groupHasChildren);
|
||||
m_ui->actionGroupSortDesc->setVisible(groupHasChildren);
|
||||
m_ui->actionGroupSortDesc->setEnabled(groupHasChildren);
|
||||
m_ui->actionGroupEmptyRecycleBin->setVisible(inRecycleBin);
|
||||
m_ui->actionGroupEmptyRecycleBin->setEnabled(inRecycleBin);
|
||||
#ifdef WITH_XC_NETWORKING
|
||||
m_ui->actionGroupDownloadFavicons->setVisible(!recycleBinSelected);
|
||||
m_ui->actionGroupDownloadFavicons->setVisible(!inRecycleBin);
|
||||
#endif
|
||||
m_ui->actionGroupDownloadFavicons->setEnabled(groupSelected && currentGroupHasEntries
|
||||
&& !recycleBinSelected);
|
||||
m_ui->actionDatabaseSecurity->setEnabled(true);
|
||||
m_ui->actionReports->setEnabled(true);
|
||||
m_ui->actionDatabaseSettings->setEnabled(true);
|
||||
m_ui->actionGroupDownloadFavicons->setEnabled(groupSelected && groupHasEntries && !inRecycleBin);
|
||||
|
||||
// Database Menu
|
||||
m_ui->actionDatabaseSave->setEnabled(m_ui->tabWidget->canSave());
|
||||
m_ui->actionDatabaseSaveAs->setEnabled(true);
|
||||
m_ui->actionDatabaseSaveBackup->setEnabled(true);
|
||||
m_ui->menuExport->setEnabled(true);
|
||||
m_ui->actionExportCsv->setEnabled(true);
|
||||
m_ui->actionExportHtml->setEnabled(true);
|
||||
m_ui->actionExportXML->setEnabled(true);
|
||||
m_ui->actionDatabaseMerge->setEnabled(m_ui->tabWidget->currentIndex() != -1);
|
||||
m_ui->actionDatabaseSaveAs->setEnabled(databaseUnlocked);
|
||||
m_ui->actionDatabaseSaveBackup->setEnabled(databaseUnlocked);
|
||||
m_ui->actionDatabaseClose->setEnabled(dbWidget);
|
||||
m_ui->actionLockDatabase->setEnabled(databaseUnlocked);
|
||||
m_ui->actionLockAllDatabases->setEnabled(hasLockableDatabase);
|
||||
m_ui->actionLockDatabaseToolbar->setEnabled(hasLockableDatabase);
|
||||
m_ui->actionDatabaseSettings->setEnabled(inDatabase || inDatabaseSettings);
|
||||
m_ui->actionDatabaseSecurity->setEnabled(inDatabase || inDatabaseSettings);
|
||||
m_ui->actionReports->setEnabled(inDatabase || inReports);
|
||||
m_ui->menuRemoteSync->setEnabled(inDatabase || inDatabaseSettings);
|
||||
m_ui->menuExport->setEnabled(inDatabase);
|
||||
m_ui->actionDatabaseMerge->setEnabled(inDatabase);
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
bool singleEntryHasPasskey = singleEntrySelected && dbWidget->currentEntryHasPasskey();
|
||||
m_ui->actionPasskeys->setEnabled(true);
|
||||
m_ui->actionImportPasskey->setEnabled(true);
|
||||
m_ui->actionEntryImportPasskey->setEnabled(singleEntrySelected);
|
||||
m_ui->actionEntryRemovePasskey->setEnabled(singleEntryHasPasskey);
|
||||
#endif
|
||||
m_ui->menuRemoteSync->setEnabled(true);
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
bool singleEntryHasSshKey =
|
||||
singleEntrySelected && sshAgent()->isEnabled() && dbWidget->currentEntryHasSshKey();
|
||||
m_ui->actionEntryAddToAgent->setVisible(singleEntryHasSshKey);
|
||||
m_ui->actionEntryAddToAgent->setEnabled(singleEntryHasSshKey);
|
||||
m_ui->actionEntryRemoveFromAgent->setVisible(singleEntryHasSshKey);
|
||||
m_ui->actionEntryRemoveFromAgent->setEnabled(singleEntryHasSshKey);
|
||||
m_ui->actionPasskeys->setEnabled(inDatabase || inReports);
|
||||
m_ui->actionImportPasskey->setEnabled(inDatabase);
|
||||
#endif
|
||||
|
||||
m_searchWidgetAction->setEnabled(true);
|
||||
|
||||
break;
|
||||
}
|
||||
case DatabaseWidget::Mode::EditMode:
|
||||
case DatabaseWidget::Mode::LockedMode: {
|
||||
// Enable select actions when editing an entry
|
||||
bool editEntryActive = dbWidget->isEntryEditActive();
|
||||
const QList<QAction*> editEntryActionsMask{m_ui->actionEntryCopyUsername,
|
||||
m_ui->actionEntryCopyPassword,
|
||||
m_ui->actionEntryCopyURL,
|
||||
m_ui->actionEntryOpenUrl,
|
||||
m_ui->actionEntryAutoType,
|
||||
m_ui->actionEntryDownloadIcon,
|
||||
m_ui->actionEntryCopyNotes,
|
||||
m_ui->actionEntryCopyTitle,
|
||||
m_ui->menuEntryCopyAttribute->menuAction(),
|
||||
m_ui->menuEntryTotp->menuAction(),
|
||||
m_ui->actionEntrySetupTotp};
|
||||
|
||||
auto entryActions = m_ui->menuEntries->actions();
|
||||
entryActions << m_ui->menuEntryCopyAttribute->actions();
|
||||
entryActions << m_ui->menuEntryTotp->actions();
|
||||
for (auto action : entryActions) {
|
||||
bool enabled = editEntryActive && editEntryActionsMask.contains(action);
|
||||
if (action->menu()) {
|
||||
action->menu()->setEnabled(enabled);
|
||||
}
|
||||
action->setEnabled(enabled);
|
||||
}
|
||||
|
||||
const auto groupActions = m_ui->menuGroups->actions();
|
||||
for (auto action : groupActions) {
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
m_ui->actionDatabaseSecurity->setEnabled(false);
|
||||
m_ui->actionReports->setEnabled(false);
|
||||
m_ui->actionDatabaseSettings->setEnabled(false);
|
||||
m_ui->actionDatabaseSave->setEnabled(false);
|
||||
m_ui->actionDatabaseSaveAs->setEnabled(false);
|
||||
m_ui->actionDatabaseSaveBackup->setEnabled(false);
|
||||
m_ui->menuExport->setEnabled(false);
|
||||
m_ui->actionExportCsv->setEnabled(false);
|
||||
m_ui->actionExportHtml->setEnabled(false);
|
||||
m_ui->actionDatabaseMerge->setEnabled(false);
|
||||
m_ui->menuRemoteSync->setEnabled(false);
|
||||
// Only disable the action in the database menu so that the
|
||||
// menu remains active in the toolbar, if necessary
|
||||
m_ui->actionLockDatabase->setEnabled(false);
|
||||
// Never show in these modes
|
||||
m_ui->actionEntryMoveUp->setVisible(false);
|
||||
m_ui->actionEntryMoveDown->setVisible(false);
|
||||
m_ui->actionEntryRestore->setVisible(false);
|
||||
m_ui->actionEntryAddToAgent->setVisible(false);
|
||||
m_ui->actionEntryRemoveFromAgent->setVisible(false);
|
||||
m_ui->actionGroupEmptyRecycleBin->setVisible(false);
|
||||
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
m_ui->actionPasskeys->setEnabled(false);
|
||||
m_ui->actionImportPasskey->setEnabled(false);
|
||||
m_ui->actionEntryImportPasskey->setEnabled(false);
|
||||
m_ui->actionEntryRemovePasskey->setEnabled(false);
|
||||
#else
|
||||
m_ui->actionPasskeys->setVisible(false);
|
||||
m_ui->actionImportPasskey->setVisible(false);
|
||||
m_ui->actionEntryImportPasskey->setVisible(false);
|
||||
m_ui->actionEntryRemovePasskey->setVisible(false);
|
||||
#endif
|
||||
|
||||
m_searchWidgetAction->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
} else {
|
||||
const auto entryActions = m_ui->menuEntries->actions();
|
||||
for (auto action : entryActions) {
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
const auto groupActions = m_ui->menuGroups->actions();
|
||||
for (auto action : groupActions) {
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
m_ui->actionDatabaseSecurity->setEnabled(false);
|
||||
m_ui->actionReports->setEnabled(false);
|
||||
m_ui->actionDatabaseSettings->setEnabled(false);
|
||||
m_ui->actionDatabaseSave->setEnabled(false);
|
||||
m_ui->actionDatabaseSaveAs->setEnabled(false);
|
||||
m_ui->actionDatabaseSaveBackup->setEnabled(false);
|
||||
m_ui->actionDatabaseClose->setEnabled(false);
|
||||
m_ui->menuExport->setEnabled(false);
|
||||
m_ui->actionExportCsv->setEnabled(false);
|
||||
m_ui->actionExportHtml->setEnabled(false);
|
||||
m_ui->actionDatabaseMerge->setEnabled(false);
|
||||
m_ui->menuRemoteSync->setEnabled(false);
|
||||
// Hide entry-specific actions
|
||||
m_ui->actionEntryMoveUp->setVisible(false);
|
||||
m_ui->actionEntryMoveDown->setVisible(false);
|
||||
m_ui->actionEntryRestore->setVisible(false);
|
||||
m_ui->actionEntryAddToAgent->setVisible(false);
|
||||
m_ui->actionEntryRemoveFromAgent->setVisible(false);
|
||||
m_ui->actionGroupEmptyRecycleBin->setVisible(false);
|
||||
|
||||
m_searchWidgetAction->setEnabled(false);
|
||||
}
|
||||
|
||||
if ((currentIndex == PasswordGeneratorScreen) != m_ui->actionPasswordGenerator->isChecked()) {
|
||||
bool blocked = m_ui->actionPasswordGenerator->blockSignals(true);
|
||||
m_ui->actionPasswordGenerator->toggle();
|
||||
m_ui->actionPasswordGenerator->blockSignals(blocked);
|
||||
} else if ((currentIndex == SettingsScreen) != m_ui->actionSettings->isChecked()) {
|
||||
bool blocked = m_ui->actionSettings->blockSignals(true);
|
||||
m_ui->actionSettings->toggle();
|
||||
m_ui->actionSettings->blockSignals(blocked);
|
||||
}
|
||||
m_searchWidgetAction->setEnabled(inDatabase);
|
||||
}
|
||||
|
||||
void MainWindow::updateToolbarSeparatorVisibility()
|
||||
|
@ -106,7 +106,7 @@ protected:
|
||||
bool focusNextPrevChild(bool next) override;
|
||||
|
||||
private slots:
|
||||
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::Mode::None);
|
||||
void updateMenuActionState();
|
||||
void updateToolbarSeparatorVisibility();
|
||||
void updateWindowTitle();
|
||||
void showAboutDialog();
|
||||
|
@ -256,9 +256,9 @@
|
||||
<addaction name="actionLockDatabase"/>
|
||||
<addaction name="actionLockAllDatabases"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionReports"/>
|
||||
<addaction name="actionDatabaseSettings"/>
|
||||
<addaction name="actionDatabaseSecurity"/>
|
||||
<addaction name="actionReports"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPasskeys"/>
|
||||
<addaction name="actionImportPasskey"/>
|
||||
@ -293,9 +293,6 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuEntryCopyAttribute">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
@ -307,9 +304,6 @@
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEntryTotp">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>TOTP</string>
|
||||
</property>
|
||||
@ -324,6 +318,7 @@
|
||||
<string>Tags</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionEntryNew"/>
|
||||
<addaction name="actionEntryEdit"/>
|
||||
<addaction name="actionEntryClone"/>
|
||||
@ -356,16 +351,17 @@
|
||||
<property name="title">
|
||||
<string>&Groups</string>
|
||||
</property>
|
||||
<addaction name="actionGroupEmptyRecycleBin"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGroupNew"/>
|
||||
<addaction name="actionGroupEdit"/>
|
||||
<addaction name="actionGroupClone"/>
|
||||
<addaction name="actionGroupDelete"/>
|
||||
<addaction name="actionGroupEmptyRecycleBin"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGroupDownloadFavicons"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGroupSortAsc"/>
|
||||
<addaction name="actionGroupSortDesc"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGroupDownloadFavicons"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
@ -436,6 +432,9 @@
|
||||
<addaction name="actionEntryCopyURL"/>
|
||||
<addaction name="actionEntryAutoType"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDatabaseSettings"/>
|
||||
<addaction name="actionReports"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPasswordGenerator"/>
|
||||
<addaction name="actionSettings"/>
|
||||
<addaction name="separator"/>
|
||||
@ -485,9 +484,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSave">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save Database</string>
|
||||
</property>
|
||||
@ -496,9 +492,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseClose">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close Database</string>
|
||||
</property>
|
||||
@ -526,9 +519,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryNew">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Entry…</string>
|
||||
</property>
|
||||
@ -540,9 +530,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Edit Entry…</string>
|
||||
</property>
|
||||
@ -554,9 +541,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryDelete">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Delete Entry…</string>
|
||||
</property>
|
||||
@ -568,9 +552,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupNew">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Group…</string>
|
||||
</property>
|
||||
@ -579,9 +560,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Edit Group…</string>
|
||||
</property>
|
||||
@ -590,9 +568,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupDelete">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Delete Group…</string>
|
||||
</property>
|
||||
@ -601,9 +576,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupDownloadFavicons">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Download All &Favicons…</string>
|
||||
</property>
|
||||
@ -612,9 +584,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupSortAsc">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort &A-Z</string>
|
||||
</property>
|
||||
@ -623,9 +592,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupSortDesc">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort &Z-A</string>
|
||||
</property>
|
||||
@ -634,9 +600,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSaveAs">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sa&ve Database As…</string>
|
||||
</property>
|
||||
@ -648,9 +611,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSecurity">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Database &Security…</string>
|
||||
</property>
|
||||
@ -659,8 +619,8 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReports">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Database &Reports…</string>
|
||||
@ -676,8 +636,8 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSettings">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Database Settings…</string>
|
||||
@ -693,9 +653,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPasskeys">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Passkeys…</string>
|
||||
</property>
|
||||
@ -707,9 +664,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImportPasskey">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import Passkey</string>
|
||||
</property>
|
||||
@ -721,9 +675,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryClone">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Clone Entry…</string>
|
||||
</property>
|
||||
@ -735,9 +686,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryMoveUp">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move u&p</string>
|
||||
</property>
|
||||
@ -749,9 +697,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryMoveDown">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move do&wn</string>
|
||||
</property>
|
||||
@ -763,9 +708,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryCopyUsername">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy &Username</string>
|
||||
</property>
|
||||
@ -777,9 +719,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryCopyPassword">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy &Password</string>
|
||||
</property>
|
||||
@ -819,25 +758,16 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryAutoType">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Perform &Auto-Type</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryImportPasskey">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import Passkey</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryRemovePasskey">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Passkey From Entry</string>
|
||||
</property>
|
||||
@ -921,9 +851,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryOpenUrl">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &URL</string>
|
||||
</property>
|
||||
@ -932,9 +859,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLockDatabase">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Lock Database</string>
|
||||
</property>
|
||||
@ -943,9 +867,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLockAllDatabases">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Lock &All Databases</string>
|
||||
</property>
|
||||
@ -954,9 +875,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryCopyTitle">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Title</string>
|
||||
</property>
|
||||
@ -968,9 +886,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryCopyURL">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy &URL</string>
|
||||
</property>
|
||||
@ -982,9 +897,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntryCopyNotes">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Notes</string>
|
||||
</property>
|
||||
@ -993,9 +905,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExportCsv">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&CSV File…</string>
|
||||
</property>
|
||||
@ -1004,9 +913,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExportHtml">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&HTML File…</string>
|
||||
</property>
|
||||
@ -1085,9 +991,6 @@
|
||||
<property name="toolTip">
|
||||
<string>Empty Recycle Bin</string>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDonate">
|
||||
<property name="text">
|
||||
@ -1141,9 +1044,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDatabaseSaveBackup">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Database Backup…</string>
|
||||
</property>
|
||||
@ -1333,9 +1233,6 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGroupClone">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clone Group...</string>
|
||||
</property>
|
||||
@ -1352,17 +1249,11 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLockDatabaseToolbar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Lock Database</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExportXML">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&XML File…</string>
|
||||
</property>
|
||||
|
@ -99,6 +99,8 @@ DatabaseSettingsDialog::~DatabaseSettingsDialog() = default;
|
||||
|
||||
void DatabaseSettingsDialog::load(const QSharedPointer<Database>& db)
|
||||
{
|
||||
setHeadline(tr("Database Settings: %1").arg(db->canonicalFilePath()));
|
||||
|
||||
m_generalWidget->loadSettings(db);
|
||||
m_databaseKeyWidget->loadSettings(db);
|
||||
m_encryptionWidget->loadSettings(db);
|
||||
|
@ -128,14 +128,23 @@ void ReportsDialog::addPage(QSharedPointer<IReportsPage> page)
|
||||
m_ui->categoryList->setCurrentCategory(category);
|
||||
}
|
||||
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
void ReportsDialog::activatePasskeysPage()
|
||||
{
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
m_ui->stackedWidget->setCurrentWidget(m_passkeysPage->m_passkeysWidget);
|
||||
auto index = m_ui->stackedWidget->currentIndex();
|
||||
m_ui->categoryList->setCurrentCategory(index);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ReportsDialog::onPassKeysPage()
|
||||
{
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
return m_ui->stackedWidget->currentWidget() == m_passkeysPage->m_passkeysWidget;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReportsDialog::reject()
|
||||
{
|
||||
@ -144,7 +153,7 @@ void ReportsDialog::reject()
|
||||
|
||||
void ReportsDialog::entryActivationSignalReceived(Entry* entry)
|
||||
{
|
||||
m_sender = static_cast<QWidget*>(sender());
|
||||
m_sender = qobject_cast<QWidget*>(sender());
|
||||
m_editEntryWidget->loadEntry(entry, false, false, entry->group()->hierarchy().join(" > "), m_db);
|
||||
m_ui->stackedWidget->setCurrentWidget(m_editEntryWidget);
|
||||
}
|
||||
|
@ -63,9 +63,8 @@ public:
|
||||
|
||||
void load(const QSharedPointer<Database>& db);
|
||||
void addPage(QSharedPointer<IReportsPage> page);
|
||||
#ifdef WITH_XC_BROWSER_PASSKEYS
|
||||
void activatePasskeysPage();
|
||||
#endif
|
||||
bool onPassKeysPage();
|
||||
|
||||
signals:
|
||||
void editFinished(bool accepted);
|
||||
|
@ -161,14 +161,13 @@ void TestGui::init()
|
||||
// Every test ends with closing the temp database without saving
|
||||
void TestGui::cleanup()
|
||||
{
|
||||
if (m_tabWidget->isVisible()) {
|
||||
// DO NOT save the database
|
||||
m_db->markAsClean();
|
||||
MessageBox::setNextAnswer(MessageBox::No);
|
||||
triggerAction("actionDatabaseClose");
|
||||
QApplication::processEvents();
|
||||
MessageBox::setNextAnswer(MessageBox::NoButton);
|
||||
|
||||
if (m_dbWidget) {
|
||||
delete m_dbWidget;
|
||||
}
|
||||
}
|
||||
@ -561,7 +560,7 @@ void TestGui::testEditEntry()
|
||||
|
||||
// Edit the first entry ("Sample Entry")
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
auto* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
|
||||
QTest::keyClicks(titleEdit, "_test");
|
||||
@ -576,7 +575,7 @@ void TestGui::testEditEntry()
|
||||
// Apply the edit
|
||||
QTRY_VERIFY(applyButton->isEnabled());
|
||||
QTest::mouseClick(applyButton, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QCOMPARE(entry->title(), QString("Sample Entry_test"));
|
||||
QCOMPARE(entry->historyItems().size(), ++editCount);
|
||||
QVERIFY(!applyButton->isEnabled());
|
||||
@ -654,7 +653,7 @@ void TestGui::testEditEntry()
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
okButton = editEntryWidgetButtonBox->button(QDialogButtonBox::Ok);
|
||||
QVERIFY(okButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
titleEdit->setText("multiline\ntitle");
|
||||
editEntryWidget->findChild<QComboBox*>("usernameComboBox")->lineEdit()->setText("multiline\nusername");
|
||||
editEntryWidget->findChild<PasswordWidget*>("passwordEdit")->setText("multiline\npassword");
|
||||
@ -713,7 +712,7 @@ void TestGui::testSearchEditEntry()
|
||||
|
||||
// Goto "Doggy"'s edit view
|
||||
QTest::keyClick(searchTextEdit, Qt::Key_Return);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Check the path in header is "parent-group > entry"
|
||||
QCOMPARE(m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget")->findChild<QLabel*>("headerLabel")->text(),
|
||||
@ -739,7 +738,7 @@ void TestGui::testAddEntry()
|
||||
|
||||
// Click the new entry button and check that we enter edit mode
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Add entry "test" and confirm added
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
@ -859,7 +858,7 @@ void TestGui::testPasswordEntryEntropy()
|
||||
|
||||
// Click the new entry button and check that we enter edit mode
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Add entry "test" and confirm added
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
@ -921,7 +920,7 @@ void TestGui::testDicewareEntryEntropy()
|
||||
|
||||
// Click the new entry button and check that we enter edit mode
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Add entry "test" and confirm added
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
@ -1008,7 +1007,7 @@ void TestGui::testTotp()
|
||||
QVERIFY(entryEditWidget->isVisible());
|
||||
QVERIFY(entryEditWidget->isEnabled());
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
editEntryWidget->setCurrentPage(1);
|
||||
@ -1212,7 +1211,7 @@ void TestGui::testSearch()
|
||||
QModelIndex item = entryView->model()->index(0, 1);
|
||||
Entry* entry = entryView->entryFromIndex(item);
|
||||
QTest::keyClick(searchTextEdit, Qt::Key_Return);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Perform the edit and save it
|
||||
EditEntryWidget* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
@ -1370,7 +1369,7 @@ void TestGui::testEntryPlaceholders()
|
||||
|
||||
// Click the new entry button and check that we enter edit mode
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
// Add entry "test" and confirm added
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
@ -1723,7 +1722,7 @@ void TestGui::testDatabaseSettings()
|
||||
QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction);
|
||||
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
QVERIFY(editEntryWidget);
|
||||
@ -1743,7 +1742,7 @@ void TestGui::testDatabaseSettings()
|
||||
|
||||
// 2.d) Create second entry to test delay timer reset
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QTest::keyClicks(titleEdit, "Test autosaveDelay 2");
|
||||
|
||||
// 2.e) Save changes
|
||||
@ -1763,7 +1762,7 @@ void TestGui::testDatabaseSettings()
|
||||
// 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);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QTest::keyClicks(titleEdit, "Test autosaveDelay 3");
|
||||
|
||||
// 4.b) Save changes
|
||||
@ -1784,7 +1783,7 @@ void TestGui::testDatabaseSettings()
|
||||
// 4.f) Repeat for autosaveDelay
|
||||
config()->set(Config::AutoSaveAfterEveryChange, true);
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QTest::keyClicks(titleEdit, "Test autosaveDelay 4");
|
||||
editEntryWidget->setCurrentPage(0);
|
||||
editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
|
||||
@ -2061,7 +2060,7 @@ void TestGui::testAutoType()
|
||||
QVERIFY(entryNewWidget->isEnabled());
|
||||
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
QVERIFY(editEntryWidget);
|
||||
@ -2096,7 +2095,7 @@ void TestGui::testAutoType()
|
||||
|
||||
// 2.a) Click the new entry button and set the title
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QTest::keyClicks(titleEdit, "2. Entry With Default Auto-Type Sequence");
|
||||
QTest::mouseClick(usernameComboBox, Qt::LeftButton);
|
||||
QTest::keyClicks(usernameComboBox, "AutocompletionUsername");
|
||||
@ -2115,7 +2114,7 @@ void TestGui::testAutoType()
|
||||
|
||||
// 3.a) Click the new entry button and set the title
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
QTest::keyClicks(titleEdit, "3. Entry With Custom Auto-Type Sequence");
|
||||
QTest::mouseClick(usernameComboBox, Qt::LeftButton);
|
||||
QTest::keyClicks(usernameComboBox, "AutocompletionUsername");
|
||||
@ -2192,6 +2191,155 @@ void TestGui::testAutoType()
|
||||
entryView->selectionModel()->clearSelection();
|
||||
}
|
||||
|
||||
void TestGui::testMenuActionStates()
|
||||
{
|
||||
auto isActionEnabled = [this](const QString& actionName) -> bool {
|
||||
auto action = m_mainWindow->findChild<QAction*>(actionName);
|
||||
if (!action) {
|
||||
QTest::qFail(qPrintable(QString("Invalid action specified: %1").arg(actionName)), __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
return action->isEnabled();
|
||||
};
|
||||
|
||||
// Start with database open and unlocked
|
||||
qInfo("Actions Test: Database open and unlocked");
|
||||
|
||||
QVERIFY(isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(isActionEnabled("actionReports"));
|
||||
QVERIFY(isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(isActionEnabled("actionLockAllDatabases"));
|
||||
QVERIFY(isActionEnabled("actionImport"));
|
||||
QVERIFY(isActionEnabled("actionExportCsv"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Edit entry actions
|
||||
qInfo("Actions Test: Editing an entry");
|
||||
|
||||
triggerAction("actionEntryEdit");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(isActionEnabled("actionEntryCopyUsername"));
|
||||
QVERIFY(!isActionEnabled("actionEntrySetupTotp"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(!isActionEnabled("actionReports"));
|
||||
QVERIFY(isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(isActionEnabled("actionLockAllDatabases"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Special Case - Recycle Bin
|
||||
qInfo("Actions Test: Special case - Recycle Bin");
|
||||
|
||||
m_dbWidget->switchToMainView();
|
||||
QApplication::processEvents();
|
||||
|
||||
QVERIFY(m_db->metadata()->recycleBinEnabled());
|
||||
triggerAction("actionEntryDelete");
|
||||
m_dbWidget->groupView()->setCurrentGroup(m_db->metadata()->recycleBin());
|
||||
QVERIFY(m_dbWidget->isRecycleBinSelected());
|
||||
QVERIFY(isActionEnabled("actionEntryRestore"));
|
||||
QVERIFY(isActionEnabled("actionGroupEmptyRecycleBin"));
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(!isActionEnabled("actionEntryClone"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(!isActionEnabled("actionGroupClone"));
|
||||
|
||||
// Database Settings
|
||||
qInfo("Actions Test: Database settings");
|
||||
triggerAction("actionDatabaseSettings");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(!isActionEnabled("actionEntrySetupTotp"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSecurity"));
|
||||
QVERIFY(!isActionEnabled("actionReports"));
|
||||
QVERIFY(isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Database Reports
|
||||
qInfo("Actions Test: Database reports");
|
||||
|
||||
triggerAction("actionDatabaseSettings");
|
||||
triggerAction("actionReports");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(!isActionEnabled("actionEntrySetupTotp"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSecurity"));
|
||||
QVERIFY(isActionEnabled("actionReports"));
|
||||
QVERIFY(isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Application Settings
|
||||
qInfo("Actions Test: Application settings");
|
||||
|
||||
triggerAction("actionSettings");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSecurity"));
|
||||
QVERIFY(!isActionEnabled("actionReports"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Locked Database
|
||||
qInfo("Actions Test: Database locked");
|
||||
|
||||
triggerAction("actionSettings");
|
||||
MessageBox::setNextAnswer(MessageBox::Discard);
|
||||
triggerAction("actionLockDatabase");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(!isActionEnabled("actionReports"));
|
||||
QVERIFY(!isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(!isActionEnabled("actionLockAllDatabases"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
|
||||
// Welcome Screen
|
||||
qInfo("Actions Test: Welcome screen");
|
||||
|
||||
triggerAction("actionDatabaseClose");
|
||||
|
||||
QVERIFY(!isActionEnabled("actionEntryNew"));
|
||||
QVERIFY(!isActionEnabled("actionGroupNew"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSaveAs"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseClose"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseMerge"));
|
||||
QVERIFY(!isActionEnabled("actionDatabaseSettings"));
|
||||
QVERIFY(!isActionEnabled("actionReports"));
|
||||
QVERIFY(!isActionEnabled("actionLockDatabase"));
|
||||
QVERIFY(!isActionEnabled("actionLockAllDatabases"));
|
||||
QVERIFY(isActionEnabled("actionImport"));
|
||||
QVERIFY(isActionEnabled("actionSettings"));
|
||||
QVERIFY(isActionEnabled("actionPasswordGenerator"));
|
||||
}
|
||||
|
||||
void TestGui::addCannedEntries()
|
||||
{
|
||||
// Find buttons
|
||||
@ -2266,8 +2414,8 @@ void TestGui::checkStatusBarText(const QString& textFragment)
|
||||
void TestGui::triggerAction(const QString& name)
|
||||
{
|
||||
auto* action = m_mainWindow->findChild<QAction*>(name);
|
||||
QVERIFY(action);
|
||||
QVERIFY(action->isEnabled());
|
||||
QVERIFY2(action, qPrintable(QString("Action doesn't exist: %1").arg(name)));
|
||||
QVERIFY2(action->isEnabled(), qPrintable(QString("Action is disabled: %1").arg(name)));
|
||||
action->trigger();
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ private slots:
|
||||
void testAutoType();
|
||||
void testTrayRestoreHide();
|
||||
void testShortcutConfig();
|
||||
void testMenuActionStates();
|
||||
|
||||
private:
|
||||
void addCannedEntries();
|
||||
|
@ -142,7 +142,7 @@ void TestGuiBrowser::testEntrySettings()
|
||||
auto* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit");
|
||||
QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction);
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
|
||||
// Switch to Properties page and select all rows from the custom data table
|
||||
@ -186,7 +186,7 @@ void TestGuiBrowser::testAdditionalURLs()
|
||||
auto* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit");
|
||||
QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction);
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditEntryMode);
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
|
||||
// Switch to Browser Integration page and add three URL's
|
||||
|
Loading…
Reference in New Issue
Block a user