Qt: Fix centering of secondary windows

The window size may be incorrect in the constructor because layouting
hasn't happened yet. We need to wait until show() is called.
This commit is contained in:
Davide Pesavento
2025-11-24 14:01:52 -05:00
committed by Connor McLaughlin
parent f9ca1f2241
commit 63f929e6f8
20 changed files with 70 additions and 86 deletions

View File

@@ -90,8 +90,6 @@ AutoUpdaterWindow::AutoUpdaterWindow() : QWidget()
m_http = HTTPDownloader::Create(Host::GetHTTPUserAgent(), &error);
if (!m_http)
ERROR_LOG("Failed to create HTTP downloader, auto updater will not be available:\n{}", error.GetDescription());
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
AutoUpdaterWindow::~AutoUpdaterWindow() = default;

View File

@@ -102,12 +102,6 @@ ControllerSettingsWindow::ControllerSettingsWindow(INISettingsInterface* game_si
}
createWidgets();
if (isEditingGlobalSettings())
{
if (!QtUtils::RestoreWindowGeometry("ControllerSettingsWindow", this))
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
}
ControllerSettingsWindow::~ControllerSettingsWindow() = default;
@@ -117,7 +111,7 @@ void ControllerSettingsWindow::editControllerSettingsForGame(QWidget* parent, IN
ControllerSettingsWindow* dlg = new ControllerSettingsWindow(sif, false, parent);
dlg->setWindowFlag(Qt::Window);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setWindowModality(Qt::WindowModality::WindowModal);
dlg->setWindowModality(Qt::WindowModal);
dlg->setWindowTitle(parent->windowTitle());
dlg->setWindowIcon(parent->windowIcon());
dlg->show();
@@ -503,10 +497,10 @@ void ControllerSettingsWindow::createWidgets()
void ControllerSettingsWindow::closeEvent(QCloseEvent* event)
{
QWidget::closeEvent(event);
if (isEditingGlobalSettings())
QtUtils::SaveWindowGeometry("ControllerSettingsWindow", this);
QWidget::closeEvent(event);
}
void ControllerSettingsWindow::updateListDescription(u32 global_slot, ControllerBindingWidget* widget)

View File

@@ -15,7 +15,6 @@ CoverDownloadWindow::CoverDownloadWindow() : QWidget()
m_ui.setupUi(this);
m_ui.coverIcon->setPixmap(QIcon::fromTheme(QStringLiteral("artboard-2-line")).pixmap(32));
updateEnabled();
QtUtils::RestoreWindowGeometry("CoverDownloadWindow", this);
connect(m_ui.start, &QPushButton::clicked, this, &CoverDownloadWindow::onStartClicked);
connect(m_ui.close, &QPushButton::clicked, this, &CoverDownloadWindow::onCloseClicked);

View File

@@ -28,7 +28,7 @@ Q_SIGNALS:
void coverRefreshRequested();
protected:
void closeEvent(QCloseEvent* ev);
void closeEvent(QCloseEvent* ev) override;
private:
class CoverDownloadThread : public QtAsyncProgressThread

View File

@@ -455,9 +455,6 @@ void DebuggerWindow::setupAdditionalUi()
setCentralWidget(nullptr);
delete m_ui.centralwidget;
if (!QtUtils::RestoreWindowGeometry("DebuggerWindow", this))
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
void DebuggerWindow::connectSignals()

View File

@@ -31,7 +31,7 @@ Q_SIGNALS:
void closed();
protected:
void closeEvent(QCloseEvent* event);
void closeEvent(QCloseEvent* event) override;
private:
void setupAdditionalUi();

View File

@@ -40,8 +40,6 @@ ISOBrowserWindow::ISOBrowserWindow(QWidget* parent) : QWidget(parent)
connect(m_ui.fileView, &QTreeWidget::itemSelectionChanged, this, &ISOBrowserWindow::onFileItemSelectionChanged);
connect(m_ui.fileView, &QTreeWidget::customContextMenuRequested, this, &ISOBrowserWindow::onFileContextMenuRequested);
connect(m_ui.close, &QAbstractButton::clicked, this, &ISOBrowserWindow::close);
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
ISOBrowserWindow::~ISOBrowserWindow() = default;

View File

@@ -30,8 +30,8 @@ public:
static void populateFilterMenu(QMenu* menu);
protected:
void closeEvent(QCloseEvent* event);
void changeEvent(QEvent* event);
void closeEvent(QCloseEvent* event) override;
void changeEvent(QEvent* event) override;
private:
static constexpr int DEFAULT_WIDTH = 750;

View File

@@ -1661,6 +1661,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
{
ib->setAttribute(Qt::WA_DeleteOnClose);
ib->show();
QtUtils::CenterWindowRelativeToParent(ib, this);
}
});
}
@@ -2778,10 +2779,10 @@ SettingsWindow* MainWindow::getSettingsWindow()
void MainWindow::doSettings(const char* category /* = nullptr */)
{
SettingsWindow* dlg = getSettingsWindow();
QtUtils::ShowOrRaiseWindow(dlg);
SettingsWindow* window = getSettingsWindow();
QtUtils::ShowOrRaiseWindow(window, this, true);
if (category)
dlg->setCategory(category);
window->setCategory(category);
}
void MainWindow::openGamePropertiesForCurrentGame(const char* category /* = nullptr */)
@@ -2832,10 +2833,10 @@ MemoryEditorWindow* MainWindow::getMemoryEditorWindow()
void MainWindow::doControllerSettings(
ControllerSettingsWindow::Category category /*= ControllerSettingsDialog::Category::Count*/)
{
ControllerSettingsWindow* dlg = getControllerSettingsWindow();
QtUtils::ShowOrRaiseWindow(dlg);
ControllerSettingsWindow* window = getControllerSettingsWindow();
QtUtils::ShowOrRaiseWindow(window, this, true);
if (category != ControllerSettingsWindow::Category::Count)
dlg->setCategory(category);
window->setCategory(category);
}
void MainWindow::onViewChangeGameListBackgroundTriggered()
@@ -2868,7 +2869,7 @@ void MainWindow::onSettingsControllerProfilesTriggered()
if (!m_input_profile_editor_window)
m_input_profile_editor_window = new ControllerSettingsWindow(nullptr, true);
QtUtils::ShowOrRaiseWindow(m_input_profile_editor_window);
QtUtils::ShowOrRaiseWindow(m_input_profile_editor_window, this);
}
void MainWindow::openInputProfileEditor(const std::string_view name)
@@ -2876,7 +2877,7 @@ void MainWindow::openInputProfileEditor(const std::string_view name)
if (!m_input_profile_editor_window)
m_input_profile_editor_window = new ControllerSettingsWindow(nullptr, true);
QtUtils::ShowOrRaiseWindow(m_input_profile_editor_window);
QtUtils::ShowOrRaiseWindow(m_input_profile_editor_window, this);
m_input_profile_editor_window->switchProfile(name);
}
@@ -3205,7 +3206,7 @@ void MainWindow::openMemoryCardEditor(const QString& card_a_path, const QString&
if (!m_memory_card_editor_window)
m_memory_card_editor_window = new MemoryCardEditorWindow();
QtUtils::ShowOrRaiseWindow(m_memory_card_editor_window);
QtUtils::ShowOrRaiseWindow(m_memory_card_editor_window, this);
if (!card_a_path.isEmpty())
{
@@ -3333,7 +3334,7 @@ void MainWindow::onToolsCoverDownloaderTriggered()
});
}
QtUtils::ShowOrRaiseWindow(m_cover_download_window);
QtUtils::ShowOrRaiseWindow(m_cover_download_window, this, true);
}
void MainWindow::onToolsMediaCaptureToggled(bool checked)
@@ -3374,7 +3375,7 @@ void MainWindow::onToolsMemoryEditorTriggered()
if (s_achievements_hardcore_mode)
return;
QtUtils::ShowOrRaiseWindow(getMemoryEditorWindow());
QtUtils::ShowOrRaiseWindow(getMemoryEditorWindow(), this, true);
}
void MainWindow::onToolsMemoryScannerTriggered()
@@ -3391,7 +3392,7 @@ void MainWindow::onToolsMemoryScannerTriggered()
});
}
QtUtils::ShowOrRaiseWindow(m_memory_scanner_window);
QtUtils::ShowOrRaiseWindow(m_memory_scanner_window, this, true);
}
void MainWindow::onToolsISOBrowserTriggered()
@@ -3399,6 +3400,7 @@ void MainWindow::onToolsISOBrowserTriggered()
ISOBrowserWindow* ib = new ISOBrowserWindow();
ib->setAttribute(Qt::WA_DeleteOnClose);
ib->show();
QtUtils::CenterWindowRelativeToParent(ib, this);
}
void MainWindow::openCPUDebugger()
@@ -3415,7 +3417,7 @@ void MainWindow::openCPUDebugger()
});
}
QtUtils::ShowOrRaiseWindow(m_debugger_window);
QtUtils::ShowOrRaiseWindow(m_debugger_window, this, true);
}
void MainWindow::onToolsOpenDataDirectoryTriggered()
@@ -3466,7 +3468,7 @@ void MainWindow::checkForUpdates(bool display_message)
if (m_auto_updater_dialog)
{
QtUtils::ShowOrRaiseWindow(m_auto_updater_dialog);
QtUtils::ShowOrRaiseWindow(m_auto_updater_dialog, this);
return;
}

View File

@@ -174,8 +174,6 @@ MemoryCardEditorWindow::MemoryCardEditorWindow() : QWidget()
m_animation_timer = new QTimer(this);
m_animation_timer->setInterval(MEMORY_CARD_ICON_FRAME_DURATION_MS);
connect(m_animation_timer, &QTimer::timeout, this, &MemoryCardEditorWindow::incrementAnimationFrame);
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
MemoryCardEditorWindow::~MemoryCardEditorWindow() = default;
@@ -226,12 +224,7 @@ bool MemoryCardEditorWindow::createMemoryCard(const QString& path, Error* error)
bool MemoryCardEditorWindow::event(QEvent* event)
{
if (event->type() == QEvent::Close)
{
m_card_a.path_cb->setCurrentIndex(0);
m_card_b.path_cb->setCurrentIndex(0);
}
else if (event->type() == QEvent::DevicePixelRatioChange)
if (event->type() == QEvent::DevicePixelRatioChange)
{
const qreal dpr = QtUtils::GetDevicePixelRatioForWidget(this);
MemoryCardEditorIconStyleDelegate::getForView(m_card_a.table)->setDevicePixelRatio(dpr);
@@ -241,6 +234,14 @@ bool MemoryCardEditorWindow::event(QEvent* event)
return QWidget::event(event);
}
void MemoryCardEditorWindow::closeEvent(QCloseEvent* event)
{
m_card_a.path_cb->setCurrentIndex(0);
m_card_b.path_cb->setCurrentIndex(0);
QWidget::closeEvent(event);
}
void MemoryCardEditorWindow::createCardButtons(Card* card, QDialogButtonBox* buttonBox)
{
card->modified_icon_label->setPixmap(QIcon(QtHost::GetResourceQPath("images/warning.svg", true)).pixmap(16, 16));

View File

@@ -33,6 +33,7 @@ public:
protected:
bool event(QEvent* event) override;
void closeEvent(QCloseEvent* event) override;
private:
struct Card

View File

@@ -13,9 +13,6 @@
#include "common/assert.h"
#include "common/string_util.h"
#include <QtCore/QSignalBlocker>
#include <QtGui/QCursor>
#include <QtGui/QFontDatabase>
#include <QtGui/QShortcut>
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QFileDialog>
@@ -383,9 +380,6 @@ void MemoryEditorWindow::setupAdditionalUi()
const QFont& fixed_font = QtHost::GetFixedFont();
m_ui.memoryView->setFont(fixed_font);
if (!QtUtils::RestoreWindowGeometry("MemoryEditorWindow", this))
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
// Set minimum width for data inspector.
m_ui.dataInspectorAddress->setFont(fixed_font);
m_ui.dataInspectorUnsignedByte->setFont(fixed_font);

View File

@@ -27,7 +27,7 @@ Q_SIGNALS:
void closed();
protected:
void closeEvent(QCloseEvent* event);
void closeEvent(QCloseEvent* event) override;
private:
void setupAdditionalUi();

View File

@@ -22,6 +22,7 @@
#include "fmt/format.h"
#include <QtGui/QColor>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QTreeWidgetItemIterator>
#include <array>
@@ -101,8 +102,6 @@ void MemoryScannerWindow::setupAdditionalUi()
{
QtUtils::SetColumnWidthsForTableView(m_ui.scanTable, {-1, 100, 100, 100});
QtUtils::SetColumnWidthsForTableView(m_ui.watchTable, {-1, 100, 100, 150, 40});
if (!QtUtils::RestoreWindowGeometry("MemoryScannerWindow", this))
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
void MemoryScannerWindow::connectUi()
@@ -335,7 +334,8 @@ void MemoryScannerWindow::addManualWatchAddressClicked()
items.append(tr(title));
bool ok = false;
const QString selected_item = QInputDialog::getItem(this, windowTitle(), tr("Select data size:"), items, 0, false, &ok);
const QString selected_item =
QInputDialog::getItem(this, windowTitle(), tr("Select data size:"), items, 0, false, &ok);
const qsizetype index = items.indexOf(selected_item);
if (index < 0 || !ok)
return;
@@ -403,7 +403,7 @@ void MemoryScannerWindow::tryOpenAddressInMemoryEditor(VirtualMemoryAddress addr
return;
}
QtUtils::ShowOrRaiseWindow(editor);
QtUtils::ShowOrRaiseWindow(editor, g_main_window, true);
}
void MemoryScannerWindow::scanItemChanged(QTableWidgetItem* item)

View File

@@ -8,8 +8,6 @@
#include "core/memory_scanner.h"
#include <QtCore/QTimer>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QWidget>
@@ -27,7 +25,7 @@ Q_SIGNALS:
void closed();
protected:
void closeEvent(QCloseEvent* event);
void closeEvent(QCloseEvent* event) override;
private:
enum : int

View File

@@ -16,8 +16,8 @@ public:
using EditCallback = void (*)(size_t offset, size_t bytes);
MemoryViewWidget(QWidget* parent = nullptr, size_t address_offset = 0, void* data_ptr = nullptr, size_t data_size = 0,
bool data_editable = false, EditCallback edit_callback = nullptr);
explicit MemoryViewWidget(QWidget* parent = nullptr, size_t address_offset = 0, void* data_ptr = nullptr,
size_t data_size = 0, bool data_editable = false, EditCallback edit_callback = nullptr);
~MemoryViewWidget();
size_t addressOffset() const { return m_address_offset; }
@@ -39,11 +39,11 @@ Q_SIGNALS:
void selectedAddressChanged(size_t address);
protected:
void paintEvent(QPaintEvent* event);
void resizeEvent(QResizeEvent* event);
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent* event);
void paintEvent(QPaintEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
private:
int addressWidth() const;
@@ -82,4 +82,4 @@ private:
EditCallback m_edit_callback = nullptr;
std::vector<u8> m_last_data;
size_t m_last_data_start_offset = 0;
};
};

View File

@@ -84,14 +84,21 @@ QWidget* QtUtils::GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog)
return widget;
}
void QtUtils::ShowOrRaiseWindow(QWidget* window)
void QtUtils::ShowOrRaiseWindow(QWidget* window, const QWidget* parent_window, bool restore_geometry)
{
if (!window)
return;
if (!window->isVisible())
{
bool restored = false;
if (restore_geometry)
restored = RestoreWindowGeometry(window->metaObject()->className(), window);
window->show();
if (!restored && parent_window)
CenterWindowRelativeToParent(window, parent_window);
}
else
{
@@ -703,14 +710,14 @@ bool QtUtils::RestoreWindowGeometry(std::string_view window_name, QWidget* widge
return true;
}
void QtUtils::CenterWindowRelativeToParent(QWidget* window, QWidget* parent_window)
void QtUtils::CenterWindowRelativeToParent(QWidget* window, const QWidget* parent_window)
{
// la la la, this won't work on fucking wankland, I don't care, it'll appear in the top-left
// corner of the screen or whatever, shit experience is shit
const QRect parent_geometry = (parent_window && parent_window->isVisible()) ?
parent_window->geometry() :
QGuiApplication::primaryScreen()->availableGeometry();
const QRect& parent_geometry = (parent_window && parent_window->isVisible()) ?
parent_window->geometry() :
QGuiApplication::primaryScreen()->availableGeometry();
const QPoint parent_center_pos = parent_geometry.center();
QRect window_geometry = window->geometry();

View File

@@ -54,7 +54,8 @@ QFrame* CreateHorizontalLine(QWidget* parent);
QWidget* GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog = true);
/// Shows or raises a window (brings it to the front).
void ShowOrRaiseWindow(QWidget* window);
/// If the window was hidden and parent_window is provided, the window is centered on parent_window.
void ShowOrRaiseWindow(QWidget* window, const QWidget* parent_window = nullptr, bool restore_geometry = false);
/// Closes and deletes a window later, outside of this event pump.
template<typename T>
@@ -174,7 +175,7 @@ void SaveWindowGeometry(std::string_view window_name, QWidget* widget, bool auto
bool RestoreWindowGeometry(std::string_view window_name, QWidget* widget);
/// Positions a window in the center of its parent or the screen.
void CenterWindowRelativeToParent(QWidget* window, QWidget* parent_window);
void CenterWindowRelativeToParent(QWidget* window, const QWidget* parent_window);
/// CPU-friendly way of blocking the UI thread while some predicate holds true.
template<typename Predicate>

View File

@@ -46,9 +46,6 @@ SettingsWindow::SettingsWindow() : QWidget()
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
addPages();
connectUi();
if (!QtUtils::RestoreWindowGeometry("SettingsWindow", this))
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
SettingsWindow::SettingsWindow(const GameList::Entry* entry, std::unique_ptr<INISettingsInterface> sif)
@@ -56,6 +53,7 @@ SettingsWindow::SettingsWindow(const GameList::Entry* entry, std::unique_ptr<INI
m_hash(entry->hash)
{
m_ui.setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
if (const QIcon icon = g_main_window->getIconForGame(QString::fromStdString(entry->path)); !icon.isNull())
setWindowIcon(icon);
@@ -71,8 +69,6 @@ SettingsWindow::SettingsWindow(const GameList::Entry* entry, std::unique_ptr<INI
connectUi();
s_open_game_properties_dialogs.push_back(this);
QtUtils::CenterWindowRelativeToParent(this, g_main_window);
}
SettingsWindow::~SettingsWindow()
@@ -83,11 +79,10 @@ SettingsWindow::~SettingsWindow()
void SettingsWindow::closeEvent(QCloseEvent* event)
{
// we need to clean up ourselves, since we're not modal
if (isPerGameSettings())
deleteLater();
else
if (!isPerGameSettings())
QtUtils::SaveWindowGeometry("SettingsWindow", this);
QWidget::closeEvent(event);
}
void SettingsWindow::addPages()
@@ -705,10 +700,7 @@ SettingsWindow* SettingsWindow::openGamePropertiesDialog(const GameList::Entry*
void SettingsWindow::closeGamePropertiesDialogs()
{
for (SettingsWindow* dialog : s_open_game_properties_dialogs)
{
dialog->close();
dialog->deleteLater();
}
}
bool SettingsWindow::setGameSettingsBoolForSerial(const std::string& serial, const char* section, const char* key,

View File

@@ -10,7 +10,7 @@
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtWidgets/QDialog>
#include <QtWidgets/QWidget>
#include <array>
#include <optional>
@@ -49,7 +49,6 @@ class SettingsWindow final : public QWidget
public:
SettingsWindow();
SettingsWindow(const GameList::Entry* entry, std::unique_ptr<INISettingsInterface> sif);
~SettingsWindow();
static SettingsWindow* openGamePropertiesDialog(const GameList::Entry* entry, const char* category = nullptr);
@@ -126,6 +125,9 @@ private:
MAX_SETTINGS_WIDGETS = 13
};
// Private constructor used by openGamePropertiesDialog()
SettingsWindow(const GameList::Entry* entry, std::unique_ptr<INISettingsInterface> sif);
void connectUi();
void addPages();
void reloadPages();