From cff1bfbae7e0e66707216958386c19df89412126 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 28 Apr 2017 17:57:18 +0200 Subject: [PATCH 01/16] Allow detaching subwindows --- data/themes/default/window.svg | 108 +++++++++++++++++++++++++++++++++ include/SubWindow.h | 8 +++ src/gui/SubWindow.cpp | 69 +++++++++++++++++---- 3 files changed, 174 insertions(+), 11 deletions(-) create mode 100644 data/themes/default/window.svg diff --git a/data/themes/default/window.svg b/data/themes/default/window.svg new file mode 100644 index 00000000000..fa32ed168c6 --- /dev/null +++ b/data/themes/default/window.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/include/SubWindow.h b/include/SubWindow.h index e2b1a9a37eb..ad51780904f 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -65,12 +65,19 @@ class LMMS_EXPORT SubWindow : public QMdiSubWindow void setTextShadowColor( const QColor &c ); void setBorderColor( const QColor &c ); +public slots: + void detach(); + void attach(); + protected: // hook the QWidget move/resize events to update the tracked geometry void moveEvent( QMoveEvent * event ) override; void resizeEvent( QResizeEvent * event ) override; void paintEvent( QPaintEvent * pe ) override; void changeEvent( QEvent * event ) override; + void showEvent( QShowEvent* event ) override; + + bool isDetached() const; signals: void focusLost(); @@ -81,6 +88,7 @@ class LMMS_EXPORT SubWindow : public QMdiSubWindow QPushButton * m_closeBtn; QPushButton * m_maximizeBtn; QPushButton * m_restoreBtn; + QPushButton * m_detachBtn; QBrush m_activeColor; QColor m_textShadowColor; QColor m_borderColor; diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 5cbac4cd6fa..690000b4e9d 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -77,6 +77,14 @@ SubWindow::SubWindow( QWidget *parent, Qt::WindowFlags windowFlags ) : m_restoreBtn->setToolTip( tr( "Restore" ) ); connect( m_restoreBtn, SIGNAL( clicked( bool ) ), this, SLOT( showNormal() ) ); + m_detachBtn = new QPushButton( embed::getIconPixmap( "window" ), QString(), this ); + m_detachBtn->resize( m_buttonSize ); + m_detachBtn->setFocusPolicy( Qt::NoFocus ); + m_detachBtn->setCursor( Qt::ArrowCursor ); + m_detachBtn->setAttribute( Qt::WA_NoMousePropagation ); + m_detachBtn->setToolTip( tr( "Detach" ) ); + connect( m_detachBtn, SIGNAL( clicked( bool ) ), this, SLOT( detach() ) ); + // QLabel for the window title and the shadow effect m_shadow = new QGraphicsDropShadowEffect(); m_shadow->setColor( m_textShadowColor ); @@ -151,6 +159,17 @@ void SubWindow::changeEvent( QEvent *event ) } +void SubWindow::showEvent(QShowEvent *e) +{ + attach(); + QMdiSubWindow::showEvent(e); +} + +bool SubWindow::isDetached() const +{ + return widget()->windowFlags().testFlag(Qt::Window); +} + @@ -234,6 +253,29 @@ void SubWindow::setBorderColor( const QColor &c ) m_borderColor = c; } +void SubWindow::detach() +{ + if (isDetached()) { + return; + } + auto pos = mapToGlobal(widget()->pos()); + widget()->setWindowFlags(Qt::Window); + widget()->show(); + widget()->move(pos); + hide(); +} + +void SubWindow::attach() +{ + if (! isDetached()) { + return; + } + auto pos = widget()->pos(); + widget()->setWindowFlags(Qt::Widget); + widget()->show(); + show(); + move(mdiArea()->mapFromGlobal(pos)); +} /** @@ -277,9 +319,8 @@ void SubWindow::adjustTitleBar() const int buttonGap = 1; const int menuButtonSpace = 24; - QPoint rightButtonPos( width() - rightSpace - m_buttonSize.width(), 3 ); - QPoint middleButtonPos( width() - rightSpace - ( 2 * m_buttonSize.width() ) - buttonGap, 3 ); - QPoint leftButtonPos( width() - rightSpace - ( 3 * m_buttonSize.width() ) - ( 2 * buttonGap ), 3 ); + QPoint buttonPos( width() - rightSpace - m_buttonSize.width(), 3 ); + const QPoint buttonStep( m_buttonSize.width() + buttonGap, 0 ); // the buttonBarWidth depends on the number of buttons. // we need it to calculate the width of window title label @@ -287,26 +328,32 @@ void SubWindow::adjustTitleBar() // set the buttons on their positions. // the close button is always needed and on the rightButtonPos - m_closeBtn->move( rightButtonPos ); + m_closeBtn->move( buttonPos ); + buttonPos -= buttonStep; // here we ask: is the Subwindow maximizable and // then we set the buttons and show them if needed if( windowFlags() & Qt::WindowMaximizeButtonHint ) { buttonBarWidth = buttonBarWidth + m_buttonSize.width() + buttonGap; - m_maximizeBtn->move( middleButtonPos ); - m_restoreBtn->move( middleButtonPos ); - m_maximizeBtn->setHidden( isMaximized() ); + m_maximizeBtn->move( buttonPos ); + m_restoreBtn->move( buttonPos ); + if ( ! isMaximized() ) { + m_maximizeBtn->show(); + buttonPos -= buttonStep; + } } // we're keeping the restore button around if we open projects // from older versions that have saved minimized windows - m_restoreBtn->setVisible( isMaximized() || isMinimized() ); - if( isMinimized() ) - { - m_restoreBtn->move( m_maximizeBtn->isHidden() ? middleButtonPos : leftButtonPos ); + if ( isMaximized() || isMinimized() ) { + m_restoreBtn->show(); + buttonPos -= buttonStep; } + m_detachBtn->move( buttonPos ); + m_detachBtn->show(); + if( widget() ) { // title QLabel adjustments From 4b3bf9f2a5d69a1c3e21c7d27a57e7f0a53477fd Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sat, 29 Apr 2017 13:20:48 +0200 Subject: [PATCH 02/16] Subwindows: Fix some size constraints --- plugins/LadspaEffect/LadspaControlDialog.cpp | 1 + src/gui/widgets/ControllerRackView.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/LadspaEffect/LadspaControlDialog.cpp b/plugins/LadspaEffect/LadspaControlDialog.cpp index 0034dfd6d0c..0009f4dfda7 100644 --- a/plugins/LadspaEffect/LadspaControlDialog.cpp +++ b/plugins/LadspaEffect/LadspaControlDialog.cpp @@ -42,6 +42,7 @@ LadspaControlDialog::LadspaControlDialog( LadspaControls * _ctl ) : m_stereoLink( nullptr ) { QVBoxLayout * mainLay = new QVBoxLayout( this ); + mainLay->setSizeConstraint(QLayout::SetFixedSize); m_effectLayout = new QHBoxLayout(); mainLay->addLayout( m_effectLayout ); diff --git a/src/gui/widgets/ControllerRackView.cpp b/src/gui/widgets/ControllerRackView.cpp index d6b7cc410d9..99d9241d736 100644 --- a/src/gui/widgets/ControllerRackView.cpp +++ b/src/gui/widgets/ControllerRackView.cpp @@ -75,6 +75,9 @@ ControllerRackView::ControllerRackView( ) : layout->addWidget( m_addButton ); this->setLayout( layout ); + setFixedWidth( 350 ); + setMinimumHeight( 200 ); + QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); // No maximize button @@ -84,9 +87,6 @@ ControllerRackView::ControllerRackView( ) : subWin->setAttribute( Qt::WA_DeleteOnClose, false ); subWin->move( 680, 310 ); - subWin->resize( 350, 200 ); - subWin->setFixedWidth( 350 ); - subWin->setMinimumHeight( 200 ); } From 4cba4193df9a11cee862acd12f6216a0bfaf80c1 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 5 May 2017 16:59:44 +0200 Subject: [PATCH 03/16] Subwindow detach: Fix minor pos & size issues --- src/gui/SubWindow.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 690000b4e9d..2dc52deb0b2 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -29,9 +29,11 @@ #include "SubWindow.h" #include +#include #include #include #include +#include #include "embed.h" @@ -261,8 +263,9 @@ void SubWindow::detach() auto pos = mapToGlobal(widget()->pos()); widget()->setWindowFlags(Qt::Window); widget()->show(); - widget()->move(pos); hide(); + + widget()->windowHandle()->setPosition(pos); } void SubWindow::attach() @@ -270,11 +273,18 @@ void SubWindow::attach() if (! isDetached()) { return; } - auto pos = widget()->pos(); + auto frame = widget()->windowHandle()->frameGeometry(); + widget()->setWindowFlags(Qt::Widget); widget()->show(); show(); - move(mdiArea()->mapFromGlobal(pos)); + + // Delay moving & resizing using event queue. Ensures that this widget is + // visible first, so that resizing works. + QObject o; connect(&o, &QObject::destroyed, this, [this, frame]() { + move(mdiArea()->mapFromGlobal(frame.topLeft())); + resize(frame.size()); + }, Qt::QueuedConnection); } From 4ff297b932cca112e6cbd30f67c03ec49945a713 Mon Sep 17 00:00:00 2001 From: Hyunin Song Date: Fri, 25 May 2018 15:11:39 +0900 Subject: [PATCH 04/16] Fix some bugs --- include/SubWindow.h | 1 + plugins/vestige/vestige.cpp | 11 +++++++++-- src/gui/ControllerDialog.cpp | 17 ++++++++++++++++- src/gui/EffectControlDialog.cpp | 17 ++++++++++++++++- src/gui/InstrumentTrackWindow.cpp | 10 +++++++--- src/gui/MixerView.cpp | 13 +++++++++---- src/gui/SampleTrackWindow.cpp | 12 ++++++++---- src/gui/SubWindow.cpp | 15 +++++++++++++++ src/gui/widgets/ControllerRackView.cpp | 9 +++++++-- src/gui/widgets/ProjectNotes.cpp | 9 +++++++-- 10 files changed, 95 insertions(+), 19 deletions(-) diff --git a/include/SubWindow.h b/include/SubWindow.h index ad51780904f..d723981417c 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -76,6 +76,7 @@ public slots: void paintEvent( QPaintEvent * pe ) override; void changeEvent( QEvent * event ) override; void showEvent( QShowEvent* event ) override; + bool eventFilter( QObject * obj, QEvent * event ) override; bool isDetached() const; diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 97af8bc43b8..98e7d639f09 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -103,8 +103,15 @@ class vstSubWin : public SubWindow { // ignore close-events - for some reason otherwise the VST GUI // remains hidden when re-opening - hide(); - e->ignore(); + if (windowFlags().testFlag(Qt::Window)) + { + e->accept(); + } + else + { + hide(); + e->ignore(); + } } }; diff --git a/src/gui/ControllerDialog.cpp b/src/gui/ControllerDialog.cpp index f854ab1b94e..8e3583f987d 100644 --- a/src/gui/ControllerDialog.cpp +++ b/src/gui/ControllerDialog.cpp @@ -27,6 +27,8 @@ #include "ControllerDialog.h" #include "Controller.h" +#include "GuiApplication.h" +#include "MainWindow.h" ControllerDialog::ControllerDialog( Controller * _controller, @@ -46,7 +48,20 @@ ControllerDialog::~ControllerDialog() void ControllerDialog::closeEvent( QCloseEvent * _ce ) { - _ce->ignore(); + if (windowFlags().testFlag(Qt::Window)) + { + _ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) + { + parentWidget()->hide(); + _ce->ignore(); + } + else + { + hide(); + _ce->ignore(); + } emit closed(); } diff --git a/src/gui/EffectControlDialog.cpp b/src/gui/EffectControlDialog.cpp index 3439835d139..f4567bed0e3 100644 --- a/src/gui/EffectControlDialog.cpp +++ b/src/gui/EffectControlDialog.cpp @@ -28,6 +28,8 @@ #include "EffectControlDialog.h" #include "EffectControls.h" +#include "GuiApplication.h" +#include "MainWindow.h" EffectControlDialog::EffectControlDialog( EffectControls * _controls ) : @@ -51,7 +53,20 @@ EffectControlDialog::~EffectControlDialog() void EffectControlDialog::closeEvent( QCloseEvent * _ce ) { - _ce->ignore(); + if (windowFlags().testFlag(Qt::Window)) + { + _ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) + { + parentWidget()->hide(); + _ce->ignore(); + } + else + { + hide(); + _ce->ignore(); + } emit closed(); } diff --git a/src/gui/InstrumentTrackWindow.cpp b/src/gui/InstrumentTrackWindow.cpp index eb6f7c410fe..d7b2826f16a 100644 --- a/src/gui/InstrumentTrackWindow.cpp +++ b/src/gui/InstrumentTrackWindow.cpp @@ -501,15 +501,19 @@ void InstrumentTrackWindow::toggleVisibility( bool on ) void InstrumentTrackWindow::closeEvent( QCloseEvent* event ) { - event->ignore(); - - if( getGUI()->mainWindow()->workspace() ) + if (windowFlags().testFlag(Qt::Window)) + { + event->accept(); + } + else if (getGUI()->mainWindow()->workspace()) { parentWidget()->hide(); + event->ignore(); } else { hide(); + event->ignore(); } m_itv->m_tlb->setFocus(); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 2cae9ad6f0d..2fb3964b7f3 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -554,17 +554,22 @@ void MixerView::keyPressEvent(QKeyEvent * e) void MixerView::closeEvent( QCloseEvent * _ce ) - { - if( parentWidget() ) +{ + if (windowFlags().testFlag(Qt::Window)) + { + _ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) { parentWidget()->hide(); + _ce->ignore(); } else { hide(); + _ce->ignore(); } - _ce->ignore(); - } +} diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 87273461fb9..88bdd89d1c0 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -230,15 +230,19 @@ void SampleTrackWindow::toggleVisibility(bool on) void SampleTrackWindow::closeEvent(QCloseEvent* ce) { - ce->ignore(); - - if(getGUI()->mainWindow()->workspace()) + if (windowFlags().testFlag(Qt::Window)) + { + ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) { parentWidget()->hide(); + ce->ignore(); } else { hide(); + ce->ignore(); } m_stv->m_tlb->setFocus(); @@ -262,4 +266,4 @@ void SampleTrackWindow::loadSettings(const QDomElement& element) { m_stv->m_tlb->setChecked(true); } -} \ No newline at end of file +} diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 2dc52deb0b2..d4366b86dce 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -260,6 +260,7 @@ void SubWindow::detach() if (isDetached()) { return; } + auto pos = mapToGlobal(widget()->pos()); widget()->setWindowFlags(Qt::Window); widget()->show(); @@ -433,3 +434,17 @@ void SubWindow::resizeEvent( QResizeEvent * event ) m_trackedNormalGeom.setSize( event->size() ); } } + +bool SubWindow::eventFilter(QObject * obj, QEvent * event) +{ + if (obj != static_cast(widget())) { + return QMdiSubWindow::eventFilter(obj, event); + } + switch (event->type()) { + case QEvent::WindowStateChange: + event->accept(); + return true; + default: + return QMdiSubWindow::eventFilter(obj, event); + } +} diff --git a/src/gui/widgets/ControllerRackView.cpp b/src/gui/widgets/ControllerRackView.cpp index 99d9241d736..8984adecb63 100644 --- a/src/gui/widgets/ControllerRackView.cpp +++ b/src/gui/widgets/ControllerRackView.cpp @@ -203,14 +203,19 @@ void ControllerRackView::addController() void ControllerRackView::closeEvent( QCloseEvent * _ce ) { - if( parentWidget() ) + if (windowFlags().testFlag(Qt::Window)) + { + _ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) { parentWidget()->hide(); + _ce->ignore(); } else { hide(); + _ce->ignore(); } - _ce->ignore(); } diff --git a/src/gui/widgets/ProjectNotes.cpp b/src/gui/widgets/ProjectNotes.cpp index 6fac7320817..cfd607d2027 100644 --- a/src/gui/widgets/ProjectNotes.cpp +++ b/src/gui/widgets/ProjectNotes.cpp @@ -398,13 +398,18 @@ void ProjectNotes::loadSettings( const QDomElement & _this ) void ProjectNotes::closeEvent( QCloseEvent * _ce ) { - if( parentWidget() ) + if (windowFlags().testFlag(Qt::Window)) + { + _ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) { parentWidget()->hide(); + _ce->ignore(); } else { hide(); + _ce->ignore(); } - _ce->ignore(); } From 02d753dbdf8b3bc66dfd50faf246b43741ea8b2f Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Sun, 19 Nov 2023 03:05:48 -0500 Subject: [PATCH 05/16] Fix style; Use lambda to reduce duplicate code --- include/SubWindow.h | 6 +-- src/gui/ControllerRackView.cpp | 4 +- src/gui/SubWindow.cpp | 94 ++++++++++++++++------------------ 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/include/SubWindow.h b/include/SubWindow.h index 44067273d7f..6838b40e012 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -81,8 +81,8 @@ public slots: void resizeEvent( QResizeEvent * event ) override; void paintEvent( QPaintEvent * pe ) override; void changeEvent( QEvent * event ) override; - void showEvent( QShowEvent* event ) override; - bool eventFilter( QObject * obj, QEvent * event ) override; + void showEvent(QShowEvent* event) override; + bool eventFilter(QObject* obj, QEvent* event) override; bool isDetached() const; @@ -95,7 +95,7 @@ public slots: QPushButton * m_closeBtn; QPushButton * m_maximizeBtn; QPushButton * m_restoreBtn; - QPushButton * m_detachBtn; + QPushButton* m_detachBtn; QBrush m_activeColor; QColor m_textShadowColor; QColor m_borderColor; diff --git a/src/gui/ControllerRackView.cpp b/src/gui/ControllerRackView.cpp index 9e95254043c..60f5d35e2b2 100644 --- a/src/gui/ControllerRackView.cpp +++ b/src/gui/ControllerRackView.cpp @@ -76,8 +76,8 @@ ControllerRackView::ControllerRackView() : layout->addWidget( m_addButton ); this->setLayout( layout ); - setFixedWidth( 350 ); - setMinimumHeight( 200 ); + setFixedWidth(350); + setMinimumHeight(200); QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 931dca64ce2..bcd7fe59cfd 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -59,38 +59,28 @@ SubWindow::SubWindow(QWidget *parent, Qt::WindowFlags windowFlags) : m_textShadowColor = Qt::black; m_borderColor = Qt::black; - // close, maximize and restore (after maximizing) buttons - m_closeBtn = new QPushButton( embed::getIconPixmap( "close" ), QString(), this ); - m_closeBtn->resize( m_buttonSize ); - m_closeBtn->setFocusPolicy( Qt::NoFocus ); - m_closeBtn->setCursor( Qt::ArrowCursor ); - m_closeBtn->setAttribute( Qt::WA_NoMousePropagation ); - m_closeBtn->setToolTip( tr( "Close" ) ); - connect( m_closeBtn, SIGNAL(clicked(bool)), this, SLOT(close())); - - m_maximizeBtn = new QPushButton( embed::getIconPixmap( "maximize" ), QString(), this ); - m_maximizeBtn->resize( m_buttonSize ); - m_maximizeBtn->setFocusPolicy( Qt::NoFocus ); - m_maximizeBtn->setCursor( Qt::ArrowCursor ); - m_maximizeBtn->setAttribute( Qt::WA_NoMousePropagation ); - m_maximizeBtn->setToolTip( tr( "Maximize" ) ); - connect( m_maximizeBtn, SIGNAL(clicked(bool)), this, SLOT(showMaximized())); - - m_restoreBtn = new QPushButton( embed::getIconPixmap( "restore" ), QString(), this ); - m_restoreBtn->resize( m_buttonSize ); - m_restoreBtn->setFocusPolicy( Qt::NoFocus ); - m_restoreBtn->setCursor( Qt::ArrowCursor ); - m_restoreBtn->setAttribute( Qt::WA_NoMousePropagation ); - m_restoreBtn->setToolTip( tr( "Restore" ) ); - connect( m_restoreBtn, SIGNAL(clicked(bool)), this, SLOT(showNormal())); - - m_detachBtn = new QPushButton( embed::getIconPixmap( "window" ), QString(), this ); - m_detachBtn->resize( m_buttonSize ); - m_detachBtn->setFocusPolicy( Qt::NoFocus ); - m_detachBtn->setCursor( Qt::ArrowCursor ); - m_detachBtn->setAttribute( Qt::WA_NoMousePropagation ); - m_detachBtn->setToolTip( tr( "Detach" ) ); - connect( m_detachBtn, SIGNAL( clicked( bool ) ), this, SLOT( detach() ) ); + // close, maximize, restore, and detach buttons + auto createButton = [this](const QIcon& icon, const QString& tooltip) -> QPushButton* { + auto button = new QPushButton{icon, QString{}, this}; + button->resize(m_buttonSize); + button->setFocusPolicy(Qt::NoFocus); + button->setCursor(Qt::ArrowCursor); + button->setAttribute(Qt::WA_NoMousePropagation); + button->setToolTip(tooltip); + return button; + }; + + m_closeBtn = createButton(embed::getIconPixmap("close"), tr("Close")); + connect(m_closeBtn, &QPushButton::clicked, this, &QWidget::close); + + m_maximizeBtn = createButton(embed::getIconPixmap("maximize"), tr("Maximize")); + connect(m_maximizeBtn, &QPushButton::clicked, this, &QWidget::showMaximized); + + m_restoreBtn = createButton(embed::getIconPixmap("restore"), tr("Restore")); + connect(m_restoreBtn, &QPushButton::clicked, this, &QWidget::showNormal); + + m_detachBtn = createButton(embed::getIconPixmap("window"), tr("Detach")); + connect(m_detachBtn, &QPushButton::clicked, this, &SubWindow::detach); // QLabel for the window title and the shadow effect m_shadow = new QGraphicsDropShadowEffect(); @@ -166,7 +156,7 @@ void SubWindow::changeEvent( QEvent *event ) } -void SubWindow::showEvent(QShowEvent *e) +void SubWindow::showEvent(QShowEvent* e) { attach(); QMdiSubWindow::showEvent(e); @@ -262,9 +252,7 @@ void SubWindow::setBorderColor( const QColor &c ) void SubWindow::detach() { - if (isDetached()) { - return; - } + if (isDetached()) { return; } auto pos = mapToGlobal(widget()->pos()); widget()->setWindowFlags(Qt::Window); @@ -276,18 +264,17 @@ void SubWindow::detach() void SubWindow::attach() { - if (! isDetached()) { - return; - } - auto frame = widget()->windowHandle()->frameGeometry(); + if (!isDetached()) { return; } + auto frame = widget()->windowHandle()->frameGeometry(); widget()->setWindowFlags(Qt::Widget); widget()->show(); show(); // Delay moving & resizing using event queue. Ensures that this widget is // visible first, so that resizing works. - QObject o; connect(&o, &QObject::destroyed, this, [this, frame]() { + QObject obj; + connect(&obj, &QObject::destroyed, this, [this, frame]() { move(mdiArea()->mapFromGlobal(frame.topLeft())); resize(frame.size()); }, Qt::QueuedConnection); @@ -356,7 +343,7 @@ void SubWindow::adjustTitleBar() const int buttonGap = 1; const int menuButtonSpace = 24; - QPoint buttonPos( width() - rightSpace - m_buttonSize.width(), 3 ); + QPoint buttonPos(width() - rightSpace - m_buttonSize.width(), 3); const QPoint buttonStep( m_buttonSize.width() + buttonGap, 0 ); // the buttonBarWidth depends on the number of buttons. @@ -365,7 +352,7 @@ void SubWindow::adjustTitleBar() // set the buttons on their positions. // the close button is always needed and on the rightButtonPos - m_closeBtn->move( buttonPos ); + m_closeBtn->move(buttonPos); buttonPos -= buttonStep; // here we ask: is the Subwindow maximizable and @@ -373,9 +360,10 @@ void SubWindow::adjustTitleBar() if( windowFlags() & Qt::WindowMaximizeButtonHint ) { buttonBarWidth = buttonBarWidth + m_buttonSize.width() + buttonGap; - m_maximizeBtn->move( buttonPos ); - m_restoreBtn->move( buttonPos ); - if ( ! isMaximized() ) { + m_maximizeBtn->move(buttonPos); + m_restoreBtn->move(buttonPos); + if (!isMaximized()) + { m_maximizeBtn->show(); buttonPos -= buttonStep; } @@ -383,12 +371,13 @@ void SubWindow::adjustTitleBar() // we're keeping the restore button around if we open projects // from older versions that have saved minimized windows - if ( isMaximized() || isMinimized() ) { + if (isMaximized() || isMinimized()) + { m_restoreBtn->show(); buttonPos -= buttonStep; } - m_detachBtn->move( buttonPos ); + m_detachBtn->move(buttonPos); m_detachBtn->show(); if( widget() ) @@ -461,12 +450,15 @@ void SubWindow::resizeEvent( QResizeEvent * event ) } } -bool SubWindow::eventFilter(QObject * obj, QEvent * event) +bool SubWindow::eventFilter(QObject* obj, QEvent* event) { - if (obj != static_cast(widget())) { + if (obj != static_cast(widget())) + { return QMdiSubWindow::eventFilter(obj, event); } - switch (event->type()) { + + switch (event->type()) + { case QEvent::WindowStateChange: event->accept(); return true; From 2fd7df8753aaccaf8571406778f278be91ccd02e Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Sun, 19 Nov 2023 16:51:58 -0500 Subject: [PATCH 06/16] Refactor; Fix close event for editor windows --- include/ControllerDialog.h | 21 ++----- include/ControllerRackView.h | 12 +--- include/DetachableWidget.h | 47 +++++++++++++++ include/DetachableWindow.h | 47 +++++++++++++++ include/Editor.h | 6 +- include/EffectControlDialog.h | 23 ++------ include/MixerView.h | 11 ++-- include/ProjectNotes.h | 6 +- include/SampleTrackWindow.h | 9 ++- include/SongEditor.h | 1 - src/gui/CMakeLists.txt | 2 + src/gui/ControllerDialog.cpp | 36 ++---------- src/gui/ControllerRackView.cpp | 33 ++--------- src/gui/DetachableWidget.cpp | 60 ++++++++++++++++++++ src/gui/DetachableWindow.cpp | 60 ++++++++++++++++++++ src/gui/EffectControlDialog.cpp | 41 +++---------- src/gui/MixerView.cpp | 28 ++------- src/gui/ProjectNotes.cpp | 26 +-------- src/gui/SampleTrackWindow.cpp | 32 +++-------- src/gui/editors/Editor.cpp | 21 +------ src/gui/editors/SongEditor.cpp | 15 ----- src/gui/instrument/InstrumentTrackWindow.cpp | 1 + 22 files changed, 278 insertions(+), 260 deletions(-) create mode 100644 include/DetachableWidget.h create mode 100644 include/DetachableWindow.h create mode 100644 src/gui/DetachableWidget.cpp create mode 100644 src/gui/DetachableWindow.cpp diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h index 0c53a8c849b..f9145d3b06f 100644 --- a/include/ControllerDialog.h +++ b/include/ControllerDialog.h @@ -26,8 +26,7 @@ #ifndef LMMS_GUI_CONTROLLER_DIALOG_H #define LMMS_GUI_CONTROLLER_DIALOG_H -#include - +#include "DetachableWidget.h" #include "ModelView.h" namespace lmms @@ -38,24 +37,12 @@ class Controller; namespace gui { -class ControllerDialog : public QWidget, public ModelView +class ControllerDialog : public DetachableWidget, public ModelView { - Q_OBJECT public: - ControllerDialog( Controller * _controller, QWidget * _parent ); - + ControllerDialog(Controller* controller, QWidget* parent); ~ControllerDialog() override = default; - - -signals: - void closed(); - - -protected: - void closeEvent( QCloseEvent * _ce ) override; - -} ; - +}; } // namespace gui diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index 303cc2b401f..bccac49f9e1 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -25,18 +25,14 @@ #ifndef LMMS_GUI_CONTROLLER_RACK_VIEW_H #define LMMS_GUI_CONTROLLER_RACK_VIEW_H -#include -#include - +#include "DetachableWidget.h" #include "SerializingObject.h" #include "lmms_basics.h" - class QPushButton; class QScrollArea; class QVBoxLayout; - namespace lmms { @@ -47,8 +43,7 @@ namespace gui class ControllerView; - -class ControllerRackView : public QWidget, public SerializingObject +class ControllerRackView : public DetachableWidget, public SerializingObject { Q_OBJECT public: @@ -69,9 +64,6 @@ public slots: void onControllerAdded( lmms::Controller * ); void onControllerRemoved( lmms::Controller * ); -protected: - void closeEvent( QCloseEvent * _ce ) override; - private slots: void addController(); diff --git a/include/DetachableWidget.h b/include/DetachableWidget.h new file mode 100644 index 00000000000..35184137f70 --- /dev/null +++ b/include/DetachableWidget.h @@ -0,0 +1,47 @@ +/* + * DetachableWidget.h - Allows a widget to be detached from + * LMMS's main window + * + * Copyright (c) 2023 Dalton Messmer + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_GUI_DETACHABLE_WIDGET +#define LMMS_GUI_DETACHABLE_WIDGET + +#include + +namespace lmms::gui { + +class DetachableWidget : public QWidget +{ + Q_OBJECT +public: + explicit DetachableWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags{}); + + void closeEvent(QCloseEvent* ce) override; + +signals: + void closed(); +}; + +} // namespace lmms::gui + +#endif // LMMS_GUI_DETACHABLE_WIDGET diff --git a/include/DetachableWindow.h b/include/DetachableWindow.h new file mode 100644 index 00000000000..5f0a81bfc20 --- /dev/null +++ b/include/DetachableWindow.h @@ -0,0 +1,47 @@ +/* + * DetachableWindow.h - Allows a window to be detached from + * LMMS's main window + * + * Copyright (c) 2023 Dalton Messmer + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_GUI_DETACHABLE_WINDOW +#define LMMS_GUI_DETACHABLE_WINDOW + +#include + +namespace lmms::gui { + +class DetachableWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit DetachableWindow(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags{}); + + void closeEvent(QCloseEvent* ce) override; + +signals: + void closed(); +}; + +} // namespace lmms::gui + +#endif // LMMS_GUI_DETACHABLE_WINDOW diff --git a/include/Editor.h b/include/Editor.h index 681bce46ccc..b9e30ccdeae 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -25,9 +25,10 @@ #ifndef LMMS_GUI_EDITOR_H #define LMMS_GUI_EDITOR_H -#include #include +#include "DetachableWindow.h" + class QAction; namespace lmms::gui @@ -45,7 +46,7 @@ class DropToolBar; /// /// Those editors include the Song Editor, the Automation Editor, B&B Editor, /// and the Piano Roll. -class Editor : public QMainWindow +class Editor : public DetachableWindow { Q_OBJECT public: @@ -56,7 +57,6 @@ class Editor : public QMainWindow DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle); DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle); - void closeEvent( QCloseEvent * _ce ) override; protected slots: virtual void play() {} virtual void record() {} diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h index 4bef5ee7960..1cc748e9a5f 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -26,8 +26,7 @@ #ifndef LMMS_GUI_EFFECT_CONTROL_DIALOG_H #define LMMS_GUI_EFFECT_CONTROL_DIALOG_H -#include - +#include "DetachableWidget.h" #include "ModelView.h" namespace lmms @@ -35,30 +34,20 @@ namespace lmms class EffectControls; - namespace gui { -class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView +class LMMS_EXPORT EffectControlDialog : public DetachableWidget, public ModelView { - Q_OBJECT public: - EffectControlDialog( EffectControls * _controls ); + EffectControlDialog(EffectControls* controls); ~EffectControlDialog() override = default; - virtual bool isResizable() const {return false;} - - -signals: - void closed(); - + virtual bool isResizable() const { return false; } protected: - void closeEvent( QCloseEvent * _ce ) override; - - EffectControls * m_effectControls; - -} ; + EffectControls* m_effectControls; +}; } // namespace gui diff --git a/include/MixerView.h b/include/MixerView.h index 2bb5ed4170f..3755e0bc63b 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -25,11 +25,11 @@ #ifndef LMMS_GUI_MIXER_VIEW_H #define LMMS_GUI_MIXER_VIEW_H -#include #include #include #include +#include "DetachableWidget.h" #include "ModelView.h" #include "Engine.h" #include "Fader.h" @@ -45,8 +45,10 @@ namespace lmms::gui class MixerLine; -class LMMS_EXPORT MixerView : public QWidget, public ModelView, - public SerializingObjectHook +class LMMS_EXPORT MixerView + : public DetachableWidget + , public ModelView + , public SerializingObjectHook { Q_OBJECT public: @@ -114,9 +116,6 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, public slots: int addNewChannel(); -protected: - void closeEvent( QCloseEvent * _ce ) override; - private slots: void updateFaders(); void toggledSolo(); diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h index 861dcb4a847..9154f13ea04 100644 --- a/include/ProjectNotes.h +++ b/include/ProjectNotes.h @@ -25,8 +25,7 @@ #ifndef LMMS_GUI_PROJECT_NOTES_H #define LMMS_GUI_PROJECT_NOTES_H -#include - +#include "DetachableWindow.h" #include "SerializingObject.h" class QAction; @@ -38,7 +37,7 @@ namespace lmms::gui { -class LMMS_EXPORT ProjectNotes : public QMainWindow, public SerializingObject +class LMMS_EXPORT ProjectNotes : public DetachableWindow, public SerializingObject { Q_OBJECT public: @@ -58,7 +57,6 @@ class LMMS_EXPORT ProjectNotes : public QMainWindow, public SerializingObject protected: - void closeEvent( QCloseEvent * _ce ) override; void setupActions(); diff --git a/include/SampleTrackWindow.h b/include/SampleTrackWindow.h index c2a722d53ab..a0a766d2b8b 100644 --- a/include/SampleTrackWindow.h +++ b/include/SampleTrackWindow.h @@ -25,8 +25,7 @@ #ifndef LMMS_GUI_SAMPLE_TRACK_WINDOW_H #define LMMS_GUI_SAMPLE_TRACK_WINDOW_H -#include - +#include "DetachableWidget.h" #include "ModelView.h" #include "SampleTrack.h" #include "SerializingObject.h" @@ -42,11 +41,11 @@ class MixerLineLcdSpinBox; class SampleTrackView; -class SampleTrackWindow : public QWidget, public ModelView, public SerializingObjectHook +class SampleTrackWindow : public DetachableWidget, public ModelView, public SerializingObjectHook { Q_OBJECT public: - SampleTrackWindow(SampleTrackView * tv); + SampleTrackWindow(SampleTrackView* stv); ~SampleTrackWindow() override = default; SampleTrack * model() @@ -75,7 +74,7 @@ public slots: protected: // capture close-events for toggling sample-track-button - void closeEvent(QCloseEvent * ce) override; + void closeEvent(QCloseEvent* ce) override; void saveSettings(QDomDocument & doc, QDomElement & element) override; void loadSettings(const QDomElement & element) override; diff --git a/include/SongEditor.h b/include/SongEditor.h index ee9e83f44c3..d02a99abc58 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -91,7 +91,6 @@ public slots: void selectAllClips( bool select ); protected: - void closeEvent( QCloseEvent * ce ) override; void mousePressEvent(QMouseEvent * me) override; void mouseMoveEvent(QMouseEvent * me) override; void mouseReleaseEvent(QMouseEvent * me) override; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 1e809e9d710..bf389bd7ed5 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -9,6 +9,8 @@ SET(LMMS_SRCS gui/ControllerRackView.cpp gui/ControllerView.cpp gui/Controls.cpp + gui/DetachableWidget.cpp + gui/DetachableWindow.cpp gui/EffectControlDialog.cpp gui/EffectRackView.cpp gui/EffectView.cpp diff --git a/src/gui/ControllerDialog.cpp b/src/gui/ControllerDialog.cpp index 22f8a363ffc..d47da1a98de 100644 --- a/src/gui/ControllerDialog.cpp +++ b/src/gui/ControllerDialog.cpp @@ -23,45 +23,17 @@ * */ -#include - #include "ControllerDialog.h" + #include "Controller.h" -#include "GuiApplication.h" -#include "MainWindow.h" namespace lmms::gui { - -ControllerDialog::ControllerDialog( Controller * _controller, - QWidget * _parent ) : - QWidget( _parent ), - ModelView( _controller, this ) -{ -} - - - -void ControllerDialog::closeEvent( QCloseEvent * _ce ) +ControllerDialog::ControllerDialog(Controller* controller, QWidget* parent) + : DetachableWidget{parent} + , ModelView{controller, this} { - if (windowFlags().testFlag(Qt::Window)) - { - _ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - _ce->ignore(); - } - else - { - hide(); - _ce->ignore(); - } - emit closed(); } - - } // namespace lmms::gui diff --git a/src/gui/ControllerRackView.cpp b/src/gui/ControllerRackView.cpp index 60f5d35e2b2..dfde71cea88 100644 --- a/src/gui/ControllerRackView.cpp +++ b/src/gui/ControllerRackView.cpp @@ -23,6 +23,8 @@ * */ +#include "ControllerRackView.h" + #include #include #include @@ -30,21 +32,20 @@ #include #include "Song.h" -#include "embed.h" #include "GuiApplication.h" #include "MainWindow.h" -#include "ControllerRackView.h" #include "ControllerView.h" #include "LfoController.h" #include "SubWindow.h" +#include "embed.h" namespace lmms::gui { -ControllerRackView::ControllerRackView() : - QWidget(), - m_nextIndex(0) +ControllerRackView::ControllerRackView() + : DetachableWidget{} + , m_nextIndex{0} { setWindowIcon( embed::getIconPixmap( "controller" ) ); setWindowTitle( tr( "Controller Rack" ) ); @@ -192,26 +193,4 @@ void ControllerRackView::addController() setFocus(); } - - - -void ControllerRackView::closeEvent( QCloseEvent * _ce ) - { - if (windowFlags().testFlag(Qt::Window)) - { - _ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - _ce->ignore(); - } - else - { - hide(); - _ce->ignore(); - } - } - - } // namespace lmms::gui diff --git a/src/gui/DetachableWidget.cpp b/src/gui/DetachableWidget.cpp new file mode 100644 index 00000000000..85f9c5b2359 --- /dev/null +++ b/src/gui/DetachableWidget.cpp @@ -0,0 +1,60 @@ +/* + * DetachableWidget.cpp - Allows a widget to be detached from + * LMMS's main window + * + * Copyright (c) 2023 Dalton Messmer + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "DetachableWidget.h" + +#include +#include + +#include "GuiApplication.h" +#include "MainWindow.h" + +namespace lmms::gui { + +DetachableWidget::DetachableWidget(QWidget* parent, Qt::WindowFlags f) + : QWidget{parent, f} +{ +} + +void DetachableWidget::closeEvent(QCloseEvent* ce) +{ + if (windowFlags().testFlag(Qt::Window)) + { + ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) + { + parentWidget()->hide(); + ce->ignore(); + } + else + { + hide(); + ce->ignore(); + } + emit closed(); +} + +} // namespace lmms::gui diff --git a/src/gui/DetachableWindow.cpp b/src/gui/DetachableWindow.cpp new file mode 100644 index 00000000000..33e0970c520 --- /dev/null +++ b/src/gui/DetachableWindow.cpp @@ -0,0 +1,60 @@ +/* + * DetachableWindow.cpp - Allows a window to be detached from + * LMMS's main window + * + * Copyright (c) 2023 Dalton Messmer + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "DetachableWindow.h" + +#include +#include + +#include "GuiApplication.h" +#include "MainWindow.h" + +namespace lmms::gui { + +DetachableWindow::DetachableWindow(QWidget* parent, Qt::WindowFlags f) + : QMainWindow{parent, f} +{ +} + +void DetachableWindow::closeEvent(QCloseEvent* ce) +{ + if (windowFlags().testFlag(Qt::Window)) + { + ce->accept(); + } + else if (getGUI()->mainWindow()->workspace()) + { + parentWidget()->hide(); + ce->ignore(); + } + else + { + hide(); + ce->ignore(); + } + emit closed(); +} + +} // namespace lmms::gui diff --git a/src/gui/EffectControlDialog.cpp b/src/gui/EffectControlDialog.cpp index a934077c927..9c689bf5ba9 100644 --- a/src/gui/EffectControlDialog.cpp +++ b/src/gui/EffectControlDialog.cpp @@ -23,47 +23,20 @@ * */ -#include - #include "EffectControlDialog.h" + #include "EffectControls.h" -#include "GuiApplication.h" -#include "MainWindow.h" namespace lmms::gui { - -EffectControlDialog::EffectControlDialog( EffectControls * _controls ) : - QWidget( nullptr ), - ModelView( _controls, this ), - m_effectControls( _controls ) -{ - setWindowTitle( m_effectControls->effect()->displayName() ); - setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); -} - - - - -void EffectControlDialog::closeEvent( QCloseEvent * _ce ) +EffectControlDialog::EffectControlDialog(EffectControls* controls) + : DetachableWidget{nullptr} + , ModelView{controls, this} + , m_effectControls{controls} { - if (windowFlags().testFlag(Qt::Window)) - { - _ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - _ce->ignore(); - } - else - { - hide(); - _ce->ignore(); - } - emit closed(); + setWindowTitle(m_effectControls->effect()->displayName()); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); } - } // namespace lmms::gui diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 3c6225f3c31..5e0e82d1e8f 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -52,10 +52,10 @@ namespace lmms::gui { -MixerView::MixerView() : - QWidget(), - ModelView( nullptr, this ), - SerializingObjectHook() +MixerView::MixerView() + : DetachableWidget{} + , ModelView{nullptr, this} + , SerializingObjectHook{} { #if QT_VERSION < 0x50C00 // Workaround for a bug in Qt versions below 5.12, @@ -585,26 +585,6 @@ void MixerView::keyPressEvent(QKeyEvent * e) -void MixerView::closeEvent( QCloseEvent * _ce ) -{ - if (windowFlags().testFlag(Qt::Window)) - { - _ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - _ce->ignore(); - } - else - { - hide(); - _ce->ignore(); - } -} - - - void MixerView::setCurrentMixerLine( int _line ) { if( _line >= 0 && _line < m_mixerChannelViews.size() ) diff --git a/src/gui/ProjectNotes.cpp b/src/gui/ProjectNotes.cpp index 5de6103b6c8..d180b63c8a2 100644 --- a/src/gui/ProjectNotes.cpp +++ b/src/gui/ProjectNotes.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -48,8 +47,8 @@ namespace lmms::gui { -ProjectNotes::ProjectNotes() : - QMainWindow( getGUI()->mainWindow()->workspace() ) +ProjectNotes::ProjectNotes() + : DetachableWindow{getGUI()->mainWindow()->workspace()} { m_edit = new QTextEdit( this ); m_edit->setAutoFillBackground( true ); @@ -389,25 +388,4 @@ void ProjectNotes::loadSettings( const QDomElement & _this ) m_edit->setHtml( _this.text() ); } - - - -void ProjectNotes::closeEvent( QCloseEvent * _ce ) -{ - if (windowFlags().testFlag(Qt::Window)) - { - _ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - _ce->ignore(); - } - else - { - hide(); - _ce->ignore(); - } - } - } // namespace lmms::gui diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index e61e5c1370c..e2beda7e21f 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -48,11 +48,11 @@ namespace lmms::gui { -SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : - QWidget(), - ModelView(nullptr, this), - m_track(tv->model()), - m_stv(tv) +SampleTrackWindow::SampleTrackWindow(SampleTrackView* stv) + : DetachableWidget{} + , ModelView{nullptr, this} + , m_track{stv->model()} + , m_stv{stv} { #if QT_VERSION < 0x50C00 // Workaround for a bug in Qt versions below 5.12, @@ -145,14 +145,14 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : generalSettingsLayout->addLayout(basicControlsLayout); - m_effectRack = new EffectRackView(tv->model()->audioPort()->effects()); + m_effectRack = new EffectRackView(stv->model()->audioPort()->effects()); m_effectRack->setFixedSize(EffectRackView::DEFAULT_WIDTH, 242); vlayout->addWidget(generalSettingsWidget); vlayout->addWidget(m_effectRack); - setModel(tv->model()); + setModel(stv->model()); QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget(this); Qt::WindowFlags flags = subWin->windowFlags(); @@ -244,20 +244,7 @@ void SampleTrackWindow::toggleVisibility(bool on) void SampleTrackWindow::closeEvent(QCloseEvent* ce) { - if (windowFlags().testFlag(Qt::Window)) - { - ce->accept(); - } - else if (getGUI()->mainWindow()->workspace()) - { - parentWidget()->hide(); - ce->ignore(); - } - else - { - hide(); - ce->ignore(); - } + DetachableWidget::closeEvent(ce); m_stv->m_tlb->setFocus(); m_stv->m_tlb->setChecked(false); @@ -265,10 +252,9 @@ void SampleTrackWindow::closeEvent(QCloseEvent* ce) -void SampleTrackWindow::saveSettings(QDomDocument& doc, QDomElement & element) +void SampleTrackWindow::saveSettings([[maybe_unused]] QDomDocument& doc, QDomElement& element) { MainWindow::saveWidgetState(this, element); - Q_UNUSED(element) } diff --git a/src/gui/editors/Editor.cpp b/src/gui/editors/Editor.cpp index 7091c094ba5..61d7391bb05 100644 --- a/src/gui/editors/Editor.cpp +++ b/src/gui/editors/Editor.cpp @@ -24,14 +24,11 @@ #include "Editor.h" -#include "Song.h" - -#include "embed.h" - #include #include -#include +#include "Song.h" +#include "embed.h" namespace lmms::gui { @@ -87,6 +84,7 @@ void Editor::toggleMaximize() } Editor::Editor(bool record, bool stepRecord) : + DetachableWindow(), m_toolBar(new DropToolBar(this)), m_playAction(nullptr), m_recordAction(nullptr), @@ -138,19 +136,6 @@ QAction *Editor::playAction() const return m_playAction; } -void Editor::closeEvent( QCloseEvent * _ce ) -{ - if( parentWidget() ) - { - parentWidget()->hide(); - } - else - { - hide(); - } - _ce->ignore(); - } - DropToolBar::DropToolBar(QWidget* parent) : QToolBar(parent) { setAcceptDrops(true); diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 5180687596e..f5a328cfb43 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -586,21 +586,6 @@ void SongEditor::wheelEvent( QWheelEvent * we ) -void SongEditor::closeEvent( QCloseEvent * ce ) -{ - if( parentWidget() ) - { - parentWidget()->hide(); - } - else - { - hide(); - } - ce->ignore(); -} - - - void SongEditor::mousePressEvent(QMouseEvent *me) { diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index c62655bf672..55eebdb3219 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -518,6 +518,7 @@ void InstrumentTrackWindow::toggleVisibility( bool on ) void InstrumentTrackWindow::closeEvent( QCloseEvent* event ) { + // TODO: When is this event used? if (windowFlags().testFlag(Qt::Window)) { event->accept(); From 2043cac8a5e8c0fee536f485ef566355f6d9dccc Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Sun, 19 Nov 2023 17:01:30 -0500 Subject: [PATCH 07/16] Fix Windows build --- include/DetachableWidget.h | 4 +++- include/DetachableWindow.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/DetachableWidget.h b/include/DetachableWidget.h index 35184137f70..12228e49728 100644 --- a/include/DetachableWidget.h +++ b/include/DetachableWidget.h @@ -28,9 +28,11 @@ #include +#include "lmms_export.h" + namespace lmms::gui { -class DetachableWidget : public QWidget +class LMMS_EXPORT DetachableWidget : public QWidget { Q_OBJECT public: diff --git a/include/DetachableWindow.h b/include/DetachableWindow.h index 5f0a81bfc20..bf3aa7b1aca 100644 --- a/include/DetachableWindow.h +++ b/include/DetachableWindow.h @@ -28,9 +28,11 @@ #include +#include "lmms_export.h" + namespace lmms::gui { -class DetachableWindow : public QMainWindow +class LMMS_EXPORT DetachableWindow : public QMainWindow { Q_OBJECT public: From bf922af3e8d93ec4bb9246cb2c9f7996ac3054c6 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Mon, 18 Dec 2023 03:39:05 -0500 Subject: [PATCH 08/16] Prevent resizing in detached Mixer and Sample Track windows --- include/DetachableWidget.h | 2 +- include/DetachableWindow.h | 2 +- src/gui/DetachableWidget.cpp | 6 ------ src/gui/DetachableWindow.cpp | 6 ------ src/gui/MixerView.cpp | 10 ++++++++++ src/gui/SampleTrackWindow.cpp | 9 +++++++++ src/gui/SubWindow.cpp | 34 +++++++++++++++++++++++++++++++--- 7 files changed, 52 insertions(+), 17 deletions(-) diff --git a/include/DetachableWidget.h b/include/DetachableWidget.h index 12228e49728..532dec3303f 100644 --- a/include/DetachableWidget.h +++ b/include/DetachableWidget.h @@ -36,7 +36,7 @@ class LMMS_EXPORT DetachableWidget : public QWidget { Q_OBJECT public: - explicit DetachableWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags{}); + using QWidget::QWidget; void closeEvent(QCloseEvent* ce) override; diff --git a/include/DetachableWindow.h b/include/DetachableWindow.h index bf3aa7b1aca..1636b4fad25 100644 --- a/include/DetachableWindow.h +++ b/include/DetachableWindow.h @@ -36,7 +36,7 @@ class LMMS_EXPORT DetachableWindow : public QMainWindow { Q_OBJECT public: - explicit DetachableWindow(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags{}); + using QMainWindow::QMainWindow; void closeEvent(QCloseEvent* ce) override; diff --git a/src/gui/DetachableWidget.cpp b/src/gui/DetachableWidget.cpp index 85f9c5b2359..be952e33e95 100644 --- a/src/gui/DetachableWidget.cpp +++ b/src/gui/DetachableWidget.cpp @@ -25,7 +25,6 @@ #include "DetachableWidget.h" -#include #include #include "GuiApplication.h" @@ -33,11 +32,6 @@ namespace lmms::gui { -DetachableWidget::DetachableWidget(QWidget* parent, Qt::WindowFlags f) - : QWidget{parent, f} -{ -} - void DetachableWidget::closeEvent(QCloseEvent* ce) { if (windowFlags().testFlag(Qt::Window)) diff --git a/src/gui/DetachableWindow.cpp b/src/gui/DetachableWindow.cpp index 33e0970c520..d86ac9447dd 100644 --- a/src/gui/DetachableWindow.cpp +++ b/src/gui/DetachableWindow.cpp @@ -25,7 +25,6 @@ #include "DetachableWindow.h" -#include #include #include "GuiApplication.h" @@ -33,11 +32,6 @@ namespace lmms::gui { -DetachableWindow::DetachableWindow(QWidget* parent, Qt::WindowFlags f) - : QMainWindow{parent, f} -{ -} - void DetachableWindow::closeEvent(QCloseEvent* ce) { if (windowFlags().testFlag(Qt::Window)) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 5e0e82d1e8f..9cf9fa53fdf 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -163,6 +163,15 @@ MixerView::MixerView() this, SLOT(updateFaders())); + // adjust window size + layout()->invalidate(); + resize(sizeHint()); + if (parentWidget()) + { + parentWidget()->resize(parentWidget()->sizeHint()); + } + setFixedHeight(height()); + // add ourself to workspace QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); Qt::WindowFlags flags = subWin->windowFlags(); @@ -170,6 +179,7 @@ MixerView::MixerView() subWin->setWindowFlags( flags ); layout()->setSizeConstraint( QLayout::SetMinimumSize ); subWin->layout()->setSizeConstraint( QLayout::SetMinAndMaxSize ); + subWin->setFixedHeight(subWin->height()); parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false ); parentWidget()->move( 5, 310 ); diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index e2beda7e21f..f76cb8a211d 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -160,6 +160,15 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView* stv) flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags(flags); + // adjust window size + layout()->invalidate(); + resize(sizeHint()); + if (parentWidget()) + { + parentWidget()->resize(parentWidget()->sizeHint()); + } + setFixedSize(size()); + // Hide the Size and Maximize options from the system menu // since the dialog size is fixed. QMenu * systemMenu = subWin->systemMenu(); diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index bcd7fe59cfd..d22a337bf7b 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -252,10 +252,24 @@ void SubWindow::setBorderColor( const QColor &c ) void SubWindow::detach() { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + if (isDetached()) { return; } - auto pos = mapToGlobal(widget()->pos()); - widget()->setWindowFlags(Qt::Window); + const auto pos = mapToGlobal(widget()->pos()); + + auto flags = windowFlags(); + flags |= Qt::Window; + flags &= ~Qt::Widget; + widget()->setWindowFlags(flags); widget()->show(); hide(); @@ -264,10 +278,24 @@ void SubWindow::detach() void SubWindow::attach() { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + if (!isDetached()) { return; } auto frame = widget()->windowHandle()->frameGeometry(); - widget()->setWindowFlags(Qt::Widget); + + auto flags = windowFlags(); + flags &= ~Qt::Window; + flags |= Qt::Widget; + widget()->setWindowFlags(flags); widget()->show(); show(); From a8fddfcd7b60b735eed0fc3288f83b35c658fe53 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Sun, 17 Nov 2024 13:16:38 -0500 Subject: [PATCH 09/16] fix detached windows being shown after toggleVisibility() is called (#7584) Signed-off-by: Dalton Messmer Co-authored-by: SpomJ --- src/gui/instrument/InstrumentTrackWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 55eebdb3219..a2fcc1a2ec4 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -510,6 +510,7 @@ void InstrumentTrackWindow::toggleVisibility( bool on ) else { parentWidget()->hide(); + hide(); } } From 114ae56e4c59561912c1e906c47507d868f5e005 Mon Sep 17 00:00:00 2001 From: SpomJ Date: Mon, 18 Nov 2024 01:03:53 +0300 Subject: [PATCH 10/16] fix wrong embedded rack constrains (resulting in add button not displayed) --- src/gui/ControllerRackView.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/ControllerRackView.cpp b/src/gui/ControllerRackView.cpp index c6bb7c6a936..d7d5ee8dee2 100644 --- a/src/gui/ControllerRackView.cpp +++ b/src/gui/ControllerRackView.cpp @@ -78,10 +78,15 @@ ControllerRackView::ControllerRackView() layout->addWidget( m_addButton ); this->setLayout( layout ); + QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); + + // TODO: Automate setting one of these, stop hardcoding title bar height + // Set dimensions for detached mode setFixedWidth(350); setMinimumHeight(200); - - QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); + // Set dimensions for embedded mode + subWin->setFixedWidth(350); + subWin->setMinimumHeight(230); // No maximize button Qt::WindowFlags flags = subWin->windowFlags(); From 72385ad3570183de90fe454df43bfe2d09149210 Mon Sep 17 00:00:00 2001 From: SpomJ Date: Mon, 18 Nov 2024 02:44:19 +0300 Subject: [PATCH 11/16] Prevent resizing detached instrument windows --- src/gui/instrument/InstrumentTrackWindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 30b1a0041fe..7f598636534 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -288,9 +288,13 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : if (!m_instrumentView->isResizable()) { flags |= Qt::MSWindowsFixedSizeDialogHint; // any better way than this? + setFixedSize(sizeHint()); + // this should replace that; it does not. Ask Qt why. + // Does the same thing, for detached detached windows, for other OSs. + } else { - subWin->setMaximumSize(m_instrumentView->maximumHeight() + 12, m_instrumentView->maximumWidth() + 208); - subWin->setMinimumSize( m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); + subWin->setMaximumSize(m_instrumentView->maximumWidth() + 12, m_instrumentView->maximumHeight() + 208); + subWin->setMinimumSize(m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); } flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); From 041bdf8f301fc4d26ec76ed673592ec57319fce9 Mon Sep 17 00:00:00 2001 From: SpomJ Date: Mon, 18 Nov 2024 21:05:54 +0300 Subject: [PATCH 12/16] Fix microtuner config window being unable to closed while detached --- include/MicrotunerConfig.h | 8 ++------ src/gui/MicrotunerConfig.cpp | 10 +--------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/include/MicrotunerConfig.h b/include/MicrotunerConfig.h index 0706a530f54..dc3632b87dd 100644 --- a/include/MicrotunerConfig.h +++ b/include/MicrotunerConfig.h @@ -25,10 +25,9 @@ #ifndef LMMS_GUI_MICROTUNER_CONFIG_H #define LMMS_GUI_MICROTUNER_CONFIG_H -#include - #include "AutomatableModel.h" #include "ComboBoxModel.h" +#include "DetachableWidget.h" #include "SerializingObject.h" class QLineEdit; @@ -38,7 +37,7 @@ namespace lmms::gui { -class LMMS_EXPORT MicrotunerConfig : public QWidget, public SerializingObject +class LMMS_EXPORT MicrotunerConfig : public DetachableWidget, public SerializingObject { Q_OBJECT public: @@ -59,9 +58,6 @@ public slots: void updateScaleForm(); void updateKeymapForm(); -protected: - void closeEvent(QCloseEvent *ce) override; - private slots: bool loadScaleFromFile(); bool loadKeymapFromFile(); diff --git a/src/gui/MicrotunerConfig.cpp b/src/gui/MicrotunerConfig.cpp index 20660df4110..783c65e2870 100644 --- a/src/gui/MicrotunerConfig.cpp +++ b/src/gui/MicrotunerConfig.cpp @@ -55,7 +55,7 @@ namespace lmms::gui MicrotunerConfig::MicrotunerConfig() : - QWidget(), + DetachableWidget(), m_scaleComboModel(nullptr, tr("Selected scale slot")), m_keymapComboModel(nullptr, tr("Selected keymap slot")), m_firstKeyModel(0, 0, NumKeys - 1, nullptr, tr("First key")), @@ -680,12 +680,4 @@ void MicrotunerConfig::loadSettings(const QDomElement &element) } -void MicrotunerConfig::closeEvent(QCloseEvent *ce) -{ - if (parentWidget()) {parentWidget()->hide();} - else {hide();} - ce->ignore(); -} - - } // namespace lmms::gui From 9961644f789dbf49c199bd1008d346dcccbfa783 Mon Sep 17 00:00:00 2001 From: SpomJ Date: Wed, 20 Nov 2024 17:39:12 +0300 Subject: [PATCH 13/16] Transition SimpleTextFloat to QToolTip to enable displaying it outside windows --- include/SimpleTextFloat.h | 4 ++-- src/gui/widgets/SimpleTextFloat.cpp | 25 ++++++++++--------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h index bde6c84faab..069c28623c4 100644 --- a/include/SimpleTextFloat.h +++ b/include/SimpleTextFloat.h @@ -30,7 +30,6 @@ #include "lmms_export.h" -class QLabel; class QTimer; namespace lmms::gui @@ -55,9 +54,10 @@ class LMMS_EXPORT SimpleTextFloat : public QWidget } void hide(); + void show(); private: - QLabel * m_textLabel; + QString m_text; QTimer * m_showTimer; QTimer * m_hideTimer; }; diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index e37753229ac..17ff3f77694 100644 --- a/src/gui/widgets/SimpleTextFloat.cpp +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -25,26 +25,16 @@ #include "SimpleTextFloat.h" #include -#include -#include -#include - -#include "GuiApplication.h" -#include "MainWindow.h" +#include namespace lmms::gui { SimpleTextFloat::SimpleTextFloat() : - QWidget(getGUI()->mainWindow(), Qt::ToolTip) + QWidget() { - QHBoxLayout * layout = new QHBoxLayout(this); - layout->setMargin(3); - setLayout(layout); - - m_textLabel = new QLabel(this); - layout->addWidget(m_textLabel); + m_text = QString(); m_showTimer = new QTimer(this); m_showTimer->setSingleShot(true); @@ -57,7 +47,7 @@ SimpleTextFloat::SimpleTextFloat() : void SimpleTextFloat::setText(const QString & text) { - m_textLabel->setText(text); + m_text = text; } void SimpleTextFloat::showWithDelay(int msecBeforeDisplay, int msecDisplayTime) @@ -77,11 +67,16 @@ void SimpleTextFloat::showWithDelay(int msecBeforeDisplay, int msecDisplayTime) } } +void SimpleTextFloat::show() +{ + QToolTip::showText(mapToGlobal(QPoint(0, 0)), m_text); +} + void SimpleTextFloat::hide() { m_showTimer->stop(); m_hideTimer->stop(); - QWidget::hide(); + QToolTip::hideText(); } void SimpleTextFloat::setVisibilityTimeOut(int msecs) From adce178d2427a412d6e193992fae74a172c7f88c Mon Sep 17 00:00:00 2001 From: SpomJ <75751809+SpomJ@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:38:59 +0300 Subject: [PATCH 14/16] fix windows doing offscreen when attached on wayland (#7592) --- src/gui/SubWindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index a9b09464c68..533777d32ac 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -29,6 +29,7 @@ #include "SubWindow.h" #include +#include #include #include #include @@ -303,7 +304,10 @@ void SubWindow::attach() // visible first, so that resizing works. QObject obj; connect(&obj, &QObject::destroyed, this, [this, frame]() { - move(mdiArea()->mapFromGlobal(frame.topLeft())); + if (QGuiApplication::platformName() != "wayland") + { // Workaround for wayland reporting on-screen pos as 0-0. If ever solved on wayland side, this check is safe to remove. + move(mdiArea()->mapFromGlobal(frame.topLeft())); + } resize(frame.size()); }, Qt::QueuedConnection); } From c85b4982b048d4067ed5470788febd6f451c7de9 Mon Sep 17 00:00:00 2001 From: SpomJ <75751809+SpomJ@users.noreply.github.com> Date: Tue, 3 Dec 2024 23:19:25 +0300 Subject: [PATCH 15/16] [feature/detach-window] Transfer size restrictions to embedded widget from SubWindow (#7596) * Improve the way size constraints are placed * Transition VeSTige to patched SubWindow (fix missing minimize button and constraint issues) * Move window constraints to embed in LadspaBrowser (fix resizing) * Fix detached window resizeability for TapTempo * Codestyle --- plugins/LadspaBrowser/LadspaBrowser.cpp | 9 ++------- plugins/TapTempo/TapTempoView.cpp | 2 +- plugins/Vestige/Vestige.cpp | 9 +++------ plugins/Vestige/Vestige.h | 3 ++- src/gui/ControllerRackView.cpp | 7 +------ src/gui/MicrotunerConfig.cpp | 9 +++------ src/gui/MidiCCRackView.cpp | 7 +++---- src/gui/MixerView.cpp | 10 ++-------- src/gui/SubWindow.cpp | 4 ++++ src/gui/instrument/InstrumentTrackWindow.cpp | 6 +++--- src/gui/widgets/TempoSyncBarModelEditor.cpp | 4 ++-- src/gui/widgets/TempoSyncKnob.cpp | 4 ++-- 12 files changed, 28 insertions(+), 46 deletions(-) diff --git a/plugins/LadspaBrowser/LadspaBrowser.cpp b/plugins/LadspaBrowser/LadspaBrowser.cpp index e6a31e15a3c..6f2111234dc 100644 --- a/plugins/LadspaBrowser/LadspaBrowser.cpp +++ b/plugins/LadspaBrowser/LadspaBrowser.cpp @@ -140,18 +140,13 @@ LadspaBrowserView::LadspaBrowserView( ToolPlugin * _tool ) : hlayout->addWidget( ws ); hlayout->addSpacing( 10 ); hlayout->addStretch(); + + layout()->setSizeConstraint(QLayout::SetFixedSize); hide(); if( parentWidget() ) { parentWidget()->hide(); - parentWidget()->layout()->setSizeConstraint( - QLayout::SetFixedSize ); - - Qt::WindowFlags flags = parentWidget()->windowFlags(); - flags |= Qt::MSWindowsFixedSizeDialogHint; - flags &= ~Qt::WindowMaximizeButtonHint; - parentWidget()->setWindowFlags( flags ); } } diff --git a/plugins/TapTempo/TapTempoView.cpp b/plugins/TapTempo/TapTempoView.cpp index ed451eaa50e..9d6c58fa8c7 100644 --- a/plugins/TapTempo/TapTempoView.cpp +++ b/plugins/TapTempo/TapTempoView.cpp @@ -129,10 +129,10 @@ TapTempoView::TapTempoView(TapTempo* plugin) }); hide(); + layout()->setSizeConstraint(QLayout::SetFixedSize); if (parentWidget()) { parentWidget()->hide(); - parentWidget()->layout()->setSizeConstraint(QLayout::SetFixedSize); Qt::WindowFlags flags = parentWidget()->windowFlags(); flags |= Qt::MSWindowsFixedSizeDialogHint; diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp index 552f76406de..7c916f3a06b 100644 --- a/plugins/Vestige/Vestige.cpp +++ b/plugins/Vestige/Vestige.cpp @@ -937,12 +937,9 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume widget = new QWidget(this); l = new QGridLayout( this ); - m_vi->m_subWindow = getGUI()->mainWindow()->addWindowedWidget(nullptr, Qt::SubWindow | - Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); - m_vi->m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding ); - m_vi->m_subWindow->setFixedWidth( 960 ); - m_vi->m_subWindow->setMinimumHeight( 300 ); - m_vi->m_subWindow->setWidget(m_vi->m_scrollArea); + m_vi->m_subWindow = getGUI()->mainWindow()->addWindowedWidget(m_vi->m_scrollArea); + m_vi->m_scrollArea->setFixedWidth(960); + m_vi->m_scrollArea->setMinimumHeight(300); m_vi->m_subWindow->setWindowTitle( m_vi->instrumentTrack()->name() + tr( " - VST plugin control" ) ); m_vi->m_subWindow->setWindowIcon( PLUGIN_NAME::getIconPixmap( "logo" ) ); diff --git a/plugins/Vestige/Vestige.h b/plugins/Vestige/Vestige.h index 6a308ad2c20..4dcc0b8e5d8 100644 --- a/plugins/Vestige/Vestige.h +++ b/plugins/Vestige/Vestige.h @@ -32,6 +32,7 @@ #include "Instrument.h" #include "InstrumentView.h" +#include "SubWindow.h" class QPixmap; @@ -87,7 +88,7 @@ protected slots: QMutex m_pluginMutex; QString m_pluginDLL; - QMdiSubWindow * m_subWindow; + gui::SubWindow* m_subWindow; QScrollArea * m_scrollArea; FloatModel ** knobFModel; QObject * p_subWindow; diff --git a/src/gui/ControllerRackView.cpp b/src/gui/ControllerRackView.cpp index d7d5ee8dee2..9b49dd47cca 100644 --- a/src/gui/ControllerRackView.cpp +++ b/src/gui/ControllerRackView.cpp @@ -78,15 +78,10 @@ ControllerRackView::ControllerRackView() layout->addWidget( m_addButton ); this->setLayout( layout ); - QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this ); + SubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget(this); - // TODO: Automate setting one of these, stop hardcoding title bar height - // Set dimensions for detached mode setFixedWidth(350); setMinimumHeight(200); - // Set dimensions for embedded mode - subWin->setFixedWidth(350); - subWin->setMinimumHeight(230); // No maximize button Qt::WindowFlags flags = subWin->windowFlags(); diff --git a/src/gui/MicrotunerConfig.cpp b/src/gui/MicrotunerConfig.cpp index 783c65e2870..0fa1f09eeeb 100644 --- a/src/gui/MicrotunerConfig.cpp +++ b/src/gui/MicrotunerConfig.cpp @@ -202,13 +202,10 @@ MicrotunerConfig::MicrotunerConfig() : this->setLayout(microtunerLayout); // Add to the main window and setup fixed size etc. - QMdiSubWindow *subWin = getGUI()->mainWindow()->addWindowedWidget(this); - + SubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget(this); subWin->setAttribute(Qt::WA_DeleteOnClose, false); - subWin->setMinimumWidth(300); - subWin->setMinimumHeight(300); - subWin->setMaximumWidth(500); - subWin->setMaximumHeight(700); + setMinimumSize(300, 300); + setMaximumSize(500, 700); subWin->hide(); // No maximize button diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index a0b1496fb54..84d377d5ff9 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -49,7 +49,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : setWindowIcon(embed::getIconPixmap("midi_cc_rack")); setWindowTitle(tr("MIDI CC Rack - %1").arg(m_track->name())); - QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget(this); + SubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget(this); // Remove maximize button Qt::WindowFlags flags = subWin->windowFlags(); @@ -58,9 +58,8 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Adjust window attributes, sizing and position subWin->setAttribute(Qt::WA_DeleteOnClose, false); - subWin->resize(350, 300); - subWin->setFixedWidth(350); - subWin->setMinimumHeight(300); + setFixedWidth(350); + setMinimumHeight(300); subWin->hide(); // Main window layout diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index e34e4ecbb97..d38b07330da 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -169,17 +169,11 @@ MixerView::MixerView(Mixer* mixer) : // adjust window size layout()->invalidate(); resize(sizeHint()); - if (parentWidget()) - { - parentWidget()->resize(parentWidget()->sizeHint()); - } setFixedHeight(height()); + layout()->setSizeConstraint(QLayout::SetMinimumSize); // add ourself to workspace - QMdiSubWindow* subWin = mainWindow->addWindowedWidget(this); - layout()->setSizeConstraint(QLayout::SetMinimumSize); - subWin->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize); - subWin->setFixedHeight(subWin->height()); + [[maybe_unused]] SubWindow* subWin = mainWindow->addWindowedWidget(this); parentWidget()->setAttribute(Qt::WA_DeleteOnClose, false); parentWidget()->move(5, 310); diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 533777d32ac..05d240aed63 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "embed.h" @@ -93,6 +94,8 @@ SubWindow::SubWindow(QWidget *parent, Qt::WindowFlags windowFlags) : m_windowTitle->setAttribute( Qt::WA_TransparentForMouseEvents, true ); m_windowTitle->setGraphicsEffect( m_shadow ); + layout()->setSizeConstraint(QLayout::SetMinAndMaxSize); + // Disable the minimize button and make sure that the custom window hint is set setWindowFlags((this->windowFlags() & ~Qt::WindowMinimizeButtonHint) | Qt::CustomizeWindowHint); @@ -518,4 +521,5 @@ bool SubWindow::eventFilter(QObject* obj, QEvent* event) } } + } // namespace lmms::gui diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 7f598636534..f98a985d98c 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -283,7 +283,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : updateInstrumentView(); - QMdiSubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget( this ); + SubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget( this ); Qt::WindowFlags flags = subWin->windowFlags(); if (!m_instrumentView->isResizable()) { flags |= Qt::MSWindowsFixedSizeDialogHint; @@ -293,8 +293,8 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // Does the same thing, for detached detached windows, for other OSs. } else { - subWin->setMaximumSize(m_instrumentView->maximumWidth() + 12, m_instrumentView->maximumHeight() + 208); - subWin->setMinimumSize(m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); + setMaximumSize(m_instrumentView->maximumWidth() + 12, m_instrumentView->maximumHeight() + 208); + setMinimumSize(m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); } flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); diff --git a/src/gui/widgets/TempoSyncBarModelEditor.cpp b/src/gui/widgets/TempoSyncBarModelEditor.cpp index 5ff2332e051..acf8dde6210 100644 --- a/src/gui/widgets/TempoSyncBarModelEditor.cpp +++ b/src/gui/widgets/TempoSyncBarModelEditor.cpp @@ -202,11 +202,11 @@ void TempoSyncBarModelEditor::showCustom() if(m_custom == nullptr) { m_custom = new MeterDialog(getGUI()->mainWindow()->workspace()); - QMdiSubWindow * subWindow = getGUI()->mainWindow()->addWindowedWidget(m_custom); + SubWindow* subWindow = getGUI()->mainWindow()->addWindowedWidget(m_custom); Qt::WindowFlags flags = subWindow->windowFlags(); flags &= ~Qt::WindowMaximizeButtonHint; subWindow->setWindowFlags(flags); - subWindow->setFixedSize(subWindow->size()); + setFixedSize(size()); m_custom->setWindowTitle("Meter"); m_custom->setModel(&model()->getCustomMeterModel()); } diff --git a/src/gui/widgets/TempoSyncKnob.cpp b/src/gui/widgets/TempoSyncKnob.cpp index 473cee28ca9..df9b50eb2f8 100644 --- a/src/gui/widgets/TempoSyncKnob.cpp +++ b/src/gui/widgets/TempoSyncKnob.cpp @@ -295,11 +295,11 @@ void TempoSyncKnob::showCustom() if( m_custom == nullptr ) { m_custom = new MeterDialog( getGUI()->mainWindow()->workspace() ); - QMdiSubWindow * subWindow = getGUI()->mainWindow()->addWindowedWidget( m_custom ); + SubWindow* subWindow = getGUI()->mainWindow()->addWindowedWidget(m_custom); Qt::WindowFlags flags = subWindow->windowFlags(); flags &= ~Qt::WindowMaximizeButtonHint; subWindow->setWindowFlags( flags ); - subWindow->setFixedSize( subWindow->size() ); + setFixedSize(size()); m_custom->setWindowTitle( "Meter" ); m_custom->setModel( &model()->m_custom ); } From 439e9d393d645b7c7f18851ad51893abac9558a3 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Mon, 3 Feb 2025 18:10:56 -0500 Subject: [PATCH 16/16] Fix regression from merge --- src/gui/instrument/InstrumentTrackWindow.cpp | 30 ++++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index a4825f12d7d..b3853059831 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -667,7 +667,7 @@ void InstrumentTrackWindow::viewInstrumentInDirection(int d) // enable the new window by checking its track list button & moving it to where our window just was newView->m_tlb->setChecked(true); - newView->getInstrumentTrackWindow()->parentWidget()->move(curPos); + newView->getInstrumentTrackWindow()->parentWidget()->move(curPos); // TODO // scroll the SongEditor/PatternEditor to make sure the new trackview label is visible bringToFront->trackContainerView()->scrollToTrackView(bringToFront); @@ -677,13 +677,8 @@ void InstrumentTrackWindow::viewInstrumentInDirection(int d) } Q_ASSERT(bringToFront); bringToFront->getInstrumentTrackWindow()->setFocus(); - Qt::WindowFlags flags = windowFlags(); - if (!m_instrumentView->isResizable()) { - flags |= Qt::MSWindowsFixedSizeDialogHint; - } else { - flags &= ~Qt::MSWindowsFixedSizeDialogHint; - } - setWindowFlags( flags ); + + updateSubWindow(); } void InstrumentTrackWindow::viewNextInstrument() @@ -738,8 +733,8 @@ void InstrumentTrackWindow::updateSubWindow() { // TODO As of writing SlicerT is the only resizable instrument. Is this code specific to SlicerT? const auto extraSpace = QSize(12, 208); - subWindow->setMaximumSize(m_instrumentView->maximumSize() + extraSpace); - subWindow->setMinimumSize(m_instrumentView->minimumSize() + extraSpace); + setMaximumSize(m_instrumentView->maximumSize() + extraSpace); + setMinimumSize(m_instrumentView->minimumSize() + extraSpace); flags &= ~Qt::MSWindowsFixedSizeDialogHint; flags |= Qt::WindowMaximizeButtonHint; @@ -749,6 +744,8 @@ void InstrumentTrackWindow::updateSubWindow() flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; + setFixedSize(sizeHint()); + // The sub window might be reused from an instrument that was maximized. Show the sub window // as normal, i.e. not maximized, if the instrument view is not resizable. if (subWindow->isMaximized()) @@ -759,11 +756,6 @@ void InstrumentTrackWindow::updateSubWindow() subWindow->setWindowFlags(flags); - // Show or hide the Size and Maximize options from the system menu depending on whether the view is resizable or not - QMenu * systemMenu = subWindow->systemMenu(); - systemMenu->actions().at(2)->setVisible(instrumentViewResizable); // Size - systemMenu->actions().at(4)->setVisible(instrumentViewResizable); // Maximize - // TODO This is only needed if the sub window is implemented with LMMS' own SubWindow class. // If an QMdiSubWindow is used everything works automatically. It seems that SubWindow is // missing some implementation details that QMdiSubWindow has. @@ -772,6 +764,14 @@ void InstrumentTrackWindow::updateSubWindow() { subWin->updateTitleBar(); } + else + { + // TODO: Can this be removed? + // Show or hide the Size and Maximize options from the system menu depending on whether the view is resizable or not + QMenu* systemMenu = subWindow->systemMenu(); + systemMenu->actions().at(2)->setVisible(instrumentViewResizable); // Size + systemMenu->actions().at(4)->setVisible(instrumentViewResizable); // Maximize + } } }