[office/kmymoney] kmymoney: Remember the size of the dialogs that are resized over and over
Thomas Baumgart <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit bc9f97fa487d93e285bb82158bca106d15699f4b by Thomas Baumgart, on behalf of Simone Iori.
Committed on 27/07/2026 at 19:11.
Pushed by tbaumgart into branch 'master'.
Remember the size of the dialogs that are resized over and over
Dialogs open at the size their layout asks for every time, so the ones
that show a list have to be enlarged again at every use. Bug 422462 asks
for this, with two of the dialogs named explicitly, and it has three
duplicates.
The commit adds KGuiUtils::keepDialogSize(), which takes a dialog and
keeps its size from then on, in a configuration group named after the
class of the dialog - the convention the existing implementations
already follow, so the sizes stored so far keep working.
The size is restored when the dialog is shown and stored when it is
hidden or destroyed, rather than in the constructor and the destructor:
* while the dialog is being constructed it has no window handle, and
creating one there by means of `winId()` is not an option, since that
crashed on MS-Windows and was removed for that reason in 5.0.4 (bug
404848). The dialog for entering a schedule has silently not restored
its size since then, which the second commit fixes by moving it to the
helper.
* a dialog that is deleted while it is still visible never sees a hide
event. The find dialog is the one that does this, its Close button
deletes it directly, so its size was only stored when it was closed
with the window decoration and not with its own Close button.
Not addressed here:
* only the size is restored, not the position. A client cannot place its
own windows on Wayland, which is why KWindowConfig separates the
two, and the other KDE applications behave this way as well.
* the settings dialog, the import summary and the report configuration
store their geometry with QWidget::saveGeometry() and some of them
column states along with it. That works without a window handle, so
they are left alone.
M +2 -0 kmymoney/dialogs/kcurrencyeditdlg.cpp
M +2 -0 kmymoney/dialogs/kequitypriceupdatedlg.cpp
M +2 -0 kmymoney/dialogs/kmymoneypricedlg.cpp
M +5 -14 kmymoney/plugins/views/reports/kbalancechartdlg.cpp
M +5 -14 kmymoney/views/kenterscheduledlg.cpp
M +2 -0 kmymoney/views/ksearchtransactiondlg.cpp
M +2 -0 kmymoney/views/ktransactionselectdlg.cpp
M +1 -0 kmymoney/widgets/CMakeLists.txt
M +80 -0 kmymoney/widgets/kguiutils.cpp
M +11 -0 kmymoney/widgets/kguiutils.h
https://invent.kde.org/office/kmymoney/-/commit/bc9f97fa487d93e285bb82158bca106d15699f4b
diff --git a/kmymoney/dialogs/kcurrencyeditdlg.cpp b/kmymoney/dialogs/kcurrencyeditdlg.cpp
index 4663f19b7..d97f3e71b 100644
--- a/kmymoney/dialogs/kcurrencyeditdlg.cpp
+++ b/kmymoney/dialogs/kcurrencyeditdlg.cpp
@@ -39,6 +39,7 @@
#include "icons/icons.h"
#include "kavailablecurrencydlg.h"
#include "kcurrencyeditordlg.h"
+#include "kguiutils.h"
#include "kmymoneyutils.h"
#include "menuenums.h"
#include "mymoneyenums.h"
@@ -226,6 +227,7 @@ KCurrencyEditDlg::KCurrencyEditDlg(QWidget* parent)
{
Q_D(KCurrencyEditDlg);
d->ui->setupUi(this);
+ KGuiUtils::keepDialogSize(this);
d->m_searchWidget = new KTreeWidgetSearchLineWidget(this, d->ui->m_currencyList);
d->m_searchWidget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
d->m_searchWidget->setFocus();
diff --git a/kmymoney/dialogs/kequitypriceupdatedlg.cpp b/kmymoney/dialogs/kequitypriceupdatedlg.cpp
index 584e2e74a..acb6717ec 100644
--- a/kmymoney/dialogs/kequitypriceupdatedlg.cpp
+++ b/kmymoney/dialogs/kequitypriceupdatedlg.cpp
@@ -43,6 +43,7 @@
#include "dialogenums.h"
#include "icons.h"
#include "kequitypriceupdateconfdlg.h"
+#include "kguiutils.h"
#include "kmmonlinequotesprofilemanager.h"
#include "kmmyesno.h"
#include "kmymoneyutils.h"
@@ -125,6 +126,7 @@ public:
{
Q_Q(KEquityPriceUpdateDlg);
ui->setupUi(q);
+ KGuiUtils::keepDialogSize(q);
m_filterModel = new KEquityFilterModel(this);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
diff --git a/kmymoney/dialogs/kmymoneypricedlg.cpp b/kmymoney/dialogs/kmymoneypricedlg.cpp
index 53eb5551f..35058f106 100644
--- a/kmymoney/dialogs/kmymoneypricedlg.cpp
+++ b/kmymoney/dialogs/kmymoneypricedlg.cpp
@@ -32,6 +32,7 @@
#include "icons.h"
#include "kcurrencycalculator.h"
#include "kequitypriceupdatedlg.h"
+#include "kguiutils.h"
#include "kmymoneycurrencyselector.h"
#include "kmymoneyutils.h"
#include "kpricetreeitem.h"
@@ -184,6 +185,7 @@ KMyMoneyPriceDlg::KMyMoneyPriceDlg(QWidget* parent)
{
Q_D(KMyMoneyPriceDlg);
d->ui->setupUi(this);
+ KGuiUtils::keepDialogSize(this);
d->ui->m_deleteButton->setIcon(Icons::get(Icon::EditRemove));
d->ui->m_newButton->setIcon(Icons::get(Icon::DocumentNew));
diff --git a/kmymoney/plugins/views/reports/kbalancechartdlg.cpp b/kmymoney/plugins/views/reports/kbalancechartdlg.cpp
index 638c7c279..a55dab6c0 100644
--- a/kmymoney/plugins/views/reports/kbalancechartdlg.cpp
+++ b/kmymoney/plugins/views/reports/kbalancechartdlg.cpp
@@ -23,13 +23,13 @@
#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
-#include <KWindowConfig>
#include <KXmlGuiWindow>
// ----------------------------------------------------------------------------
// Project Includes
#include "icons.h"
+#include "kguiutils.h"
#include "kmymoneyutils.h"
#include "kreportchartview.h"
#include "mymoneyenums.h"
@@ -214,14 +214,10 @@ KBalanceChartDlg::KBalanceChartDlg(const MyMoneyAccount& account, QWidget* paren
setSizeGripEnabled(true);
setModal(true);
- // restore the last used dialog size
- winId(); // needs to be called to create the QWindow
- KConfigGroup grp = KSharedConfig::openConfig()->group("KBalanceChartDlg");
- if (grp.isValid()) {
- KWindowConfig::restoreWindowSize(windowHandle(), grp);
- }
- // let the minimum size be 700x500
- resize(QSize(700, 500).expandedTo(windowHandle() ? windowHandle()->size() : QSize()));
+ // keep the size the dialog is left at from one use to the next
+ KGuiUtils::keepDialogSize(this);
+ // the size it opens with as long as none was stored
+ resize(700, 500);
QVBoxLayout* mainLayout = new QVBoxLayout;
setLayout(mainLayout);
@@ -260,11 +256,6 @@ KBalanceChartDlg::KBalanceChartDlg(const MyMoneyAccount& account, QWidget* paren
KBalanceChartDlg::~KBalanceChartDlg()
{
- // store the last used dialog size
- KConfigGroup grp = KSharedConfig::openConfig()->group("KBalanceChartDlg");
- if (grp.isValid()) {
- KWindowConfig::saveWindowSize(windowHandle(), grp);
- }
}
void KBalanceChartDlg::configureReport()
diff --git a/kmymoney/views/kenterscheduledlg.cpp b/kmymoney/views/kenterscheduledlg.cpp
index 194601f65..8dfdf592b 100644
--- a/kmymoney/views/kenterscheduledlg.cpp
+++ b/kmymoney/views/kenterscheduledlg.cpp
@@ -23,7 +23,6 @@
#include <KMessageBox>
#include <KSharedConfig>
#include <KStandardGuiItem>
-#include <KWindowConfig>
// ----------------------------------------------------------------------------
// Project Includes
@@ -32,6 +31,7 @@
#include "dialogenums.h"
#include "icons.h"
+#include "kguiutils.h"
#include "kmymoneyutils.h"
#include "mymoneyaccount.h"
#include "mymoneyenums.h"
@@ -93,13 +93,10 @@ KEnterScheduleDlg::KEnterScheduleDlg(QWidget* parent, const MyMoneySchedule& sch
{
Q_D(KEnterScheduleDlg);
- // restore the last used dialog size
- KConfigGroup grp = KSharedConfig::openConfig()->group("KEnterScheduleDlg");
- if (grp.isValid()) {
- KWindowConfig::restoreWindowSize(windowHandle(), grp);
- }
- // let the minimum size be 780x410
- resize(QSize(780, 410).expandedTo(windowHandle() ? windowHandle()->size() : QSize()));
+ // keep the size the dialog is left at from one use to the next
+ KGuiUtils::keepDialogSize(this);
+ // the size it opens with as long as none was stored
+ resize(780, 410);
// position the dialog centered on the application (for some reason without
// a call to winId() the dialog is positioned in the upper left corner of
@@ -191,12 +188,6 @@ KEnterScheduleDlg::~KEnterScheduleDlg()
{
Q_D(KEnterScheduleDlg);
- // store the last used dialog size
- KConfigGroup grp = KSharedConfig::openConfig()->group("KEnterScheduleDlg");
- if (grp.isValid()) {
- KWindowConfig::saveWindowSize(windowHandle(), grp);
- }
-
delete d;
}
diff --git a/kmymoney/views/ksearchtransactiondlg.cpp b/kmymoney/views/ksearchtransactiondlg.cpp
index 36f8cbef2..49db241be 100644
--- a/kmymoney/views/ksearchtransactiondlg.cpp
+++ b/kmymoney/views/ksearchtransactiondlg.cpp
@@ -24,6 +24,7 @@
// Project Includes
#include "journalmodel.h"
+#include "kguiutils.h"
#include "ktransactionfilter.h"
#include "ledgerjournalidfilter.h"
#include "menuenums.h"
@@ -51,6 +52,7 @@ public:
Q_Q(KSearchTransactionDlg);
ui.setupUi(q);
+ KGuiUtils::keepDialogSize(q);
filterTab = new KTransactionFilter(q);
ui.m_tabWidget->insertTab(0, filterTab, i18nc("Criteria tab", "Criteria"));
diff --git a/kmymoney/views/ktransactionselectdlg.cpp b/kmymoney/views/ktransactionselectdlg.cpp
index 423c988ea..58a18e157 100644
--- a/kmymoney/views/ktransactionselectdlg.cpp
+++ b/kmymoney/views/ktransactionselectdlg.cpp
@@ -18,6 +18,7 @@
#include "icons.h"
#include "journalmodel.h"
+#include "kguiutils.h"
#include "ledgerjournalidfilter.h"
#include "mymoneyfile.h"
@@ -51,6 +52,7 @@ KTransactionSelectDlg::KTransactionSelectDlg(QWidget* parent)
{
Q_D(KTransactionSelectDlg);
d->ui->setupUi(this);
+ KGuiUtils::keepDialogSize(this);
d->ui->switchButton->hide();
d->ui->label->setText(i18nc("@info:label Description of select transaction dialog", "Select the transaction to use as template."));
diff --git a/kmymoney/widgets/CMakeLists.txt b/kmymoney/widgets/CMakeLists.txt
index dcbb703c1..13dbd15cf 100644
--- a/kmymoney/widgets/CMakeLists.txt
+++ b/kmymoney/widgets/CMakeLists.txt
@@ -135,6 +135,7 @@ add_library(kmm_base_widgets ${kmm_base_widgets_SOURCES})
target_link_libraries(kmm_base_widgets PUBLIC
KF${QT_MAJOR_VERSION}::Completion
+ KF${QT_MAJOR_VERSION}::ConfigGui
KF${QT_MAJOR_VERSION}::Notifications
KF${QT_MAJOR_VERSION}::TextWidgets
Alkimia::alkimia
diff --git a/kmymoney/widgets/kguiutils.cpp b/kmymoney/widgets/kguiutils.cpp
index 1f03cff69..1413afb2c 100644
--- a/kmymoney/widgets/kguiutils.cpp
+++ b/kmymoney/widgets/kguiutils.cpp
@@ -17,16 +17,21 @@
#include <QListWidget>
#include <QPushButton>
#include <QSpinBox>
+#include <QEvent>
#include <QTreeWidget>
#include <QWidget>
+#include <QWindow>
// ----------------------------------------------------------------------------
// KDE Includes
#include <KComboBox>
+#include <KConfigGroup>
#include <KLineEdit>
#include <KLocalizedString>
+#include <KSharedConfig>
#include <KUrlRequester>
+#include <KWindowConfig>
// ----------------------------------------------------------------------------
// Project Includes
@@ -299,3 +304,78 @@ void KGuiUtils::setupExpandCollapseButton(QPushButton* button, QTreeWidget* widg
button->setProperty("expanded", !expanded);
});
}
+
+namespace
+{
+/**
+ * Restores the size of a dialog when it is shown and stores it when it is
+ * hidden or destroyed. The window handle needed for this only exists once
+ * the dialog is shown, and creating it earlier (by a call to winId()) is not
+ * an option since that crashes on MS-Windows (see bug 404848).
+ */
+class DialogSizeKeeper : public QObject
+{
+public:
+ explicit DialogSizeKeeper(QWidget* dialog)
+ : QObject(dialog)
+ , m_dialog(dialog)
+ // the name of the class is only available as long as the dialog is
+ // not being destroyed, so it is kept here right away
+ , m_groupName(QLatin1String(dialog->metaObject()->className()))
+ {
+ dialog->installEventFilter(this);
+ }
+
+ ~DialogSizeKeeper() override
+ {
+ // dialogs that are deleted while they are still visible never see a
+ // hide event. A widget deletes its children before it gets rid of its
+ // window handle, so the size is still available here.
+ saveSize();
+ }
+
+protected:
+ bool eventFilter(QObject* watched, QEvent* event) override
+ {
+ if (watched == m_dialog) {
+ switch (event->type()) {
+ case QEvent::Show:
+ if (m_dialog->windowHandle()) {
+ KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), KSharedConfig::openConfig()->group(m_groupName));
+ // the window handle does not pass the size on to the widget by itself
+ m_dialog->resize(m_dialog->windowHandle()->size());
+ }
+ break;
+
+ case QEvent::Hide:
+ saveSize();
+ break;
+
+ default:
+ break;
+ }
+ }
+ return QObject::eventFilter(watched, event);
+ }
+
+private:
+ void saveSize()
+ {
+ if (m_dialog->windowHandle()) {
+ auto grp = KSharedConfig::openConfig()->group(m_groupName);
+ KWindowConfig::saveWindowSize(m_dialog->windowHandle(), grp);
+ grp.sync();
+ }
+ }
+
+ QWidget* const m_dialog;
+ const QString m_groupName;
+};
+}
+
+void KGuiUtils::keepDialogSize(QWidget* dialog)
+{
+ if (dialog) {
+ new DialogSizeKeeper(dialog);
+ }
+}
diff --git a/kmymoney/widgets/kguiutils.h b/kmymoney/widgets/kguiutils.h
index a17c3374f..3b3d36130 100644
--- a/kmymoney/widgets/kguiutils.h
+++ b/kmymoney/widgets/kguiutils.h
@@ -97,6 +97,17 @@ private:
namespace KGuiUtils {
void KMM_BASE_WIDGETS_EXPORT setupExpandCollapseButton(QPushButton* button, QTreeWidget* widget, int rows = -1);
+
+/**
+ * Make @a dialog open with the size it had the last time it was closed. The
+ * size is kept in a configuration group named after the class of the dialog,
+ * separately for each screen resolution. Call this once, e.g. in the
+ * constructor of the dialog; the size is restored and stored from then on.
+ *
+ * As long as no size has been stored, the dialog keeps the size its layout
+ * asks for.
+ */
+void KMM_BASE_WIDGETS_EXPORT keepDialogSize(QWidget* dialog);
}
#endif // KGUIUTILS_H