From 80bff48c2b4b3876b97528558ee97419848e581f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 14 Dec 2021 00:31:55 +0600 Subject: [PATCH] Status bar improvements * Fix crashes on non-continuous floppy/CD-ROM/ZIP/MO media lists * Status bar icons should now display tooltips and trigger loading menus --- src/qt/qt_machinestatus.cpp | 90 ++++++++++++++++++++++++++++++++++--- src/qt/qt_machinestatus.hpp | 19 ++++++++ src/qt/qt_mainwindow.cpp | 6 ++- src/qt/qt_mainwindow.hpp | 1 + src/qt/qt_mediamenu.cpp | 38 ++++++++-------- src/qt/qt_mediamenu.hpp | 13 +++--- src/qt/qt_ui.cpp | 2 +- 7 files changed, 136 insertions(+), 33 deletions(-) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index a3aad56a4..377eb3517 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -28,9 +28,16 @@ extern uint64_t tsc; #include #include #include +#include + +#include "qt_mediamenu.hpp" +#include "qt_mainwindow.hpp" +#include "qt_soundgain.hpp" #include +extern MainWindow* main_window; + namespace { struct PixmapSetActive { QPixmap normal; @@ -195,7 +202,7 @@ struct MachineStatus::States { std::array mo; std::array hdds; StateActive net; - std::unique_ptr sound; + std::unique_ptr sound; std::unique_ptr text; }; @@ -330,8 +337,12 @@ void MachineStatus::refresh(QStatusBar* sbar) { sbar->removeWidget(d->sound.get()); if (cassette_enable) { - d->cassette.label = std::make_unique(); + d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); + connect((ClickableLabel*)d->cassette.label.get(), &ClickableLabel::clicked, [this](QPoint pos) { + MediaMenu::ptr->cassetteMenu->popup(pos); + }); + d->cassette.label->setToolTip(MediaMenu::ptr->cassetteMenu->title()); sbar->addWidget(d->cassette.label.get()); } @@ -339,6 +350,10 @@ void MachineStatus::refresh(QStatusBar* sbar) { for (int i = 0; i < 2; ++i) { d->cartridge[i].label = std::make_unique(); d->cartridge[i].setEmpty(QString(cart_fns[i]).isEmpty()); + connect((ClickableLabel*)d->cartridge[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + MediaMenu::ptr->cartridgeMenus[i]->popup(pos); + }); + d->cartridge[i].label->setToolTip(MediaMenu::ptr->cartridgeMenus[i]->title()); sbar->addWidget(d->cartridge[i].label.get()); } } @@ -352,30 +367,46 @@ void MachineStatus::refresh(QStatusBar* sbar) { } else { d->fdd[i].pixmaps = &d->pixmaps.floppy_35; } - d->fdd[i].label = std::make_unique(); + d->fdd[i].label = std::make_unique(); d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); d->fdd[i].setActive(false); + connect((ClickableLabel*)d->fdd[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + MediaMenu::ptr->floppyMenus[i]->popup(pos); + }); + d->fdd[i].label->setToolTip(MediaMenu::ptr->floppyMenus[i]->title()); sbar->addWidget(d->fdd[i].label.get()); }); iterateCDROM([this, sbar](int i) { - d->cdrom[i].label = std::make_unique(); + d->cdrom[i].label = std::make_unique(); d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty()); d->cdrom[i].setActive(false); + connect((ClickableLabel*)d->cdrom[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + MediaMenu::ptr->cdromMenus[i]->popup(pos); + }); + d->cdrom[i].label->setToolTip(MediaMenu::ptr->cdromMenus[i]->title()); sbar->addWidget(d->cdrom[i].label.get()); }); iterateZIP([this, sbar](int i) { - d->zip[i].label = std::make_unique(); + d->zip[i].label = std::make_unique(); d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); d->zip[i].setActive(false); + connect((ClickableLabel*)d->zip[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + MediaMenu::ptr->zipMenus[i]->popup(pos); + }); + d->zip[i].label->setToolTip(MediaMenu::ptr->zipMenus[i]->title()); sbar->addWidget(d->zip[i].label.get()); }); iterateMO([this, sbar](int i) { - d->mo[i].label = std::make_unique(); + d->mo[i].label = std::make_unique(); d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); d->mo[i].setActive(false); + connect((ClickableLabel*)d->mo[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + MediaMenu::ptr->moMenus[i]->popup(pos); + }); + d->mo[i].label->setToolTip(MediaMenu::ptr->moMenus[i]->title()); sbar->addWidget(d->mo[i].label.get()); }); @@ -383,37 +414,49 @@ void MachineStatus::refresh(QStatusBar* sbar) { if ((has_mfm || hdc_name == QStringLiteral("st506")) && c_mfm > 0) { d->hdds[HDD_BUS_MFM].label = std::make_unique(); d->hdds[HDD_BUS_MFM].setActive(false); + d->hdds[HDD_BUS_MFM].label->setToolTip(QStringLiteral("Hard Disk (%1)").arg("MFM/RLL")); sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get()); } if ((has_esdi || hdc_name == QStringLiteral("esdi")) && c_esdi > 0) { d->hdds[HDD_BUS_ESDI].label = std::make_unique(); d->hdds[HDD_BUS_ESDI].setActive(false); + d->hdds[HDD_BUS_ESDI].label->setToolTip(QStringLiteral("Hard Disk (%1)").arg("ESDI")); sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get()); } if ((has_xta || hdc_name == QStringLiteral("xta")) && c_xta > 0) { d->hdds[HDD_BUS_XTA].label = std::make_unique(); d->hdds[HDD_BUS_XTA].setActive(false); + d->hdds[HDD_BUS_XTA].label->setToolTip(QStringLiteral("Hard Disk (%1)").arg("XTA")); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } if ((hasIDE() || hdc_name == QStringLiteral("xtide") || hdc_name == QStringLiteral("ide")) && c_ide > 0) { d->hdds[HDD_BUS_IDE].label = std::make_unique(); d->hdds[HDD_BUS_IDE].setActive(false); + d->hdds[HDD_BUS_IDE].label->setToolTip(QStringLiteral("Hard Disk (%1)").arg("IDE")); sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); } if ((hasSCSI() || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) { d->hdds[HDD_BUS_SCSI].label = std::make_unique(); d->hdds[HDD_BUS_SCSI].setActive(false); + d->hdds[HDD_BUS_SCSI].label->setToolTip(QStringLiteral("Hard Disk (%1)").arg("SCSI")); sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get()); } if (do_net) { d->net.label = std::make_unique(); d->net.setActive(false); + d->net.label->setToolTip("Network"); sbar->addWidget(d->net.label.get()); } - d->sound = std::make_unique(); + d->sound = std::make_unique(); d->sound->setPixmap(d->pixmaps.sound); + // Triggering on click makes the mouse move the window when the button is releases. Do it on button release instead. + connect(d->sound.get(), &ClickableLabel::clickedRelease, d->sound.get(), [this](QPoint pos) { + SoundGain gain(main_window); + gain.exec(); + }); + d->sound->setToolTip("Sound"); sbar->addWidget(d->sound.get()); d->text = std::make_unique(); sbar->addWidget(d->text.get()); @@ -489,3 +532,36 @@ void MachineStatus::message(const QString &msg) { d->text->setText(msg); } +void MachineStatus::updateTip(int tag) +{ + int category = tag & 0xfffffff0; + int item = tag & 0xf; + switch (category) { + case SB_CASSETTE: + d->cassette.label->setToolTip(MediaMenu::ptr->cassetteMenu->title()); + break; + case SB_CARTRIDGE: + d->cartridge[item].label->setToolTip(MediaMenu::ptr->cartridgeMenus[item]->title()); + break; + case SB_FLOPPY: + d->fdd[item].label->setToolTip(MediaMenu::ptr->floppyMenus[item]->title()); + break; + case SB_CDROM: + d->cdrom[item].label->setToolTip(MediaMenu::ptr->cdromMenus[item]->title()); + break; + case SB_ZIP: + d->zip[item].label->setToolTip(MediaMenu::ptr->zipMenus[item]->title()); + break; + case SB_MO: + d->mo[item].label->setToolTip(MediaMenu::ptr->moMenus[item]->title()); + break; + case SB_HDD: + break; + case SB_NETWORK: + break; + case SB_SOUND: + break; + case SB_TEXT: + break; + } +} diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index ea48178ed..6bbbe0416 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -2,9 +2,27 @@ #define QT_MACHINESTATUS_HPP #include +#include +#include class QStatusBar; +class ClickableLabel : public QLabel { + Q_OBJECT; + public: + explicit ClickableLabel(QWidget* parent = nullptr) + : QLabel(parent) {} + ~ClickableLabel() {}; + + signals: + void clicked(QPoint); + void clickedRelease(QPoint); + + protected: + void mousePressedEvent(QMouseEvent* event) { emit clicked(event->globalPos()); } + void mouseReleasedEvent(QMouseEvent* event) { emit clickedRelease(event->globalPos()); } +}; + class MachineStatus : public QObject { Q_OBJECT @@ -26,6 +44,7 @@ public slots: void setActivity(int tag, bool active); void setEmpty(int tag, bool active); void message(const QString& msg); + void updateTip(int tag); private: struct States; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index ad7fa7497..8a8df2491 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -49,9 +49,9 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow) { Q_INIT_RESOURCE(qt_resources); - status = std::make_unique(this); mm = std::make_shared(this); MediaMenu::ptr = mm; + status = std::make_unique(this); ui->setupUi(this); ui->stackedWidget->setMouseTracking(true); @@ -118,9 +118,10 @@ MainWindow::MainWindow(QWidget *parent) : }); connect(this, &MainWindow::updateStatusBarPanes, this, [this] { - status->refresh(ui->statusbar); + refreshMediaMenu(); }); connect(this, &MainWindow::updateStatusBarPanes, this, &MainWindow::refreshMediaMenu); + connect(this, &MainWindow::updateStatusBarTip, status.get(), &MachineStatus::updateTip); connect(this, &MainWindow::updateStatusBarActivity, status.get(), &MachineStatus::setActivity); connect(this, &MainWindow::updateStatusBarEmpty, status.get(), &MachineStatus::setEmpty); connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message); @@ -920,6 +921,7 @@ bool MainWindow::eventFilter(QObject* receiver, QEvent* event) void MainWindow::refreshMediaMenu() { mm->refresh(ui->menuMedia); + status->refresh(ui->statusbar); } void MainWindow::showMessage(const QString& header, const QString& message) { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 5a4582442..01586df3e 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -37,6 +37,7 @@ signals: void updateStatusBarPanes(); void updateStatusBarActivity(int tag, bool active); void updateStatusBarEmpty(int tag, bool empty); + void updateStatusBarTip(int tag); void updateMenuResizeOptions(); void updateWindowRememberOption(); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 898f79c01..2b7faef0f 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -63,7 +63,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { menu->addSeparator(); cartridgeEjectPos = menu->children().count(); menu->addAction("Eject", [this, i]() { cartridgeEject(i); }); - cartridgeMenus.append(menu); + cartridgeMenus[i] = menu; cartridgeUpdateMenu(i); } } @@ -81,7 +81,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { menu->addSeparator(); floppyEjectPos = menu->children().count(); menu->addAction("Eject", [this, i]() { floppyEject(i); }); - floppyMenus.append(menu); + floppyMenus[i] = menu; floppyUpdateMenu(i); }); @@ -98,7 +98,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { menu->addSeparator(); cdromImagePos = menu->children().count(); menu->addAction("Image", [this, i]() { cdromMount(i); })->setCheckable(true); - cdromMenus.append(menu); + cdromMenus[i] = menu; cdromUpdateMenu(i); }); @@ -114,7 +114,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { menu->addAction("Eject", [this, i]() { zipEject(i); }); zipReloadPos = menu->children().count(); menu->addAction("Reload previous image", [this, i]() { zipReload(i); }); - zipMenus.append(menu); + zipMenus[i] = menu; zipUpdateMenu(i); }); @@ -130,7 +130,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { menu->addAction("Eject", [this, i]() { moEject(i); }); moReloadPos = menu->children().count(); menu->addAction("Reload previous image", [this, i]() { moReload(i); }); - moMenus.append(menu); + moMenus[i] = menu; moUpdateMenu(i); }); } @@ -161,8 +161,8 @@ void MediaMenu::cassetteMount(const QString& filename, bool wp) { } ui_sb_update_icon_state(SB_CASSETTE, filename.isEmpty() ? 1 : 0); - ui_sb_update_tip(SB_CASSETTE); cassetteUpdateMenu(); + ui_sb_update_tip(SB_CASSETTE); config_save(); } @@ -170,8 +170,8 @@ void MediaMenu::cassetteEject() { pc_cas_set_fname(cassette, nullptr); memset(cassette_fname, 0, sizeof(cassette_fname)); ui_sb_update_icon_state(SB_CASSETTE, 1); - ui_sb_update_tip(SB_CASSETTE); cassetteUpdateMenu(); + ui_sb_update_tip(SB_CASSETTE); config_save(); } @@ -208,16 +208,16 @@ void MediaMenu::cartridgeSelectImage(int i) { cart_load(i, filenameBytes.data()); ui_sb_update_icon_state(SB_CARTRIDGE | i, filename.isEmpty() ? 1 : 0); - ui_sb_update_tip(SB_CARTRIDGE | i); cartridgeUpdateMenu(i); + ui_sb_update_tip(SB_CARTRIDGE | i); config_save(); } void MediaMenu::cartridgeEject(int i) { cart_close(i); ui_sb_update_icon_state(SB_CARTRIDGE | i, 1); - ui_sb_update_tip(SB_CARTRIDGE | i); cartridgeUpdateMenu(i); + ui_sb_update_tip(SB_CARTRIDGE | i); config_save(); } @@ -253,16 +253,16 @@ void MediaMenu::floppyMount(int i, const QString &filename, bool wp) { fdd_load(i, filenameBytes.data()); } ui_sb_update_icon_state(SB_FLOPPY | i, filename.isEmpty() ? 1 : 0); - ui_sb_update_tip(SB_FLOPPY | i); floppyUpdateMenu(i); + ui_sb_update_tip(SB_FLOPPY | i); config_save(); } void MediaMenu::floppyEject(int i) { fdd_close(i); ui_sb_update_icon_state(SB_FLOPPY | i, 1); - ui_sb_update_tip(SB_FLOPPY | i); floppyUpdateMenu(i); + ui_sb_update_tip(SB_FLOPPY | i); config_save(); } @@ -329,19 +329,21 @@ void MediaMenu::cdromMount(int i) { } else { ui_sb_update_icon_state(SB_CDROM | i, 1); } - ui_sb_update_tip(SB_CDROM | i); cdromUpdateMenu(i); + ui_sb_update_tip(SB_CDROM | i); config_save(); } void MediaMenu::cdromEject(int i) { cdrom_eject(i); cdromUpdateMenu(i); + ui_sb_update_tip(SB_CDROM | i); } void MediaMenu::cdromReload(int i) { cdrom_reload(i); cdromUpdateMenu(i); + ui_sb_update_tip(SB_CDROM | i); } void MediaMenu::cdromUpdateMenu(int i) { @@ -400,8 +402,8 @@ void MediaMenu::zipMount(int i, const QString &filename, bool wp) { } ui_sb_update_icon_state(SB_ZIP | i, filename.isEmpty() ? 1 : 0); - ui_sb_update_tip(SB_ZIP | i); zipUpdateMenu(i); + ui_sb_update_tip(SB_ZIP | i); config_save(); } @@ -416,8 +418,8 @@ void MediaMenu::zipEject(int i) { } ui_sb_update_icon_state(SB_ZIP | i, 1); - ui_sb_update_tip(SB_ZIP | i); zipUpdateMenu(i); + ui_sb_update_tip(SB_ZIP | i); config_save(); } @@ -431,8 +433,8 @@ void MediaMenu::zipReload(int i) { ui_sb_update_icon_state(SB_ZIP|i, 0); } - ui_sb_update_tip(SB_ZIP|i); zipUpdateMenu(i); + ui_sb_update_tip(SB_ZIP|i); config_save(); } @@ -488,8 +490,8 @@ void MediaMenu::moMount(int i, const QString &filename, bool wp) { } ui_sb_update_icon_state(SB_MO | i, filename.isEmpty() ? 1 : 0); - ui_sb_update_tip(SB_MO | i); moUpdateMenu(i); + ui_sb_update_tip(SB_MO | i); config_save(); } @@ -504,8 +506,8 @@ void MediaMenu::moEject(int i) { } ui_sb_update_icon_state(SB_MO | i, 1); - ui_sb_update_tip(SB_MO | i); moUpdateMenu(i); + ui_sb_update_tip(SB_MO | i); config_save(); } @@ -519,8 +521,8 @@ void MediaMenu::moReload(int i) { ui_sb_update_icon_state(SB_MO|i, 0); } - ui_sb_update_tip(SB_MO|i); moUpdateMenu(i); + ui_sb_update_tip(SB_MO|i); config_save(); } diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp index 2908e8ae9..3dc859fe9 100644 --- a/src/qt/qt_mediamenu.hpp +++ b/src/qt/qt_mediamenu.hpp @@ -2,6 +2,7 @@ #include #include +#include class QMenu; @@ -57,11 +58,11 @@ private: QWidget* parentWidget = nullptr; QMenu* cassetteMenu = nullptr; - QList cartridgeMenus; - QList floppyMenus; - QList cdromMenus; - QList zipMenus; - QList moMenus; + QMap cartridgeMenus; + QMap floppyMenus; + QMap cdromMenus; + QMap zipMenus; + QMap moMenus; int cassetteRecordPos; int cassettePlayPos; @@ -84,4 +85,6 @@ private: int moEjectPos; int moReloadPos; + + friend class MachineStatus; }; diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 3ff8da064..d00e262e3 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -83,7 +83,7 @@ void ui_sb_set_text_w(wchar_t *wstr) { void ui_sb_update_tip(int arg) { - qDebug() << Q_FUNC_INFO << arg; + main_window->updateStatusBarTip(arg); } void