From 4bab38192cf0cfc9d6d33cbab992f74e6ff6e887 Mon Sep 17 00:00:00 2001 From: saker Date: Mon, 30 Sep 2024 19:27:31 -0400 Subject: [PATCH] Reformat MixerChannelView classes --- include/MixerChannelView.h | 198 ++++---- src/gui/MixerChannelView.cpp | 853 +++++++++++++++++------------------ 2 files changed, 520 insertions(+), 531 deletions(-) diff --git a/include/MixerChannelView.h b/include/MixerChannelView.h index 13d149e8740..8074d4dceaa 100644 --- a/include/MixerChannelView.h +++ b/include/MixerChannelView.h @@ -25,6 +25,13 @@ #ifndef MIXER_CHANNEL_VIEW_H #define MIXER_CHANNEL_VIEW_H +#include +#include +#include +#include +#include +#include + #include "EffectRackView.h" #include "Fader.h" #include "Knob.h" @@ -32,109 +39,100 @@ #include "PixmapButton.h" #include "SendButtonIndicator.h" -#include -#include -#include -#include -#include -#include - -namespace lmms -{ - class MixerChannel; +namespace lmms { +class MixerChannel; } -namespace lmms::gui +namespace lmms::gui { +class PeakIndicator; + +constexpr int MIXER_CHANNEL_INNER_BORDER_SIZE = 3; +constexpr int MIXER_CHANNEL_OUTER_BORDER_SIZE = 1; + +class MixerChannelView : public QWidget { - class PeakIndicator; - - constexpr int MIXER_CHANNEL_INNER_BORDER_SIZE = 3; - constexpr int MIXER_CHANNEL_OUTER_BORDER_SIZE = 1; - - class MixerChannelView : public QWidget - { - Q_OBJECT - Q_PROPERTY(QBrush backgroundActive READ backgroundActive WRITE setBackgroundActive) - Q_PROPERTY(QColor strokeOuterActive READ strokeOuterActive WRITE setStrokeOuterActive) - Q_PROPERTY(QColor strokeOuterInactive READ strokeOuterInactive WRITE setStrokeOuterInactive) - Q_PROPERTY(QColor strokeInnerActive READ strokeInnerActive WRITE setStrokeInnerActive) - Q_PROPERTY(QColor strokeInnerInactive READ strokeInnerInactive WRITE setStrokeInnerInactive) - public: - MixerChannelView(QWidget* parent, MixerView* mixerView, int channelIndex); - void paintEvent(QPaintEvent* event) override; - void contextMenuEvent(QContextMenuEvent*) override; - void mousePressEvent(QMouseEvent*) override; - void mouseDoubleClickEvent(QMouseEvent*) override; - bool eventFilter(QObject* dist, QEvent* event) override; - - int channelIndex() const; - void setChannelIndex(int index); - - QBrush backgroundActive() const; - void setBackgroundActive(const QBrush& c); - - QColor strokeOuterActive() const; - void setStrokeOuterActive(const QColor& c); - - QColor strokeOuterInactive() const; - void setStrokeOuterInactive(const QColor& c); - - QColor strokeInnerActive() const; - void setStrokeInnerActive(const QColor& c); - - QColor strokeInnerInactive() const; - void setStrokeInnerInactive(const QColor& c); - - void reset(); - - public slots: - void renameChannel(); - void resetColor(); - void selectColor(); - void randomizeColor(); - - private slots: - void renameFinished(); - void removeChannel(); - void removeUnusedChannels(); - void moveChannelLeft(); - void moveChannelRight(); - - private: - bool confirmRemoval(int index); - QString elideName(const QString& name); - MixerChannel* mixerChannel() const; - auto isMasterChannel() const -> bool { return m_channelIndex == 0; } - - private: - SendButtonIndicator* m_sendButton; - QLabel* m_receiveArrow; - QStackedWidget* m_receiveArrowOrSendButton; - int m_receiveArrowStackedIndex = -1; - int m_sendButtonStackedIndex = -1; - - Knob* m_sendKnob; - LcdWidget* m_channelNumberLcd; - QLineEdit* m_renameLineEdit; - QGraphicsView* m_renameLineEditView; - QLabel* m_sendArrow; - PixmapButton* m_muteButton; - PixmapButton* m_soloButton; - PeakIndicator* m_peakIndicator = nullptr; - Fader* m_fader; - EffectRackView* m_effectRackView; - MixerView* m_mixerView; - int m_channelIndex = 0; - bool m_inRename = false; - - QBrush m_backgroundActive; - QColor m_strokeOuterActive; - QColor m_strokeOuterInactive; - QColor m_strokeInnerActive; - QColor m_strokeInnerInactive; - - friend class MixerView; - }; + Q_OBJECT + Q_PROPERTY(QBrush backgroundActive READ backgroundActive WRITE setBackgroundActive) + Q_PROPERTY(QColor strokeOuterActive READ strokeOuterActive WRITE setStrokeOuterActive) + Q_PROPERTY(QColor strokeOuterInactive READ strokeOuterInactive WRITE setStrokeOuterInactive) + Q_PROPERTY(QColor strokeInnerActive READ strokeInnerActive WRITE setStrokeInnerActive) + Q_PROPERTY(QColor strokeInnerInactive READ strokeInnerInactive WRITE setStrokeInnerInactive) +public: + MixerChannelView(QWidget* parent, MixerView* mixerView, int channelIndex); + void paintEvent(QPaintEvent* event) override; + void contextMenuEvent(QContextMenuEvent*) override; + void mousePressEvent(QMouseEvent*) override; + void mouseDoubleClickEvent(QMouseEvent*) override; + bool eventFilter(QObject* dist, QEvent* event) override; + + int channelIndex() const; + void setChannelIndex(int index); + + QBrush backgroundActive() const; + void setBackgroundActive(const QBrush& c); + + QColor strokeOuterActive() const; + void setStrokeOuterActive(const QColor& c); + + QColor strokeOuterInactive() const; + void setStrokeOuterInactive(const QColor& c); + + QColor strokeInnerActive() const; + void setStrokeInnerActive(const QColor& c); + + QColor strokeInnerInactive() const; + void setStrokeInnerInactive(const QColor& c); + + void reset(); + +public slots: + void renameChannel(); + void resetColor(); + void selectColor(); + void randomizeColor(); + +private slots: + void renameFinished(); + void removeChannel(); + void removeUnusedChannels(); + void moveChannelLeft(); + void moveChannelRight(); + +private: + bool confirmRemoval(int index); + QString elideName(const QString& name); + MixerChannel* mixerChannel() const; + auto isMasterChannel() const -> bool { return m_channelIndex == 0; } + +private: + SendButtonIndicator* m_sendButton; + QLabel* m_receiveArrow; + QStackedWidget* m_receiveArrowOrSendButton; + int m_receiveArrowStackedIndex = -1; + int m_sendButtonStackedIndex = -1; + + Knob* m_sendKnob; + LcdWidget* m_channelNumberLcd; + QLineEdit* m_renameLineEdit; + QGraphicsView* m_renameLineEditView; + QLabel* m_sendArrow; + PixmapButton* m_muteButton; + PixmapButton* m_soloButton; + PeakIndicator* m_peakIndicator = nullptr; + Fader* m_fader; + EffectRackView* m_effectRackView; + MixerView* m_mixerView; + int m_channelIndex = 0; + bool m_inRename = false; + + QBrush m_backgroundActive; + QColor m_strokeOuterActive; + QColor m_strokeOuterInactive; + QColor m_strokeInnerActive; + QColor m_strokeInnerInactive; + + friend class MixerView; +}; } // namespace lmms::gui #endif // MIXER_CHANNEL_VIEW_H diff --git a/src/gui/MixerChannelView.cpp b/src/gui/MixerChannelView.cpp index 82bbedb0378..2228c850882 100644 --- a/src/gui/MixerChannelView.cpp +++ b/src/gui/MixerChannelView.cpp @@ -22,450 +22,441 @@ * */ +#include "MixerChannelView.h" + +#include +#include +#include +#include +#include +#include +#include +#include + #include "CaptionMenu.h" #include "ColorChooser.h" +#include "ConfigManager.h" +#include "FontHelper.h" #include "GuiApplication.h" #include "Mixer.h" -#include "MixerChannelView.h" #include "MixerView.h" #include "PeakIndicator.h" #include "Song.h" -#include "ConfigManager.h" -#include "FontHelper.h" -#include -#include -#include -#include -#include -#include -#include +namespace lmms::gui { +MixerChannelView::MixerChannelView(QWidget* parent, MixerView* mixerView, int channelIndex) + : QWidget(parent) + , m_mixerView(mixerView) + , m_channelIndex(channelIndex) +{ + auto retainSizeWhenHidden = [](QWidget* widget) { + auto sizePolicy = widget->sizePolicy(); + sizePolicy.setRetainSizeWhenHidden(true); + widget->setSizePolicy(sizePolicy); + }; + + auto receiveArrowContainer = new QWidget{}; + auto receiveArrowLayout = new QVBoxLayout{receiveArrowContainer}; + m_receiveArrow = new QLabel{}; + m_receiveArrow->setPixmap(embed::getIconPixmap("receive_bg_arrow")); + receiveArrowLayout->setContentsMargins(0, 0, 0, 0); + receiveArrowLayout->setSpacing(0); + receiveArrowLayout->addWidget(m_receiveArrow, 0, Qt::AlignHCenter); + + auto sendButtonContainer = new QWidget{}; + auto sendButtonLayout = new QVBoxLayout{sendButtonContainer}; + m_sendButton = new SendButtonIndicator{this, this, mixerView}; + sendButtonLayout->setContentsMargins(0, 0, 0, 0); + sendButtonLayout->setSpacing(0); + sendButtonLayout->addWidget(m_sendButton, 0, Qt::AlignHCenter); + + m_receiveArrowOrSendButton = new QStackedWidget{this}; + m_receiveArrowStackedIndex = m_receiveArrowOrSendButton->addWidget(receiveArrowContainer); + m_sendButtonStackedIndex = m_receiveArrowOrSendButton->addWidget(sendButtonContainer); + retainSizeWhenHidden(m_receiveArrowOrSendButton); + + m_sendKnob = new Knob{KnobType::Bright26, this, tr("Channel send amount")}; + retainSizeWhenHidden(m_sendKnob); + + m_sendArrow = new QLabel{}; + m_sendArrow->setPixmap(embed::getIconPixmap("send_bg_arrow")); + retainSizeWhenHidden(m_sendArrow); + + m_channelNumberLcd = new LcdWidget{2, this}; + m_channelNumberLcd->setValue(channelIndex); + retainSizeWhenHidden(m_channelNumberLcd); + + const auto mixerChannel = Engine::mixer()->mixerChannel(channelIndex); + const auto mixerName = mixerChannel->m_name; + setToolTip(mixerName); + + m_renameLineEdit = new QLineEdit{mixerName, nullptr}; + m_renameLineEdit->setFixedWidth(65); + m_renameLineEdit->setFont(adjustedToPixelSize(font(), LARGE_FONT_SIZE)); + m_renameLineEdit->setReadOnly(true); + m_renameLineEdit->installEventFilter(this); + + auto renameLineEditScene = new QGraphicsScene{}; + m_renameLineEditView = new QGraphicsView{}; + m_renameLineEditView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_renameLineEditView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_renameLineEditView->setAttribute(Qt::WA_TransparentForMouseEvents, true); + m_renameLineEditView->setScene(renameLineEditScene); + + auto renameLineEditProxy = renameLineEditScene->addWidget(m_renameLineEdit); + renameLineEditProxy->setRotation(-90); + m_renameLineEditView->setFixedSize(m_renameLineEdit->height() + 5, m_renameLineEdit->width() + 5); + + m_muteButton = new PixmapButton(this, tr("Mute")); + m_muteButton->setModel(&mixerChannel->m_muteModel); + m_muteButton->setActiveGraphic(embed::getIconPixmap("led_off")); + m_muteButton->setInactiveGraphic(embed::getIconPixmap("led_green")); + m_muteButton->setCheckable(true); + m_muteButton->setToolTip(tr("Mute this channel")); + + m_soloButton = new PixmapButton(this, tr("Solo")); + m_soloButton->setModel(&mixerChannel->m_soloModel); + m_soloButton->setActiveGraphic(embed::getIconPixmap("led_red")); + m_soloButton->setInactiveGraphic(embed::getIconPixmap("led_off")); + m_soloButton->setCheckable(true); + m_soloButton->setToolTip(tr("Solo this channel")); + + auto soloMuteLayout = new QVBoxLayout(); + soloMuteLayout->setContentsMargins(0, 0, 0, 0); + soloMuteLayout->setSpacing(0); + soloMuteLayout->addWidget(m_soloButton, 0, Qt::AlignHCenter); + soloMuteLayout->addWidget(m_muteButton, 0, Qt::AlignHCenter); + + m_fader = new Fader{&mixerChannel->m_volumeModel, tr("Fader %1").arg(channelIndex), this}; + + m_peakIndicator = new PeakIndicator(this); + connect(m_fader, &Fader::peakChanged, m_peakIndicator, &PeakIndicator::updatePeak); + + m_effectRackView = new EffectRackView{&mixerChannel->m_fxChain, mixerView->m_racksWidget}; + m_effectRackView->setFixedWidth(EffectRackView::DEFAULT_WIDTH); + + auto mainLayout = new QVBoxLayout{this}; + mainLayout->setContentsMargins(4, 4, 4, 4); + mainLayout->setSpacing(2); + + mainLayout->addWidget(m_receiveArrowOrSendButton, 0, Qt::AlignHCenter); + mainLayout->addWidget(m_sendKnob, 0, Qt::AlignHCenter); + mainLayout->addWidget(m_sendArrow, 0, Qt::AlignHCenter); + mainLayout->addWidget(m_channelNumberLcd, 0, Qt::AlignHCenter); + mainLayout->addWidget(m_renameLineEditView, 0, Qt::AlignHCenter); + mainLayout->addLayout(soloMuteLayout); + mainLayout->addWidget(m_peakIndicator); + mainLayout->addWidget(m_fader, 1, Qt::AlignHCenter); + + connect(m_renameLineEdit, &QLineEdit::editingFinished, this, &MixerChannelView::renameFinished); +} + +void MixerChannelView::contextMenuEvent(QContextMenuEvent*) +{ + auto contextMenu = new CaptionMenu(mixerChannel()->m_name, this); -#include + if (!isMasterChannel()) // no move-options in master + { + contextMenu->addAction(tr("Move &left"), this, &MixerChannelView::moveChannelLeft); + contextMenu->addAction(tr("Move &right"), this, &MixerChannelView::moveChannelRight); + } + + contextMenu->addAction(tr("Rename &channel"), this, &MixerChannelView::renameChannel); + contextMenu->addSeparator(); + + if (!isMasterChannel()) // no remove-option in master + { + contextMenu->addAction( + embed::getIconPixmap("cancel"), tr("R&emove channel"), this, &MixerChannelView::removeChannel); + contextMenu->addSeparator(); + } + + contextMenu->addAction( + embed::getIconPixmap("cancel"), tr("Remove &unused channels"), this, &MixerChannelView::removeUnusedChannels); + contextMenu->addSeparator(); + + auto colorMenu = QMenu{tr("Color"), this}; + colorMenu.setIcon(embed::getIconPixmap("colorize")); + colorMenu.addAction(tr("Change"), this, &MixerChannelView::selectColor); + colorMenu.addAction(tr("Reset"), this, &MixerChannelView::resetColor); + colorMenu.addAction(tr("Pick random"), this, &MixerChannelView::randomizeColor); + contextMenu->addMenu(&colorMenu); + + contextMenu->exec(QCursor::pos()); + delete contextMenu; +} + +void MixerChannelView::paintEvent(QPaintEvent* event) +{ + const auto channel = mixerChannel(); + const bool muted = channel->m_muteModel.value(); + const auto name = channel->m_name; + const auto elidedName = elideName(name); + const auto isActive = m_mixerView->currentMixerChannel() == this; + + if (!m_inRename && m_renameLineEdit->text() != elidedName) { m_renameLineEdit->setText(elidedName); } + + const auto width = rect().width(); + const auto height = rect().height(); + auto painter = QPainter{this}; + + if (channel->color().has_value() && !muted) + { + painter.fillRect(rect(), channel->color()->darker(isActive ? 120 : 150)); + } + else { painter.fillRect(rect(), isActive ? backgroundActive().color() : painter.background().color()); } + + // inner border + painter.setPen(isActive ? strokeInnerActive() : strokeInnerInactive()); + painter.drawRect(1, 1, width - MIXER_CHANNEL_INNER_BORDER_SIZE, height - MIXER_CHANNEL_INNER_BORDER_SIZE); + + // outer border + painter.setPen(isActive ? strokeOuterActive() : strokeOuterInactive()); + painter.drawRect(0, 0, width - MIXER_CHANNEL_OUTER_BORDER_SIZE, height - MIXER_CHANNEL_OUTER_BORDER_SIZE); + + QWidget::paintEvent(event); +} + +void MixerChannelView::mousePressEvent(QMouseEvent*) +{ + if (m_mixerView->currentMixerChannel() != this) { m_mixerView->setCurrentMixerChannel(this); } +} + +void MixerChannelView::mouseDoubleClickEvent(QMouseEvent*) +{ + renameChannel(); +} + +bool MixerChannelView::eventFilter(QObject* dist, QEvent* event) +{ + // If we are in a rename, capture the enter/return events and handle them + if (event->type() == QEvent::KeyPress) + { + auto keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) + { + if (m_inRename) + { + renameFinished(); + event->accept(); // Stop the event from propagating + return true; + } + } + } + return false; +} + +int MixerChannelView::channelIndex() const +{ + return m_channelIndex; +} + +void MixerChannelView::setChannelIndex(int index) +{ + MixerChannel* mixerChannel = Engine::mixer()->mixerChannel(index); + m_fader->setModel(&mixerChannel->m_volumeModel); + m_muteButton->setModel(&mixerChannel->m_muteModel); + m_soloButton->setModel(&mixerChannel->m_soloModel); + m_effectRackView->setModel(&mixerChannel->m_fxChain); + m_channelNumberLcd->setValue(index); + m_channelIndex = index; +} + +QBrush MixerChannelView::backgroundActive() const +{ + return m_backgroundActive; +} + +void MixerChannelView::setBackgroundActive(const QBrush& c) +{ + m_backgroundActive = c; +} + +QColor MixerChannelView::strokeOuterActive() const +{ + return m_strokeOuterActive; +} + +void MixerChannelView::setStrokeOuterActive(const QColor& c) +{ + m_strokeOuterActive = c; +} + +QColor MixerChannelView::strokeOuterInactive() const +{ + return m_strokeOuterInactive; +} + +void MixerChannelView::setStrokeOuterInactive(const QColor& c) +{ + m_strokeOuterInactive = c; +} + +QColor MixerChannelView::strokeInnerActive() const +{ + return m_strokeInnerActive; +} + +void MixerChannelView::setStrokeInnerActive(const QColor& c) +{ + m_strokeInnerActive = c; +} + +QColor MixerChannelView::strokeInnerInactive() const +{ + return m_strokeInnerInactive; +} + +void MixerChannelView::setStrokeInnerInactive(const QColor& c) +{ + m_strokeInnerInactive = c; +} + +void MixerChannelView::reset() +{ + m_peakIndicator->resetPeakToMinusInf(); +} + +void MixerChannelView::renameChannel() +{ + m_inRename = true; + setToolTip(""); + m_renameLineEdit->setReadOnly(false); + + m_channelNumberLcd->hide(); + m_renameLineEdit->setFixedWidth(m_renameLineEdit->width()); + m_renameLineEdit->setText(mixerChannel()->m_name); -namespace lmms::gui + m_renameLineEditView->setFocus(); + m_renameLineEdit->selectAll(); + m_renameLineEdit->setFocus(); +} + +void MixerChannelView::renameFinished() { - MixerChannelView::MixerChannelView(QWidget* parent, MixerView* mixerView, int channelIndex) : - QWidget(parent), - m_mixerView(mixerView), - m_channelIndex(channelIndex) - { - auto retainSizeWhenHidden = [](QWidget* widget) - { - auto sizePolicy = widget->sizePolicy(); - sizePolicy.setRetainSizeWhenHidden(true); - widget->setSizePolicy(sizePolicy); - }; - - auto receiveArrowContainer = new QWidget{}; - auto receiveArrowLayout = new QVBoxLayout{receiveArrowContainer}; - m_receiveArrow = new QLabel{}; - m_receiveArrow->setPixmap(embed::getIconPixmap("receive_bg_arrow")); - receiveArrowLayout->setContentsMargins(0, 0, 0, 0); - receiveArrowLayout->setSpacing(0); - receiveArrowLayout->addWidget(m_receiveArrow, 0, Qt::AlignHCenter); - - auto sendButtonContainer = new QWidget{}; - auto sendButtonLayout = new QVBoxLayout{sendButtonContainer}; - m_sendButton = new SendButtonIndicator{this, this, mixerView}; - sendButtonLayout->setContentsMargins(0, 0, 0, 0); - sendButtonLayout->setSpacing(0); - sendButtonLayout->addWidget(m_sendButton, 0, Qt::AlignHCenter); - - m_receiveArrowOrSendButton = new QStackedWidget{this}; - m_receiveArrowStackedIndex = m_receiveArrowOrSendButton->addWidget(receiveArrowContainer); - m_sendButtonStackedIndex = m_receiveArrowOrSendButton->addWidget(sendButtonContainer); - retainSizeWhenHidden(m_receiveArrowOrSendButton); - - m_sendKnob = new Knob{KnobType::Bright26, this, tr("Channel send amount")}; - retainSizeWhenHidden(m_sendKnob); - - m_sendArrow = new QLabel{}; - m_sendArrow->setPixmap(embed::getIconPixmap("send_bg_arrow")); - retainSizeWhenHidden(m_sendArrow); - - m_channelNumberLcd = new LcdWidget{2, this}; - m_channelNumberLcd->setValue(channelIndex); - retainSizeWhenHidden(m_channelNumberLcd); - - const auto mixerChannel = Engine::mixer()->mixerChannel(channelIndex); - const auto mixerName = mixerChannel->m_name; - setToolTip(mixerName); - - m_renameLineEdit = new QLineEdit{mixerName, nullptr}; - m_renameLineEdit->setFixedWidth(65); - m_renameLineEdit->setFont(adjustedToPixelSize(font(), LARGE_FONT_SIZE)); - m_renameLineEdit->setReadOnly(true); - m_renameLineEdit->installEventFilter(this); - - auto renameLineEditScene = new QGraphicsScene{}; - m_renameLineEditView = new QGraphicsView{}; - m_renameLineEditView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_renameLineEditView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_renameLineEditView->setAttribute(Qt::WA_TransparentForMouseEvents, true); - m_renameLineEditView->setScene(renameLineEditScene); - - auto renameLineEditProxy = renameLineEditScene->addWidget(m_renameLineEdit); - renameLineEditProxy->setRotation(-90); - m_renameLineEditView->setFixedSize(m_renameLineEdit->height() + 5, m_renameLineEdit->width() + 5); - - m_muteButton = new PixmapButton(this, tr("Mute")); - m_muteButton->setModel(&mixerChannel->m_muteModel); - m_muteButton->setActiveGraphic(embed::getIconPixmap("led_off")); - m_muteButton->setInactiveGraphic(embed::getIconPixmap("led_green")); - m_muteButton->setCheckable(true); - m_muteButton->setToolTip(tr("Mute this channel")); - - m_soloButton = new PixmapButton(this, tr("Solo")); - m_soloButton->setModel(&mixerChannel->m_soloModel); - m_soloButton->setActiveGraphic(embed::getIconPixmap("led_red")); - m_soloButton->setInactiveGraphic(embed::getIconPixmap("led_off")); - m_soloButton->setCheckable(true); - m_soloButton->setToolTip(tr("Solo this channel")); - - auto soloMuteLayout = new QVBoxLayout(); - soloMuteLayout->setContentsMargins(0, 0, 0, 0); - soloMuteLayout->setSpacing(0); - soloMuteLayout->addWidget(m_soloButton, 0, Qt::AlignHCenter); - soloMuteLayout->addWidget(m_muteButton, 0, Qt::AlignHCenter); - - m_fader = new Fader{&mixerChannel->m_volumeModel, tr("Fader %1").arg(channelIndex), this}; - - m_peakIndicator = new PeakIndicator(this); - connect(m_fader, &Fader::peakChanged, m_peakIndicator, &PeakIndicator::updatePeak); - - m_effectRackView = new EffectRackView{&mixerChannel->m_fxChain, mixerView->m_racksWidget}; - m_effectRackView->setFixedWidth(EffectRackView::DEFAULT_WIDTH); - - auto mainLayout = new QVBoxLayout{this}; - mainLayout->setContentsMargins(4, 4, 4, 4); - mainLayout->setSpacing(2); - - mainLayout->addWidget(m_receiveArrowOrSendButton, 0, Qt::AlignHCenter); - mainLayout->addWidget(m_sendKnob, 0, Qt::AlignHCenter); - mainLayout->addWidget(m_sendArrow, 0, Qt::AlignHCenter); - mainLayout->addWidget(m_channelNumberLcd, 0, Qt::AlignHCenter); - mainLayout->addWidget(m_renameLineEditView, 0, Qt::AlignHCenter); - mainLayout->addLayout(soloMuteLayout); - mainLayout->addWidget(m_peakIndicator); - mainLayout->addWidget(m_fader, 1, Qt::AlignHCenter); - - connect(m_renameLineEdit, &QLineEdit::editingFinished, this, &MixerChannelView::renameFinished); - } - - void MixerChannelView::contextMenuEvent(QContextMenuEvent*) - { - auto contextMenu = new CaptionMenu(mixerChannel()->m_name, this); - - if (!isMasterChannel()) // no move-options in master - { - contextMenu->addAction(tr("Move &left"), this, &MixerChannelView::moveChannelLeft); - contextMenu->addAction(tr("Move &right"), this, &MixerChannelView::moveChannelRight); - } - - contextMenu->addAction(tr("Rename &channel"), this, &MixerChannelView::renameChannel); - contextMenu->addSeparator(); - - if (!isMasterChannel()) // no remove-option in master - { - contextMenu->addAction(embed::getIconPixmap("cancel"), tr("R&emove channel"), this, &MixerChannelView::removeChannel); - contextMenu->addSeparator(); - } - - contextMenu->addAction(embed::getIconPixmap("cancel"), tr("Remove &unused channels"), this, &MixerChannelView::removeUnusedChannels); - contextMenu->addSeparator(); - - auto colorMenu = QMenu{tr("Color"), this}; - colorMenu.setIcon(embed::getIconPixmap("colorize")); - colorMenu.addAction(tr("Change"), this, &MixerChannelView::selectColor); - colorMenu.addAction(tr("Reset"), this, &MixerChannelView::resetColor); - colorMenu.addAction(tr("Pick random"), this, &MixerChannelView::randomizeColor); - contextMenu->addMenu(&colorMenu); - - contextMenu->exec(QCursor::pos()); - delete contextMenu; - } - - void MixerChannelView::paintEvent(QPaintEvent* event) - { - const auto channel = mixerChannel(); - const bool muted = channel->m_muteModel.value(); - const auto name = channel->m_name; - const auto elidedName = elideName(name); - const auto isActive = m_mixerView->currentMixerChannel() == this; - - if (!m_inRename && m_renameLineEdit->text() != elidedName) - { - m_renameLineEdit->setText(elidedName); - } - - const auto width = rect().width(); - const auto height = rect().height(); - auto painter = QPainter{this}; - - if (channel->color().has_value() && !muted) - { - painter.fillRect(rect(), channel->color()->darker(isActive ? 120 : 150)); - } - else - { - painter.fillRect(rect(), isActive ? backgroundActive().color() : painter.background().color()); - } - - // inner border - painter.setPen(isActive ? strokeInnerActive() : strokeInnerInactive()); - painter.drawRect(1, 1, width - MIXER_CHANNEL_INNER_BORDER_SIZE, height - MIXER_CHANNEL_INNER_BORDER_SIZE); - - // outer border - painter.setPen(isActive ? strokeOuterActive() : strokeOuterInactive()); - painter.drawRect(0, 0, width - MIXER_CHANNEL_OUTER_BORDER_SIZE, height - MIXER_CHANNEL_OUTER_BORDER_SIZE); - - QWidget::paintEvent(event); - } - - void MixerChannelView::mousePressEvent(QMouseEvent*) - { - if (m_mixerView->currentMixerChannel() != this) - { - m_mixerView->setCurrentMixerChannel(this); - } - } - - void MixerChannelView::mouseDoubleClickEvent(QMouseEvent*) - { - renameChannel(); - } - - bool MixerChannelView::eventFilter(QObject* dist, QEvent* event) - { - // If we are in a rename, capture the enter/return events and handle them - if (event->type() == QEvent::KeyPress) - { - auto keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) - { - if (m_inRename) - { - renameFinished(); - event->accept(); // Stop the event from propagating - return true; - } - } - } - return false; - } - - int MixerChannelView::channelIndex() const - { - return m_channelIndex; - } - - void MixerChannelView::setChannelIndex(int index) - { - MixerChannel* mixerChannel = Engine::mixer()->mixerChannel(index); - m_fader->setModel(&mixerChannel->m_volumeModel); - m_muteButton->setModel(&mixerChannel->m_muteModel); - m_soloButton->setModel(&mixerChannel->m_soloModel); - m_effectRackView->setModel(&mixerChannel->m_fxChain); - m_channelNumberLcd->setValue(index); - m_channelIndex = index; - } - - QBrush MixerChannelView::backgroundActive() const - { - return m_backgroundActive; - } - - void MixerChannelView::setBackgroundActive(const QBrush& c) - { - m_backgroundActive = c; - } - - QColor MixerChannelView::strokeOuterActive() const - { - return m_strokeOuterActive; - } - - void MixerChannelView::setStrokeOuterActive(const QColor& c) - { - m_strokeOuterActive = c; - } - - QColor MixerChannelView::strokeOuterInactive() const - { - return m_strokeOuterInactive; - } - - void MixerChannelView::setStrokeOuterInactive(const QColor& c) - { - m_strokeOuterInactive = c; - } - - QColor MixerChannelView::strokeInnerActive() const - { - return m_strokeInnerActive; - } - - void MixerChannelView::setStrokeInnerActive(const QColor& c) - { - m_strokeInnerActive = c; - } - - QColor MixerChannelView::strokeInnerInactive() const - { - return m_strokeInnerInactive; - } - - void MixerChannelView::setStrokeInnerInactive(const QColor& c) - { - m_strokeInnerInactive = c; - } - - void MixerChannelView::reset() - { - m_peakIndicator->resetPeakToMinusInf(); - } - - void MixerChannelView::renameChannel() - { - m_inRename = true; - setToolTip(""); - m_renameLineEdit->setReadOnly(false); - - m_channelNumberLcd->hide(); - m_renameLineEdit->setFixedWidth(m_renameLineEdit->width()); - m_renameLineEdit->setText(mixerChannel()->m_name); - - m_renameLineEditView->setFocus(); - m_renameLineEdit->selectAll(); - m_renameLineEdit->setFocus(); - } - - void MixerChannelView::renameFinished() - { - m_inRename = false; - - m_renameLineEdit->deselect(); - m_renameLineEdit->setReadOnly(true); - m_renameLineEdit->setFixedWidth(m_renameLineEdit->width()); - m_channelNumberLcd->show(); - - auto newName = m_renameLineEdit->text(); - setFocus(); - - const auto mc = mixerChannel(); - if (!newName.isEmpty() && mc->m_name != newName) - { - mc->m_name = newName; - m_renameLineEdit->setText(elideName(newName)); - Engine::getSong()->setModified(); - } - - setToolTip(mc->m_name); - } - - void MixerChannelView::resetColor() - { - mixerChannel()->setColor(std::nullopt); - Engine::getSong()->setModified(); - update(); - } - - void MixerChannelView::selectColor() - { - const auto channel = mixerChannel(); - - const auto initialColor = channel->color().value_or(backgroundActive().color()); - const auto * colorChooser = ColorChooser{this}.withPalette(ColorChooser::Palette::Mixer); - const auto newColor = colorChooser->getColor(initialColor); - - if (!newColor.isValid()) { return; } - - channel->setColor(newColor); - - Engine::getSong()->setModified(); - update(); - } - - void MixerChannelView::randomizeColor() - { - auto channel = mixerChannel(); - channel->setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[rand() % 48]); - Engine::getSong()->setModified(); - update(); - } - - bool MixerChannelView::confirmRemoval(int index) + m_inRename = false; + + m_renameLineEdit->deselect(); + m_renameLineEdit->setReadOnly(true); + m_renameLineEdit->setFixedWidth(m_renameLineEdit->width()); + m_channelNumberLcd->show(); + + auto newName = m_renameLineEdit->text(); + setFocus(); + + const auto mc = mixerChannel(); + if (!newName.isEmpty() && mc->m_name != newName) { - // if config variable is set to false, there is no need for user confirmation - bool needConfirm = ConfigManager::inst()->value("ui", "mixerchanneldeletionwarning", "1").toInt(); - if (!needConfirm) { return true; } - - // is the channel is not in use, there is no need for user confirmation - if (!getGUI()->mixerView()->getMixer()->isChannelInUse(index)) { return true; } - - QString messageRemoveTrack = tr("This Mixer Channel is being used.\n" - "Are you sure you want to remove this channel?\n\n" - "Warning: This operation can not be undone."); - - QString messageTitleRemoveTrack = tr("Confirm removal"); - QString askAgainText = tr("Don't ask again"); - auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr); - connect(askAgainCheckBox, &QCheckBox::stateChanged, [](int state) { - // Invert button state, if it's checked we *shouldn't* ask again - ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", state ? "0" : "1"); - }); - - QMessageBox mb(this); - mb.setText(messageRemoveTrack); - mb.setWindowTitle(messageTitleRemoveTrack); - mb.setIcon(QMessageBox::Warning); - mb.addButton(QMessageBox::Cancel); - mb.addButton(QMessageBox::Ok); - mb.setCheckBox(askAgainCheckBox); - mb.setDefaultButton(QMessageBox::Cancel); - - int answer = mb.exec(); - - return answer == QMessageBox::Ok; + mc->m_name = newName; + m_renameLineEdit->setText(elideName(newName)); + Engine::getSong()->setModified(); } - void MixerChannelView::removeChannel() - { - if (!confirmRemoval(m_channelIndex)) { return; } - auto mix = getGUI()->mixerView(); - mix->deleteChannel(m_channelIndex); - } - - void MixerChannelView::removeUnusedChannels() - { - auto mix = getGUI()->mixerView(); - mix->deleteUnusedChannels(); - } - - void MixerChannelView::moveChannelLeft() - { - auto mix = getGUI()->mixerView(); - mix->moveChannelLeft(m_channelIndex); - } - - void MixerChannelView::moveChannelRight() - { - auto mix = getGUI()->mixerView(); - mix->moveChannelRight(m_channelIndex); - } - - QString MixerChannelView::elideName(const QString& name) - { - const auto maxTextHeight = m_renameLineEdit->width(); - const auto metrics = QFontMetrics{m_renameLineEdit->font()}; - const auto elidedName = metrics.elidedText(name, Qt::ElideRight, maxTextHeight); - return elidedName; - } - - MixerChannel* MixerChannelView::mixerChannel() const - { - return Engine::mixer()->mixerChannel(m_channelIndex); - } + setToolTip(mc->m_name); +} + +void MixerChannelView::resetColor() +{ + mixerChannel()->setColor(std::nullopt); + Engine::getSong()->setModified(); + update(); +} + +void MixerChannelView::selectColor() +{ + const auto channel = mixerChannel(); + + const auto initialColor = channel->color().value_or(backgroundActive().color()); + const auto* colorChooser = ColorChooser{this}.withPalette(ColorChooser::Palette::Mixer); + const auto newColor = colorChooser->getColor(initialColor); + + if (!newColor.isValid()) { return; } + + channel->setColor(newColor); + + Engine::getSong()->setModified(); + update(); +} + +void MixerChannelView::randomizeColor() +{ + auto channel = mixerChannel(); + channel->setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[rand() % 48]); + Engine::getSong()->setModified(); + update(); +} + +bool MixerChannelView::confirmRemoval(int index) +{ + // if config variable is set to false, there is no need for user confirmation + bool needConfirm = ConfigManager::inst()->value("ui", "mixerchanneldeletionwarning", "1").toInt(); + if (!needConfirm) { return true; } + + // is the channel is not in use, there is no need for user confirmation + if (!getGUI()->mixerView()->getMixer()->isChannelInUse(index)) { return true; } + + QString messageRemoveTrack = tr("This Mixer Channel is being used.\n" + "Are you sure you want to remove this channel?\n\n" + "Warning: This operation can not be undone."); + + QString messageTitleRemoveTrack = tr("Confirm removal"); + QString askAgainText = tr("Don't ask again"); + auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr); + connect(askAgainCheckBox, &QCheckBox::stateChanged, [](int state) { + // Invert button state, if it's checked we *shouldn't* ask again + ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", state ? "0" : "1"); + }); + + QMessageBox mb(this); + mb.setText(messageRemoveTrack); + mb.setWindowTitle(messageTitleRemoveTrack); + mb.setIcon(QMessageBox::Warning); + mb.addButton(QMessageBox::Cancel); + mb.addButton(QMessageBox::Ok); + mb.setCheckBox(askAgainCheckBox); + mb.setDefaultButton(QMessageBox::Cancel); + + int answer = mb.exec(); + + return answer == QMessageBox::Ok; +} + +void MixerChannelView::removeChannel() +{ + if (!confirmRemoval(m_channelIndex)) { return; } + auto mix = getGUI()->mixerView(); + mix->deleteChannel(m_channelIndex); +} + +void MixerChannelView::removeUnusedChannels() +{ + auto mix = getGUI()->mixerView(); + mix->deleteUnusedChannels(); +} + +void MixerChannelView::moveChannelLeft() +{ + auto mix = getGUI()->mixerView(); + mix->moveChannelLeft(m_channelIndex); +} + +void MixerChannelView::moveChannelRight() +{ + auto mix = getGUI()->mixerView(); + mix->moveChannelRight(m_channelIndex); +} + +QString MixerChannelView::elideName(const QString& name) +{ + const auto maxTextHeight = m_renameLineEdit->width(); + const auto metrics = QFontMetrics{m_renameLineEdit->font()}; + const auto elidedName = metrics.elidedText(name, Qt::ElideRight, maxTextHeight); + return elidedName; +} + +MixerChannel* MixerChannelView::mixerChannel() const +{ + return Engine::mixer()->mixerChannel(m_channelIndex); +} } // namespace lmms::gui