mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-21 04:01:03 -05:00
a31c5ba006
Fixes #6942 and fixes #4443 - Return number of deleted entries - Fix minor memory leak - FdoSecrets: make all prompt truly async per spec and update tests * the waited signal may already be emitted before calling spy.wait(), causing the test to fail. This commit checks the count before waiting. * check unlock result after waiting for signal - FdoSecrets: implement unlockBeforeSearch option - FdoSecrets: make search always work regardless of entry group searching settings, fixes #6942 - FdoSecrets: cleanup gracefully even if some test failed - FdoSecrets: make it safe to call prompts concurrently - FdoSecrets: make sure in unit test we click on the correct dialog Note on the unit tests: objects are not deleted (due to deleteLater event not handled). So there may be multiple AccessControlDialog. But only one of it is visible and is the correctly one to click on. Before this change, a random one may be clicked on, causing the completed signal never be sent.
122 lines
5.1 KiB
C++
122 lines
5.1 KiB
C++
/*
|
|
* Copyright (C) 2021 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
|
|
* the Free Software Foundation, either version 2 or (at your option)
|
|
* version 3 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "GuiTools.h"
|
|
|
|
#include "core/Config.h"
|
|
#include "core/Group.h"
|
|
#include "gui/MessageBox.h"
|
|
|
|
namespace GuiTools
|
|
{
|
|
bool confirmDeleteEntries(QWidget* parent, const QList<Entry*>& entries, bool permanent)
|
|
{
|
|
if (!parent || entries.isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
if (permanent) {
|
|
QString prompt;
|
|
if (entries.size() == 1) {
|
|
prompt = QObject::tr("Do you really want to delete the entry \"%1\" for good?")
|
|
.arg(entries.first()->title().toHtmlEscaped());
|
|
} else {
|
|
prompt = QObject::tr("Do you really want to delete %n entry(s) for good?", "", entries.size());
|
|
}
|
|
|
|
auto answer = MessageBox::question(parent,
|
|
QObject::tr("Delete entry(s)?", "", entries.size()),
|
|
prompt,
|
|
MessageBox::Delete | MessageBox::Cancel,
|
|
MessageBox::Cancel);
|
|
|
|
return answer == MessageBox::Delete;
|
|
} else if (config()->get(Config::Security_NoConfirmMoveEntryToRecycleBin).toBool()) {
|
|
return true;
|
|
} else {
|
|
QString prompt;
|
|
if (entries.size() == 1) {
|
|
prompt = QObject::tr("Do you really want to move entry \"%1\" to the recycle bin?")
|
|
.arg(entries.first()->title().toHtmlEscaped());
|
|
} else {
|
|
prompt = QObject::tr("Do you really want to move %n entry(s) to the recycle bin?", "", entries.size());
|
|
}
|
|
|
|
auto answer = MessageBox::question(parent,
|
|
QObject::tr("Move entry(s) to recycle bin?", "", entries.size()),
|
|
prompt,
|
|
MessageBox::Move | MessageBox::Cancel,
|
|
MessageBox::Cancel);
|
|
|
|
return answer == MessageBox::Move;
|
|
}
|
|
}
|
|
|
|
size_t deleteEntriesResolveReferences(QWidget* parent, const QList<Entry*>& entries, bool permanent)
|
|
{
|
|
if (!parent || entries.isEmpty()) {
|
|
return 0;
|
|
}
|
|
|
|
QList<Entry*> selectedEntries;
|
|
// Find references to entries and prompt for direction if necessary
|
|
for (auto entry : entries) {
|
|
if (permanent) {
|
|
auto references = entry->database()->rootGroup()->referencesRecursive(entry);
|
|
if (!references.isEmpty()) {
|
|
// Ignore references that are part of this cohort
|
|
for (auto e : entries) {
|
|
references.removeAll(e);
|
|
}
|
|
// Prompt the user on what to do with the reference (Overwrite, Delete, Skip)
|
|
auto result = MessageBox::question(
|
|
parent,
|
|
QObject::tr("Replace references to entry?"),
|
|
QObject::tr(
|
|
"Entry \"%1\" has %2 reference(s). "
|
|
"Do you want to overwrite references with values, skip this entry, or delete anyway?",
|
|
"",
|
|
references.size())
|
|
.arg(entry->resolvePlaceholder(entry->title()).toHtmlEscaped())
|
|
.arg(references.size()),
|
|
MessageBox::Overwrite | MessageBox::Skip | MessageBox::Delete,
|
|
MessageBox::Overwrite);
|
|
|
|
if (result == MessageBox::Overwrite) {
|
|
for (auto ref : references) {
|
|
ref->replaceReferencesWithValues(entry);
|
|
}
|
|
} else if (result == MessageBox::Skip) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
// Marked for deletion
|
|
selectedEntries << entry;
|
|
}
|
|
|
|
for (auto entry : asConst(selectedEntries)) {
|
|
if (permanent) {
|
|
delete entry;
|
|
} else {
|
|
entry->database()->recycleEntry(entry);
|
|
}
|
|
}
|
|
return selectedEntries.size();
|
|
}
|
|
} // namespace GuiTools
|