From c239abeb2e72d023c61af41728f2568596eb518e Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Fri, 9 Jan 2026 00:58:29 -0800 Subject: [PATCH 1/6] Add button to clear clipboard Calls a slot that clears the clipboard. `Clipboard::clearCopiedText()` already has a signal to clear the keyboard and make the progress bar and label disappear. --- src/gui/MainWindow.cpp | 19 +++++++++++++++++++ src/gui/MainWindow.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index d51588ac50..6af03b3a2b 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -679,6 +679,7 @@ MainWindow::MainWindow() m_progressBarLabel = new QLabel(statusBar()); m_progressBarLabel->setVisible(false); statusBar()->addPermanentWidget(m_progressBarLabel); + m_progressBar = new QProgressBar(statusBar()); m_progressBar->setVisible(false); m_progressBar->setTextVisible(false); @@ -686,7 +687,14 @@ MainWindow::MainWindow() m_progressBar->setFixedHeight(15); m_progressBar->setMaximum(100); statusBar()->addPermanentWidget(m_progressBar); + + m_clearClipboardButton = new QPushButton(statusBar()); + m_clearClipboardButton->setText(tr("Clear Clipboard")); + m_clearClipboardButton->setVisible(false); + statusBar()->addPermanentWidget(m_clearClipboardButton); + connect(clipboard(), &Clipboard::updateCountdown, this, &MainWindow::updateProgressBar); + connect(m_clearClipboardButton.data(), &QPushButton::clicked, this, &MainWindow::clearClipboard); m_actionMultiplexer.connect(SIGNAL(updateSyncProgress(int, QString)), this, SLOT(updateProgressBar(int, QString))); m_actionMultiplexer.connect(SIGNAL(databaseSyncInProgress()), this, SLOT(disableMenuAndToolbar())); m_actionMultiplexer.connect(SIGNAL(databaseSyncCompleted(QString)), this, SLOT(enableMenuAndToolbar())); @@ -1535,6 +1543,11 @@ void MainWindow::clearSSHAgent() #endif } +void MainWindow::clearClipboard() +{ + clipboard()->clearCopiedText(); +} + void MainWindow::saveWindowInformation() { if (isVisible()) { @@ -1633,11 +1646,17 @@ void MainWindow::updateProgressBar(int percentage, QString message) if (percentage < 0) { m_progressBar->setVisible(false); m_progressBarLabel->setVisible(false); + m_clearClipboardButton->setVisible(false); } else { m_progressBar->setValue(percentage); m_progressBar->setVisible(true); m_progressBarLabel->setText(message); m_progressBarLabel->setVisible(true); + + Clipboard *cb = qobject_cast(sender()); + if(cb) { + m_clearClipboardButton->setVisible(true); + } } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 8effd06f43..d6b8ef56e0 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "core/SignalMultiplexer.h" #include "gui/DatabaseWidget.h" @@ -155,6 +156,7 @@ private slots: void enableMenuAndToolbar(); void disableMenuAndToolbar(); void clearSSHAgent(); + void clearClipboard(); private: static const QString BaseWindowTitle; @@ -190,6 +192,7 @@ private slots: QPointer m_progressBar; QPointer m_progressBarLabel; QPointer m_statusBarLabel; + QPointer m_clearClipboardButton; Q_DISABLE_COPY(MainWindow) From 536999daea7fca460c582a28b5b6c55d70429ec2 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sat, 10 Jan 2026 01:58:55 -0800 Subject: [PATCH 2/6] Update language files and add test case --- share/translations/keepassxc_en.ts | 4 ++++ src/gui/MainWindow.cpp | 1 + tests/gui/TestGui.cpp | 20 ++++++++++++++++++++ tests/gui/TestGui.h | 1 + 4 files changed, 26 insertions(+) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index f974db170b..8cf846a48a 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -6432,6 +6432,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes. + + Clear Clipboard + + ManageDatabase diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 6af03b3a2b..bb5830343d 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -690,6 +690,7 @@ MainWindow::MainWindow() m_clearClipboardButton = new QPushButton(statusBar()); m_clearClipboardButton->setText(tr("Clear Clipboard")); + m_clearClipboardButton->setObjectName("clearClipboardButton"); m_clearClipboardButton->setVisible(false); statusBar()->addPermanentWidget(m_clearClipboardButton); diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 96c8b0703d..6174f8b62f 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -2494,6 +2494,26 @@ void TestGui::addCannedEntries() QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); } +void TestGui::testClearClipboard() +{ + addCannedEntries(); + + EntryView* entryView = m_dbWidget->findChild("entryView"); + QVERIFY(entryView->isVisible()); + + QClipboard* clipboard = QApplication::clipboard(); + + clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton); + QTRY_VERIFY(entryView->hasFocus()); + QTest::keyClick(entryView, Qt::Key_C, Qt::ControlModifier); + QTRY_COMPARE(clipboard->text(), entryView->currentEntry()->password()); + + QPushButton *clearClipboardButton = m_mainWindow->findChild("clearClipboardButton"); + QTRY_VERIFY(clearClipboardButton->isVisible()); + clearClipboardButton->click(); + QCOMPARE(clipboard->text(), QString()); +} + void TestGui::checkDatabase(const QString& filePath, const QString& expectedDbName) { auto key = QSharedPointer::create(); diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 514f7ce95b..f052bfa56f 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -71,6 +71,7 @@ private slots: void testTrayRestoreHide(); void testShortcutConfig(); void testMenuActionStates(); + void testClearClipboard(); private: void addCannedEntries(); From c93d341441f4354959d259eeede5ca61d5179968 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sun, 11 Jan 2026 16:54:48 -0800 Subject: [PATCH 3/6] Use sweeping broom icon instead of text --- share/icons/application/scalable/actions/sweep.svg | 1 + share/icons/icons.qrc | 1 + share/translations/keepassxc_en.ts | 2 +- src/gui/MainWindow.cpp | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 share/icons/application/scalable/actions/sweep.svg diff --git a/share/icons/application/scalable/actions/sweep.svg b/share/icons/application/scalable/actions/sweep.svg new file mode 100644 index 0000000000..e3c519562c --- /dev/null +++ b/share/icons/application/scalable/actions/sweep.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/icons.qrc b/share/icons/icons.qrc index 3e82e172d5..72b3b2dc89 100644 --- a/share/icons/icons.qrc +++ b/share/icons/icons.qrc @@ -85,6 +85,7 @@ application/scalable/actions/system-help.svg application/scalable/actions/system-search.svg application/scalable/actions/system-software-update.svg + application/scalable/actions/sweep.svg application/scalable/actions/tag.svg application/scalable/actions/tag-multiple.svg application/scalable/actions/tag-search.svg diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 8cf846a48a..a46483df3a 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -6433,7 +6433,7 @@ Expect some bugs and minor issues, this version is meant for testing purposes. - Clear Clipboard + Clear the clipboard immediately diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index bb5830343d..dc7f462300 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -689,7 +689,8 @@ MainWindow::MainWindow() statusBar()->addPermanentWidget(m_progressBar); m_clearClipboardButton = new QPushButton(statusBar()); - m_clearClipboardButton->setText(tr("Clear Clipboard")); + m_clearClipboardButton->setIcon(icons()->icon("sweep")); + m_clearClipboardButton->setToolTip(tr("Clear the clipboard immediately")); m_clearClipboardButton->setObjectName("clearClipboardButton"); m_clearClipboardButton->setVisible(false); statusBar()->addPermanentWidget(m_clearClipboardButton); From f2e34566cd06850cbc3d39a7463573e4f24c32c0 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sun, 11 Jan 2026 16:59:37 -0800 Subject: [PATCH 4/6] Update COPYING file --- COPYING | 1 + 1 file changed, 1 insertion(+) diff --git a/COPYING b/COPYING index a00aaf28c3..1fe3a06626 100644 --- a/COPYING +++ b/COPYING @@ -216,6 +216,7 @@ Files: share/icons/application/scalable/actions/application-exit.svg share/icons/application/scalable/actions/system-help.svg share/icons/application/scalable/actions/system-search.svg share/icons/application/scalable/actions/system-software-update.svg + share/icons/application/scalable/actions/sweep.svg share/icons/application/scalable/actions/tag.svg share/icons/application/scalable/actions/tag-multiple.svg share/icons/application/scalable/actions/tag-search.svg From 336170f91fb78e8e0c09fc63baac2d1594dbd6c8 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sun, 11 Jan 2026 22:52:47 -0800 Subject: [PATCH 5/6] Fix formatting --- src/gui/MainWindow.cpp | 4 ++-- src/gui/MainWindow.h | 2 +- tests/gui/TestGui.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index dc7f462300..f30b376fbb 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1655,8 +1655,8 @@ void MainWindow::updateProgressBar(int percentage, QString message) m_progressBarLabel->setText(message); m_progressBarLabel->setVisible(true); - Clipboard *cb = qobject_cast(sender()); - if(cb) { + Clipboard* cb = qobject_cast(sender()); + if (cb) { m_clearClipboardButton->setVisible(true); } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index d6b8ef56e0..73ea946ac2 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -23,9 +23,9 @@ #include #include #include +#include #include #include -#include #include "core/SignalMultiplexer.h" #include "gui/DatabaseWidget.h" diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 6174f8b62f..c06388af6a 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -2508,7 +2508,7 @@ void TestGui::testClearClipboard() QTest::keyClick(entryView, Qt::Key_C, Qt::ControlModifier); QTRY_COMPARE(clipboard->text(), entryView->currentEntry()->password()); - QPushButton *clearClipboardButton = m_mainWindow->findChild("clearClipboardButton"); + QPushButton* clearClipboardButton = m_mainWindow->findChild("clearClipboardButton"); QTRY_VERIFY(clearClipboardButton->isVisible()); clearClipboardButton->click(); QCOMPARE(clipboard->text(), QString()); From 1b75fd99696fff8dae8a91ee6680d892968ec852 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Tue, 13 Jan 2026 00:09:13 -0800 Subject: [PATCH 6/6] Use QToolButton instead --- src/gui/MainWindow.cpp | 5 +++-- src/gui/MainWindow.h | 4 ++-- tests/gui/TestGui.cpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index f30b376fbb..3ec0387c39 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -688,15 +688,16 @@ MainWindow::MainWindow() m_progressBar->setMaximum(100); statusBar()->addPermanentWidget(m_progressBar); - m_clearClipboardButton = new QPushButton(statusBar()); + m_clearClipboardButton = new QToolButton(statusBar()); m_clearClipboardButton->setIcon(icons()->icon("sweep")); m_clearClipboardButton->setToolTip(tr("Clear the clipboard immediately")); m_clearClipboardButton->setObjectName("clearClipboardButton"); m_clearClipboardButton->setVisible(false); + m_clearClipboardButton->setStyleSheet("QToolButton { border: none; background-color: transparent; }"); statusBar()->addPermanentWidget(m_clearClipboardButton); connect(clipboard(), &Clipboard::updateCountdown, this, &MainWindow::updateProgressBar); - connect(m_clearClipboardButton.data(), &QPushButton::clicked, this, &MainWindow::clearClipboard); + connect(m_clearClipboardButton.data(), &QToolButton::clicked, this, &MainWindow::clearClipboard); m_actionMultiplexer.connect(SIGNAL(updateSyncProgress(int, QString)), this, SLOT(updateProgressBar(int, QString))); m_actionMultiplexer.connect(SIGNAL(databaseSyncInProgress()), this, SLOT(disableMenuAndToolbar())); m_actionMultiplexer.connect(SIGNAL(databaseSyncCompleted(QString)), this, SLOT(enableMenuAndToolbar())); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 73ea946ac2..2b38ea84ae 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -23,9 +23,9 @@ #include #include #include -#include #include #include +#include #include "core/SignalMultiplexer.h" #include "gui/DatabaseWidget.h" @@ -192,7 +192,7 @@ private slots: QPointer m_progressBar; QPointer m_progressBarLabel; QPointer m_statusBarLabel; - QPointer m_clearClipboardButton; + QPointer m_clearClipboardButton; Q_DISABLE_COPY(MainWindow) diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index c06388af6a..da59fd01f6 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -2508,7 +2508,7 @@ void TestGui::testClearClipboard() QTest::keyClick(entryView, Qt::Key_C, Qt::ControlModifier); QTRY_COMPARE(clipboard->text(), entryView->currentEntry()->password()); - QPushButton* clearClipboardButton = m_mainWindow->findChild("clearClipboardButton"); + QToolButton* clearClipboardButton = m_mainWindow->findChild("clearClipboardButton"); QTRY_VERIFY(clearClipboardButton->isVisible()); clearClipboardButton->click(); QCOMPARE(clipboard->text(), QString());