Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKyle Kneitinger <kyle@kneit.in>2018-12-20 07:14:11 +0300
committerJonathan White <support@dmapps.us>2018-12-20 07:14:11 +0300
commit4d4c839afae2beb9da24ee5a5c6a3756a0d6b2c8 (patch)
tree2a51e60150691f2765b299cc2d2a798a8322396c /src
parent8ac9d0a131257b82728488592e1111c4546e051a (diff)
Customize buttons on MessageBox and confirm before recycling (#2376)
* Add confirmation prompt before moving groups to the recycling bin Spawn a yes/no QMessage box when "Delete Group" is selected on a group that is not already in the recycle bin (note: the prompt for deletion from the recycle bin was already implemented). This follows the same pattern and language as entry deletion. Fixes #2125 * Make prompts for destructive operations use action words on buttons Replace yes/no, yes/cancel (and other such buttons on prompts that cause data to be destroyed) use language that indicates the action that it is going to take. This makes destructive/unsafe and/or irreversible operations more clear to the user. Address feedback on PR #2376 * Refactor MessageBox class to allow for custom buttons Replaces arguments and return values of type QMessageBox::StandardButton(s) with MessageBox::Button(s), which reimplements the entire set of QMessageBox::StandardButton and allows for custom KeePassXC buttons, such as "Skip". Modifies all calls to MessageBox functions to use MessageBox::Button(s). Addresses feedback on #2376 * Remove MessageBox::addButton in favor of map lookup Replaced the switch statement mechanism in MessageBox::addButton with a map lookup to address CodeFactor Complex Method issue. This has a side-effect of a small performance/cleanliness increase, as an extra QPushButton is no longer created/destroyed (to obtain it's label text) everytime a MessageBox button based on QMessageBox::StandardButton is created; now the text is obtained once, at application start up.
Diffstat (limited to 'src')
-rw-r--r--src/browser/BrowserService.cpp85
-rw-r--r--src/core/Bootstrap.cpp3
-rw-r--r--src/gui/DatabaseTabWidget.cpp4
-rw-r--r--src/gui/DatabaseWidget.cpp84
-rw-r--r--src/gui/EditWidgetIcons.cpp22
-rw-r--r--src/gui/EditWidgetProperties.cpp15
-rw-r--r--src/gui/MessageBox.cpp165
-rw-r--r--src/gui/MessageBox.h103
-rw-r--r--src/gui/csvImport/CsvImportWidget.cpp4
-rw-r--r--src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp40
-rw-r--r--src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp14
-rw-r--r--src/gui/entry/EditEntryWidget.cpp27
-rw-r--r--src/gui/entry/EntryAttachmentsWidget.cpp32
13 files changed, 383 insertions, 215 deletions
diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp
index 6b85c7864..bf42eab31 100644
--- a/src/browser/BrowserService.cpp
+++ b/src/browser/BrowserService.cpp
@@ -34,6 +34,7 @@
#include "core/Metadata.h"
#include "core/PasswordGenerator.h"
#include "gui/MainWindow.h"
+#include "gui/MessageBox.h"
const char BrowserService::KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
const char BrowserService::KEEPASSXCBROWSER_OLD_NAME[] = "keepassxc-browser Settings";
@@ -157,7 +158,7 @@ QString BrowserService::storeKey(const QString& key)
}
bool contains;
- QMessageBox::StandardButton dialogResult = QMessageBox::No;
+ MessageBox::Button dialogResult = MessageBox::Cancel;
do {
QInputDialog keyDialog;
@@ -180,14 +181,15 @@ QString BrowserService::storeKey(const QString& key)
contains = db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
if (contains) {
- dialogResult = QMessageBox::warning(nullptr,
- tr("KeePassXC: Overwrite existing key?"),
- tr("A shared encryption key with the name \"%1\" "
- "already exists.\nDo you want to overwrite it?")
- .arg(id),
- QMessageBox::Yes | QMessageBox::No);
+ dialogResult = MessageBox::warning(nullptr,
+ tr("KeePassXC: Overwrite existing key?"),
+ tr("A shared encryption key with the name \"%1\" "
+ "already exists.\nDo you want to overwrite it?")
+ .arg(id),
+ MessageBox::Overwrite | MessageBox::Cancel,
+ MessageBox::Cancel);
}
- } while (contains && dialogResult == QMessageBox::No);
+ } while (contains && dialogResult == MessageBox::Cancel);
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key);
return id;
@@ -367,21 +369,17 @@ void BrowserService::updateEntry(const QString& id,
if (username.compare(login, Qt::CaseSensitive) != 0
|| entry->password().compare(password, Qt::CaseSensitive) != 0) {
- int dialogResult = QMessageBox::No;
+ MessageBox::Button dialogResult = MessageBox::No;
if (!browserSettings()->alwaysAllowUpdate()) {
- QMessageBox msgBox;
- msgBox.setWindowTitle(tr("KeePassXC: Update Entry"));
- msgBox.setText(tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host(), username));
- msgBox.setStandardButtons(QMessageBox::Yes);
- msgBox.addButton(QMessageBox::No);
- msgBox.setDefaultButton(QMessageBox::No);
- msgBox.setWindowFlags(Qt::WindowStaysOnTopHint);
- msgBox.activateWindow();
- msgBox.raise();
- dialogResult = msgBox.exec();
+ dialogResult = MessageBox::question(nullptr,
+ tr("KeePassXC: Update Entry"),
+ tr("Do you want to update the information in %1 - %2?")
+ .arg(QUrl(url).host(), username),
+ MessageBox::Save | MessageBox::Cancel,
+ MessageBox::Cancel);
}
- if (browserSettings()->alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) {
+ if (browserSettings()->alwaysAllowUpdate() || dialogResult == MessageBox::Save) {
entry->beginUpdate();
entry->setUsername(login);
entry->setPassword(password);
@@ -497,24 +495,24 @@ void BrowserService::convertAttributesToCustomData(QSharedPointer<Database> curr
progress.reset();
if (counter > 0) {
- QMessageBox::information(nullptr,
- tr("KeePassXC: Converted KeePassHTTP attributes"),
- tr("Successfully converted attributes from %1 entry(s).\n"
- "Moved %2 keys to custom data.",
- "")
- .arg(counter)
- .arg(keyCounter),
- QMessageBox::Ok);
+ MessageBox::information(nullptr,
+ tr("KeePassXC: Converted KeePassHTTP attributes"),
+ tr("Successfully converted attributes from %1 entry(s).\n"
+ "Moved %2 keys to custom data.",
+ "")
+ .arg(counter)
+ .arg(keyCounter),
+ MessageBox::Ok);
} else if (counter == 0 && keyCounter > 0) {
- QMessageBox::information(nullptr,
- tr("KeePassXC: Converted KeePassHTTP attributes"),
- tr("Successfully moved %n keys to custom data.", "", keyCounter),
- QMessageBox::Ok);
+ MessageBox::information(nullptr,
+ tr("KeePassXC: Converted KeePassHTTP attributes"),
+ tr("Successfully moved %n keys to custom data.", "", keyCounter),
+ MessageBox::Ok);
} else {
- QMessageBox::information(nullptr,
- tr("KeePassXC: No entry with KeePassHTTP attributes found!"),
- tr("The active database does not contain an entry with KeePassHTTP attributes."),
- QMessageBox::Ok);
+ MessageBox::information(nullptr,
+ tr("KeePassXC: No entry with KeePassHTTP attributes found!"),
+ tr("The active database does not contain an entry with KeePassHTTP attributes."),
+ MessageBox::Ok);
}
// Rename password groupName
@@ -901,13 +899,14 @@ bool BrowserService::checkLegacySettings()
return false;
}
- auto dialogResult = QMessageBox::warning(nullptr,
- tr("KeePassXC: Legacy browser integration settings detected"),
- tr("Legacy browser integration settings have been detected.\n"
- "Do you want to upgrade the settings to the latest standard?\n"
- "This is necessary to maintain compatibility with the browser plugin."),
- QMessageBox::Yes | QMessageBox::No);
- return dialogResult == QMessageBox::Yes;
+ auto dialogResult = MessageBox::warning(nullptr,
+ tr("KeePassXC: Legacy browser integration settings detected"),
+ tr("Legacy browser integration settings have been detected.\n"
+ "Do you want to upgrade the settings to the latest standard?\n"
+ "This is necessary to maintain compatibility with the browser plugin."),
+ MessageBox::Yes | MessageBox::No);
+
+ return dialogResult == MessageBox::Yes;
}
void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
diff --git a/src/core/Bootstrap.cpp b/src/core/Bootstrap.cpp
index a62cc5a9b..2d8213b27 100644
--- a/src/core/Bootstrap.cpp
+++ b/src/core/Bootstrap.cpp
@@ -18,10 +18,12 @@
#include "Bootstrap.h"
#include "core/Config.h"
#include "core/Translator.h"
+#include "gui/MessageBox.h"
#ifdef Q_OS_WIN
#include <aclapi.h> // for createWindowsDACL()
#include <windows.h> // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ...
+#undef MessageBox
#endif
namespace Bootstrap
@@ -56,6 +58,7 @@ namespace Bootstrap
setupSearchPaths();
applyEarlyQNetworkAccessManagerWorkaround();
Translator::installTranslators();
+ MessageBox::initializeButtonDefs();
#ifdef Q_OS_MACOS
// Don't show menu icons on OSX
diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp
index b45c5a8a5..21c90cfa0 100644
--- a/src/gui/DatabaseTabWidget.cpp
+++ b/src/gui/DatabaseTabWidget.cpp
@@ -98,8 +98,8 @@ QSharedPointer<Database> DatabaseTabWidget::execNewDatabaseWizard()
tr("Database creation error"),
tr("The created database has no key or KDF, refusing to save it.\n"
"This is definitely a bug, please report it to the developers."),
- QMessageBox::Ok,
- QMessageBox::Ok);
+ MessageBox::Ok,
+ MessageBox::Ok);
return {};
}
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 234f7e042..fb2d1a9a8 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -445,6 +445,7 @@ void DatabaseWidget::deleteEntries()
bool inRecycleBin = recycleBin && recycleBin->findEntryByUuid(selectedEntries.first()->uuid());
if (inRecycleBin || !m_db->metadata()->recycleBinEnabled()) {
QString prompt;
+ refreshSearch();
if (selected.size() == 1) {
prompt = tr("Do you really want to delete the entry \"%1\" for good?")
.arg(selectedEntries.first()->title().toHtmlEscaped());
@@ -452,12 +453,16 @@ void DatabaseWidget::deleteEntries()
prompt = tr("Do you really want to delete %n entry(s) for good?", "", selected.size());
}
- QMessageBox::StandardButton result = MessageBox::question(
- this, tr("Delete entry(s)?", "", selected.size()), prompt, QMessageBox::Yes | QMessageBox::No);
+ auto answer = MessageBox::question(this,
+ tr("Delete entry(s)?", "", selected.size()),
+ prompt,
+ MessageBox::Delete | MessageBox::Cancel,
+ MessageBox::Cancel);
- if (result == QMessageBox::Yes) {
+ if (answer == MessageBox::Delete) {
for (Entry* entry : asConst(selectedEntries)) {
delete entry;
+ refreshSearch();
}
refreshSearch();
}
@@ -470,10 +475,13 @@ void DatabaseWidget::deleteEntries()
prompt = tr("Do you really want to move %n entry(s) to the recycle bin?", "", selected.size());
}
- QMessageBox::StandardButton result = MessageBox::question(
- this, tr("Move entry(s) to recycle bin?", "", selected.size()), prompt, QMessageBox::Yes | QMessageBox::No);
+ auto answer = MessageBox::question(this,
+ tr("Move entry(s) to recycle bin?", "", selected.size()),
+ prompt,
+ MessageBox::Move | MessageBox::Cancel,
+ MessageBox::Cancel);
- if (result == QMessageBox::No) {
+ if (answer == MessageBox::Cancel) {
return;
}
@@ -650,16 +658,27 @@ void DatabaseWidget::deleteGroup()
bool isRecycleBin = recycleBin && (currentGroup == recycleBin);
bool isRecycleBinSubgroup = recycleBin && currentGroup->findGroupByUuid(recycleBin->uuid());
if (inRecycleBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) {
- QMessageBox::StandardButton result = MessageBox::question(
- this,
- tr("Delete group?"),
- tr("Do you really want to delete the group \"%1\" for good?").arg(currentGroup->name().toHtmlEscaped()),
- QMessageBox::Yes | QMessageBox::No);
- if (result == QMessageBox::Yes) {
+ auto result = MessageBox::question(this,
+ tr("Delete group"),
+ tr("Do you really want to delete the group \"%1\" for good?")
+ .arg(currentGroup->name().toHtmlEscaped()),
+ MessageBox::Delete | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Delete) {
delete currentGroup;
}
} else {
- m_db->recycleGroup(currentGroup);
+ auto result = MessageBox::question(this,
+ tr("Move group to recycle bin?"),
+ tr("Do you really want to move the group "
+ "\"%1\" to the recycle bin?")
+ .arg(currentGroup->name().toHtmlEscaped()),
+ MessageBox::Move | MessageBox::Cancel,
+ MessageBox::Cancel);
+ if (result == MessageBox::Move) {
+ m_db->recycleGroup(currentGroup);
+ }
}
}
@@ -1127,8 +1146,8 @@ bool DatabaseWidget::lock()
if (currentMode() == DatabaseWidget::Mode::EditMode) {
auto result = MessageBox::question(this, tr("Lock Database?"),
tr("You are editing an entry. Discard changes and lock anyway?"),
- QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
- if (result == QMessageBox::Cancel) {
+ MessageBox::Discard | MessageBox::Cancel, MessageBox::Cancel);
+ if (result == MessageBox::Cancel) {
return false;
}
}
@@ -1146,10 +1165,10 @@ bool DatabaseWidget::lock()
msg = tr("Database was modified.\nSave changes?");
}
auto result = MessageBox::question(this, tr("Save changes?"), msg,
- QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Yes);
- if (result == QMessageBox::Yes && !m_db->save(nullptr, false, false)) {
+ MessageBox::Save | MessageBox::Discard | MessageBox::Cancel, MessageBox::Save);
+ if (result == MessageBox::Save && !m_db->save(nullptr, false, false)) {
return false;
- } else if (result == QMessageBox::Cancel) {
+ } else if (result == MessageBox::Cancel) {
return false;
}
}
@@ -1240,9 +1259,9 @@ void DatabaseWidget::reloadDatabaseFile()
auto result = MessageBox::question(this,
tr("File has changed"),
tr("The database file has changed. Do you want to load the changes?"),
- QMessageBox::Yes | QMessageBox::No);
+ MessageBox::Yes | MessageBox::No);
- if (result == QMessageBox::No) {
+ if (result == MessageBox::No) {
// Notify everyone the database does not match the file
m_db->markAsModified();
// Rewatch the database file
@@ -1259,9 +1278,10 @@ void DatabaseWidget::reloadDatabaseFile()
auto result = MessageBox::question(this,
tr("Merge Request"),
tr("The database file has changed and you have unsaved changes.\nDo you want to merge your changes?"),
- QMessageBox::Yes | QMessageBox::No);
+ MessageBox::Merge | MessageBox::Cancel,
+ MessageBox::Merge);
- if (result == QMessageBox::Yes) {
+ if (result == MessageBox::Merge) {
// Merge the old database into the new one
Merger merger(m_db.data(), db.data());
merger.merge();
@@ -1447,14 +1467,14 @@ bool DatabaseWidget::save(int attempt)
if (attempt > 2 && useAtomicSaves) {
// Saving failed 3 times, issue a warning and attempt to resolve
- auto choice = MessageBox::question(this,
+ auto result = MessageBox::question(this,
tr("Disable safe saves?"),
tr("KeePassXC has failed to save the database multiple times. "
"This is likely caused by file sync services holding a lock on "
"the save file.\nDisable safe saves and try again?"),
- QMessageBox::Yes | QMessageBox::No,
- QMessageBox::Yes);
- if (choice == QMessageBox::Yes) {
+ MessageBox::Disable | MessageBox::Cancel,
+ MessageBox::Disable);
+ if (result == MessageBox::Disable) {
config()->set("UseAtomicSaves", false);
return save(attempt + 1);
}
@@ -1529,13 +1549,13 @@ void DatabaseWidget::emptyRecycleBin()
return;
}
- QMessageBox::StandardButton result =
- MessageBox::question(this,
- tr("Empty recycle bin?"),
- tr("Are you sure you want to permanently delete everything from your recycle bin?"),
- QMessageBox::Yes | QMessageBox::No);
+ auto result = MessageBox::question(this,
+ tr("Empty recycle bin?"),
+ tr("Are you sure you want to permanently delete everything from your recycle bin?"),
+ MessageBox::Empty | MessageBox::Cancel,
+ MessageBox::Cancel);
- if (result == QMessageBox::Yes) {
+ if (result == MessageBox::Empty) {
m_db->emptyRecycleBin();
refreshSearch();
}
diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp
index abb65c00d..6ac298255 100644
--- a/src/gui/EditWidgetIcons.cpp
+++ b/src/gui/EditWidgetIcons.cpp
@@ -416,16 +416,18 @@ void EditWidgetIcons::removeCustomIcon()
int iconUseCount = entriesWithSameIcon.size() + groupsWithSameIcon.size();
if (iconUseCount > 0) {
- QMessageBox::StandardButton ans =
- MessageBox::question(this,
- tr("Confirm Delete"),
- tr("This icon is used by %n entry(s), and will be replaced "
- "by the default icon. Are you sure you want to delete it?",
- "",
- iconUseCount),
- QMessageBox::Yes | QMessageBox::No);
-
- if (ans == QMessageBox::No) {
+
+
+ auto result = MessageBox::question(this,
+ tr("Confirm Delete"),
+ tr("This icon is used by %n entry(s), and will be replaced "
+ "by the default icon. Are you sure you want to delete it?",
+ "",
+ iconUseCount),
+ MessageBox::Delete | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Cancel) {
// Early out, nothing is changed
return;
} else {
diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp
index bc0f6e164..d89bf62b9 100644
--- a/src/gui/EditWidgetProperties.cpp
+++ b/src/gui/EditWidgetProperties.cpp
@@ -68,13 +68,14 @@ const CustomData* EditWidgetProperties::customData() const
void EditWidgetProperties::removeSelectedPluginData()
{
- if (QMessageBox::Yes
- != MessageBox::question(this,
- tr("Delete plugin data?"),
- tr("Do you really want to delete the selected plugin data?\n"
- "This may cause the affected plugins to malfunction."),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel)) {
+ auto result = MessageBox::question(this,
+ tr("Delete plugin data?"),
+ tr("Do you really want to delete the selected plugin data?\n"
+ "This may cause the affected plugins to malfunction."),
+ MessageBox::Delete | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Cancel) {
return;
}
diff --git a/src/gui/MessageBox.cpp b/src/gui/MessageBox.cpp
index 7aba6a2a6..1460a6c78 100644
--- a/src/gui/MessageBox.cpp
+++ b/src/gui/MessageBox.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
+ * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,69 +18,139 @@
#include "MessageBox.h"
-QMessageBox::StandardButton MessageBox::m_nextAnswer(QMessageBox::NoButton);
+MessageBox::Button MessageBox::m_nextAnswer(MessageBox::NoButton);
-QMessageBox::StandardButton MessageBox::critical(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons,
- QMessageBox::StandardButton defaultButton)
+QMap<QAbstractButton*, MessageBox::Button>
+MessageBox::m_addedButtonLookup =
+ QMap<QAbstractButton*, MessageBox::Button>();
+
+QMap<MessageBox::Button, std::pair<QString, QMessageBox::ButtonRole>>
+MessageBox::m_buttonDefs =
+ QMap<MessageBox::Button, std::pair<QString, QMessageBox::ButtonRole>>();
+
+void MessageBox::initializeButtonDefs()
{
- if (m_nextAnswer == QMessageBox::NoButton) {
- return QMessageBox::critical(parent, title, text, buttons, defaultButton);
- } else {
- QMessageBox::StandardButton returnButton = m_nextAnswer;
- m_nextAnswer = QMessageBox::NoButton;
- return returnButton;
- }
+ m_buttonDefs =
+ QMap<Button, std::pair<QString, QMessageBox::ButtonRole>>
+ {
+ // Reimplementation of Qt StandardButtons
+ {Ok, {stdButtonText(QMessageBox::Ok), QMessageBox::ButtonRole::AcceptRole}},
+ {Open, {stdButtonText(QMessageBox::Open), QMessageBox::ButtonRole::AcceptRole}},
+ {Save, {stdButtonText(QMessageBox::Save), QMessageBox::ButtonRole::AcceptRole}},
+ {Cancel, {stdButtonText(QMessageBox::Cancel), QMessageBox::ButtonRole::RejectRole}},
+ {Close, {stdButtonText(QMessageBox::Close), QMessageBox::ButtonRole::RejectRole}},
+ {Discard, {stdButtonText(QMessageBox::Discard), QMessageBox::ButtonRole::DestructiveRole}},
+ {Apply, {stdButtonText(QMessageBox::Apply), QMessageBox::ButtonRole::ApplyRole}},
+ {Reset, {stdButtonText(QMessageBox::Reset), QMessageBox::ButtonRole::ResetRole}},
+ {RestoreDefaults, {stdButtonText(QMessageBox::RestoreDefaults), QMessageBox::ButtonRole::ResetRole}},
+ {Help, {stdButtonText(QMessageBox::Help), QMessageBox::ButtonRole::HelpRole}},
+ {SaveAll, {stdButtonText(QMessageBox::SaveAll), QMessageBox::ButtonRole::AcceptRole}},
+ {Yes, {stdButtonText(QMessageBox::Yes), QMessageBox::ButtonRole::YesRole}},
+ {YesToAll, {stdButtonText(QMessageBox::YesToAll), QMessageBox::ButtonRole::YesRole}},
+ {No, {stdButtonText(QMessageBox::No), QMessageBox::ButtonRole::NoRole}},
+ {NoToAll, {stdButtonText(QMessageBox::NoToAll), QMessageBox::ButtonRole::NoRole}},
+ {Abort, {stdButtonText(QMessageBox::Abort), QMessageBox::ButtonRole::RejectRole}},
+ {Retry, {stdButtonText(QMessageBox::Retry), QMessageBox::ButtonRole::AcceptRole}},
+ {Ignore, {stdButtonText(QMessageBox::Ignore), QMessageBox::ButtonRole::AcceptRole}},
+
+ // KeePassXC Buttons
+ {Overwrite, {QMessageBox::tr("Overwrite"), QMessageBox::ButtonRole::AcceptRole}},
+ {Delete, {QMessageBox::tr("Delete"), QMessageBox::ButtonRole::AcceptRole}},
+ {Move, {QMessageBox::tr("Move"), QMessageBox::ButtonRole::AcceptRole}},
+ {Empty, {QMessageBox::tr("Empty"), QMessageBox::ButtonRole::AcceptRole}},
+ {Remove, {QMessageBox::tr("Remove"), QMessageBox::ButtonRole::AcceptRole}},
+ {Skip, {QMessageBox::tr("Skip"), QMessageBox::ButtonRole::AcceptRole}},
+ {Disable, {QMessageBox::tr("Disable"), QMessageBox::ButtonRole::AcceptRole}},
+ {Merge, {QMessageBox::tr("Merge"), QMessageBox::ButtonRole::AcceptRole}},
+ };
}
-QMessageBox::StandardButton MessageBox::information(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons,
- QMessageBox::StandardButton defaultButton)
+QString MessageBox::stdButtonText(QMessageBox::StandardButton button)
{
- if (m_nextAnswer == QMessageBox::NoButton) {
- return QMessageBox::information(parent, title, text, buttons, defaultButton);
- } else {
- QMessageBox::StandardButton returnButton = m_nextAnswer;
- m_nextAnswer = QMessageBox::NoButton;
- return returnButton;
- }
+ QMessageBox buttonHost;
+ return buttonHost.addButton(button)->text();
}
-QMessageBox::StandardButton MessageBox::question(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons,
- QMessageBox::StandardButton defaultButton)
+MessageBox::Button MessageBox::messageBox(QWidget* parent,
+ QMessageBox::Icon icon,
+ const QString& title,
+ const QString& text,
+ MessageBox::Buttons buttons,
+ MessageBox::Button defaultButton)
{
- if (m_nextAnswer == QMessageBox::NoButton) {
- return QMessageBox::question(parent, title, text, buttons, defaultButton);
+ if (m_nextAnswer == MessageBox::NoButton) {
+ QMessageBox msgBox(parent);
+ msgBox.setIcon(icon);
+ msgBox.setWindowTitle(title);
+ msgBox.setText(text);
+
+ for (uint64_t b = First; b <= Last; b <<= 1) {
+ if (b & buttons) {
+ QString text = m_buttonDefs[static_cast<Button>(b)].first;
+ QMessageBox::ButtonRole role = m_buttonDefs[static_cast<Button>(b)].second;
+
+ auto buttonPtr = msgBox.addButton(text, role);
+ m_addedButtonLookup.insert(buttonPtr, static_cast<Button>(b));
+ }
+ }
+
+ if (defaultButton != MessageBox::NoButton) {
+ QList<QAbstractButton*> defPtrList = m_addedButtonLookup.keys(defaultButton);
+ if (defPtrList.count() > 0) {
+ msgBox.setDefaultButton(static_cast<QPushButton*>(defPtrList[0]));
+ }
+ }
+
+ msgBox.exec();
+
+ Button returnButton = m_addedButtonLookup[msgBox.clickedButton()];
+ m_addedButtonLookup.clear();
+ return returnButton;
+
} else {
- QMessageBox::StandardButton returnButton = m_nextAnswer;
- m_nextAnswer = QMessageBox::NoButton;
+ MessageBox::Button returnButton = m_nextAnswer;
+ m_nextAnswer = MessageBox::NoButton;
return returnButton;
}
}
-QMessageBox::StandardButton MessageBox::warning(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons,
- QMessageBox::StandardButton defaultButton)
+MessageBox::Button MessageBox::critical(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ MessageBox::Buttons buttons,
+ MessageBox::Button defaultButton)
{
- if (m_nextAnswer == QMessageBox::NoButton) {
- return QMessageBox::warning(parent, title, text, buttons, defaultButton);
- } else {
- QMessageBox::StandardButton returnButton = m_nextAnswer;
- m_nextAnswer = QMessageBox::NoButton;
- return returnButton;
- }
+ return messageBox(parent, QMessageBox::Critical, title, text, buttons, defaultButton);
+}
+
+MessageBox::Button MessageBox::information(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ MessageBox::Buttons buttons,
+ MessageBox::Button defaultButton)
+{
+ return messageBox(parent, QMessageBox::Information, title, text, buttons, defaultButton);
+}
+
+MessageBox::Button MessageBox::question(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ MessageBox::Buttons buttons,
+ MessageBox::Button defaultButton)
+{
+ return messageBox(parent, QMessageBox::Question, title, text, buttons, defaultButton);
+}
+
+MessageBox::Button MessageBox::warning(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ MessageBox::Buttons buttons,
+ MessageBox::Button defaultButton)
+{
+ return messageBox(parent, QMessageBox::Warning, title, text, buttons, defaultButton);
}
-void MessageBox::setNextAnswer(QMessageBox::StandardButton button)
+void MessageBox::setNextAnswer(MessageBox::Button button)
{
m_nextAnswer = button;
}
diff --git a/src/gui/MessageBox.h b/src/gui/MessageBox.h
index c6cdaa28c..696b28844 100644
--- a/src/gui/MessageBox.h
+++ b/src/gui/MessageBox.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
+ * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,35 +20,91 @@
#define KEEPASSX_MESSAGEBOX_H
#include <QMessageBox>
+#include <QPushButton>
+#include <QMap>
class MessageBox
{
public:
- static QMessageBox::StandardButton critical(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons = QMessageBox::Ok,
- QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
- static QMessageBox::StandardButton information(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons = QMessageBox::Ok,
- QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
- static QMessageBox::StandardButton question(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons = QMessageBox::Ok,
- QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
- static QMessageBox::StandardButton warning(QWidget* parent,
- const QString& title,
- const QString& text,
- QMessageBox::StandardButtons buttons = QMessageBox::Ok,
- QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
-
- static void setNextAnswer(QMessageBox::StandardButton button);
+ enum Button : uint64_t {
+ // Reimplementation of Qt StandardButtons
+ NoButton = 0,
+ Ok = 1 << 1,
+ Open = 1 << 2,
+ Save = 1 << 3,
+ Cancel = 1 << 4,
+ Close = 1 << 5,
+ Discard = 1 << 6,
+ Apply = 1 << 7,
+ Reset = 1 << 8,
+ RestoreDefaults = 1 << 9,
+ Help = 1 << 10,
+ SaveAll = 1 << 11,
+ Yes = 1 << 12,
+ YesToAll = 1 << 13,
+ No = 1 << 14,
+ NoToAll = 1 << 15,
+ Abort = 1 << 16,
+ Retry = 1 << 17,
+ Ignore = 1 << 18,
+
+ // KeePassXC Buttons
+ Overwrite = 1 << 19,
+ Delete = 1 << 20,
+ Move = 1 << 21,
+ Empty = 1 << 22,
+ Remove = 1 << 23,
+ Skip = 1 << 24,
+ Disable = 1 << 25,
+ Merge = 1 << 26,
+
+ // Internal loop markers. Update Last when new KeePassXC button is added
+ First = Ok,
+ Last = Merge,
+ };
+
+ typedef uint64_t Buttons;
+
+ static void initializeButtonDefs();
+ static void setNextAnswer(Button button);
+
+ static Button critical(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ Buttons buttons = MessageBox::Ok,
+ Button defaultButton = MessageBox::NoButton);
+ static Button information(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ Buttons buttons = MessageBox::Ok,
+ Button defaultButton = MessageBox::NoButton);
+ static Button question(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ Buttons buttons = MessageBox::Ok,
+ Button defaultButton = MessageBox::NoButton);
+ static Button warning(QWidget* parent,
+ const QString& title,
+ const QString& text,
+ Buttons buttons = MessageBox::Ok,
+ Button defaultButton = MessageBox::NoButton);
private:
- static QMessageBox::StandardButton m_nextAnswer;
+ static Button m_nextAnswer;
+ static QMap<QAbstractButton*, Button> m_addedButtonLookup;
+ static QMap<Button, std::pair<QString, QMessageBox::ButtonRole>> m_buttonDefs;
+
+ static Button messageBox(QWidget* parent,
+ QMessageBox::Icon icon,
+ const QString& title,
+ const QString& text,
+ Buttons buttons = MessageBox::Ok,
+ Button defaultButton = MessageBox::NoButton);
+
+ static QString stdButtonText(QMessageBox::StandardButton button);
+
+
+
};
#endif // KEEPASSX_MESSAGEBOX_H
diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp
index 19b5732bc..6e6c282b9 100644
--- a/src/gui/csvImport/CsvImportWidget.cpp
+++ b/src/gui/csvImport/CsvImportWidget.cpp
@@ -278,8 +278,8 @@ void CsvImportWidget::writeDatabase()
MessageBox::warning(this,
tr("Error"),
tr("CSV import: writer has errors:\n%1").arg(writer.errorString()),
- QMessageBox::Ok,
- QMessageBox::Ok);
+ MessageBox::Ok,
+ MessageBox::Ok);
}
emit editFinished(true);
}
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp
index 9f2714ea3..fc86ca5a7 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp
@@ -91,13 +91,13 @@ bool DatabaseSettingsWidgetBrowser::save()
void DatabaseSettingsWidgetBrowser::removeSelectedKey()
{
- if (QMessageBox::Yes
+ if (MessageBox::Yes
!= MessageBox::question(this,
tr("Delete the selected key?"),
tr("Do you really want to delete the selected key?\n"
"This may prevent connection to the browser plugin."),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel)) {
+ MessageBox::Yes | MessageBox::Cancel,
+ MessageBox::Cancel)) {
return;
}
@@ -156,13 +156,13 @@ void DatabaseSettingsWidgetBrowser::settingsWarning()
void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
{
- if (QMessageBox::Yes
+ if (MessageBox::Yes
!= MessageBox::question(this,
tr("Disconnect all browsers"),
tr("Do you really want to disconnect all browsers?\n"
"This may prevent connection to the browser plugin."),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel)) {
+ MessageBox::Yes | MessageBox::Cancel,
+ MessageBox::Cancel)) {
return;
}
@@ -174,10 +174,10 @@ void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
}
if (keysToRemove.isEmpty()) {
- QMessageBox::information(this,
+ MessageBox::information(this,
tr("KeePassXC: No keys found"),
tr("No shared encryption keys found in KeePassXC settings."),
- QMessageBox::Ok);
+ MessageBox::Ok);
return;
}
@@ -186,21 +186,21 @@ void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
}
const int count = keysToRemove.count();
- QMessageBox::information(this,
+ MessageBox::information(this,
tr("KeePassXC: Removed keys from database"),
tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
- QMessageBox::Ok);
+ MessageBox::Ok);
}
void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
{
- if (QMessageBox::Yes
+ if (MessageBox::Yes
!= MessageBox::question(this,
tr("Forget all site-specific settings on entries"),
tr("Do you really want forget all site-specific settings on every entry?\n"
"Permissions to access entries will be revoked."),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel)) {
+ MessageBox::Yes | MessageBox::Cancel,
+ MessageBox::Cancel)) {
return;
}
@@ -226,28 +226,28 @@ void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
progress.reset();
if (counter > 0) {
- QMessageBox::information(this,
+ MessageBox::information(this,
tr("KeePassXC: Removed permissions"),
tr("Successfully removed permissions from %n entry(s).", "", counter),
- QMessageBox::Ok);
+ MessageBox::Ok);
} else {
- QMessageBox::information(this,
+ MessageBox::information(this,
tr("KeePassXC: No entry with permissions found!"),
tr("The active database does not contain an entry with permissions."),
- QMessageBox::Ok);
+ MessageBox::Ok);
}
}
void DatabaseSettingsWidgetBrowser::convertAttributesToCustomData()
{
- if (QMessageBox::Yes
+ if (MessageBox::Yes
!= MessageBox::question(
this,
tr("Move KeePassHTTP attributes to custom data"),
tr("Do you really want to move all legacy browser integration data to the latest standard?\n"
"This is necessary to maintain compatibility with the browser plugin."),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel)) {
+ MessageBox::Yes | MessageBox::Cancel,
+ MessageBox::Cancel)) {
return;
}
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp
index b1f07211e..a95f5b322 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp
@@ -172,8 +172,8 @@ bool DatabaseSettingsWidgetMasterKey::save()
MessageBox::critical(this,
tr("No encryption key added"),
tr("You must add at least one encryption key to secure your database!"),
- QMessageBox::Ok,
- QMessageBox::Ok);
+ MessageBox::Ok,
+ MessageBox::Ok);
return false;
}
@@ -183,9 +183,9 @@ bool DatabaseSettingsWidgetMasterKey::save()
tr("WARNING! You have not set a password. Using a database without "
"a password is strongly discouraged!\n\n"
"Are you sure you want to continue without a password?"),
- QMessageBox::Yes | QMessageBox::Cancel,
- QMessageBox::Cancel);
- if (answer != QMessageBox::Yes) {
+ MessageBox::Yes | MessageBox::Cancel,
+ MessageBox::Cancel);
+ if (answer != MessageBox::Yes) {
return false;
}
}
@@ -221,7 +221,7 @@ bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widg
if (widget->visiblePage() == KeyComponentWidget::Edit) {
QString error = tr("Unknown error");
if (!widget->validate(error) || !widget->addToCompositeKey(newKey)) {
- QMessageBox::critical(this, tr("Failed to change master key"), error, QMessageBox::Ok);
+ MessageBox::critical(this, tr("Failed to change master key"), error, MessageBox::Ok);
return false;
}
} else if (widget->visiblePage() == KeyComponentWidget::LeaveOrRemove) {
@@ -238,7 +238,7 @@ bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widg
if (widget->visiblePage() == KeyComponentWidget::Edit) {
QString error = tr("Unknown error");
if (!widget->validate(error) || !widget->addToCompositeKey(newKey)) {
- QMessageBox::critical(this, tr("Failed to change master key"), error, QMessageBox::Ok);
+ MessageBox::critical(this, tr("Failed to change master key"), error, MessageBox::Ok);
return false;
}
} else if (widget->visiblePage() == KeyComponentWidget::LeaveOrRemove) {
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 99200a1f9..5da6e6605 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -821,9 +821,9 @@ bool EditEntryWidget::commitEntry()
auto answer = MessageBox::question(this,
tr("Apply generated password?"),
tr("Do you want to apply the generated password to this entry?"),
- QMessageBox::Yes | QMessageBox::No,
- QMessageBox::Yes);
- if (answer == QMessageBox::Yes) {
+ MessageBox::Yes | MessageBox::No,
+ MessageBox::Yes);
+ if (answer == MessageBox::Yes) {
m_mainUi->passwordGenerator->applyPassword();
}
}
@@ -947,13 +947,13 @@ void EditEntryWidget::cancel()
auto result = MessageBox::question(this,
QString(),
tr("Entry has unsaved changes"),
- QMessageBox::Cancel | QMessageBox::Save | QMessageBox::Discard,
- QMessageBox::Cancel);
- if (result == QMessageBox::Cancel) {
+ MessageBox::Cancel | MessageBox::Save | MessageBox::Discard,
+ MessageBox::Cancel);
+ if (result == MessageBox::Cancel) {
m_mainUi->passwordGenerator->reset();
return;
}
- if (result == QMessageBox::Save) {
+ if (result == MessageBox::Save) {
commitEntry();
m_saved = true;
}
@@ -1058,11 +1058,14 @@ void EditEntryWidget::removeCurrentAttribute()
QModelIndex index = m_advancedUi->attributesView->currentIndex();
if (index.isValid()) {
- if (MessageBox::question(this,
- tr("Confirm Remove"),
- tr("Are you sure you want to remove this attribute?"),
- QMessageBox::Yes | QMessageBox::No)
- == QMessageBox::Yes) {
+
+ auto result = MessageBox::question(this,
+ tr("Confirm Removal"),
+ tr("Are you sure you want to remove this attribute?"),
+ MessageBox::Remove | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Remove) {
m_entryAttributes->remove(m_attributesModel->keyByIndex(index));
setUnsavedChanges(true);
}
diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp
index e7a72c51e..a3eb38a43 100644
--- a/src/gui/entry/EntryAttachmentsWidget.cpp
+++ b/src/gui/entry/EntryAttachmentsWidget.cpp
@@ -165,10 +165,13 @@ void EntryAttachmentsWidget::removeSelectedAttachments()
return;
}
- const QString question = tr("Are you sure you want to remove %n attachment(s)?", "", indexes.count());
- QMessageBox::StandardButton answer =
- MessageBox::question(this, tr("Confirm remove"), question, QMessageBox::Yes | QMessageBox::No);
- if (answer == QMessageBox::Yes) {
+ auto result = MessageBox::question(this,
+ tr("Confirm remove"),
+ tr("Are you sure you want to remove %n attachment(s)?", "", indexes.count()),
+ MessageBox::Remove | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Remove) {
QStringList keys;
for (const QModelIndex& index : indexes) {
keys.append(m_attachmentsModel->keyByIndex(index));
@@ -211,15 +214,24 @@ void EntryAttachmentsWidget::saveSelectedAttachments()
const QString attachmentPath = saveDir.absoluteFilePath(filename);
if (QFileInfo::exists(attachmentPath)) {
- const QString question(
+
+ MessageBox::Buttons buttons = MessageBox::Overwrite | MessageBox::Cancel;
+ if (indexes.length() > 1) {
+ buttons |= MessageBox::Skip;
+ }
+
+ const QString questionText(
tr("Are you sure you want to overwrite the existing file \"%1\" with the attachment?"));
- auto answer = MessageBox::question(this,
+
+ auto result = MessageBox::question(this,
tr("Confirm overwrite"),
- question.arg(filename),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- if (answer == QMessageBox::No) {
+ questionText.arg(filename),
+ buttons,
+ MessageBox::Cancel);
+
+ if (result == MessageBox::Skip) {
continue;
- } else if (answer == QMessageBox::Cancel) {
+ } else if (result == MessageBox::Cancel) {
return;
}
}