Detachable windows (#3532)

Allows detaching a window from LMMS's main window, making things like working on multiple screens easier.

The behavior of detached windows can be customized in the Settings.

Closes #1259

---------

Signed-off-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: SpomJ <mihail_a_m@mail.ru>
This commit is contained in:
Lukas W
2026-02-27 06:20:36 +01:00
committed by GitHub
parent 6854a655a4
commit 5d5f319942
50 changed files with 546 additions and 487 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -73,8 +73,6 @@ public slots:
void moveUp();
void moveDown();
void deletePlugin();
void closeEffects();
signals:
void movedUp(EffectView* view);

View File

@@ -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();

View File

@@ -59,9 +59,6 @@ public slots:
void updateScaleForm();
void updateKeymapForm();
protected:
void closeEvent(QCloseEvent *ce) override;
private slots:
bool loadScaleFromFile();
bool loadKeymapFromFile();

View File

@@ -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

View File

@@ -58,7 +58,6 @@ public:
protected:
void closeEvent( QCloseEvent * _ce ) override;
void setupActions();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();