From 2367903ac6c6f6778935ed1bbab88fd8342dffa0 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 19 Nov 2022 11:55:40 -0300 Subject: [PATCH 1/6] refactor: clean up WideBar a bit Signed-off-by: flow --- launcher/ui/widgets/WideBar.cpp | 130 +++++++++++++++----------------- launcher/ui/widgets/WideBar.h | 15 ++-- 2 files changed, 68 insertions(+), 77 deletions(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 79f1e0c96..ed5c5bc86 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -1,19 +1,21 @@ #include "WideBar.h" #include -#include -class ActionButton : public QToolButton -{ +class ActionButton : public QToolButton { Q_OBJECT -public: - ActionButton(QAction * action, QWidget * parent = 0) : QToolButton(parent), m_action(action) { + public: + ActionButton(QAction* action, QWidget* parent = nullptr) : QToolButton(parent), m_action(action) + { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + connect(action, &QAction::changed, this, &ActionButton::actionChanged); connect(this, &ActionButton::clicked, action, &QAction::trigger); + actionChanged(); }; -private slots: - void actionChanged() { + private slots: + void actionChanged() + { setEnabled(m_action->isEnabled()); setChecked(m_action->isChecked()); setCheckable(m_action->isCheckable()); @@ -23,10 +25,10 @@ private slots: setHidden(!m_action->isVisible()); setFocusPolicy(Qt::NoFocus); } -private: - QAction * m_action; -}; + private: + QAction* m_action; +}; WideBar::WideBar(const QString& title, QWidget* parent) : QToolBar(title, parent) { @@ -40,116 +42,102 @@ WideBar::WideBar(QWidget* parent) : QToolBar(parent) setMovable(false); } -struct WideBar::BarEntry { - enum Type { - None, - Action, - Separator, - Spacer - } type = None; - QAction *qAction = nullptr; - QAction *wideAction = nullptr; -}; - - -WideBar::~WideBar() -{ - for(auto *iter: m_entries) { - delete iter; - } -} - void WideBar::addAction(QAction* action) { - auto entry = new BarEntry(); - entry->qAction = addWidget(new ActionButton(action, this)); - entry->wideAction = action; - entry->type = BarEntry::Action; + BarEntry entry; + entry.bar_action = addWidget(new ActionButton(action, this)); + entry.menu_action = action; + entry.type = BarEntry::Type::Action; + m_entries.push_back(entry); } void WideBar::addSeparator() { - auto entry = new BarEntry(); - entry->qAction = QToolBar::addSeparator(); - entry->type = BarEntry::Separator; + BarEntry entry; + entry.bar_action = QToolBar::addSeparator(); + entry.type = BarEntry::Type::Separator; + m_entries.push_back(entry); } -auto WideBar::getMatching(QAction* act) -> QList::iterator +auto WideBar::getMatching(QAction* act) -> QList::iterator { - auto iter = std::find_if(m_entries.begin(), m_entries.end(), [act](BarEntry * entry) { - return entry->wideAction == act; - }); - + auto iter = std::find_if(m_entries.begin(), m_entries.end(), [act](BarEntry const& entry) { return entry.menu_action == act; }); + return iter; } -void WideBar::insertActionBefore(QAction* before, QAction* action){ +void WideBar::insertActionBefore(QAction* before, QAction* action) +{ auto iter = getMatching(before); - if(iter == m_entries.end()) + if (iter == m_entries.end()) return; - auto entry = new BarEntry(); - entry->qAction = insertWidget((*iter)->qAction, new ActionButton(action, this)); - entry->wideAction = action; - entry->type = BarEntry::Action; + BarEntry entry; + entry.bar_action = insertWidget(iter->bar_action, new ActionButton(action, this)); + entry.menu_action = action; + entry.type = BarEntry::Type::Action; + m_entries.insert(iter, entry); } -void WideBar::insertActionAfter(QAction* after, QAction* action){ +void WideBar::insertActionAfter(QAction* after, QAction* action) +{ auto iter = getMatching(after); - if(iter == m_entries.end()) + if (iter == m_entries.end()) return; - auto entry = new BarEntry(); - entry->qAction = insertWidget((*(iter+1))->qAction, new ActionButton(action, this)); - entry->wideAction = action; - entry->type = BarEntry::Action; + BarEntry entry; + entry.bar_action = insertWidget((iter + 1)->bar_action, new ActionButton(action, this)); + entry.menu_action = action; + entry.type = BarEntry::Type::Action; + m_entries.insert(iter + 1, entry); } void WideBar::insertSpacer(QAction* action) { auto iter = getMatching(action); - if(iter == m_entries.end()) + if (iter == m_entries.end()) return; - QWidget* spacer = new QWidget(); + auto* spacer = new QWidget(); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - auto entry = new BarEntry(); - entry->qAction = insertWidget((*iter)->qAction, spacer); - entry->type = BarEntry::Spacer; + BarEntry entry; + entry.bar_action = insertWidget(iter->bar_action, spacer); + entry.type = BarEntry::Type::Spacer; m_entries.insert(iter, entry); } void WideBar::insertSeparator(QAction* before) { auto iter = getMatching(before); - if(iter == m_entries.end()) + if (iter == m_entries.end()) return; - auto entry = new BarEntry(); - entry->qAction = QToolBar::insertSeparator(before); - entry->type = BarEntry::Separator; + BarEntry entry; + entry.bar_action = QToolBar::insertSeparator(before); + entry.type = BarEntry::Type::Separator; + m_entries.insert(iter, entry); } -QMenu * WideBar::createContextMenu(QWidget *parent, const QString & title) +QMenu* WideBar::createContextMenu(QWidget* parent, const QString& title) { - QMenu *contextMenu = new QMenu(title, parent); - for(auto & item: m_entries) { - switch(item->type) { + auto* contextMenu = new QMenu(title, parent); + for (auto& item : m_entries) { + switch (item.type) { default: - case BarEntry::None: + case BarEntry::Type::None: break; - case BarEntry::Separator: - case BarEntry::Spacer: + case BarEntry::Type::Separator: + case BarEntry::Type::Spacer: contextMenu->addSeparator(); break; - case BarEntry::Action: - contextMenu->addAction(item->wideAction); + case BarEntry::Type::Action: + contextMenu->addAction(item.menu_action); break; } } diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 8ff62ef24..4a714c80c 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -2,17 +2,16 @@ #include #include +#include #include -class QMenu; - class WideBar : public QToolBar { Q_OBJECT public: explicit WideBar(const QString& title, QWidget* parent = nullptr); explicit WideBar(QWidget* parent = nullptr); - virtual ~WideBar(); + ~WideBar() override = default; void addAction(QAction* action); void addSeparator(); @@ -25,10 +24,14 @@ class WideBar : public QToolBar { QMenu* createContextMenu(QWidget* parent = nullptr, const QString& title = QString()); private: - struct BarEntry; + struct BarEntry { + enum class Type { None, Action, Separator, Spacer } type = Type::None; + QAction* bar_action = nullptr; + QAction* menu_action = nullptr; + }; - auto getMatching(QAction* act) -> QList::iterator; + auto getMatching(QAction* act) -> QList::iterator; private: - QList m_entries; + QList m_entries; }; From 6e1639551bbe98b32e9abef2d816e8abe01789e4 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 19 Nov 2022 13:39:43 -0300 Subject: [PATCH 2/6] feat(WideBar): allow hiding buttons with right-click Signed-off-by: flow --- launcher/ui/widgets/WideBar.cpp | 58 ++++++++++++++++++++++++++++++++- launcher/ui/widgets/WideBar.h | 7 ++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ed5c5bc86..ed7dc5fa0 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -1,4 +1,6 @@ #include "WideBar.h" + +#include #include class ActionButton : public QToolButton { @@ -13,7 +15,7 @@ class ActionButton : public QToolButton { actionChanged(); }; - private slots: + public slots: void actionChanged() { setEnabled(m_action->isEnabled()); @@ -34,12 +36,16 @@ WideBar::WideBar(const QString& title, QWidget* parent) : QToolBar(title, parent { setFloatable(false); setMovable(false); + + m_bar_menu = std::make_unique(this); } WideBar::WideBar(QWidget* parent) : QToolBar(parent) { setFloatable(false); setMovable(false); + + m_bar_menu = std::make_unique(this); } void WideBar::addAction(QAction* action) @@ -50,6 +56,8 @@ void WideBar::addAction(QAction* action) entry.type = BarEntry::Type::Action; m_entries.push_back(entry); + + m_menu_state = MenuState::Dirty; } void WideBar::addSeparator() @@ -80,6 +88,8 @@ void WideBar::insertActionBefore(QAction* before, QAction* action) entry.type = BarEntry::Type::Action; m_entries.insert(iter, entry); + + m_menu_state = MenuState::Dirty; } void WideBar::insertActionAfter(QAction* after, QAction* action) @@ -94,6 +104,8 @@ void WideBar::insertActionAfter(QAction* after, QAction* action) entry.type = BarEntry::Type::Action; m_entries.insert(iter + 1, entry); + + m_menu_state = MenuState::Dirty; } void WideBar::insertSpacer(QAction* action) @@ -144,4 +156,48 @@ QMenu* WideBar::createContextMenu(QWidget* parent, const QString& title) return contextMenu; } +static void copyAction(QAction* from, QAction* to) +{ + Q_ASSERT(from); + Q_ASSERT(to); + + to->setText(from->text()); + to->setIcon(from->icon()); + to->setToolTip(from->toolTip()); +} + +void WideBar::contextMenuEvent(QContextMenuEvent* event) +{ + if (m_menu_state == MenuState::Dirty) { + for (auto* old_action : m_bar_menu->actions()) + old_action->deleteLater(); + + m_bar_menu->clear(); + + for (auto& entry : m_entries) { + if (entry.type != BarEntry::Type::Action) + continue; + + auto act = new QAction(); + copyAction(entry.menu_action, act); + + act->setCheckable(true); + act->setChecked(entry.bar_action->isVisible()); + + connect(act, &QAction::toggled, entry.bar_action, [this, &entry](bool toggled){ + entry.bar_action->setVisible(toggled); + + // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. + static_cast(widgetForAction(entry.bar_action))->actionChanged(); + }); + + m_bar_menu->addAction(act); + } + + m_menu_state = MenuState::Fresh; + } + + m_bar_menu->popup(event->globalPos()); +} + #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 4a714c80c..8421eaf4b 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -5,6 +5,8 @@ #include #include +#include + class WideBar : public QToolBar { Q_OBJECT @@ -22,6 +24,7 @@ class WideBar : public QToolBar { void insertActionAfter(QAction* after, QAction* action); QMenu* createContextMenu(QWidget* parent = nullptr, const QString& title = QString()); + void contextMenuEvent(QContextMenuEvent*) override; private: struct BarEntry { @@ -34,4 +37,8 @@ class WideBar : public QToolBar { private: QList m_entries; + + // Menu to toggle visibility from buttons in the bar + std::unique_ptr m_bar_menu = nullptr; + enum class MenuState { Fresh, Dirty } m_menu_state = MenuState::Dirty; }; From 479843f56b42d7044d3d02278a9cabc2c24e147a Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 19 Nov 2022 17:10:43 -0300 Subject: [PATCH 3/6] feat(WideBar): allow loading/unloading visibility via a byte array I really wanted to use a QBitArray :c Signed-off-by: flow --- launcher/ui/widgets/WideBar.cpp | 30 ++++++++++++++++++++++++++++++ launcher/ui/widgets/WideBar.h | 6 ++++++ 2 files changed, 36 insertions(+) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ed7dc5fa0..2ad2caec7 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -200,4 +200,34 @@ void WideBar::contextMenuEvent(QContextMenuEvent* event) m_bar_menu->popup(event->globalPos()); } +[[nodiscard]] QByteArray WideBar::getVisibilityState() const +{ + QByteArray state; + + for (auto const& entry : m_entries) { + if (entry.type != BarEntry::Type::Action) + continue; + + state.append(entry.bar_action->isVisible() ? '1' : '0'); + } + + return state; +} + +void WideBar::setVisibilityState(QByteArray&& state) +{ + qsizetype i = 0; + for (auto& entry : m_entries) { + if (entry.type != BarEntry::Type::Action) + continue; + if (i == state.size()) + break; + + entry.bar_action->setVisible(state.at(i++) == '1'); + + // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. + static_cast(widgetForAction(entry.bar_action))->actionChanged(); + } +} + #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 8421eaf4b..0d60f8a4a 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -26,6 +26,12 @@ class WideBar : public QToolBar { QMenu* createContextMenu(QWidget* parent = nullptr, const QString& title = QString()); void contextMenuEvent(QContextMenuEvent*) override; + // Ideally we would use a QBitArray for this, but it doesn't support string conversion, + // so using it in settings is very messy. + + [[nodiscard]] QByteArray getVisibilityState() const; + void setVisibilityState(QByteArray&&); + private: struct BarEntry { enum class Type { None, Action, Separator, Spacer } type = Type::None; From 2d69d63efe12a1cfaf391a59cb6b7630a436410e Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 19 Nov 2022 17:12:31 -0300 Subject: [PATCH 4/6] feat(InstancePages): save/load wide bar visibility settings Signed-off-by: flow --- .../ui/pages/instance/ExternalResourcesPage.cpp | 10 ++++++++++ .../ui/pages/instance/ExternalResourcesPage.h | 3 +++ launcher/ui/pages/instance/ScreenshotsPage.cpp | 13 +++++++++++++ launcher/ui/pages/instance/ScreenshotsPage.h | 7 ++++++- launcher/ui/pages/instance/ServersPage.cpp | 10 ++++++++++ launcher/ui/pages/instance/ServersPage.h | 4 ++++ launcher/ui/pages/instance/VersionPage.cpp | 15 +++++++++++++++ launcher/ui/pages/instance/VersionPage.h | 5 +++++ launcher/ui/pages/instance/WorldListPage.cpp | 10 ++++++++++ launcher/ui/pages/instance/WorldListPage.h | 4 ++++ 10 files changed, 80 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index b6c873cc2..381fa30cc 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -70,11 +70,21 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos) void ExternalResourcesPage::openedImpl() { m_model->startWatching(); + + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); + if (!APPLICATION->settings()->contains(setting_name)) + m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); + else + m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); + + ui->actionsToolbar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); } void ExternalResourcesPage::closedImpl() { m_model->stopWatching(); + + m_wide_bar_setting->set(ui->actionsToolbar->getVisibilityState()); } void ExternalResourcesPage::retranslate() diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index 8e352cef9..b816e742a 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -4,6 +4,7 @@ #include #include "Application.h" +#include "settings/Setting.h" #include "minecraft/MinecraftInstance.h" #include "ui/pages/BasePage.h" @@ -71,4 +72,6 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { QString m_viewFilter; bool m_controlsEnabled = true; + + std::shared_ptr m_wide_bar_setting = nullptr; }; diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index c97253e4b..0092aef33 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -537,6 +537,19 @@ void ScreenshotsPage::openedImpl() ui->listView->setModel(nullptr); } } + + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); + if (!APPLICATION->settings()->contains(setting_name)) + m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); + else + m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); + + ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); +} + +void ScreenshotsPage::closedImpl() +{ + m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); } #include "ScreenshotsPage.moc" diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h index c22706af9..2eb0de04f 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.h +++ b/launcher/ui/pages/instance/ScreenshotsPage.h @@ -40,6 +40,8 @@ #include "ui/pages/BasePage.h" #include +#include "settings/Setting.h" + class QFileSystemModel; class QIdentityProxyModel; namespace Ui @@ -59,7 +61,8 @@ public: explicit ScreenshotsPage(QString path, QWidget *parent = 0); virtual ~ScreenshotsPage(); - virtual void openedImpl() override; + void openedImpl() override; + void closedImpl() override; enum { @@ -110,4 +113,6 @@ private: QString m_folder; bool m_valid = false; bool m_uploadActive = false; + + std::shared_ptr m_wide_bar_setting = nullptr; }; diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index d64bcb767..a625e20b6 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -765,11 +765,21 @@ void ServersPage::updateState() void ServersPage::openedImpl() { m_model->observe(); + + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); + if (!APPLICATION->settings()->contains(setting_name)) + m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); + else + m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); + + ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); } void ServersPage::closedImpl() { m_model->unobserve(); + + m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); } void ServersPage::on_actionAdd_triggered() diff --git a/launcher/ui/pages/instance/ServersPage.h b/launcher/ui/pages/instance/ServersPage.h index 37399d49f..548d4d1b1 100644 --- a/launcher/ui/pages/instance/ServersPage.h +++ b/launcher/ui/pages/instance/ServersPage.h @@ -42,6 +42,8 @@ #include "ui/pages/BasePage.h" #include +#include "settings/Setting.h" + namespace Ui { class ServersPage; @@ -112,5 +114,7 @@ private: // data Ui::ServersPage *ui = nullptr; ServersModel * m_model = nullptr; InstancePtr m_inst = nullptr; + + std::shared_ptr m_wide_bar_setting = nullptr; }; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index a021c633f..84052f373 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -125,6 +125,21 @@ void VersionPage::retranslate() ui->retranslateUi(this); } +void VersionPage::openedImpl() +{ + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); + if (!APPLICATION->settings()->contains(setting_name)) + m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); + else + m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); + + ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); +} +void VersionPage::closedImpl() +{ + m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); +} + QMenu * VersionPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index 979311fcf..9996e7763 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -69,6 +69,9 @@ public: virtual bool shouldDisplay() const override; void retranslate() override; + void openedImpl() override; + void closedImpl() override; + private slots: void on_actionChange_version_triggered(); void on_actionInstall_Forge_triggered(); @@ -114,6 +117,8 @@ private: int currentIdx = 0; bool controlsEnabled = false; + std::shared_ptr m_wide_bar_setting = nullptr; + public slots: void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 85cc01ff0..93458ce4f 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -113,11 +113,21 @@ WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr worl void WorldListPage::openedImpl() { m_worlds->startWatching(); + + auto const setting_name = QString("WideBarVisibility_%1").arg(id()); + if (!APPLICATION->settings()->contains(setting_name)) + m_wide_bar_setting = APPLICATION->settings()->registerSetting(setting_name); + else + m_wide_bar_setting = APPLICATION->settings()->getSetting(setting_name); + + ui->toolBar->setVisibilityState(m_wide_bar_setting->get().toByteArray()); } void WorldListPage::closedImpl() { m_worlds->stopWatching(); + + m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); } WorldListPage::~WorldListPage() diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index 1dc9e53e0..925521bec 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -42,6 +42,8 @@ #include #include +#include "settings/Setting.h" + class WorldList; namespace Ui { @@ -102,6 +104,8 @@ private: unique_qobject_ptr m_mceditProcess; bool m_mceditStarting = false; + std::shared_ptr m_wide_bar_setting = nullptr; + private slots: void on_actionCopy_Seed_triggered(); void on_actionMCEdit_triggered(); From 20c281d6f8d5f25573a8c4c930a961ea9ab45380 Mon Sep 17 00:00:00 2001 From: flow Date: Tue, 22 Nov 2022 14:30:54 -0300 Subject: [PATCH 5/6] fix: reset wide bar settings when the list of actions changes This prevents changes to the actions to cause non-intuitive issues in the Wide bar, hiding items that previously weren't hidden. Signed-off-by: flow --- launcher/ui/widgets/WideBar.cpp | 35 +++++++++++++++++++++++++++++++-- launcher/ui/widgets/WideBar.h | 4 ++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 2ad2caec7..81c445cb1 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -1,6 +1,7 @@ #include "WideBar.h" #include +#include #include class ActionButton : public QToolButton { @@ -211,23 +212,53 @@ void WideBar::contextMenuEvent(QContextMenuEvent* event) state.append(entry.bar_action->isVisible() ? '1' : '0'); } + state.append(','); + state.append(getHash()); + return state; } void WideBar::setVisibilityState(QByteArray&& state) { + auto split = state.split(','); + + auto bits = split.first(); + auto hash = split.last(); + + // If the actions changed, we better not try to load the old one to avoid unwanted hiding + if (!checkHash(hash)) + return; + qsizetype i = 0; for (auto& entry : m_entries) { if (entry.type != BarEntry::Type::Action) continue; - if (i == state.size()) + if (i == bits.size()) break; - entry.bar_action->setVisible(state.at(i++) == '1'); + entry.bar_action->setVisible(bits.at(i++) == '1'); // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. static_cast(widgetForAction(entry.bar_action))->actionChanged(); } } +QByteArray WideBar::getHash() const +{ + QCryptographicHash hash(QCryptographicHash::Sha1); + for (auto const& entry : m_entries) { + if (entry.type != BarEntry::Type::Action) + continue; + hash.addData(entry.menu_action->text().toLatin1()); + } + + return hash.result().toBase64(); +} + +bool WideBar::checkHash(QByteArray const& old_hash) const +{ + return old_hash == getHash(); +} + + #include "WideBar.moc" diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index 0d60f8a4a..ed4cb3c71 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -41,6 +41,10 @@ class WideBar : public QToolBar { auto getMatching(QAction* act) -> QList::iterator; + /** Used to distinguish between versions of the WideBar with different actions */ + [[nodiscard]] QByteArray getHash() const; + [[nodiscard]] bool checkHash(QByteArray const&) const; + private: QList m_entries; From 4a1d08261408b63308dc1164c687e53c4f1fd08e Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 25 Nov 2022 09:33:05 -0300 Subject: [PATCH 6/6] reafctor(WideBar): connect to signal instead of overriding menu method This makes stuff more standard and closer to what we do in other places in the codebase. Signed-off-by: flow --- launcher/ui/widgets/WideBar.cpp | 13 +++++++++---- launcher/ui/widgets/WideBar.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 81c445cb1..428be563b 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -38,7 +38,8 @@ WideBar::WideBar(const QString& title, QWidget* parent) : QToolBar(title, parent setFloatable(false); setMovable(false); - m_bar_menu = std::make_unique(this); + setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + connect(this, &QToolBar::customContextMenuRequested, this, &WideBar::showVisibilityMenu); } WideBar::WideBar(QWidget* parent) : QToolBar(parent) @@ -46,7 +47,8 @@ WideBar::WideBar(QWidget* parent) : QToolBar(parent) setFloatable(false); setMovable(false); - m_bar_menu = std::make_unique(this); + setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + connect(this, &QToolBar::customContextMenuRequested, this, &WideBar::showVisibilityMenu); } void WideBar::addAction(QAction* action) @@ -167,8 +169,11 @@ static void copyAction(QAction* from, QAction* to) to->setToolTip(from->toolTip()); } -void WideBar::contextMenuEvent(QContextMenuEvent* event) +void WideBar::showVisibilityMenu(QPoint const& position) { + if (!m_bar_menu) + m_bar_menu = std::make_unique(this); + if (m_menu_state == MenuState::Dirty) { for (auto* old_action : m_bar_menu->actions()) old_action->deleteLater(); @@ -198,7 +203,7 @@ void WideBar::contextMenuEvent(QContextMenuEvent* event) m_menu_state = MenuState::Fresh; } - m_bar_menu->popup(event->globalPos()); + m_bar_menu->popup(mapToGlobal(position)); } [[nodiscard]] QByteArray WideBar::getVisibilityState() const diff --git a/launcher/ui/widgets/WideBar.h b/launcher/ui/widgets/WideBar.h index ed4cb3c71..a0a7896cb 100644 --- a/launcher/ui/widgets/WideBar.h +++ b/launcher/ui/widgets/WideBar.h @@ -24,7 +24,7 @@ class WideBar : public QToolBar { void insertActionAfter(QAction* after, QAction* action); QMenu* createContextMenu(QWidget* parent = nullptr, const QString& title = QString()); - void contextMenuEvent(QContextMenuEvent*) override; + void showVisibilityMenu(const QPoint&); // Ideally we would use a QBitArray for this, but it doesn't support string conversion, // so using it in settings is very messy.