diff --git a/data/themes/default/detach.svg b/data/themes/default/detach.svg
new file mode 100644
index 000000000..337e36608
--- /dev/null
+++ b/data/themes/default/detach.svg
@@ -0,0 +1,6 @@
+
diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h
index 0c53a8c84..a8803de60 100644
--- a/include/ControllerDialog.h
+++ b/include/ControllerDialog.h
@@ -40,22 +40,10 @@ namespace gui
class ControllerDialog : public QWidget, 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 02f90b623..f54b3e1a1 100644
--- a/include/ControllerRackView.h
+++ b/include/ControllerRackView.h
@@ -29,7 +29,6 @@
#include "SerializingObject.h"
-
class QPushButton;
class QScrollArea;
class QVBoxLayout;
@@ -45,7 +44,6 @@ namespace gui
class ControllerView;
-
class ControllerRackView : public QWidget, public SerializingObject
{
Q_OBJECT
@@ -69,9 +67,6 @@ public slots:
void addController(Controller* controller);
void removeController(Controller* controller);
-protected:
- void closeEvent( QCloseEvent * _ce ) override;
-
private slots:
void addController();
diff --git a/include/ControllerView.h b/include/ControllerView.h
index 9b442672d..03fb1ec32 100644
--- a/include/ControllerView.h
+++ b/include/ControllerView.h
@@ -64,7 +64,6 @@ public:
public slots:
void editControls();
void removeController();
- void closeControls();
void renameController();
void moveUp();
void moveDown();
@@ -85,9 +84,7 @@ private:
QMdiSubWindow * m_subWindow;
ControllerDialog * m_controllerDlg;
QLabel * m_nameLabel;
- bool m_show;
-
-} ;
+};
} // namespace lmms::gui
diff --git a/include/Editor.h b/include/Editor.h
index 4687d0448..2141717af 100644
--- a/include/Editor.h
+++ b/include/Editor.h
@@ -57,8 +57,8 @@ protected:
DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle);
DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle);
- void closeEvent(QCloseEvent * event) override;
- void keyPressEvent(QKeyEvent *ke) override;
+ void keyPressEvent(QKeyEvent* ke) override;
+
public slots:
//! Called by pressing the space key. Plays or stops.
void togglePlayStop();
diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h
index 4bef5ee79..5f475594c 100644
--- a/include/EffectControlDialog.h
+++ b/include/EffectControlDialog.h
@@ -35,30 +35,18 @@ namespace lmms
class EffectControls;
-
namespace gui
{
class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView
{
- Q_OBJECT
public:
- EffectControlDialog( EffectControls * _controls );
+ EffectControlDialog(EffectControls* controls);
~EffectControlDialog() override = default;
- virtual bool isResizable() const {return false;}
-
-
-signals:
- void closed();
-
-
protected:
- void closeEvent( QCloseEvent * _ce ) override;
-
- EffectControls * m_effectControls;
-
-} ;
+ EffectControls* m_effectControls;
+};
} // namespace gui
diff --git a/include/EffectView.h b/include/EffectView.h
index cd45b735e..bb9c91498 100644
--- a/include/EffectView.h
+++ b/include/EffectView.h
@@ -73,8 +73,6 @@ public slots:
void moveUp();
void moveDown();
void deletePlugin();
- void closeEffects();
-
signals:
void movedUp(EffectView* view);
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 5f0f23f71..40d376fe3 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -141,9 +141,13 @@ public:
static void saveWidgetState( QWidget * _w, QDomElement & _de );
static void restoreWidgetState( QWidget * _w, const QDomElement & _de );
+ void setAllSubWindowsDetached(bool detached);
bool eventFilter(QObject* watched, QEvent* event) override;
+signals:
+ void detachAllSubWindows(bool detached);
+
public slots:
void resetWindowTitle();
diff --git a/include/MicrotunerConfig.h b/include/MicrotunerConfig.h
index 0706a530f..13d4bbc97 100644
--- a/include/MicrotunerConfig.h
+++ b/include/MicrotunerConfig.h
@@ -59,9 +59,6 @@ public slots:
void updateScaleForm();
void updateKeymapForm();
-protected:
- void closeEvent(QCloseEvent *ce) override;
-
private slots:
bool loadScaleFromFile();
bool loadKeymapFromFile();
diff --git a/include/MixerView.h b/include/MixerView.h
index 6d9fded64..ac95b3c68 100644
--- a/include/MixerView.h
+++ b/include/MixerView.h
@@ -44,8 +44,11 @@ namespace lmms
namespace lmms::gui
{
-class LMMS_EXPORT MixerView : public QWidget, public ModelView,
- public SerializingObjectHook
+
+class LMMS_EXPORT MixerView
+ : public QWidget
+ , public ModelView
+ , public SerializingObjectHook
{
Q_OBJECT
public:
@@ -94,9 +97,6 @@ public:
public slots:
int addNewChannel();
-protected:
- void closeEvent(QCloseEvent* ce) override;
-
private slots:
void updateFaders();
// TODO This should be improved. Currently the solo and mute models are connected via
diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h
index 861dcb4a8..daa7436b9 100644
--- a/include/ProjectNotes.h
+++ b/include/ProjectNotes.h
@@ -58,7 +58,6 @@ public:
protected:
- void closeEvent( QCloseEvent * _ce ) override;
void setupActions();
diff --git a/include/SampleTrackWindow.h b/include/SampleTrackWindow.h
index 05e38fd2f..47ce765f1 100644
--- a/include/SampleTrackWindow.h
+++ b/include/SampleTrackWindow.h
@@ -47,7 +47,7 @@ class SampleTrackWindow : public QWidget, public ModelView, public SerializingOb
{
Q_OBJECT
public:
- SampleTrackWindow(SampleTrackView * tv);
+ SampleTrackWindow(SampleTrackView* stv);
~SampleTrackWindow() override = default;
SampleTrack * model()
@@ -76,7 +76,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/SetupDialog.h b/include/SetupDialog.h
index a382df917..a82d21ace 100644
--- a/include/SetupDialog.h
+++ b/include/SetupDialog.h
@@ -85,6 +85,7 @@ private slots:
void toggleMMPZ(bool enabled);
void toggleDisableBackup(bool enabled);
void toggleOpenLastProject(bool enabled);
+ void detachBehaviorChanged();
void loopMarkerModeChanged();
void setLanguage(int lang);
@@ -147,6 +148,8 @@ private:
bool m_MMPZ;
bool m_disableBackup;
bool m_openLastProject;
+ QString m_detachBehavior;
+ QComboBox* m_detachBehaviorComboBox;
QString m_loopMarkerMode;
QComboBox* m_loopMarkerComboBox;
QString m_autoScroll;
diff --git a/include/SongEditor.h b/include/SongEditor.h
index 932d026be..afbcc5141 100644
--- a/include/SongEditor.h
+++ b/include/SongEditor.h
@@ -94,7 +94,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/include/SubWindow.h b/include/SubWindow.h
index 246bbdd9f..a29378fcf 100644
--- a/include/SubWindow.h
+++ b/include/SubWindow.h
@@ -63,24 +63,34 @@ public:
QBrush activeColor() const;
QColor textShadowColor() const;
QColor borderColor() const;
+ QMargins decorationMargins() const;
void setActiveColor( const QBrush & b );
void setTextShadowColor( const QColor &c );
void setBorderColor( const QColor &c );
int titleBarHeight() const;
int frameWidth() const;
+ bool isDetachable() const;
+ void setDetachable(bool on);
+ bool isDetached() const;
+ void setDetached(bool on);
// TODO Needed to update the title bar when replacing instruments.
// Update works automatically if QMdiSubWindows are used.
void updateTitleBar();
+public slots:
+ void detach();
+ void attach();
+ void setVisible(bool visible) override;
+
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;
-
- QPushButton* addTitleButton(const std::string& iconName, const QString& toolTip);
+ void moveEvent(QMoveEvent* event) override;
+ void resizeEvent(QResizeEvent* event) override;
+ void paintEvent(QPaintEvent* pe) override;
+ void changeEvent(QEvent* event) override;
+ void showEvent(QShowEvent* e) override;
+ bool eventFilter(QObject* obj, QEvent* event) override;
signals:
void focusLost();
@@ -91,6 +101,7 @@ private:
QPushButton * m_closeBtn;
QPushButton * m_maximizeBtn;
QPushButton * m_restoreBtn;
+ QPushButton* m_detachBtn;
QBrush m_activeColor;
QColor m_textShadowColor;
QColor m_borderColor;
@@ -99,6 +110,7 @@ private:
QLabel * m_windowTitle;
QGraphicsDropShadowEffect * m_shadow;
bool m_hasFocus;
+ bool m_isDetachable;
static void elideText( QLabel *label, QString text );
void adjustTitleBar();
diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp
index 9bf0bb649..44c0e3be2 100644
--- a/plugins/Amplifier/AmplifierControlDialog.cpp
+++ b/plugins/Amplifier/AmplifierControlDialog.cpp
@@ -57,6 +57,7 @@ AmplifierControlDialog::AmplifierControlDialog(AmplifierControls* controls) :
gridLayout->addWidget(makeKnob(tr("PAN"), tr("Panning:"), "%", &controls->m_panModel, false), 0, 1, Qt::AlignHCenter);
gridLayout->addWidget(makeKnob(tr("LEFT"), tr("Left gain:"), "%", &controls->m_leftModel, true), 1, 0, Qt::AlignHCenter);
gridLayout->addWidget(makeKnob(tr("RIGHT"), tr("Right gain:"), "%", &controls->m_rightModel, true), 1, 1, Qt::AlignHCenter);
+ gridLayout->setSizeConstraint(QLayout::SetFixedSize);
}
} // namespace lmms::gui
diff --git a/plugins/BassBooster/BassBoosterControlDialog.cpp b/plugins/BassBooster/BassBoosterControlDialog.cpp
index fcdf10cc2..93708dbd7 100644
--- a/plugins/BassBooster/BassBoosterControlDialog.cpp
+++ b/plugins/BassBooster/BassBoosterControlDialog.cpp
@@ -67,6 +67,7 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control
tl->addLayout( l );
setLayout( tl );
+ tl->setSizeConstraint(QLayout::SetFixedSize);
}
diff --git a/plugins/Compressor/CompressorControlDialog.h b/plugins/Compressor/CompressorControlDialog.h
index b7e2a87e1..7fe79dcc5 100755
--- a/plugins/Compressor/CompressorControlDialog.h
+++ b/plugins/Compressor/CompressorControlDialog.h
@@ -71,7 +71,6 @@ class CompressorControlDialog : public EffectControlDialog
public:
CompressorControlDialog(CompressorControls* controls);
- bool isResizable() const override {return true;}
QSize sizeHint() const override {return QSize(COMP_SCREEN_X, COMP_SCREEN_Y);}
// For theming purposes
diff --git a/plugins/Dispersion/DispersionControlDialog.cpp b/plugins/Dispersion/DispersionControlDialog.cpp
index fbf37923c..2784da35c 100644
--- a/plugins/Dispersion/DispersionControlDialog.cpp
+++ b/plugins/Dispersion/DispersionControlDialog.cpp
@@ -43,6 +43,7 @@ DispersionControlDialog::DispersionControlDialog(DispersionControls* controls) :
setAutoFillBackground(true);
auto layout = new QHBoxLayout(this);
layout->setSpacing(5);
+ layout->setSizeConstraint(QLayout::SetFixedSize);
auto amountBox = new LcdSpinBox(3, this, "Amount");
amountBox->setModel(&controls->m_amountModel);
diff --git a/plugins/Flanger/FlangerControlsDialog.cpp b/plugins/Flanger/FlangerControlsDialog.cpp
index 7433a6b2c..e8d382e52 100644
--- a/plugins/Flanger/FlangerControlsDialog.cpp
+++ b/plugins/Flanger/FlangerControlsDialog.cpp
@@ -44,6 +44,7 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
setPalette( pal );
auto mainLayout = new QVBoxLayout(this);
+ mainLayout->setSizeConstraint(QLayout::SetFixedSize);
auto knobLayout = new QHBoxLayout();
mainLayout->addLayout(knobLayout);
diff --git a/plugins/LadspaBrowser/LadspaBrowser.cpp b/plugins/LadspaBrowser/LadspaBrowser.cpp
index e6a31e15a..6f2111234 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/LadspaEffect/LadspaMatrixControlDialog.cpp b/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp
index f8cfbe3b3..134e0de02 100644
--- a/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp
+++ b/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp
@@ -47,6 +47,7 @@ LadspaMatrixControlDialog::LadspaMatrixControlDialog(LadspaControls * ladspaCont
m_stereoLink(nullptr)
{
QVBoxLayout * mainLayout = new QVBoxLayout(this);
+ mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
m_scrollArea = new QScrollArea(this);
m_scrollArea->setWidgetResizable(true);
@@ -72,11 +73,6 @@ LadspaMatrixControlDialog::LadspaMatrixControlDialog(LadspaControls * ladspaCont
}
}
-bool LadspaMatrixControlDialog::isResizable() const
-{
- return true;
-}
-
bool LadspaMatrixControlDialog::needsLinkColumn() const
{
LadspaControls * ladspaControls = getLadspaControls();
diff --git a/plugins/LadspaEffect/LadspaMatrixControlDialog.h b/plugins/LadspaEffect/LadspaMatrixControlDialog.h
index fa9a6e1b3..0189c8159 100644
--- a/plugins/LadspaEffect/LadspaMatrixControlDialog.h
+++ b/plugins/LadspaEffect/LadspaMatrixControlDialog.h
@@ -50,7 +50,6 @@ class LadspaMatrixControlDialog : public EffectControlDialog
Q_OBJECT
public:
LadspaMatrixControlDialog(LadspaControls* ctl);
- bool isResizable() const override;
private slots:
void updateEffectView(LadspaControls* ctl);
diff --git a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
index 7ce05bc45..d89ef02bf 100644
--- a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
+++ b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
@@ -95,6 +95,8 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog(
mainLayout->addLayout( knobLayout );
mainLayout->addLayout( ledLayout );
+ mainLayout->setSizeConstraint(QLayout::SetFixedSize);
+
setLayout( mainLayout );
}
diff --git a/plugins/ReverbSC/ReverbSCControlDialog.cpp b/plugins/ReverbSC/ReverbSCControlDialog.cpp
index 3be156396..d507a8792 100644
--- a/plugins/ReverbSC/ReverbSCControlDialog.cpp
+++ b/plugins/ReverbSC/ReverbSCControlDialog.cpp
@@ -44,6 +44,7 @@ ReverbSCControlDialog::ReverbSCControlDialog( ReverbSCControls* controls ) :
setPalette( pal );
auto knobLayout = new QHBoxLayout(this);
+ knobLayout->setSizeConstraint(QLayout::SetFixedSize);
auto inputGainKnob = new Knob(KnobType::Bright26, tr("Input"), this);
inputGainKnob->setModel( &controls->m_inputGainModel );
@@ -68,4 +69,4 @@ ReverbSCControlDialog::ReverbSCControlDialog( ReverbSCControls* controls ) :
}
-} // namespace lmms::gui
\ No newline at end of file
+} // namespace lmms::gui
diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.h b/plugins/SpectrumAnalyzer/SaControlsDialog.h
index f8d67f1e8..8567561f3 100644
--- a/plugins/SpectrumAnalyzer/SaControlsDialog.h
+++ b/plugins/SpectrumAnalyzer/SaControlsDialog.h
@@ -48,7 +48,6 @@ public:
explicit SaControlsDialog(SaControls *controls, SaProcessor *processor);
~SaControlsDialog() override = default;
- bool isResizable() const override {return true;}
QSize sizeHint() const override;
private:
diff --git a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
index 1440a4be5..e19d7363a 100644
--- a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
+++ b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
@@ -39,6 +39,7 @@ StereoEnhancerControlDialog::StereoEnhancerControlDialog(
EffectControlDialog( _controls )
{
auto l = new QHBoxLayout(this);
+ l->setSizeConstraint(QLayout::SetFixedSize);
auto widthKnob = new Knob(KnobType::Bright26, tr("WIDTH"), this);
widthKnob->setModel( &_controls->m_widthModel );
diff --git a/plugins/TapTempo/TapTempoView.cpp b/plugins/TapTempo/TapTempoView.cpp
index 182218cdd..468e951f3 100644
--- a/plugins/TapTempo/TapTempoView.cpp
+++ b/plugins/TapTempo/TapTempoView.cpp
@@ -128,10 +128,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/Vectorscope/VecControlsDialog.h b/plugins/Vectorscope/VecControlsDialog.h
index 8fee75b4b..400e04ff5 100644
--- a/plugins/Vectorscope/VecControlsDialog.h
+++ b/plugins/Vectorscope/VecControlsDialog.h
@@ -45,7 +45,6 @@ public:
explicit VecControlsDialog(VecControls *controls);
~VecControlsDialog() override = default;
- bool isResizable() const override {return true;}
QSize sizeHint() const override;
private:
diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp
index 34fd431cd..56dda1eea 100644
--- a/plugins/Vestige/Vestige.cpp
+++ b/plugins/Vestige/Vestige.cpp
@@ -103,8 +103,9 @@ public:
vstSubWin( QWidget * _parent ) :
SubWindow( _parent )
{
- setAttribute( Qt::WA_DeleteOnClose, false );
- setWindowFlags( Qt::WindowCloseButtonHint );
+ setAttribute(Qt::WA_DeleteOnClose, false);
+ setWindowFlag(Qt::WindowMaximizeButtonHint, false);
+ setDetachable(false);
}
~vstSubWin() override = default;
@@ -918,12 +919,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 69833065e..3bdd0644e 100644
--- a/plugins/Vestige/Vestige.h
+++ b/plugins/Vestige/Vestige.h
@@ -31,6 +31,7 @@
#include "Instrument.h"
#include "InstrumentView.h"
+#include "SubWindow.h"
class QGridLayout;
@@ -86,7 +87,7 @@ private:
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/ControllerDialog.cpp b/src/gui/ControllerDialog.cpp
index 344898808..ef4cec2c3 100644
--- a/src/gui/ControllerDialog.cpp
+++ b/src/gui/ControllerDialog.cpp
@@ -23,30 +23,17 @@
*
*/
-#include
-
#include "ControllerDialog.h"
+
#include "Controller.h"
namespace lmms::gui
{
-
-ControllerDialog::ControllerDialog( Controller * _controller,
- QWidget * _parent ) :
- QWidget( _parent ),
- ModelView( _controller, this )
+ControllerDialog::ControllerDialog(Controller* controller, QWidget* parent)
+ : QWidget{parent}
+ , ModelView{controller, this}
{
}
-
-
-void ControllerDialog::closeEvent( QCloseEvent * _ce )
-{
- _ce->ignore();
- emit closed();
-}
-
-
-
} // namespace lmms::gui
diff --git a/src/gui/ControllerRackView.cpp b/src/gui/ControllerRackView.cpp
index a3c504323..508b4197a 100644
--- a/src/gui/ControllerRackView.cpp
+++ b/src/gui/ControllerRackView.cpp
@@ -45,9 +45,9 @@ namespace lmms::gui
{
-ControllerRackView::ControllerRackView() :
- QWidget(),
- m_nextIndex(0)
+ControllerRackView::ControllerRackView()
+ : QWidget{}
+ , m_nextIndex{0}
{
setWindowIcon( embed::getIconPixmap( "controller" ) );
setWindowTitle( tr( "Controller Rack" ) );
@@ -79,7 +79,10 @@ ControllerRackView::ControllerRackView() :
layout->addWidget( m_addButton );
this->setLayout( layout );
- QMdiSubWindow * subWin = getGUI()->mainWindow()->addWindowedWidget( this );
+ SubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget(this);
+
+ setFixedWidth(350);
+ setMinimumHeight(200);
// No maximize button
Qt::WindowFlags flags = subWin->windowFlags();
@@ -88,9 +91,6 @@ ControllerRackView::ControllerRackView() :
subWin->setAttribute( Qt::WA_DeleteOnClose, false );
subWin->move( 680, 310 );
- subWin->resize( 350, 200 );
- subWin->setFixedWidth( 350 );
- subWin->setMinimumHeight( 200 );
}
@@ -229,21 +229,4 @@ void ControllerRackView::addController()
setFocus();
}
-
-
-
-void ControllerRackView::closeEvent( QCloseEvent * _ce )
- {
- if( parentWidget() )
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
- _ce->ignore();
- }
-
-
} // namespace lmms::gui
diff --git a/src/gui/ControllerView.cpp b/src/gui/ControllerView.cpp
index 7f7c4729c..adf2d2eb7 100644
--- a/src/gui/ControllerView.cpp
+++ b/src/gui/ControllerView.cpp
@@ -44,15 +44,14 @@ namespace lmms::gui
{
-ControllerView::ControllerView( Controller * _model, QWidget * _parent ) :
- QFrame( _parent ),
- ModelView( _model, this ),
- m_subWindow( nullptr ),
- m_controllerDlg( nullptr ),
- m_show( true )
+ControllerView::ControllerView(Controller* model, QWidget* parent)
+ : QFrame{parent}
+ , ModelView{model, this}
+ , m_subWindow{nullptr}
+ , m_controllerDlg{nullptr}
{
- this->setFrameStyle( QFrame::StyledPanel );
- this->setFrameShadow( QFrame::Raised );
+ setFrameStyle(QFrame::StyledPanel);
+ setFrameShadow(QFrame::Raised);
setFocusPolicy(Qt::StrongFocus);
auto vBoxLayout = new QVBoxLayout(this);
@@ -60,7 +59,7 @@ ControllerView::ControllerView( Controller * _model, QWidget * _parent ) :
auto hBox = new QHBoxLayout();
vBoxLayout->addLayout(hBox);
- auto label = new QLabel("" + _model->displayName() + "", this);
+ auto label = new QLabel("" + model->displayName() + "", this);
QSizePolicy sizePolicy = label->sizePolicy();
sizePolicy.setHorizontalStretch(1);
label->setSizePolicy(sizePolicy);
@@ -72,27 +71,17 @@ ControllerView::ControllerView( Controller * _model, QWidget * _parent ) :
hBox->addWidget(controlsButton);
- m_nameLabel = new QLabel(_model->name(), this);
+ m_nameLabel = new QLabel(model->name(), this);
vBoxLayout->addWidget(m_nameLabel);
- m_controllerDlg = getController()->createDialog( getGUI()->mainWindow()->workspace() );
-
- m_subWindow = getGUI()->mainWindow()->addWindowedWidget( m_controllerDlg );
-
- Qt::WindowFlags flags = m_subWindow->windowFlags();
- flags &= ~Qt::WindowMaximizeButtonHint;
- m_subWindow->setWindowFlags( flags );
- m_subWindow->setFixedSize( m_subWindow->size() );
-
- m_subWindow->setWindowIcon( m_controllerDlg->windowIcon() );
-
- connect( m_controllerDlg, SIGNAL(closed()),
- this, SLOT(closeControls()));
+ m_controllerDlg = getController()->createDialog(getGUI()->mainWindow()->workspace());
+ m_subWindow = getGUI()->mainWindow()->addWindowedWidget(m_controllerDlg);
+ m_subWindow->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
m_subWindow->hide();
- setModel( _model );
+ setModel(model);
}
@@ -111,28 +100,20 @@ ControllerView::~ControllerView()
void ControllerView::editControls()
{
- if( m_show )
+ if (!m_controllerDlg->isVisible())
{
m_subWindow->show();
m_subWindow->raise();
- m_show = false;
}
else
{
m_subWindow->hide();
- m_show = true;
}
}
-void ControllerView::closeControls()
-{
- m_subWindow->hide();
- m_show = true;
-}
-
void ControllerView::moveUp() { emit movedUp(this); }
void ControllerView::moveDown() { emit movedDown(this); }
@@ -188,4 +169,4 @@ void ControllerView::contextMenuEvent( QContextMenuEvent * )
}
-} // namespace lmms::gui
\ No newline at end of file
+} // namespace lmms::gui
diff --git a/src/gui/EffectControlDialog.cpp b/src/gui/EffectControlDialog.cpp
index 1e0fbb802..6a624e4dc 100644
--- a/src/gui/EffectControlDialog.cpp
+++ b/src/gui/EffectControlDialog.cpp
@@ -23,32 +23,20 @@
*
*/
-#include
-
#include "EffectControlDialog.h"
+
#include "EffectControls.h"
namespace lmms::gui
{
-
-EffectControlDialog::EffectControlDialog( EffectControls * _controls ) :
- QWidget( nullptr ),
- ModelView( _controls, this ),
- m_effectControls( _controls )
+EffectControlDialog::EffectControlDialog(EffectControls* controls)
+ : QWidget{nullptr}
+ , ModelView{controls, this}
+ , m_effectControls{controls}
{
- setWindowTitle( m_effectControls->effect()->displayName() );
- setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ setWindowTitle(m_effectControls->effect()->displayName());
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}
-
-
-
-void EffectControlDialog::closeEvent( QCloseEvent * _ce )
-{
- _ce->ignore();
- emit closed();
-}
-
-
} // namespace lmms::gui
diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp
index 428035b95..5db377de4 100644
--- a/src/gui/EffectView.cpp
+++ b/src/gui/EffectView.cpp
@@ -87,26 +87,10 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
this, SLOT(editControls()));
m_controlView = effect()->controls()->createView();
- if( m_controlView )
+ if (m_controlView)
{
- m_subWindow = getGUI()->mainWindow()->addWindowedWidget( m_controlView );
-
- if ( !m_controlView->isResizable() )
- {
- m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
- if (m_subWindow->layout())
- {
- m_subWindow->layout()->setSizeConstraint(QLayout::SetFixedSize);
- }
- }
-
- Qt::WindowFlags flags = m_subWindow->windowFlags();
- flags &= ~Qt::WindowMaximizeButtonHint;
- m_subWindow->setWindowFlags( flags );
-
- connect( m_controlView, SIGNAL(closed()),
- this, SLOT(closeEffects()));
-
+ m_subWindow = getGUI()->mainWindow()->addWindowedWidget(m_controlView);
+ m_subWindow->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
m_subWindow->hide();
}
}
@@ -134,11 +118,11 @@ void EffectView::editControls()
{
if( m_subWindow )
{
- if( !m_subWindow->isVisible() )
+ if (!m_controlView->isVisible())
{
m_subWindow->show();
m_subWindow->raise();
- effect()->controls()->setViewVisible( true );
+ effect()->controls()->setViewVisible(true); // TODO is this even needed?
}
else
{
@@ -174,17 +158,6 @@ void EffectView::deletePlugin()
-void EffectView::closeEffects()
-{
- if( m_subWindow )
- {
- m_subWindow->hide();
- }
- effect()->controls()->setViewVisible( false );
-}
-
-
-
void EffectView::contextMenuEvent( QContextMenuEvent * )
{
QPointer contextMenu = new CaptionMenu( model()->displayName(), this );
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 7e9c16ab9..73c477647 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -329,15 +329,8 @@ void MainWindow::finalize()
m_redoAction = addAction(edit_menu, "edit_redo", tr("Redo"),
QKeySequence::Redo, &MainWindow::redo);
- // Ensure that both (Ctrl+Y) and (Ctrl+Shift+Z) activate redo shortcut regardless of OS defaults
- if (QKeySequence(QKeySequence::Redo) != keySequence(Qt::CTRL, Qt::Key_Y))
- {
- new QShortcut(keySequence(Qt::CTRL, Qt::Key_Y), this, SLOT(redo()));
- }
- if (QKeySequence(QKeySequence::Redo) != keySequence(Qt::CTRL, Qt::SHIFT, Qt::Key_Z))
- {
- new QShortcut(keySequence(Qt::CTRL, Qt::SHIFT, Qt::Key_Z), this, SLOT(redo()));
- }
+ m_undoAction->setShortcutContext(Qt::ApplicationShortcut);
+ m_redoAction->setShortcutContext(Qt::ApplicationShortcut);
edit_menu->addSeparator();
edit_menu->addAction(embed::getIconPixmap("microtuner"), tr("Scales and keymaps"),
@@ -353,6 +346,7 @@ void MainWindow::finalize()
this, SLOT(updateViewMenu()));
connect( m_viewMenu, SIGNAL(triggered(QAction*)), this,
SLOT(updateConfig(QAction*)));
+ updateViewMenu();
m_toolsMenu = new QMenu( this );
@@ -493,18 +487,10 @@ void MainWindow::finalize()
}
// Add editor subwindows
- for (QWidget* widget : std::list{
- getGUI()->automationEditor(),
- getGUI()->patternEditor(),
- getGUI()->pianoRoll(),
- getGUI()->songEditor()
- })
- {
- QMdiSubWindow* window = addWindowedWidget(widget);
- window->setWindowIcon(widget->windowIcon());
- window->setAttribute(Qt::WA_DeleteOnClose, false);
- window->resize(widget->sizeHint());
- }
+ addWindowedWidget(getGUI()->automationEditor());
+ addWindowedWidget(getGUI()->patternEditor());
+ addWindowedWidget(getGUI()->pianoRoll());
+ addWindowedWidget(getGUI()->songEditor());
getGUI()->automationEditor()->parentWidget()->hide();
getGUI()->patternEditor()->parentWidget()->move(610, 5);
@@ -552,19 +538,35 @@ SubWindow* MainWindow::addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags
{
// wrap the widget in our own *custom* window that patches some errors in QMdiSubWindow
auto win = new SubWindow(m_workspace->viewport(), windowFlags);
- win->setAttribute(Qt::WA_DeleteOnClose);
+ connect(this, &MainWindow::detachAllSubWindows, win, &SubWindow::setDetached);
win->setWidget(w);
- if (w && w->sizeHint().isValid()) {
- auto titleBarHeight = win->titleBarHeight();
- auto frameWidth = win->frameWidth();
- QSize delta(2* frameWidth, titleBarHeight + frameWidth);
- win->resize(delta + w->sizeHint());
+
+ if (w)
+ {
+ // TODO: somehow make this work on any setWidget
+ connect(w, &QWidget::destroyed, win, &SubWindow::deleteLater);
+
+ if (w->sizeHint().isValid())
+ {
+ auto titleBarHeight = win->titleBarHeight();
+ auto frameWidth = win->frameWidth();
+ QSize delta(2* frameWidth, titleBarHeight + frameWidth);
+ win->resize(delta + w->sizeHint());
+ }
}
+
m_workspace->addSubWindow(win);
return win;
}
+
+void MainWindow::setAllSubWindowsDetached(bool detached)
+{
+ emit detachAllSubWindows(detached);
+}
+
+
void MainWindow::resetWindowTitle()
{
QString title(tr( "Untitled" ));
@@ -659,77 +661,80 @@ void MainWindow::clearKeyModifiers()
-void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de )
+void MainWindow::saveWidgetState(QWidget* w, QDomElement& de)
{
- // If our widget is the main content of a window (e.g. piano roll, Mixer, etc),
- // we really care about the position of the *window* - not the position of the widget within its window
- if( _w->parentWidget() != nullptr &&
- _w->parentWidget()->inherits( "QMdiSubWindow" ) )
+ // TODO: Only use one of these
+ auto win = qobject_cast(w);
+ if (!win)
{
- _w = _w->parentWidget();
+ // Fall back on parent
+ win = qobject_cast(w->parentWidget());
+ if (!win)
+ {
+ // Still could not find the window - soft fail
+ return;
+ }
}
- // If the widget is a SubWindow, then we can make use of the getTrueNormalGeometry() method that
- // performs the same as normalGeometry, but isn't broken on X11 ( see https://bugreports.qt.io/browse/QTBUG-256 )
- auto asSubWindow = qobject_cast(_w);
- QRect normalGeom = asSubWindow != nullptr ? asSubWindow->getTrueNormalGeometry() : _w->normalGeometry();
+ de.setAttribute("visible", bool{win->widget() && win->widget()->isVisible()});
+ de.setAttribute("maximized", win->isMaximized());
- bool visible = _w->isVisible();
- _de.setAttribute( "visible", visible );
- _de.setAttribute( "minimized", _w->isMinimized() );
- _de.setAttribute( "maximized", _w->isMaximized() );
-
- _de.setAttribute( "x", normalGeom.x() );
- _de.setAttribute( "y", normalGeom.y() );
-
- QSize sizeToStore = normalGeom.size();
- _de.setAttribute( "width", sizeToStore.width() );
- _de.setAttribute( "height", sizeToStore.height() );
+ QRect normalGeometry = win->getTrueNormalGeometry();
+ de.setAttribute("x", normalGeometry.x());
+ de.setAttribute("y", normalGeometry.y() );
+ de.setAttribute("width", normalGeometry.width());
+ de.setAttribute("height", normalGeometry.height());
}
-void MainWindow::restoreWidgetState( QWidget * _w, const QDomElement & _de )
+void MainWindow::restoreWidgetState(QWidget* w, const QDomElement& de)
{
- QRect r( qMax( 1, _de.attribute( "x" ).toInt() ),
- qMax( 1, _de.attribute( "y" ).toInt() ),
- qMax( _w->sizeHint().width(), _de.attribute( "width" ).toInt() ),
- qMax( _w->minimumHeight(), _de.attribute( "height" ).toInt() ) );
- if( _de.hasAttribute( "visible" ) && !r.isNull() )
+ // TODO: Only use one of these
+ auto win = qobject_cast(w);
+ if (!win)
{
- // If our widget is the main content of a window (e.g. piano roll, Mixer, etc),
- // we really care about the position of the *window* - not the position of the widget within its window
- if ( _w->parentWidget() != nullptr &&
- _w->parentWidget()->inherits( "QMdiSubWindow" ) )
+ // Fall back on parent
+ win = qobject_cast(w->parentWidget());
+ if (!win)
{
- _w = _w->parentWidget();
+ // Still could not find the window - soft fail
+ return;
}
- // first restore the window, as attempting to resize a maximized window causes graphics glitching
- _w->setWindowState( _w->windowState() & ~(Qt::WindowMaximized | Qt::WindowMinimized) );
+ }
- // Check isEmpty() to work around corrupt project files with empty size
- if ( ! r.size().isEmpty() ) {
- _w->resize( r.size() );
- }
- _w->move( r.topLeft() );
+ const auto normalGeometry = QRect {
+ de.attribute("x").toInt(),
+ de.attribute("y").toInt(),
+ de.attribute("width").toInt(),
+ de.attribute("height").toInt()
+ };
+
+ if (normalGeometry.isValid())
+ {
+ // first restore the window, as attempting to resize a maximized window causes graphics glitching
+ win->setWindowState(win->windowState() & ~(Qt::WindowMaximized | Qt::WindowMinimized));
+
+ win->setGeometry(normalGeometry);
// set the window to its correct minimized/maximized/restored state
- Qt::WindowStates flags = _w->windowState();
- flags = _de.attribute( "minimized" ).toInt() ?
- ( flags | Qt::WindowMinimized ) :
- ( flags & ~Qt::WindowMinimized );
- flags = _de.attribute( "maximized" ).toInt() ?
- ( flags | Qt::WindowMaximized ) :
- ( flags & ~Qt::WindowMaximized );
- _w->setWindowState( flags );
+ Qt::WindowStates winState = win->windowState();
+ winState = de.attribute("maximized").toInt()
+ ? (winState | Qt::WindowMaximized)
+ : (winState & ~Qt::WindowMaximized);
+ win->setWindowState(winState);
+ }
- _w->setVisible( _de.attribute( "visible" ).toInt() );
+ if (const auto visible = de.attribute("visible"); !visible.isEmpty())
+ {
+ win->setVisible(visible.toInt());
}
}
+
void MainWindow::emptySlot()
{
}
@@ -1086,6 +1091,22 @@ void MainWindow::updateViewMenu()
m_viewMenu->addSeparator();
+ auto detachAllAction = m_viewMenu->addAction(embed::getIconPixmap("detach"),
+ tr("Detach all subwindows"),
+ this, [this](){ setAllSubWindowsDetached(true); },
+ QKeySequence{Qt::CTRL | Qt::SHIFT | Qt::Key_D}
+ );
+ auto attachAllAction = m_viewMenu->addAction(embed::getIconPixmap("detach"),
+ tr("Attach all subwindows"),
+ this, [this](){ setAllSubWindowsDetached(false); },
+ QKeySequence{Qt::CTRL | Qt::ALT | Qt::SHIFT | Qt::Key_D}
+ );
+
+ detachAllAction->setShortcutContext(Qt::ApplicationShortcut);
+ attachAllAction->setShortcutContext(Qt::ApplicationShortcut);
+
+ m_viewMenu->addSeparator();
+
// Here we should put all look&feel -stuff from configmanager
// that is safe to change on the fly. There is probably some
// more elegant way to do this.
diff --git a/src/gui/MicrotunerConfig.cpp b/src/gui/MicrotunerConfig.cpp
index 4dbb6064d..59f293dab 100644
--- a/src/gui/MicrotunerConfig.cpp
+++ b/src/gui/MicrotunerConfig.cpp
@@ -192,13 +192,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
@@ -654,12 +651,4 @@ void MicrotunerConfig::loadSettings(const QDomElement &element)
}
-void MicrotunerConfig::closeEvent(QCloseEvent *ce)
-{
- if (parentWidget()) {parentWidget()->hide();}
- else {hide();}
- ce->ignore();
-}
-
-
} // namespace lmms::gui
diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp
index efeb46d46..86271a252 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 ef1f35a20..dc1626d5a 100644
--- a/src/gui/MixerView.cpp
+++ b/src/gui/MixerView.cpp
@@ -162,10 +162,10 @@ MixerView::MixerView(Mixer* mixer) :
// timer for updating faders
connect(mainWindow, &MainWindow::periodicUpdate, this, &MixerView::updateFaders);
- // add ourself to workspace
- QMdiSubWindow* subWin = mainWindow->addWindowedWidget(this);
layout()->setSizeConstraint(QLayout::SetMinimumSize);
- subWin->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);
+
+ // add ourself to workspace
+ mainWindow->addWindowedWidget(this);
parentWidget()->setAttribute(Qt::WA_DeleteOnClose, false);
parentWidget()->move(5, 310);
@@ -532,21 +532,6 @@ void MixerView::keyPressEvent(QKeyEvent * e)
-void MixerView::closeEvent(QCloseEvent * ce)
- {
- if (parentWidget())
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
- ce->ignore();
- }
-
-
-
void MixerView::setCurrentMixerChannel(int channel)
{
if (channel >= 0 && channel < m_mixerChannelViews.size())
diff --git a/src/gui/ProjectNotes.cpp b/src/gui/ProjectNotes.cpp
index 8cbe18d87..56d694969 100644
--- a/src/gui/ProjectNotes.cpp
+++ b/src/gui/ProjectNotes.cpp
@@ -28,7 +28,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -50,8 +49,8 @@ namespace lmms::gui
{
-ProjectNotes::ProjectNotes() :
- QMainWindow( getGUI()->mainWindow()->workspace() )
+ProjectNotes::ProjectNotes()
+ : QMainWindow{getGUI()->mainWindow()->workspace()}
{
m_edit = new QTextEdit( this );
m_edit->setAutoFillBackground( true );
@@ -391,20 +390,4 @@ void ProjectNotes::loadSettings( const QDomElement & _this )
m_edit->setHtml( _this.text() );
}
-
-
-
-void ProjectNotes::closeEvent( QCloseEvent * _ce )
-{
- if( parentWidget() )
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
- _ce->ignore();
- }
-
} // namespace lmms::gui
diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp
index e0fea45ce..872e7ad20 100644
--- a/src/gui/SampleTrackWindow.cpp
+++ b/src/gui/SampleTrackWindow.cpp
@@ -47,11 +47,11 @@ namespace lmms::gui
{
-SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) :
- QWidget(),
- ModelView(nullptr, this),
- m_track(tv->model()),
- m_stv(tv)
+SampleTrackWindow::SampleTrackWindow(SampleTrackView* stv)
+ : QWidget{}
+ , ModelView{nullptr, this}
+ , m_track{stv->model()}
+ , m_stv{stv}
{
// init own layout + widgets
setFocusPolicy(Qt::StrongFocus);
@@ -148,29 +148,25 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) :
generalSettingsLayout->addLayout(basicControlsLayout);
- m_effectRack = new EffectRackView(tv->model()->audioBusHandle()->effects());
+ m_effectRack = new EffectRackView(stv->model()->audioBusHandle()->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();
- flags |= Qt::MSWindowsFixedSizeDialogHint;
+ flags |= Qt::MSWindowsFixedSizeDialogHint; // resizing is disabled regardless, this makes SubWindow hide related actions
flags &= ~Qt::WindowMaximizeButtonHint;
subWin->setWindowFlags(flags);
- // Hide the Size and Maximize options from the system menu
- // since the dialog size is fixed.
- QMenu * systemMenu = subWin->systemMenu();
- systemMenu->actions().at(2)->setVisible(false); // Size
- systemMenu->actions().at(4)->setVisible(false); // Maximize
+ // better than `setFixedSize` because it still responds to layout changes
+ layout()->setSizeConstraint(QLayout::SetFixedSize);
- subWin->setWindowIcon(embed::getIconPixmap("sample_track"));
- subWin->setFixedSize(subWin->size());
+ setWindowIcon(embed::getIconPixmap("sample_track"));
subWin->hide();
}
@@ -247,27 +243,15 @@ void SampleTrackWindow::toggleVisibility(bool on)
void SampleTrackWindow::closeEvent(QCloseEvent* ce)
{
- ce->ignore();
-
- if(getGUI()->mainWindow()->workspace())
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
-
m_stv->setFocus();
m_stv->m_tlb->setChecked(false);
}
-void SampleTrackWindow::saveSettings(QDomDocument& doc, QDomElement & element)
+void SampleTrackWindow::saveSettings(QDomDocument& doc, QDomElement& element)
{
MainWindow::saveWidgetState(this, element);
- Q_UNUSED(element)
}
diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp
index a9a652e98..d65964048 100644
--- a/src/gui/SubWindow.cpp
+++ b/src/gui/SubWindow.cpp
@@ -28,25 +28,34 @@
#include "SubWindow.h"
+#include
+
#include
+#include
#include
+#include
#include
+#include
#include
#include
#include
+#include
#include
+#include
+#include "ConfigManager.h"
#include "embed.h"
namespace lmms::gui
{
-SubWindow::SubWindow(QWidget *parent, Qt::WindowFlags windowFlags) :
- QMdiSubWindow(parent, windowFlags),
- m_buttonSize(17, 17),
- m_titleBarHeight(titleBarHeight()),
- m_hasFocus(false)
+SubWindow::SubWindow(QWidget* parent, Qt::WindowFlags windowFlags)
+ : QMdiSubWindow{parent, windowFlags}
+ , m_buttonSize{17, 17}
+ , m_titleBarHeight{titleBarHeight()}
+ , m_hasFocus{false}
+ , m_isDetachable{true}
{
// initialize the tracked geometry to whatever Qt thinks the normal geometry currently is.
// this should always work, since QMdiSubWindows will not start as maximized
@@ -57,15 +66,27 @@ SubWindow::SubWindow(QWidget *parent, Qt::WindowFlags windowFlags) :
m_textShadowColor = Qt::black;
m_borderColor = Qt::black;
- // close, maximize and restore (after maximizing) buttons
- m_closeBtn = addTitleButton("close", tr("Close"));
- connect( m_closeBtn, SIGNAL(clicked(bool)), this, SLOT(close()));
+ // close, maximize, restore, and detach buttons
+ auto createButton = [this](std::string_view iconName, const QString& tooltip) -> QPushButton* {
+ auto button = new QPushButton{embed::getIconPixmap(iconName), 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("close", tr("Close"));
+ connect(m_closeBtn, &QPushButton::clicked, this, &QWidget::close);
- m_maximizeBtn = addTitleButton("maximize", tr("Maximize"));
- connect( m_maximizeBtn, SIGNAL(clicked(bool)), this, SLOT(showMaximized()));
+ m_maximizeBtn = createButton("maximize", tr("Maximize"));
+ connect(m_maximizeBtn, &QPushButton::clicked, this, &QWidget::showMaximized);
- m_restoreBtn = addTitleButton("restore", tr("Restore"));
- connect( m_restoreBtn, SIGNAL(clicked(bool)), this, SLOT(showNormal()));
+ m_restoreBtn = createButton("restore", tr("Restore"));
+ connect(m_restoreBtn, &QPushButton::clicked, this, &QWidget::showNormal);
+
+ m_detachBtn = createButton("detach", tr("Detach"));
+ connect(m_detachBtn, &QPushButton::clicked, this, &SubWindow::detach);
// QLabel for the window title and the shadow effect
m_shadow = new QGraphicsDropShadowEffect();
@@ -78,6 +99,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);
@@ -139,7 +162,60 @@ void SubWindow::changeEvent( QEvent *event )
{
adjustTitleBar();
}
+}
+
+
+
+void SubWindow::setVisible(bool visible)
+{
+ if (isDetached() || visible) { widget()->setVisible(visible); }
+ if (!isDetached()) { QMdiSubWindow::setVisible(visible); }
+}
+
+
+
+
+void SubWindow::showEvent(QShowEvent* e)
+{
+ if (ConfigManager::inst()->value("ui", "detachbehavior", "show") == "detached") { detach(); }
+ if (isDetached())
+ {
+ widget()->setWindowState((widget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
+ }
+}
+
+
+
+
+bool SubWindow::isDetachable() const
+{
+ return m_isDetachable;
+}
+
+
+
+
+void SubWindow::setDetachable(bool on)
+{
+ m_isDetachable = on;
+}
+
+
+
+
+bool SubWindow::isDetached() const
+{
+ return widget()->windowFlags().testFlag(Qt::Window);
+}
+
+
+
+
+void SubWindow::setDetached(bool on)
+{
+ if (on) { detach(); }
+ else { attach(); }
}
@@ -228,6 +304,73 @@ void SubWindow::setBorderColor( const QColor &c )
+void SubWindow::detach()
+{
+ if (!isDetachable() || isDetached()) { return; }
+
+ const auto pos = mapToGlobal(widget()->pos());
+ const bool shown = isVisible();
+
+ auto flags = windowFlags();
+ flags |= Qt::Window;
+ flags &= ~Qt::SubWindow;
+ flags |= Qt::WindowMinimizeButtonHint;
+
+ hide();
+ widget()->setWindowFlags(flags);
+
+ if (shown) { widget()->show(); }
+
+ widget()->move(pos);
+}
+
+void SubWindow::attach()
+{
+ if (!isDetached()) { return; }
+
+ const bool shown = widget()->isVisible();
+
+ auto frame = widget()->geometry();
+ frame.moveTo(mdiArea()->mapFromGlobal(frame.topLeft()));
+ frame += decorationMargins();
+
+ // Make sure the window fully fits on screen
+ frame.setSize({
+ std::min(frame.width(), mdiArea()->width()),
+ std::min(frame.height(), mdiArea()->height())
+ });
+
+ frame.moveTo(
+ std::clamp(frame.left(), 0, mdiArea()->rect().width() - frame.width()),
+ std::clamp(frame.top(), 0, mdiArea()->rect().height() - frame.height())
+ );
+
+ auto flags = windowFlags();
+ flags &= ~Qt::Window;
+ flags |= Qt::SubWindow;
+ flags &= ~Qt::WindowMinimizeButtonHint;
+ widget()->setWindowFlags(flags);
+
+ if (shown)
+ {
+ widget()->show();
+ show();
+ }
+
+ if (QGuiApplication::platformName() == "wayland")
+ {
+ // Workaround for wayland reporting position as 0-0
+ // See https://doc.qt.io/qt-6.9/application-windows.html#wayland-peculiarities
+ resize(frame.size());
+ }
+ else
+ {
+ setGeometry(frame);
+ }
+}
+
+
+
int SubWindow::titleBarHeight() const
{
QStyleOptionTitleBar so;
@@ -246,6 +389,21 @@ int SubWindow::frameWidth() const
}
+
+
+QMargins SubWindow::decorationMargins() const
+{
+ return {
+ frameWidth(), // left
+ titleBarHeight(), // top
+ frameWidth(), // right
+ frameWidth() // bottom
+ };
+}
+
+
+
+
void SubWindow::updateTitleBar()
{
adjustTitleBar();
@@ -306,15 +464,15 @@ void SubWindow::adjustTitleBar()
// button adjustments
m_maximizeBtn->hide();
m_restoreBtn->hide();
+ m_detachBtn->hide();
m_closeBtn->show();
const int rightSpace = 3;
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 );
+ auto buttonPos = QPoint{width() - rightSpace - m_buttonSize.width(), 3};
+ const auto buttonStep = QPoint{m_buttonSize.width() + buttonGap, 0};
// the buttonBarWidth depends on the number of buttons.
// we need it to calculate the width of window title label
@@ -322,24 +480,36 @@ 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->setVisible(true);
+ 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(isMinimized());
- if( isMinimized() )
+ if (isMinimized())
{
- m_restoreBtn->move( m_maximizeBtn->isHidden() ? middleButtonPos : leftButtonPos );
+ m_restoreBtn->show();
+ buttonPos -= buttonStep;
+ }
+
+ if (isDetachable())
+ {
+ m_detachBtn->move(buttonPos);
+ m_detachBtn->show();
+ buttonBarWidth = buttonBarWidth + m_buttonSize.width() + buttonGap;
}
if( widget() )
@@ -412,16 +582,63 @@ void SubWindow::resizeEvent( QResizeEvent * event )
}
}
-QPushButton* SubWindow::addTitleButton(const std::string& iconName, const QString& toolTip)
-{
- auto button = new QPushButton(embed::getIconPixmap(iconName), QString(), this);
- button->resize(m_buttonSize);
- button->setFocusPolicy(Qt::NoFocus);
- button->setCursor(Qt::ArrowCursor);
- button->setAttribute(Qt::WA_NoMousePropagation);
- button->setToolTip(toolTip);
- return button;
+
+
+/**
+ * @brief SubWindow::eventFilter
+ *
+ * Override of QMdiSubWindow's event filter.
+ * This is not how regular eventFilters work, it is never installed explicitly.
+ * Instead, it is installed by Qt and conveniently installs itself
+ * onto the child widget. Despite relying on internal implementation details,
+ * as of writing this it seems to be the best way to do so as soon as the widget is set.
+ */
+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;
+
+ case QEvent::Close:
+ if (isDetached())
+ {
+ QString detachBehavior = ConfigManager::inst()->value("ui", "detachbehavior", "show");
+ if (detachBehavior == "show")
+ {
+ attach();
+ event->ignore();
+ return true;
+ }
+ else if (detachBehavior == "hide")
+ {
+ attach();
+ hide();
+ event->ignore();
+ return QMdiSubWindow::eventFilter(obj, event);
+ }
+ else if (detachBehavior == "detached")
+ {
+ event->accept();
+ return QMdiSubWindow::eventFilter(obj, event);
+ }
+ }
+ else
+ {
+ hide();
+ }
+ return QMdiSubWindow::eventFilter(obj, event);
+
+ default:
+ return QMdiSubWindow::eventFilter(obj, event);
+ }
}
diff --git a/src/gui/editors/Editor.cpp b/src/gui/editors/Editor.cpp
index 2b2c1534c..92c778cd2 100644
--- a/src/gui/editors/Editor.cpp
+++ b/src/gui/editors/Editor.cpp
@@ -24,18 +24,15 @@
#include "Editor.h"
+#include
+#include
+
#include "DeprecationHelper.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "Song.h"
-
#include "embed.h"
-#include
-#include
-#include
-
-
namespace lmms::gui
{
@@ -92,6 +89,7 @@ void Editor::toggleMaximize()
}
Editor::Editor(bool record, bool stepRecord) :
+ QMainWindow(),
m_toolBar(new DropToolBar(this)),
m_playAction(nullptr),
m_recordAction(nullptr),
@@ -141,22 +139,8 @@ QAction *Editor::playAction() const
return m_playAction;
}
-void Editor::closeEvent(QCloseEvent * event)
+void Editor::keyPressEvent(QKeyEvent* ke)
{
- if( parentWidget() )
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
- getGUI()->mainWindow()->refocus();
- event->ignore();
- }
-
- void Editor::keyPressEvent(QKeyEvent *ke)
- {
if (ke->key() == Qt::Key_Space)
{
if (ke->modifiers() & Qt::ShiftModifier)
@@ -170,7 +154,7 @@ void Editor::closeEvent(QCloseEvent * event)
return;
}
ke->ignore();
- }
+}
DropToolBar::DropToolBar(QWidget* parent) : QToolBar(parent)
{
diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp
index 55400cd3f..2abde6b7d 100644
--- a/src/gui/editors/SongEditor.cpp
+++ b/src/gui/editors/SongEditor.cpp
@@ -572,21 +572,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 2b5f71e6e..71d2eadd8 100644
--- a/src/gui/instrument/InstrumentTrackWindow.cpp
+++ b/src/gui/instrument/InstrumentTrackWindow.cpp
@@ -293,7 +293,6 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) :
// we can reuse this method.
updateSubWindow();
- subWin->setWindowIcon(embed::getIconPixmap("instrument_track"));
subWin->hide();
}
@@ -530,6 +529,7 @@ void InstrumentTrackWindow::toggleVisibility( bool on )
else
{
parentWidget()->hide();
+ hide();
}
}
@@ -538,17 +538,6 @@ void InstrumentTrackWindow::toggleVisibility( bool on )
void InstrumentTrackWindow::closeEvent( QCloseEvent* event )
{
- event->ignore();
-
- if( getGUI()->mainWindow()->workspace() )
- {
- parentWidget()->hide();
- }
- else
- {
- hide();
- }
-
m_itv->setFocus();
m_itv->m_tlb->setChecked(false);
}
@@ -620,6 +609,7 @@ void InstrumentTrackWindow::dropEvent( QDropEvent* event )
event->accept();
setFocus();
}
+ updateSubWindow();
}
@@ -679,13 +669,34 @@ void InstrumentTrackWindow::viewInstrumentInDirection(int d)
// avoid reloading the window if there is only one instrument, as that will just change the active tab
if (idxOfNext != idxOfMe)
{
+ const auto sourceSubwin = static_cast(parentWidget());
+ const auto targetSubwin = static_cast(newView->getInstrumentTrackWindow()->parentWidget());
+ QWidget* sourceWidget;
+ QWidget* targetWidget;
+
+ // set widgets we move and get our position from
+ if (sourceSubwin->isDetached())
+ {
+ sourceWidget = this;
+ targetWidget = newView->getInstrumentTrackWindow();
+ }
+ else
+ {
+ sourceWidget = parentWidget();
+ targetWidget = newView->getInstrumentTrackWindow()->parentWidget();
+ }
+
// save current window pos and then hide the window by unchecking its button in the track list
- QPoint curPos = parentWidget()->pos();
+ QPoint curPos = sourceWidget->pos();
m_itv->m_tlb->setChecked(false);
// 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);
+
+ // sync detached state with current widget like we do with position
+ targetSubwin->setDetached(sourceSubwin->isDetached());
+
+ targetWidget->move(curPos);
// scroll the SongEditor/PatternEditor to make sure the new trackview label is visible
bringToFront->trackContainerView()->scrollToTrackView(bringToFront);
@@ -695,13 +706,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()
@@ -748,24 +754,19 @@ void InstrumentTrackWindow::updateSubWindow()
auto subWindow = findSubWindowInParents();
if (subWindow && m_instrumentView)
{
- Qt::WindowFlags flags = subWindow->windowFlags();
-
const auto instrumentViewResizable = m_instrumentView->isResizable();
if (instrumentViewResizable)
{
// TODO As of writing SlicerT is the only resizable instrument. Is this code specific to SlicerT?
+ // TODO Expand extraSpace in terms of specific widget sizes or replace with QLayout::setSizeConstraint.
const auto extraSpace = QSize(12, 208);
- subWindow->setMaximumSize(m_instrumentView->maximumSize() + extraSpace);
- subWindow->setMinimumSize(m_instrumentView->minimumSize() + extraSpace);
-
- flags &= ~Qt::MSWindowsFixedSizeDialogHint;
- flags |= Qt::WindowMaximizeButtonHint;
+ setMaximumSize(m_instrumentView->maximumSize() + extraSpace);
+ setMinimumSize(m_instrumentView->minimumSize() + extraSpace);
}
else
{
- 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.
@@ -775,13 +776,8 @@ void InstrumentTrackWindow::updateSubWindow()
}
}
- subWindow->setWindowFlags(flags);
+ subWindow->setWindowFlag(Qt::WindowMaximizeButtonHint, instrumentViewResizable);
- // 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.
diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp
index 258a176ad..a6ab7a76a 100644
--- a/src/gui/modals/SetupDialog.cpp
+++ b/src/gui/modals/SetupDialog.cpp
@@ -119,6 +119,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) :
"app", "disablebackup").toInt()),
m_openLastProject(ConfigManager::inst()->value(
"app", "openlastproject").toInt()),
+ m_detachBehavior{ConfigManager::inst()->value("ui", "detachbehavior", "show")},
m_loopMarkerMode{ConfigManager::inst()->value("app", "loopmarkermode", "dual")},
m_autoScroll(ConfigManager::inst()->value("ui", "autoscroll", "stepped")),
m_lang(ConfigManager::inst()->value(
@@ -257,6 +258,19 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) :
addCheckBox(tr("Show warning when deleting a mixer channel that is in use"), guiGroupBox, guiGroupLayout,
m_mixerChannelDeletionWarning, SLOT(toggleMixerChannelDeletionWarning(bool)), false);
+ m_detachBehaviorComboBox = new QComboBox{guiGroupBox};
+
+ m_detachBehaviorComboBox->addItem(tr("Attach and show when closed"), "show");
+ m_detachBehaviorComboBox->addItem(tr("Attach and hide when closed"), "hide");
+ m_detachBehaviorComboBox->addItem(tr("Always detached"), "detached");
+
+ m_detachBehaviorComboBox->setCurrentIndex(m_detachBehaviorComboBox->findData(m_detachBehavior));
+ connect(m_detachBehaviorComboBox, qOverload(&QComboBox::currentIndexChanged),
+ this, &SetupDialog::detachBehaviorChanged);
+
+ guiGroupLayout->addWidget(new QLabel{tr("Detached window behavior"), guiGroupBox});
+ guiGroupLayout->addWidget(m_detachBehaviorComboBox);
+
m_loopMarkerComboBox = new QComboBox{guiGroupBox};
m_loopMarkerComboBox->addItem(tr("Dual-button"), "dual");
@@ -991,6 +1005,7 @@ void SetupDialog::accept()
QString::number(!m_disableBackup));
ConfigManager::inst()->setValue("app", "openlastproject",
QString::number(m_openLastProject));
+ ConfigManager::inst()->setValue("ui", "detachbehavior", m_detachBehavior);
ConfigManager::inst()->setValue("app", "loopmarkermode", m_loopMarkerMode);
ConfigManager::inst()->setValue("app", "language", m_lang);
ConfigManager::inst()->setValue("ui", "autoscroll", m_autoScroll);
@@ -1131,6 +1146,12 @@ void SetupDialog::toggleOpenLastProject(bool enabled)
}
+void SetupDialog::detachBehaviorChanged()
+{
+ m_detachBehavior = m_detachBehaviorComboBox->currentData().toString();
+}
+
+
void SetupDialog::loopMarkerModeChanged()
{
m_loopMarkerMode = m_loopMarkerComboBox->currentData().toString();
diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp
index c0cba7eef..782b4e6a6 100644
--- a/src/gui/tracks/InstrumentTrackView.cpp
+++ b/src/gui/tracks/InstrumentTrackView.cpp
@@ -24,6 +24,8 @@
#include "InstrumentTrackView.h"
+#include
+
#include
#include
#include
@@ -205,20 +207,21 @@ void InstrumentTrackView::toggleMidiCCRack()
-InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow()
+InstrumentTrackWindow* InstrumentTrackView::topLevelInstrumentTrackWindow()
{
- InstrumentTrackWindow * w = nullptr;
- for( const QMdiSubWindow * sw :
- getGUI()->mainWindow()->workspace()->subWindowList(
- QMdiArea::ActivationHistoryOrder ) )
+ const auto subWindows = getGUI()->mainWindow()->workspace()->subWindowList(QMdiArea::ActivationHistoryOrder);
+
+ for (QMdiSubWindow* sw : subWindows | std::views::reverse)
{
- if( sw->isVisible() && sw->widget()->inherits( "lmms::gui::InstrumentTrackWindow" ) )
+ if (!sw->widget() || !sw->widget()->isVisible()) { continue; }
+
+ if (auto itw = qobject_cast(sw->widget()))
{
- w = qobject_cast( sw->widget() );
+ return itw;
}
}
- return w;
+ return nullptr;
}
diff --git a/src/gui/widgets/TempoSyncBarModelEditor.cpp b/src/gui/widgets/TempoSyncBarModelEditor.cpp
index d524e5844..628e470d8 100644
--- a/src/gui/widgets/TempoSyncBarModelEditor.cpp
+++ b/src/gui/widgets/TempoSyncBarModelEditor.cpp
@@ -205,11 +205,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 895e5bd01..3ed2a1100 100644
--- a/src/gui/widgets/TempoSyncKnob.cpp
+++ b/src/gui/widgets/TempoSyncKnob.cpp
@@ -315,11 +315,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 );
}