diff --git a/data/themes/classic/peak_controller_artwork.png b/data/themes/classic/peak_controller_artwork.png new file mode 100644 index 00000000000..5977f83cc27 Binary files /dev/null and b/data/themes/classic/peak_controller_artwork.png differ diff --git a/data/themes/default/peak_controller_artwork.png b/data/themes/default/peak_controller_artwork.png new file mode 100644 index 00000000000..5977f83cc27 Binary files /dev/null and b/data/themes/default/peak_controller_artwork.png differ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 5d889295cae..d7ce9f8910c 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -137,6 +137,10 @@ QMenu::indicator:selected { background-color: #101213; } +ControllerView { + background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 #636c7a, stop:1 #343840); +} + PianoRoll { background-color: #141616; qproperty-backgroundShade: rgba(255, 255, 255, 10); diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index cb393f5cacb..62fe55e1400 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -2,6 +2,7 @@ * ControllerRackView.h - view for song's controllers * * Copyright (c) 2008-2009 Paul Giblock + * Copyright (c) 2019 Steffen Baranowsky * * This file is part of LMMS - https://lmms.io * @@ -25,11 +26,12 @@ #ifndef CONTROLLER_RACK_VIEW_H #define CONTROLLER_RACK_VIEW_H -#include #include +#include +#include -#include "SerializingObject.h" #include "lmms_basics.h" +#include "SerializingObject.h" class QPushButton; @@ -40,44 +42,54 @@ class ControllerView; class Controller; -class ControllerRackView : public QWidget, public SerializingObject +class LMMS_EXPORT ControllerRackView : public QWidget, public SerializingObject { Q_OBJECT public: ControllerRackView(); virtual ~ControllerRackView(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + virtual void saveSettings(QDomDocument &, QDomElement & parent); + virtual void loadSettings(const QDomElement & _this); inline virtual QString nodeName() const { return "ControllerRackView"; } + QMdiSubWindow *subWin() const; + + bool allExpanded() const; + bool allCollapsed() const; public slots: - void deleteController( ControllerView * _view ); - void onControllerAdded( Controller * ); - void onControllerRemoved( Controller * ); + void deleteController(ControllerView * view); + void collapsingAll(); + void expandAll(); + void onControllerAdded(Controller *); + void onControllerRemoved(Controller *); + void onControllerCollapsed(); + + const QVector controllerViews() const; protected: - virtual void closeEvent( QCloseEvent * _ce ); + virtual void closeEvent(QCloseEvent * ce); + virtual void resizeEvent(QResizeEvent *); + virtual void paintEvent(QPaintEvent *); private slots: - void addController(); - + void addLfoController(); + void moveControllerUp(ControllerView * cv); + void moveControllerDown(ControllerView * cv); private: QVector m_controllerViews; + QVector m_collapsingStateOnLoad; QScrollArea * m_scrollArea; QVBoxLayout * m_scrollAreaLayout; QPushButton * m_addButton; - - // Stores the index of where to insert the next ControllerView. - // Needed so that the StretchItem always stays at the last position. - int m_nextIndex; -} ; + QMdiSubWindow * m_subWin; +}; #endif diff --git a/include/ControllerView.h b/include/ControllerView.h index 4b215feca9b..ceaecd58b75 100644 --- a/include/ControllerView.h +++ b/include/ControllerView.h @@ -2,6 +2,7 @@ * ControllerView.h - view-component for an control * * Copyright (c) 2008 Paul Giblock + * Copyright (c) 2019 Steffen Baranowsky * * This file is part of LMMS - https://lmms.io * @@ -26,59 +27,74 @@ #define CONTROLLER_VIEW_H #include +#include #include "AutomatableModel.h" #include "Controller.h" #include "ModelView.h" -class QGroupBox; -class QLabel; -class QPushButton; -class QMdiSubWindow; -class LedCheckBox; +class QLineEdit; +class QPushButton; class ControllerView : public QFrame, public ModelView { Q_OBJECT public: - ControllerView( Controller * _controller, QWidget * _parent ); + ControllerView(Controller * controller, QWidget * parent); virtual ~ControllerView(); inline Controller * getController() { - return( castModel() ); + return castModel(); } inline const Controller * getController() const { - return( castModel() ); + return castModel(); } + bool isCollapsed() const; + public slots: - void editControls(); + void collapseController(bool collapse); + void toggleCollapseController(); + + void rename(); + void renameFinished(); + void moveUp(); + void moveDown(); void deleteController(); - void closeControls(); - void renameController(); + signals: - void deleteController( ControllerView * _view ); + void deleteController(ControllerView * view); + void controllerCollapsed(); + void collapseAll(); + void expandAll(); + void controllerMoveUp(ControllerView * view); + void controllerMoveDown(ControllerView * view); protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); + virtual void paintEvent(QPaintEvent *); + virtual void contextMenuEvent(QContextMenuEvent *); virtual void modelChanged(); - virtual void mouseDoubleClickEvent( QMouseEvent * event ); + virtual void mouseDoubleClickEvent(QMouseEvent * me); + virtual void dragEnterEvent(QDragEnterEvent * dee); + virtual void dropEvent(QDropEvent * de); private: - QMdiSubWindow * m_subWindow; ControllerDialog * m_controllerDlg; - QLabel * m_nameLabel; + const int m_titleBarHeight; bool m_show; - -} ; + QLabel * controllerTypeLabel; + QLineEdit * m_nameLineEdit; + QPushButton * m_collapseButton; + Controller * m_modelC; +}; #endif diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h index c0a60cfa65a..6726cd1116d 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -27,6 +27,8 @@ #define EFFECT_CONTROL_DIALOG_H #include +#include + #include "ModelView.h" @@ -42,6 +44,9 @@ class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView virtual bool isResizable() const {return false;} + virtual void showDialog(); + virtual void toggleView(); + signals: void closed(); @@ -52,6 +57,8 @@ class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView EffectControls * m_effectControls; +private: + QMdiSubWindow * m_subWindow; } ; #endif diff --git a/include/EffectView.h b/include/EffectView.h index 71a0e7128cb..50af810c03c 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -63,7 +63,7 @@ public slots: void moveUp(); void moveDown(); void deletePlugin(); - void closeEffects(); + signals: @@ -84,7 +84,6 @@ public slots: Knob * m_wetDry; TempoSyncKnob * m_autoQuit; Knob * m_gate; - QMdiSubWindow * m_subWindow; EffectControlDialog * m_controlView; } ; diff --git a/include/PeakController.h b/include/PeakController.h index b2824f0ac55..c195ad4e786 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -49,6 +49,7 @@ class LMMS_EXPORT PeakController : public Controller virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); virtual void loadSettings( const QDomElement & _this ); virtual QString nodeName() const; + PeakControllerEffect *getPeakControllerEffect(); static void initGetControllerBySetting(); static PeakController * getControllerBySetting( const QDomElement & _this ); @@ -87,7 +88,7 @@ class PeakControllerDialog : public ControllerDialog { Q_OBJECT public: - PeakControllerDialog( Controller * _controller, QWidget * _parent ); + PeakControllerDialog( PeakController *_controller, QWidget * _parent ); virtual ~PeakControllerDialog(); protected: diff --git a/include/Song.h b/include/Song.h index 32ead7181f5..3f022def9c6 100644 --- a/include/Song.h +++ b/include/Song.h @@ -317,6 +317,8 @@ class LMMS_EXPORT Song : public TrackContainer void addController( Controller * c ); void removeController( Controller * c ); + void moveControllerUp(Controller * c); + void moveControllerDown(Controller * c); const ControllerVector & controllers() const diff --git a/plugins/peak_controller_effect/peak_controller_effect.cpp b/plugins/peak_controller_effect/peak_controller_effect.cpp index 9d1e6ccf465..95922ecdff4 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect.cpp @@ -66,9 +66,8 @@ PeakControllerEffect::PeakControllerEffect( m_effectId( rand() ), m_peakControls( this ), m_lastSample( 0 ), - m_autoController( NULL ) + m_autoController(new PeakController(Engine::getSong(), this)) { - m_autoController = new PeakController( Engine::getSong(), this ); if( !Engine::getSong()->isLoadingProject() && !PresetPreviewPlayHandle::isPreviewing() ) { Engine::getSong()->addController( m_autoController ); diff --git a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp index 88538b813f2..13883a003ee 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp @@ -27,9 +27,12 @@ #include #include +#include +#include "ControllerRackView.h" #include "peak_controller_effect_control_dialog.h" #include "peak_controller_effect_controls.h" +#include "GuiApplication.h" #include "Knob.h" #include "LedCheckbox.h" #include "embed.h" @@ -42,7 +45,7 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog( setWindowIcon( embed::getIconPixmap( "controller" ) ); setAutoFillBackground( true ); QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + pal.setBrush( backgroundRole(), QBrush( embed::getIconPixmap( "peak_controller_artwork" ) ) ); setPalette( pal ); setFixedSize( 240, 80 ); @@ -103,3 +106,30 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog( setLayout( mainLayout ); } + + + +void PeakControllerEffectControlDialog::showDialog() +{ + gui->getControllerRackView()->show(); + gui->getControllerRackView()->subWin()->hide(); +} + + + + +void PeakControllerEffectControlDialog::toggleView() +{ + if (!gui->getControllerRackView()->subWin()->isVisible()) + { + gui->getControllerRackView()->subWin()->show(); + gui->getControllerRackView()->subWin()->raise(); + m_effectControls->setViewVisible(true); + } + else + { + gui->getControllerRackView()->subWin()->hide(); + m_effectControls->setViewVisible(false); + } +} + diff --git a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.h b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.h index cd6a99d2b37..25f6880cc59 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.h +++ b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.h @@ -35,7 +35,6 @@ class LedCheckBox; class PeakControllerEffectControlDialog : public EffectControlDialog { - Q_OBJECT public: PeakControllerEffectControlDialog( PeakControllerEffectControls * _controls ); @@ -43,6 +42,8 @@ class PeakControllerEffectControlDialog : public EffectControlDialog { } + void showDialog() override; + void toggleView() override; protected: Knob * m_baseKnob; diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index b2e3bc92132..d8c98c3028a 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -245,6 +245,11 @@ QString PeakController::nodeName() const return( "Peakcontroller" ); } +PeakControllerEffect * PeakController::getPeakControllerEffect() +{ + return m_peakEffect; +} + ControllerDialog * PeakController::createDialog( QWidget * _parent ) diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 336aa3df273..ec2164904e2 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -1411,6 +1411,34 @@ void Song::removeController( Controller * controller ) +void Song::moveControllerUp(Controller *c) +{ + if (c != m_controllers.first()) + { + int index = m_controllers.indexOf(c); + m_controllers.remove(index); + m_controllers.insert(index - 1, c); + setModified(); + } +} + + + + +void Song::moveControllerDown(Controller *c) +{ + if (c != m_controllers.last()) + { + int index = m_controllers.indexOf(c); + m_controllers.remove(index); + m_controllers.insert(index + 1, c); + setModified(); + } +} + + + + void Song::clearErrors() { m_errors.clear(); diff --git a/src/gui/EffectControlDialog.cpp b/src/gui/EffectControlDialog.cpp index dc273a6a32f..2bb39663a86 100644 --- a/src/gui/EffectControlDialog.cpp +++ b/src/gui/EffectControlDialog.cpp @@ -25,15 +25,19 @@ #include #include +#include #include "EffectControlDialog.h" #include "EffectControls.h" +#include "GuiApplication.h" +#include "MainWindow.h" EffectControlDialog::EffectControlDialog( EffectControls * _controls ) : QWidget( NULL ), ModelView( _controls, this ), - m_effectControls( _controls ) + m_effectControls( _controls ), + m_subWindow(nullptr) { setWindowTitle( m_effectControls->effect()->displayName() ); setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); @@ -46,13 +50,55 @@ EffectControlDialog::~EffectControlDialog() { } +void EffectControlDialog::showDialog() +{ + if (!m_subWindow) + { + m_subWindow = gui->mainWindow()->addWindowedWidget(this); + if (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); + } + m_subWindow->hide(); +} + + + + +void EffectControlDialog::toggleView() +{ + if (m_subWindow) + { + if (!m_subWindow->isVisible()) + { + m_subWindow->show(); + m_subWindow->raise(); + m_effectControls->setViewVisible(true); + } + else + { + m_subWindow->hide(); + m_effectControls->setViewVisible(false); + } + } +} + void EffectControlDialog::closeEvent( QCloseEvent * _ce ) { + m_subWindow->hide(); _ce->ignore(); - emit closed(); } diff --git a/src/gui/PeakControllerDialog.cpp b/src/gui/PeakControllerDialog.cpp index 48f0a93da3f..ca9455e8007 100644 --- a/src/gui/PeakControllerDialog.cpp +++ b/src/gui/PeakControllerDialog.cpp @@ -24,34 +24,25 @@ */ -#include -#include -#include -#include - -#include "CaptionMenu.h" -#include "gui_templates.h" -#include "embed.h" -#include "MainWindow.h" -#include "ToolTip.h" #include "PeakController.h" -#include "Knob.h" -#include "TempoSyncKnob.h" + +#include + +#include "EffectControlDialog.h" +#include "plugins/peak_controller_effect/peak_controller_effect.h" +#include "plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp" -PeakControllerDialog::PeakControllerDialog( Controller * _model, QWidget * _parent ) : +PeakControllerDialog::PeakControllerDialog( PeakController * _model, QWidget * _parent ) : ControllerDialog( _model, _parent ) { + EffectControlDialog * dlg = _model->getPeakControllerEffect()->controls()->createView(); setWindowTitle( tr( "PEAK" ) ); setWindowIcon( embed::getIconPixmap( "controller" ) ); - setFixedSize( 256, 64 ); - - ToolTip::add( this, tr( "LFO Controller" ) ); - - QLabel * l = new QLabel( this ); - l->setText( "Use FX's controls" ); - l->move(10, 10); + setFixedSize( dlg->size() ); + dlg->setParent( this ); + dlg->show(); setModel( _model ); } diff --git a/src/gui/widgets/ControllerRackView.cpp b/src/gui/widgets/ControllerRackView.cpp index 621c41c73e6..77f90a61e86 100644 --- a/src/gui/widgets/ControllerRackView.cpp +++ b/src/gui/widgets/ControllerRackView.cpp @@ -3,6 +3,7 @@ * * Copyright (c) 2008-2009 Paul Giblock * Copyright (c) 2010-2014 Tobias Doerffel + * Copyright (c) 2019 Steffen Baranowsky * * This file is part of LMMS - https://lmms.io * @@ -23,70 +24,74 @@ * */ +#include "ControllerRackView.h" + #include #include +#include #include +#include #include #include -#include -#include +#include +#include -#include "Song.h" +#include "ControllerView.h" #include "embed.h" -#include "GuiApplication.h" -#include "MainWindow.h" #include "GroupBox.h" -#include "ControllerRackView.h" -#include "ControllerView.h" +#include "GuiApplication.h" #include "LfoController.h" +#include "MainWindow.h" +#include "Song.h" -ControllerRackView::ControllerRackView( ) : +ControllerRackView::ControllerRackView() : QWidget(), - m_nextIndex(0) + m_collapsingStateOnLoad() { - setWindowIcon( embed::getIconPixmap( "controller" ) ); - setWindowTitle( tr( "Controller Rack" ) ); - - m_scrollArea = new QScrollArea( this ); - m_scrollArea->setPalette( QApplication::palette( m_scrollArea ) ); - m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - - QWidget * scrollAreaWidget = new QWidget( m_scrollArea ); - m_scrollAreaLayout = new QVBoxLayout( scrollAreaWidget ); + setWindowIcon(embed::getIconPixmap("controller")); + setWindowTitle(tr("Controller Rack")); + + m_scrollArea = new QScrollArea(this); + m_scrollArea->setPalette(QApplication::palette(m_scrollArea)); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_scrollArea->setFrameStyle(QFrame::Plain); + m_scrollArea->setFrameShadow(QFrame::Plain); + + QWidget * scrollAreaWidget = new QWidget(m_scrollArea); + m_scrollAreaLayout = new QVBoxLayout(scrollAreaWidget); m_scrollAreaLayout->addStretch(); - scrollAreaWidget->setLayout( m_scrollAreaLayout ); + m_scrollAreaLayout->setMargin(0); + m_scrollAreaLayout->setSpacing(0); + scrollAreaWidget->setLayout(m_scrollAreaLayout); - m_scrollArea->setWidget( scrollAreaWidget ); - m_scrollArea->setWidgetResizable( true ); + m_scrollArea->setWidget(scrollAreaWidget); + m_scrollArea->setWidgetResizable(true); - m_addButton = new QPushButton( this ); - m_addButton->setText( tr( "Add" ) ); + m_addButton = new QPushButton(this); + m_addButton->setText(tr("Add LFO")); + connect(m_addButton, SIGNAL(clicked()), this, SLOT(addLfoController())); - connect( m_addButton, SIGNAL( clicked() ), - this, SLOT( addController() ) ); - - Song * song = Engine::getSong(); - connect( song, SIGNAL( controllerAdded( Controller* ) ), SLOT( onControllerAdded( Controller* ) ) ); - connect( song, SIGNAL( controllerRemoved( Controller* ) ), SLOT( onControllerRemoved( Controller* ) ) ); + connect(Engine::getSong(), SIGNAL(controllerAdded(Controller*)), SLOT(onControllerAdded(Controller*))); + connect(Engine::getSong(), SIGNAL(controllerRemoved(Controller*)), SLOT(onControllerRemoved(Controller*))); QVBoxLayout * layout = new QVBoxLayout(); - layout->addWidget( m_scrollArea ); - layout->addWidget( m_addButton ); - this->setLayout( layout ); + layout->addWidget(m_scrollArea); + layout->addWidget(m_addButton); + layout->setMargin(0); + setLayout(layout); - QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget( this ); + m_subWin = gui->mainWindow()->addWindowedWidget(this); - // No maximize button - Qt::WindowFlags flags = subWin->windowFlags(); + Qt::WindowFlags flags = m_subWin->windowFlags(); flags &= ~Qt::WindowMaximizeButtonHint; - subWin->setWindowFlags( flags ); - - subWin->setAttribute( Qt::WA_DeleteOnClose, false ); - subWin->move( 680, 310 ); - subWin->resize( 350, 200 ); - subWin->setFixedWidth( 350 ); - subWin->setMinimumHeight( 200 ); + m_subWin->setWindowFlags(flags); + + m_subWin->setAttribute(Qt::WA_DeleteOnClose, false); + m_subWin->move(680, 60); + m_subWin->resize(400, 249); + m_subWin->setFixedWidth(249); } @@ -99,111 +104,225 @@ ControllerRackView::~ControllerRackView() -void ControllerRackView::saveSettings( QDomDocument & _doc, - QDomElement & _this ) +void ControllerRackView::saveSettings(QDomDocument &, QDomElement & parent) { - MainWindow::saveWidgetState( this, _this ); + parent.setAttribute(QString("controllerCount"), m_controllerViews.size()); + for (auto i = 1; i <= m_controllerViews.size(); i++) + { + bool collapsed = m_controllerViews.at(i - 1)->isCollapsed(); + parent.setAttribute(QString("controllerView") + QString::number(i), collapsed); + } + MainWindow::saveWidgetState(this, parent); } -void ControllerRackView::loadSettings( const QDomElement & _this ) +void ControllerRackView::loadSettings(const QDomElement & _this) { - MainWindow::restoreWidgetState( this, _this ); + int controllerCount = _this.attribute(QString("controllerCount")).toInt(); + for (auto i = 1; i <= controllerCount; i++) + { + bool collapsingState = _this.attribute(QString("controllerView") + QString::number(i)).toInt(); + m_collapsingStateOnLoad.append(collapsingState); + } + MainWindow::restoreWidgetState(this, _this); } -void ControllerRackView::deleteController( ControllerView * _view ) +void ControllerRackView::deleteController(ControllerView * view) { - Controller * c = _view->getController(); + Controller * c = view->getController(); - if( c->connectionCount() > 0 ) + if (c->connectionCount() > 0) { QMessageBox msgBox; - msgBox.setIcon( QMessageBox::Question ); - msgBox.setWindowTitle( tr("Confirm Delete") ); - msgBox.setText( tr("Confirm delete? There are existing connection(s) " - "associated with this controller. There is no way to undo.") ); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle(tr("Confirm Delete")); + msgBox.setText(tr("Confirm delete? There are existing connection(s) " + "associated with this controller. There is no way to undo.")); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - if( msgBox.exec() != QMessageBox::Ok ) + if (msgBox.exec() != QMessageBox::Ok) { return; } } - Song * song = Engine::getSong(); - song->removeController( c ); + Engine::getSong()->removeController(c); } -void ControllerRackView::onControllerAdded( Controller * controller ) +void ControllerRackView::collapsingAll() { - QWidget * scrollAreaWidget = m_scrollArea->widget(); + for (auto &it : m_controllerViews) + { + it->collapseController(true); + } +} - ControllerView * controllerView = new ControllerView( controller, scrollAreaWidget ); - connect( controllerView, SIGNAL( deleteController( ControllerView * ) ), - this, SLOT( deleteController( ControllerView * ) ), Qt::QueuedConnection ); - m_controllerViews.append( controllerView ); - m_scrollAreaLayout->insertWidget( m_nextIndex, controllerView ); - ++m_nextIndex; +void ControllerRackView::expandAll() +{ + for (auto &it : m_controllerViews) + { + it->collapseController(false); + } } -void ControllerRackView::onControllerRemoved( Controller * removedController ) +void ControllerRackView::onControllerAdded(Controller * controller) { - ControllerView * viewOfRemovedController = 0; + ControllerView * controllerView = new ControllerView(controller, m_scrollArea->widget()); + connect(controllerView, SIGNAL(deleteController(ControllerView*)), this, SLOT(deleteController(ControllerView*)), Qt::QueuedConnection); + connect(controllerView, SIGNAL(controllerCollapsed()), this, SLOT(onControllerCollapsed())); + connect(controllerView, SIGNAL(collapseAll()), this, SLOT(collapsingAll())); + connect(controllerView, SIGNAL(expandAll()), this, SLOT(expandAll())); + connect(controllerView, SIGNAL(controllerMoveUp(ControllerView*)), this, SLOT(moveControllerUp(ControllerView*))); + connect(controllerView, SIGNAL(controllerMoveDown(ControllerView*)), this, SLOT(moveControllerDown(ControllerView*))); + m_controllerViews.append(controllerView); + int n = m_scrollAreaLayout->count() - 1; + m_scrollAreaLayout->insertWidget(n, controllerView); + + if (Engine::getSong()->isLoadingProject()) + { + if (!m_collapsingStateOnLoad.empty() && m_collapsingStateOnLoad.at(m_controllerViews.size() - 1)) + { + controllerView->collapseController(true); + } + } - QVector::const_iterator end = m_controllerViews.end(); - for ( QVector::const_iterator it = m_controllerViews.begin(); it != end; ++it) + update(); +} + + + + +void ControllerRackView::onControllerRemoved(Controller * removedController) +{ + for (auto &it : m_controllerViews) { - ControllerView *currentControllerView = *it; - if ( currentControllerView->getController() == removedController ) + if (it->getController() == removedController) { - viewOfRemovedController = currentControllerView; + ControllerView * viewOfRemovedController = it; + m_controllerViews.erase(std::find(m_controllerViews.begin(), + m_controllerViews.end(), viewOfRemovedController)); + + delete viewOfRemovedController; + m_scrollArea->verticalScrollBar()->hide(); + update(); break; } } +} + + - if (viewOfRemovedController ) + +void ControllerRackView::onControllerCollapsed() +{ + //we hide the scrollbar and let update() test if a scrollbar is needed + m_scrollArea->verticalScrollBar()->hide(); + update(); +} + + + + +void ControllerRackView::addLfoController() +{ + Engine::getSong()->addController(new LfoController(Engine::getSong())); + setFocus(); +} + + + + +void ControllerRackView::moveControllerUp(ControllerView *cv) +{ + if (cv != m_controllerViews.first()) { - m_controllerViews.erase( std::find( m_controllerViews.begin(), - m_controllerViews.end(), viewOfRemovedController ) ); + int index = m_controllerViews.indexOf(cv); + m_scrollAreaLayout->removeWidget(cv); + m_scrollAreaLayout->insertWidget(index - 1, cv); + m_controllerViews.remove(index); + m_controllerViews.insert(index - 1, cv); + Engine::getSong()->moveControllerUp(cv->getController()); + } +} + + - delete viewOfRemovedController; - --m_nextIndex; + +void ControllerRackView::moveControllerDown(ControllerView *cv) +{ + //move up the controller below, is the same + if (cv != m_controllerViews.last()) + { + int index = m_controllerViews.indexOf(cv); + moveControllerUp(m_controllerViews.at(index + 1)); } } -void ControllerRackView::addController() +const QVector ControllerRackView::controllerViews() const { - // TODO: Eventually let the user pick from available controller types + return m_controllerViews; +} - Engine::getSong()->addController( new LfoController( Engine::getSong() ) ); - // fix bug which always made ControllerRackView loose focus when adding - // new controller - setFocus(); + + +bool ControllerRackView::allCollapsed() const +{ + for (auto &it : m_controllerViews) + { + if (!it->isCollapsed()) + { + return false; + } + } + return true; } -void ControllerRackView::closeEvent( QCloseEvent * _ce ) - { - if( parentWidget() ) +bool ControllerRackView::allExpanded() const +{ + for (auto &it : m_controllerViews) + { + if (it->isCollapsed()) + { + return false; + } + } + return true; +} + + + + +QMdiSubWindow *ControllerRackView::subWin() const +{ + return m_subWin; +} + + + + +void ControllerRackView::closeEvent(QCloseEvent * ce) +{ + if (parentWidget()) { parentWidget()->hide(); } @@ -211,6 +330,22 @@ void ControllerRackView::closeEvent( QCloseEvent * _ce ) { hide(); } - _ce->ignore(); - } + ce->ignore(); +} + + + + +void ControllerRackView::resizeEvent(QResizeEvent *) +{ + m_subWin->setFixedWidth( m_scrollArea->verticalScrollBar()->isVisible() ? 262 : 249 ); +} + + + +void ControllerRackView::paintEvent(QPaintEvent *) +{ + m_subWin->setFixedWidth(m_scrollArea->verticalScrollBar()->isVisible() ? 262 : 249); + m_scrollArea->verticalScrollBar()->show(); +} diff --git a/src/gui/widgets/ControllerView.cpp b/src/gui/widgets/ControllerView.cpp index b61ce12c44b..6ef3ecb089c 100644 --- a/src/gui/widgets/ControllerView.cpp +++ b/src/gui/widgets/ControllerView.cpp @@ -3,6 +3,7 @@ * * Copyright (c) 2008-2009 Paul Giblock * Copyright (c) 2011-2014 Tobias Doerffel + * Copyright (c) 2019 Steffen Baranowsky * * This file is part of LMMS - https://lmms.io * @@ -23,162 +24,260 @@ * */ +#include "ControllerView.h" -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include -#include "ControllerView.h" #include "CaptionMenu.h" +#include "ControllerConnection.h" #include "ControllerDialog.h" -#include "gui_templates.h" +#include "ControllerRackView.h" #include "embed.h" +#include "Engine.h" +#include "gui_templates.h" #include "GuiApplication.h" -#include "LedCheckbox.h" #include "MainWindow.h" +#include "ProjectJournal.h" +#include "Song.h" +#include "StringPairDrag.h" #include "ToolTip.h" -ControllerView::ControllerView( Controller * _model, QWidget * _parent ) : - QFrame( _parent ), - ModelView( _model, this ), - m_subWindow( NULL ), - m_controllerDlg( NULL ), - m_show( true ) +ControllerView::ControllerView(Controller * controller, QWidget * parent) : + QFrame(parent), + ModelView(controller, this), + m_controllerDlg(NULL), + m_titleBarHeight(24), + m_show(true), + m_modelC(controller) { - this->setFrameStyle( QFrame::StyledPanel ); - this->setFrameShadow( QFrame::Raised ); + const QSize buttonsize(17, 17); + setFrameStyle(QFrame::Plain); + setFrameShadow(QFrame::Plain); + setLineWidth(0); + setContentsMargins(0, 0, 0, 0); + + m_controllerDlg = getController()->createDialog(this); + m_controllerDlg->move(1, m_titleBarHeight); + + controllerTypeLabel = new QLabel(this); + controllerTypeLabel->setText(QString(getController()->type() == Controller::LfoController + ? QString("LFO: ") + : QString("PEAK: "))); + controllerTypeLabel->move(3, 3); + controllerTypeLabel->show(); + + m_nameLineEdit = new QLineEdit(this); + m_nameLineEdit->setText(controller->name()); + m_nameLineEdit->setReadOnly(true); + m_nameLineEdit->setAttribute(Qt::WA_TransparentForMouseEvents); + m_nameLineEdit->move(controllerTypeLabel->sizeHint().width() + 3, 2); + connect(m_nameLineEdit, SIGNAL(editingFinished()), this, SLOT(renameFinished())); + + setFixedWidth(m_controllerDlg->width() + 2); + setFixedHeight(m_controllerDlg->height() + m_titleBarHeight + 1); + + m_collapseButton = new QPushButton(embed::getIconPixmap("stepper-down"), QString::null, this ); + m_collapseButton->resize(buttonsize); + m_collapseButton->setFocusPolicy(Qt::NoFocus); + m_collapseButton->setCursor(Qt::ArrowCursor); + m_collapseButton->setAttribute(Qt::WA_NoMousePropagation); + m_collapseButton->setToolTip(tr("collapse")); + m_collapseButton->move(width() - buttonsize.width() - 3, 3); + connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(toggleCollapseController())); + + setAcceptDrops(true); + setModel(controller); +} - QVBoxLayout *vBoxLayout = new QVBoxLayout(this); - QHBoxLayout *hBox = new QHBoxLayout(); - vBoxLayout->addLayout(hBox); - QLabel *label = new QLabel( "" + _model->displayName() + "", this); - QSizePolicy sizePolicy = label->sizePolicy(); - sizePolicy.setHorizontalStretch(1); - label->setSizePolicy(sizePolicy); - hBox->addWidget(label); +ControllerView::~ControllerView() +{ +} - QPushButton * controlsButton = new QPushButton( tr( "Controls" ), this ); - connect( controlsButton, SIGNAL( clicked() ), SLOT( editControls() ) ); - hBox->addWidget(controlsButton); - m_nameLabel = new QLabel(_model->name(), this); - vBoxLayout->addWidget(m_nameLabel); +bool ControllerView::isCollapsed() const +{ + return m_controllerDlg->isHidden(); +} - m_controllerDlg = getController()->createDialog( gui->mainWindow()->workspace() ); - m_subWindow = gui->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() ) ); +void ControllerView::collapseController(bool collapse) +{ + if (collapse) + { + m_collapseButton->setIcon(embed::getIconPixmap("stepper-left")); + m_controllerDlg->hide(); + setFixedHeight(m_titleBarHeight); + emit controllerCollapsed(); + } + else + { + m_controllerDlg->show(); + setFixedHeight(m_controllerDlg->height() + m_titleBarHeight + 1); + m_collapseButton->setIcon(embed::getIconPixmap("stepper-down")); + } +} - m_subWindow->hide(); - setModel( _model ); + + +void ControllerView::deleteController() +{ + emit(deleteController(this)); } -ControllerView::~ControllerView() +void ControllerView::toggleCollapseController() { - if (m_subWindow) - { - delete m_subWindow; - } + collapseController(!m_controllerDlg->isHidden()); } -void ControllerView::editControls() +void ControllerView::renameFinished() { - if( m_show ) - { - m_subWindow->show(); - m_subWindow->raise(); - m_show = false; - } - else + m_nameLineEdit->setReadOnly(true); + Controller * c = castModel(); + QString new_name = m_nameLineEdit->text(); + if (new_name != c->name()) { - m_subWindow->hide(); - m_show = true; + c->setName(new_name); + Engine::getSong()->setModified(); } } -void ControllerView::closeControls() +void ControllerView::rename() { - m_subWindow->hide(); - m_show = true; + m_nameLineEdit->setReadOnly(false); + m_nameLineEdit->setFocus(); + m_nameLineEdit->selectAll(); } -void ControllerView::deleteController() + + +void ControllerView::moveUp() { - emit( deleteController( this ) ); + emit controllerMoveUp(this); } -void ControllerView::renameController() + + + +void ControllerView::moveDown() { - bool ok; - Controller * c = castModel(); - QString new_name = QInputDialog::getText( this, - tr( "Rename controller" ), - tr( "Enter the new name for this controller" ), - QLineEdit::Normal, c->name() , &ok ); - if( ok && !new_name.isEmpty() ) + emit controllerMoveDown(this); +} + + + + +void ControllerView::mouseDoubleClickEvent(QMouseEvent * me) +{ + if (me->y() <= m_titleBarHeight) + { + rename(); + } +} + + + + +void ControllerView::dragEnterEvent(QDragEnterEvent *dee) +{ + StringPairDrag::processDragEnterEvent(dee, "automatable_model" ); +} + + + + +void ControllerView::dropEvent(QDropEvent * de) +{ + QString type = StringPairDrag::decodeKey(de); + QString val = StringPairDrag::decodeValue(de); + if (type == "automatable_model") { - c->setName( new_name ); - if( getController()->type() == Controller::LfoController ) + AutomatableModel * mod = dynamic_cast(Engine::projectJournal()->journallingObject(val.toInt())); + if (mod != nullptr) { - m_controllerDlg->setWindowTitle( tr( "LFO" ) + " (" + new_name + ")" ); + if (m_modelC->hasModel(mod)) + { + QMessageBox::warning(this, tr("LMMS"), tr("Cycle Detected.")); + } + else + { + if (mod->controllerConnection()) + { + mod->controllerConnection()->setController(getController()); + } + else + { + ControllerConnection * cc = new ControllerConnection(getController()); + mod->setControllerConnection(cc); + } + } } - m_nameLabel->setText( new_name ); } } -void ControllerView::mouseDoubleClickEvent( QMouseEvent * event ) + + +void ControllerView::modelChanged() { - renameController(); } -void ControllerView::modelChanged() + +void ControllerView::paintEvent(QPaintEvent*) { + QPainter p(this); + QRect rect(1, 1, width() - 2, m_titleBarHeight); + p.fillRect(rect, p.background()); } -void ControllerView::contextMenuEvent( QContextMenuEvent * ) + +void ControllerView::contextMenuEvent(QContextMenuEvent *) { - QPointer contextMenu = new CaptionMenu( model()->displayName(), this ); - contextMenu->addAction( embed::getIconPixmap( "cancel" ), - tr( "&Remove this controller" ), - this, SLOT( deleteController() ) ); - contextMenu->addAction( tr("Re&name this controller"), this, SLOT( renameController() )); + QPointer contextMenu = new CaptionMenu(model()->displayName(), this); + + contextMenu->addAction(embed::getIconPixmap("cancel"), tr("&Remove this controller"), this, SLOT(deleteController())); + + contextMenu->addAction(embed::getIconPixmap("stepper-left"), tr("&Collaps all controllers"), + this, SIGNAL(collapseAll()) + )->setDisabled(gui->getControllerRackView()->allCollapsed()); + contextMenu->addAction(embed::getIconPixmap("stepper-down"), tr("&Expand all controllers"), + this, SIGNAL(expandAll()) + )->setDisabled(gui->getControllerRackView()->allExpanded()); + contextMenu->addAction(embed::getIconPixmap("stepper-up"), tr("Move &up"), this, SLOT(moveUp()) + )->setDisabled(gui->getControllerRackView()->controllerViews().first() == this); + contextMenu->addAction(embed::getIconPixmap("stepper-down"), tr("Move &down"), this, SLOT(moveDown()) + )->setDisabled(gui->getControllerRackView()->controllerViews().last() == this); contextMenu->addSeparator(); - contextMenu->exec( QCursor::pos() ); + + contextMenu->exec(QCursor::pos()); + delete contextMenu; } diff --git a/src/gui/widgets/EffectView.cpp b/src/gui/widgets/EffectView.cpp index a159eedf956..57ac9c1cda9 100644 --- a/src/gui/widgets/EffectView.cpp +++ b/src/gui/widgets/EffectView.cpp @@ -24,12 +24,13 @@ */ #include +#include #include #include #include #include -#include +#include "ControllerRackView.h" #include "EffectView.h" #include "DummyEffect.h" #include "CaptionMenu.h" @@ -41,12 +42,13 @@ #include "MainWindow.h" #include "TempoSyncKnob.h" #include "ToolTip.h" +#include "Song.h" +#include "plugins/peak_controller_effect/peak_controller_effect_control_dialog.h" EffectView::EffectView( Effect * _model, QWidget * _parent ) : PluginView( _model, _parent ), m_bg( embed::getIconPixmap( "effect_plugin" ) ), - m_subWindow( NULL ), m_controlView( NULL ) { setFixedSize( 210, 60 ); @@ -90,37 +92,14 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : QFont f = ctls_btn->font(); ctls_btn->setFont( pointSize<8>( f ) ); ctls_btn->setGeometry( 140, 14, 50, 20 ); - connect( ctls_btn, SIGNAL( clicked() ), - this, SLOT( editControls() ) ); + connect(ctls_btn, SIGNAL(clicked()), this, SLOT(editControls())); m_controlView = effect()->controls()->createView(); - if( m_controlView ) + if (m_controlView) { - m_subWindow = gui->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->hide(); + m_controlView->showDialog(); } } - - - //move above vst effect view creation - //setModel( _model ); } @@ -128,33 +107,19 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : EffectView::~EffectView() { - delete m_subWindow; } - void EffectView::editControls() { - if( m_subWindow ) - { - if( !m_subWindow->isVisible() ) - { - m_subWindow->show(); - m_subWindow->raise(); - effect()->controls()->setViewVisible( true ); - } - else - { - m_subWindow->hide(); - effect()->controls()->setViewVisible( false ); - } - } + m_controlView->toggleView(); } + void EffectView::moveUp() { emit moveUp( this ); @@ -178,17 +143,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 );