Skip to content

Commit fc090b2

Browse files
committed
Move search help into reusable PopupHelpWidget
* Add PopupHelpWidget, as self-contained popup that can be positioned around a parent widget and will follow the movement and sizing of the window * Eliminated KEEPASSXC_MAIN_WINDOW macro and replaced with getMainWindow() function * Remove extra functions added to support moving popup widget
1 parent 561a76c commit fc090b2

File tree

13 files changed

+175
-78
lines changed

13 files changed

+175
-78
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ set(keepassx_SOURCES
126126
gui/UnlockDatabaseWidget.cpp
127127
gui/UnlockDatabaseDialog.cpp
128128
gui/WelcomeWidget.cpp
129-
gui/widgets/ElidedLabel.cpp
130129
gui/csvImport/CsvImportWidget.cpp
131130
gui/csvImport/CsvImportWizard.cpp
132131
gui/csvImport/CsvParserModel.cpp
@@ -154,6 +153,8 @@ set(keepassx_SOURCES
154153
gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp
155154
gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp
156155
gui/settings/SettingsWidget.cpp
156+
gui/widgets/ElidedLabel.cpp
157+
gui/widgets/PopupHelpWidget.cpp
157158
gui/wizard/NewDatabaseWizard.cpp
158159
gui/wizard/NewDatabaseWizardPage.cpp
159160
gui/wizard/NewDatabaseWizardPageMetaData.cpp

src/browser/BrowserService.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ bool BrowserService::openDatabase(bool triggerUnlock)
8888
}
8989

9090
if (triggerUnlock) {
91-
KEEPASSXC_MAIN_WINDOW->bringToFront();
91+
getMainWindow()->bringToFront();
9292
m_bringToFrontRequested = true;
9393
}
9494

@@ -901,7 +901,7 @@ void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget)
901901
{
902902
if (dbWidget) {
903903
if (m_bringToFrontRequested) {
904-
KEEPASSXC_MAIN_WINDOW->lower();
904+
getMainWindow()->lower();
905905
m_bringToFrontRequested = false;
906906
}
907907
emit databaseUnlocked();

src/gui/Application.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ namespace
4949

5050
Application::Application(int& argc, char** argv)
5151
: QApplication(argc, argv)
52-
, m_mainWindow(nullptr)
5352
#ifdef Q_OS_UNIX
5453
, m_unixSignalNotifier(nullptr)
5554
#endif
@@ -143,16 +142,6 @@ Application::~Application()
143142
}
144143
}
145144

146-
QWidget* Application::mainWindow() const
147-
{
148-
return m_mainWindow;
149-
}
150-
151-
void Application::setMainWindow(QWidget* mainWindow)
152-
{
153-
m_mainWindow = mainWindow;
154-
}
155-
156145
bool Application::event(QEvent* event)
157146
{
158147
// Handle Apple QFileOpenEvent from finder (double click on .kdbx file)

src/gui/Application.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ class Application : public QApplication
3737

3838
public:
3939
Application(int& argc, char** argv);
40-
QWidget* mainWindow() const;
4140
~Application() override;
42-
void setMainWindow(QWidget* mainWindow);
4341

4442
bool event(QEvent* event) override;
4543
bool isAlreadyRunning() const;
@@ -60,8 +58,6 @@ private slots:
6058
void socketReadyRead();
6159

6260
private:
63-
QWidget* m_mainWindow;
64-
6561
#if defined(Q_OS_UNIX)
6662
/**
6763
* Register Unix signals such as SIGINT and SIGTERM for clean shutdown.

src/gui/MainWindow.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,17 @@ class BrowserPlugin : public ISettingsPage
109109

110110
const QString MainWindow::BaseWindowTitle = "KeePassXC";
111111

112+
MainWindow* g_MainWindow = nullptr;
113+
MainWindow* getMainWindow() { return g_MainWindow; }
114+
112115
MainWindow::MainWindow()
113116
: m_ui(new Ui::MainWindow())
114117
, m_trayIcon(nullptr)
115118
, m_appExitCalled(false)
116119
, m_appExiting(false)
117120
{
121+
g_MainWindow = this;
122+
118123
m_ui->setupUi(this);
119124

120125
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(QT_NO_DBUS)
@@ -129,7 +134,6 @@ MainWindow::MainWindow()
129134
// Setup the search widget in the toolbar
130135
SearchWidget* search = new SearchWidget();
131136
search->connectSignals(m_actionMultiplexer);
132-
connect(this, SIGNAL(windowMoved()), search, SLOT(windowMoved()));
133137
m_searchWidgetAction = m_ui->toolBar->addWidget(search);
134138
m_searchWidgetAction->setEnabled(false);
135139

@@ -799,12 +803,6 @@ void MainWindow::changeEvent(QEvent* event)
799803
}
800804
}
801805

802-
void MainWindow::moveEvent(QMoveEvent* event)
803-
{
804-
emit windowMoved();
805-
QMainWindow::moveEvent(event);
806-
}
807-
808806
void MainWindow::saveWindowInformation()
809807
{
810808
if (isVisible()) {

src/gui/MainWindow.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ class MainWindow : public QMainWindow
5555
PasswordGeneratorScreen = 3
5656
};
5757

58-
signals:
59-
void windowMoved();
60-
6158
public slots:
6259
void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString());
6360
void appExit();
@@ -81,7 +78,6 @@ public slots:
8178
protected:
8279
void closeEvent(QCloseEvent* event) override;
8380
void changeEvent(QEvent* event) override;
84-
void moveEvent(QMoveEvent* event) override;
8581

8682
private slots:
8783
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None);
@@ -152,8 +148,12 @@ private slots:
152148
bool m_appExiting;
153149
};
154150

155-
#define KEEPASSXC_MAIN_WINDOW \
156-
(qobject_cast<Application*>(qApp) ? qobject_cast<MainWindow*>(qobject_cast<Application*>(qApp)->mainWindow()) \
157-
: nullptr)
151+
/**
152+
* Return instance of MainWindow created on app load
153+
* non-gui instances will return nullptr
154+
*
155+
* @return MainWindow instance or nullptr
156+
*/
157+
MainWindow* getMainWindow();
158158

159159
#endif // KEEPASSX_MAINWINDOW_H

src/gui/SearchWidget.cpp

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@
2727

2828
#include "core/Config.h"
2929
#include "core/FilePath.h"
30+
#include "gui/widgets/PopupHelpWidget.h"
3031

3132
SearchWidget::SearchWidget(QWidget* parent)
3233
: QWidget(parent)
3334
, m_ui(new Ui::SearchWidget())
34-
, m_helpUi(new Ui::SearchHelpWidget())
35-
, m_helpWidget(new QWidget(parent))
3635
, m_searchTimer(new QTimer(this))
3736
, m_clearSearchTimer(new QTimer(this))
3837
{
3938
m_ui->setupUi(this);
4039

41-
m_helpUi->setupUi(m_helpWidget);
42-
m_helpWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
43-
m_helpWidget->hide();
40+
m_helpWidget = new PopupHelpWidget(m_ui->searchEdit);
41+
m_helpWidget->setOffset(QPoint(0,1));
42+
Ui::SearchHelpWidget helpUi;
43+
helpUi.setupUi(m_helpWidget);
4444

4545
m_searchTimer->setSingleShot(true);
4646
m_clearSearchTimer->setSingleShot(true);
@@ -109,7 +109,6 @@ bool SearchWidget::eventFilter(QObject* obj, QEvent* event)
109109
}
110110
}
111111
} else if (event->type() == QEvent::FocusOut) {
112-
m_helpWidget->hide();
113112
// Auto-clear search after 5 minutes
114113
m_clearSearchTimer->start(300000);
115114
} else if (event->type() == QEvent::FocusIn) {
@@ -119,25 +118,6 @@ bool SearchWidget::eventFilter(QObject* obj, QEvent* event)
119118
return QWidget::eventFilter(obj, event);
120119
}
121120

122-
void SearchWidget::moveEvent(QMoveEvent* event)
123-
{
124-
windowMoved();
125-
QWidget::moveEvent(event);
126-
}
127-
128-
void SearchWidget::resizeEvent(QResizeEvent* event)
129-
{
130-
windowMoved();
131-
QWidget::resizeEvent(event);
132-
}
133-
134-
void SearchWidget::windowMoved()
135-
{
136-
if (m_helpWidget->isVisible()) {
137-
moveHelpPopup();
138-
}
139-
}
140-
141121
void SearchWidget::connectSignals(SignalMultiplexer& mx)
142122
{
143123
mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString)));
@@ -218,13 +198,6 @@ void SearchWidget::toggleHelp()
218198
if (m_helpWidget->isVisible()) {
219199
m_helpWidget->hide();
220200
} else {
221-
moveHelpPopup();
222201
m_helpWidget->show();
223202
}
224203
}
225-
226-
void SearchWidget::moveHelpPopup()
227-
{
228-
auto pos = mapToGlobal(m_ui->searchEdit->geometry().bottomLeft());
229-
m_helpWidget->move(pos);
230-
}

src/gui/SearchWidget.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
namespace Ui
2929
{
3030
class SearchWidget;
31-
class SearchHelpWidget;
3231
}
3332

33+
class PopupHelpWidget;
34+
3435
class SearchWidget : public QWidget
3536
{
3637
Q_OBJECT
@@ -48,8 +49,6 @@ class SearchWidget : public QWidget
4849
protected:
4950
// Filter key presses in the search field
5051
bool eventFilter(QObject* obj, QEvent* event) override;
51-
void moveEvent(QMoveEvent* event) override;
52-
void resizeEvent(QResizeEvent* event) override;
5352

5453
signals:
5554
void search(const QString& text);
@@ -62,7 +61,6 @@ class SearchWidget : public QWidget
6261

6362
public slots:
6463
void databaseChanged(DatabaseWidget* dbWidget = nullptr);
65-
void windowMoved();
6664

6765
private slots:
6866
void startSearchTimer();
@@ -73,11 +71,8 @@ private slots:
7371
void toggleHelp();
7472

7573
private:
76-
void moveHelpPopup();
77-
7874
const QScopedPointer<Ui::SearchWidget> m_ui;
79-
const QScopedPointer<Ui::SearchHelpWidget> m_helpUi;
80-
QWidget* m_helpWidget;
75+
PopupHelpWidget* m_helpWidget;
8176
QTimer* m_searchTimer;
8277
QTimer* m_clearSearchTimer;
8378
QAction* m_actionCaseSensitive;

src/gui/masterkey/KeyFileEditWidget.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ bool KeyFileEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key)
4545
}
4646

4747
if (fileKey->type() != FileKey::Hashed) {
48-
QMessageBox::warning(KEEPASSXC_MAIN_WINDOW,
48+
QMessageBox::warning(getMainWindow(),
4949
tr("Legacy key file format"),
5050
tr("You are using a legacy key file format which may become\n"
5151
"unsupported in the future.\n\n"
@@ -100,7 +100,7 @@ void KeyFileEditWidget::createKeyFile()
100100
QString errorMsg;
101101
bool created = FileKey::create(fileName, &errorMsg);
102102
if (!created) {
103-
MessageBox::critical(KEEPASSXC_MAIN_WINDOW, tr("Error creating key file"),
103+
MessageBox::critical(getMainWindow(), tr("Error creating key file"),
104104
tr("Unable to create key file: %1").arg(errorMsg), QMessageBox::Button::Ok);
105105
} else {
106106
m_compUi->keyFileCombo->setEditText(fileName);
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (C) 2017 KeePassXC Team <[email protected]>
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 2 or (at your option)
7+
* version 3 of the License.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "PopupHelpWidget.h"
19+
20+
#include <QEvent>
21+
22+
#include "gui/MainWindow.h"
23+
24+
PopupHelpWidget::PopupHelpWidget(QWidget* parent)
25+
: QWidget(parent)
26+
, m_parentWindow(parent->window())
27+
, m_appWindow(getMainWindow())
28+
, m_offset({0, 0})
29+
, m_corner(Qt::BottomLeftCorner)
30+
{
31+
Q_ASSERT(parent);
32+
33+
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
34+
hide();
35+
36+
m_appWindow->installEventFilter(this);
37+
parent->installEventFilter(this);
38+
}
39+
40+
PopupHelpWidget::~PopupHelpWidget()
41+
{
42+
m_parentWindow->removeEventFilter(this);
43+
parentWidget()->removeEventFilter(this);
44+
}
45+
46+
void PopupHelpWidget::setOffset(const QPoint& offset)
47+
{
48+
m_offset = offset;
49+
if (isVisible()) {
50+
alignWithParent();
51+
}
52+
}
53+
54+
void PopupHelpWidget::setPosition(Qt::Corner corner)
55+
{
56+
m_corner = corner;
57+
if (isVisible()) {
58+
alignWithParent();
59+
}
60+
}
61+
62+
bool PopupHelpWidget::eventFilter(QObject* obj, QEvent* event)
63+
{
64+
if (obj == parentWidget() && event->type() == QEvent::FocusOut) {
65+
hide();
66+
} else if (obj == m_appWindow && (event->type() == QEvent::Move || event->type() == QEvent::Resize)) {
67+
if (isVisible()) {
68+
alignWithParent();
69+
}
70+
}
71+
return QWidget::eventFilter(obj, event);
72+
}
73+
74+
void PopupHelpWidget::showEvent(QShowEvent* event)
75+
{
76+
alignWithParent();
77+
QWidget::showEvent(event);
78+
}
79+
80+
void PopupHelpWidget::alignWithParent()
81+
{
82+
QPoint pos;
83+
switch (m_corner) {
84+
case Qt::TopLeftCorner:
85+
pos = parentWidget()->geometry().topLeft() + m_offset - QPoint(0, height());
86+
break;
87+
case Qt::TopRightCorner:
88+
pos = parentWidget()->geometry().topRight() + m_offset - QPoint(width(), height());
89+
break;
90+
case Qt::BottomRightCorner:
91+
pos = parentWidget()->geometry().bottomRight() + m_offset - QPoint(width(), 0);
92+
break;
93+
default:
94+
pos = parentWidget()->geometry().bottomLeft() + m_offset;
95+
break;
96+
}
97+
98+
move(m_parentWindow->mapToGlobal(pos));
99+
}

0 commit comments

Comments
 (0)