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:
6
data/themes/default/detach.svg
Normal file
6
data/themes/default/detach.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="17" height="17" version="1.1" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#fff">
|
||||
<rect x="4" y="11" width="9" height="2"/>
|
||||
<path d="m4 9 4.5-5 4.5 5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 203 B |
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -73,8 +73,6 @@ public slots:
|
||||
void moveUp();
|
||||
void moveDown();
|
||||
void deletePlugin();
|
||||
void closeEffects();
|
||||
|
||||
|
||||
signals:
|
||||
void movedUp(EffectView* view);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -59,9 +59,6 @@ public slots:
|
||||
void updateScaleForm();
|
||||
void updateKeymapForm();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *ce) override;
|
||||
|
||||
private slots:
|
||||
bool loadScaleFromFile();
|
||||
bool loadKeymapFromFile();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -58,7 +58,6 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
void closeEvent( QCloseEvent * _ce ) override;
|
||||
void setupActions();
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -67,6 +67,7 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control
|
||||
|
||||
tl->addLayout( l );
|
||||
setLayout( tl );
|
||||
tl->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -50,7 +50,6 @@ class LadspaMatrixControlDialog : public EffectControlDialog
|
||||
Q_OBJECT
|
||||
public:
|
||||
LadspaMatrixControlDialog(LadspaControls* ctl);
|
||||
bool isResizable() const override;
|
||||
|
||||
private slots:
|
||||
void updateEffectView(LadspaControls* ctl);
|
||||
|
||||
@@ -95,6 +95,8 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog(
|
||||
mainLayout->addLayout( knobLayout );
|
||||
mainLayout->addLayout( ledLayout );
|
||||
|
||||
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
setLayout( mainLayout );
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -45,7 +45,6 @@ public:
|
||||
explicit VecControlsDialog(VecControls *controls);
|
||||
~VecControlsDialog() override = default;
|
||||
|
||||
bool isResizable() const override {return true;}
|
||||
QSize sizeHint() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -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" ) );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,30 +23,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QCloseEvent>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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("<b>" + _model->displayName() + "</b>", this);
|
||||
auto label = new QLabel("<b>" + model->displayName() + "</b>", 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
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -23,32 +23,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QCloseEvent>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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<CaptionMenu> contextMenu = new CaptionMenu( model()->displayName(), this );
|
||||
|
||||
@@ -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<QWidget*>{
|
||||
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<SubWindow*>(w);
|
||||
if (!win)
|
||||
{
|
||||
_w = _w->parentWidget();
|
||||
// Fall back on parent
|
||||
win = qobject_cast<SubWindow*>(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<SubWindow*>(_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<SubWindow*>(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<SubWindow*>(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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
#include <QApplication>
|
||||
#include <QCloseEvent>
|
||||
#include <QColorDialog>
|
||||
#include <QComboBox>
|
||||
#include <QFontDatabase>
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,25 +28,34 @@
|
||||
|
||||
#include "SubWindow.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QGuiApplication>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QMdiArea>
|
||||
#include <QMetaMethod>
|
||||
#include <QMoveEvent>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QStyleOption>
|
||||
#include <QStyleOptionTitleBar>
|
||||
#include <QWindow>
|
||||
|
||||
#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<QObject*>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,18 +24,15 @@
|
||||
|
||||
#include "Editor.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QShortcut>
|
||||
|
||||
#include "DeprecationHelper.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Song.h"
|
||||
|
||||
#include "embed.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QShortcut>
|
||||
#include <QCloseEvent>
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<SubWindow*>(parentWidget());
|
||||
const auto targetSubwin = static_cast<SubWindow*>(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.
|
||||
|
||||
@@ -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<int>(&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();
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "InstrumentTrackView.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QDragEnterEvent>
|
||||
@@ -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<InstrumentTrackWindow*>(sw->widget()))
|
||||
{
|
||||
w = qobject_cast<InstrumentTrackWindow *>( sw->widget() );
|
||||
return itw;
|
||||
}
|
||||
}
|
||||
|
||||
return w;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user