From 8e9ec92005a6689e271d32e91de56f6779c82e0d Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 11:06:14 -0400 Subject: [PATCH 01/13] Box format for building toolbar --- .gitignore | 1 + src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 412 ++++++++---------- .../RvCommon/RvCommon/RvBottomViewToolBar.h | 5 + .../multiple_source_media_rep.py | 33 +- 4 files changed, 203 insertions(+), 248 deletions(-) diff --git a/.gitignore b/.gitignore index c2643dc4e..f9fe83a01 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .vscode/** .idea/** +.cache/** # Qt generated **/*.moc diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 69b58a8f6..06a23aebe 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -99,54 +101,57 @@ namespace Rv setProperty("tbstyle", QVariant(QString("play_controls"))); - QAction* a; - QMenu* m; - QToolButton* b; - QFrame* qf; - - for (size_t i = 0; i < 6; i++) + constexpr int sideBoxPadding = 20; + constexpr int sideBoxFixedWidth = 450; + + auto makeBtn = [](QWidget* parent, QAction* action, const char* tbstyle, const char* tbsize = nullptr) { + QToolButton* btn = new QToolButton(parent); + btn->setDefaultAction(action); + btn->setProperty("tbstyle", QVariant(QString(tbstyle))); + if (tbsize) + btn->setProperty("tbsize", QVariant(QString(tbsize))); + btn->setToolButtonStyle(Qt::ToolButtonIconOnly); + return btn; + }; + + auto makeExpandingSpacer = [this]() { + QFrame* qf = new QFrame(this); + qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + qf->setMinimumWidth(0); + qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); + qf->setStyleSheet("background-color: transparent"); + return qf; + }; + + m_leftBox = new QWidget(this); + m_leftBox->setObjectName("leftBox"); + QHBoxLayout* leftLayout = new QHBoxLayout(m_leftBox); + leftLayout->setContentsMargins(sideBoxPadding, 0, sideBoxPadding, 0); + leftLayout->setSpacing(0); + m_leftBox->setFixedWidth(sideBoxFixedWidth); + + struct LeftActionDef { - a = addAction(""); - b = dynamic_cast(widgetForAction(a)); - b->setIcon(m_playModeLoopIcon); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setProperty("tbstyle", QVariant(QString("interior"))); - - switch (i) - { - case 0: - b->setProperty("tbstyle", QVariant(QString("left"))); - a->setIcon(QIcon(":/images/smanager.png")); - a->setToolTip("Toggle Session Manager"); - m_smAction = a; - break; - case 1: - a->setIcon(QIcon(":/images/paint_48x48.png")); - a->setToolTip("Toggle Annotation tools"); - m_paintAction = a; - break; - case 2: - a->setIcon(QIcon(":/images/about_48x48.png")); - a->setToolTip("Toggle Image Info"); - m_infoAction = a; - break; - case 3: - a->setIcon(QIcon(":/images/ntwrk_48x48.png")); - a->setToolTip("Toggle RV Networking Dialog"); - m_networkAction = a; - break; - case 4: - a->setIcon(QIcon(":/images/timeline_mag.png")); - a->setToolTip("Toggle Timeline Magnifier"); - m_timelineMagAction = a; - break; - case 5: - a->setIcon(QIcon(":/images/timeline.png")); - a->setToolTip("Toggle Timeline"); - b->setProperty("tbstyle", QVariant(QString("right"))); - m_timelineAction = a; - break; - } + const char* iconPath; + const char* tooltip; + const char* tbstyle; + QAction** target; + }; + const LeftActionDef leftDefs[] = { + {":/images/smanager.png", "Toggle Session Manager", "left", &m_smAction}, + {":/images/paint_48x48.png", "Toggle Annotation tools", "interior", &m_paintAction}, + {":/images/about_48x48.png", "Toggle Image Info", "interior", &m_infoAction}, + {":/images/ntwrk_48x48.png", "Toggle RV Networking Dialog", "interior", &m_networkAction}, + {":/images/timeline_mag.png", "Toggle Timeline Magnifier", "interior", &m_timelineMagAction}, + {":/images/timeline.png", "Toggle Timeline", "right", &m_timelineAction}, + }; + for (const auto& def : leftDefs) + { + QAction* a = new QAction("", this); + a->setIcon(QIcon(def.iconPath)); + a->setToolTip(def.tooltip); + *def.target = a; + leftLayout->addWidget(makeBtn(m_leftBox, a, def.tbstyle)); } connect(m_smAction, SIGNAL(triggered(bool)), this, SLOT(smActionTriggered(bool))); @@ -156,91 +161,69 @@ namespace Rv connect(m_timelineMagAction, SIGNAL(triggered(bool)), this, SLOT(timelineMagActionTriggered(bool))); connect(m_networkAction, SIGNAL(triggered(bool)), this, SLOT(networkActionTriggered(bool))); - a = addAction(""); - a->setIcon(QIcon(":/images/ghost.png")); - a->setToolTip("Ghost"); - a->setCheckable(true); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_ghostAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/hold.png")); - a->setToolTip("Hold"); - a->setCheckable(true); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_holdAction = a; + m_ghostAction = new QAction("", this); + m_ghostAction->setIcon(QIcon(":/images/ghost.png")); + m_ghostAction->setToolTip("Ghost"); + m_ghostAction->setCheckable(true); + leftLayout->addWidget(makeBtn(m_leftBox, m_ghostAction, "left")); + + m_holdAction = new QAction("", this); + m_holdAction->setIcon(QIcon(":/images/hold.png")); + m_holdAction->setToolTip("Hold"); + m_holdAction->setCheckable(true); + leftLayout->addWidget(makeBtn(m_leftBox, m_holdAction, "right")); connect(m_ghostAction, SIGNAL(triggered(bool)), this, SLOT(ghostTriggered(bool))); connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); - // - // Add some expanding space before the play buttons - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); - - // play buts - a = addAction(""); - a->setIcon(QIcon(":/images/control_bstep.png")); - a->setToolTip("Step back one frame"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setObjectName("backStepButton"); - m_backStepAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/control_fstep.png")); - a->setToolTip("Step forward one frame"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setObjectName("forwardStepButton"); - m_forwardStepAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/control_bplay.png")); - a->setToolTip("Play backwards"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setProperty("tbsize", QVariant(QString("double"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_backwardPlayAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/control_play.png")); - a->setToolTip("Play forwards"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setProperty("tbsize", QVariant(QString("double"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - m_forwardPlayAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/control_bmark.png")); - a->setToolTip("Skip to start of sequence"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("left"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setObjectName("firstFrameButton"); - m_backMarkAction = a; - - a = addAction(""); - a->setIcon(QIcon(":/images/control_fmark.png")); - a->setToolTip("Skip to end of sequence"); - b = dynamic_cast(widgetForAction(a)); - b->setProperty("tbstyle", QVariant(QString("right"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setObjectName("lastFrameButton"); - m_forwardMarkAction = a; + leftLayout->addStretch(); + addWidget(m_leftBox); + + addWidget(makeExpandingSpacer()); + + m_centerBox = new QWidget(this); + m_centerBox->setObjectName("centerBox"); + QHBoxLayout* centerLayout = new QHBoxLayout(m_centerBox); + centerLayout->setContentsMargins(0, 0, 0, 0); + centerLayout->setSpacing(0); + + m_backStepAction = new QAction("", this); + m_backStepAction->setIcon(QIcon(":/images/control_bstep.png")); + m_backStepAction->setToolTip("Step back one frame"); + QToolButton* backStepBtn = makeBtn(m_centerBox, m_backStepAction, "left"); + backStepBtn->setObjectName("backStepButton"); + centerLayout->addWidget(backStepBtn); + + m_forwardStepAction = new QAction("", this); + m_forwardStepAction->setIcon(QIcon(":/images/control_fstep.png")); + m_forwardStepAction->setToolTip("Step forward one frame"); + QToolButton* fwdStepBtn = makeBtn(m_centerBox, m_forwardStepAction, "right"); + fwdStepBtn->setObjectName("forwardStepButton"); + centerLayout->addWidget(fwdStepBtn); + + m_backwardPlayAction = new QAction("", this); + m_backwardPlayAction->setIcon(QIcon(":/images/control_bplay.png")); + m_backwardPlayAction->setToolTip("Play backwards"); + centerLayout->addWidget(makeBtn(m_centerBox, m_backwardPlayAction, "left", "double")); + + m_forwardPlayAction = new QAction("", this); + m_forwardPlayAction->setIcon(QIcon(":/images/control_play.png")); + m_forwardPlayAction->setToolTip("Play forwards"); + centerLayout->addWidget(makeBtn(m_centerBox, m_forwardPlayAction, "right", "double")); + + m_backMarkAction = new QAction("", this); + m_backMarkAction->setIcon(QIcon(":/images/control_bmark.png")); + m_backMarkAction->setToolTip("Skip to start of sequence"); + QToolButton* backMarkBtn = makeBtn(m_centerBox, m_backMarkAction, "left"); + backMarkBtn->setObjectName("firstFrameButton"); + centerLayout->addWidget(backMarkBtn); + + m_forwardMarkAction = new QAction("", this); + m_forwardMarkAction->setIcon(QIcon(":/images/control_fmark.png")); + m_forwardMarkAction->setToolTip("Skip to end of sequence"); + QToolButton* fwdMarkBtn = makeBtn(m_centerBox, m_forwardMarkAction, "right"); + fwdMarkBtn->setObjectName("lastFrameButton"); + centerLayout->addWidget(fwdMarkBtn); connect(m_backStepAction, SIGNAL(triggered()), this, SLOT(backStepTriggered())); connect(m_forwardStepAction, SIGNAL(triggered()), this, SLOT(forwardStepTriggered())); @@ -249,54 +232,40 @@ namespace Rv connect(m_backMarkAction, SIGNAL(triggered()), this, SLOT(backMarkTriggered())); connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); - // - // Add some expanding space after the play buttons - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); + addWidget(m_centerBox); - // - // This expanding space will not go to more than 90 pixels. It's to - // "counter balance" the buttons on the other side, so the play control - // buttons stay in the center of the view (roughly). - // - qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setMaximumWidth(90); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - addWidget(qf); - - m_playModeAction = addAction(""); - m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); - b = dynamic_cast(widgetForAction(m_playModeAction)); + addWidget(makeExpandingSpacer()); + m_rightBox = new QWidget(this); + m_rightBox->setObjectName("rightBox"); + QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); + rightLayout->setContentsMargins(sideBoxPadding, 0, sideBoxPadding, 0); + rightLayout->setSpacing(0); + m_rightBox->setFixedWidth(sideBoxFixedWidth); + + rightLayout->addStretch(); + + m_playModeAction = new QAction("", this); + m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); switch (static_cast(opts.loopMode)) { case Session::PlayOnce: m_playModeAction->setIcon(m_playModeOnceIcon); break; - case Session::PlayPingPong: m_playModeAction->setIcon(m_playModePingPongIcon); break; - default: case Session::PlayLoop: m_playModeAction->setIcon(m_playModeLoopIcon); break; } - b->setProperty("tbstyle", QVariant(QString("left_menu"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setPopupMode(QToolButton::InstantPopup); + QToolButton* playModeBtn = makeBtn(m_rightBox, m_playModeAction, "left_menu"); + playModeBtn->setObjectName("playModeButton"); + playModeBtn->setPopupMode(QToolButton::InstantPopup); - m_playModeMenu = new QMenu(b); + m_playModeMenu = new QMenu(playModeBtn); m_playModeMenu->addAction("Playback")->setDisabled(true); m_playModeOnceAction = m_playModeMenu->addAction(" Once"); m_playModeOnceAction->setData(enumCodeMap(Session::PlayOnce, "commands.setPlayMode(PlayOnce)")); @@ -304,48 +273,46 @@ namespace Rv m_playModeLoopAction->setData(enumCodeMap(Session::PlayLoop, "commands.setPlayMode(PlayLoop)")); m_playModePingPongAction = m_playModeMenu->addAction(" PingPong"); m_playModePingPongAction->setData(enumCodeMap(Session::PlayPingPong, "commands.setPlayMode(PlayPingPong)")); - // m_playModeMenu->addAction(" Loop with Black 0.5 Second"); - // m_playModeMenu->addAction(" Loop with Black 1.0 Second"); - - b->setMenu(m_playModeMenu); + playModeBtn->setMenu(m_playModeMenu); + rightLayout->addWidget(playModeBtn); - // Install event filter to show tooltips on disabled menu items m_playModeMenu->installEventFilter(this); - connect(m_playModeMenu, SIGNAL(triggered(QAction*)), this, SLOT(playModeMenuTriggered(QAction*))); connect(m_playModeMenu, SIGNAL(aboutToShow()), this, SLOT(playModeMenuUpdate())); int volumeLevel = (int)(100.0f * IPCore::SoundTrackIPNode::defaultVolume); - m_audioAction = addAction(""); + m_audioAction = new QAction("", this); m_audioAction->setToolTip("Audio control"); - b = dynamic_cast(widgetForAction(m_audioAction)); - setVolumeLevel(*b, volumeLevel); - b->setProperty("tbstyle", QVariant(QString("right_menu"))); - b->setToolButtonStyle(Qt::ToolButtonIconOnly); - b->setPopupMode(QToolButton::InstantPopup); - m = new QMenu(b); - m->setProperty("menuStyle", QVariant(QString("slim"))); - QAction* audio = m->addAction("Volume"); - audio->setDisabled(true); - QWidgetAction* wa = new QWidgetAction(b); + setVolumeLevel(*m_audioAction, volumeLevel); + + QToolButton* audioBtn = makeBtn(m_rightBox, m_audioAction, "right_menu"); + audioBtn->setPopupMode(QToolButton::InstantPopup); + + m_audioMenu = new QMenu(audioBtn); + m_audioMenu->setProperty("menuStyle", QVariant(QString("slim"))); + QAction* audioLabel = m_audioMenu->addAction("Volume"); + audioLabel->setDisabled(true); + QWidgetAction* wa = new QWidgetAction(audioBtn); setVolumeLevel(*wa, volumeLevel); - m_audioSlider = new QSlider(b); + m_audioSlider = new QSlider(audioBtn); m_audioSlider->setProperty("sliderStyle", QVariant(QString("menu"))); m_audioSlider->setTickInterval(10); wa->setDefaultWidget(m_audioSlider); - m->addAction(wa); - m->addSeparator(); - m_muteAction = m->addAction("Mute"); + m_audioMenu->addAction(wa); + m_audioMenu->addSeparator(); + m_muteAction = m_audioMenu->addAction("Mute"); m_muteAction->setIcon(QIcon(":/images/mute_32x32.png")); m_muteAction->setCheckable(true); - b->setMenu(m); - m_audioMenu = m; + audioBtn->setMenu(m_audioMenu); + rightLayout->addWidget(audioBtn); connect(m_muteAction, SIGNAL(triggered(bool)), this, SLOT(audioMuteTriggered(bool))); connect(m_audioMenu, SIGNAL(aboutToShow()), this, SLOT(audioMenuTriggered())); connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(audioSliderChanged(int))); connect(m_audioSlider, SIGNAL(sliderReleased()), this, SLOT(audioSliderReleased())); + addWidget(m_rightBox); + // Map toolbar actions to their corresponding event categories m_actionCategoryMappings = {{ {m_smAction, IPCore::EventCategories::sessionmanagerCategory, m_smAction->toolTip()}, @@ -418,42 +385,33 @@ namespace Rv } else if (name == "play-start") { - QToolButton* bb = dynamic_cast(widgetForAction(m_backwardPlayAction)); - QToolButton* bf = dynamic_cast(widgetForAction(m_forwardPlayAction)); - if (m_session->inc() == -1) { - bb->setIcon(QIcon(":/images/control_pause.png")); + m_backwardPlayAction->setIcon(QIcon(":/images/control_pause.png")); } else { - bf->setIcon(QIcon(":/images/control_pause.png")); + m_forwardPlayAction->setIcon(QIcon(":/images/control_pause.png")); } } else if (name == "play-stop") { - QToolButton* bb = dynamic_cast(widgetForAction(m_backwardPlayAction)); - QToolButton* bf = dynamic_cast(widgetForAction(m_forwardPlayAction)); - - bb->setIcon(QIcon(":/images/control_bplay.png")); - bf->setIcon(QIcon(":/images/control_play.png")); + m_backwardPlayAction->setIcon(QIcon(":/images/control_bplay.png")); + m_forwardPlayAction->setIcon(QIcon(":/images/control_play.png")); } else if (name == "play-mode-changed") { - if (QToolButton* b = dynamic_cast(widgetForAction(m_playModeAction))) + switch (m_session->playMode()) { - switch (m_session->playMode()) - { - case 0: // Session::PlayLoop - b->setIcon(m_playModeLoopIcon); - break; - case 1: // Session::PlayOnce - b->setIcon(m_playModeOnceIcon); - break; - case 2: // Session::PlayPingPong - b->setIcon(m_playModePingPongIcon); - break; - } + case 0: // Session::PlayLoop + m_playModeAction->setIcon(m_playModeLoopIcon); + break; + case 1: // Session::PlayOnce + m_playModeAction->setIcon(m_playModeOnceIcon); + break; + case 2: // Session::PlayPingPong + m_playModeAction->setIcon(m_playModePingPongIcon); + break; } } else if (name == "update-ghost-button") @@ -604,20 +562,17 @@ namespace Rv void RvBottomViewToolBar::setVolumeIcon() { - if (QToolButton* b = dynamic_cast(widgetForAction(m_audioAction))) - { - IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), "#RVSoundTrack.audio.mute"); + IntPropertyEditor editor(m_session->graph(), m_session->currentFrame(), "#RVSoundTrack.audio.mute"); - if (editor.value()) - { - b->setIcon(m_volumeHighMutedIcon); - } - else - { - int volumeLevel = m_audioSlider->value(); // 0 - 99; + if (editor.value()) + { + m_audioAction->setIcon(m_volumeHighMutedIcon); + } + else + { + int volumeLevel = m_audioSlider->value(); // 0 - 99; - setVolumeLevel(*b, volumeLevel); - } + setVolumeLevel(*m_audioAction, volumeLevel); } } @@ -751,22 +706,19 @@ namespace Rv m_session->userGenericEvent("remote-eval", UTF8::qconvert(a->data().toMap()["code"].toString())); - if (QToolButton* b = dynamic_cast(widgetForAction(m_playModeAction))) + switch (m_session->playMode()) { - switch (m_session->playMode()) - { - case Session::PlayOnce: - b->setIcon(m_playModeOnceIcon); - break; + case Session::PlayOnce: + m_playModeAction->setIcon(m_playModeOnceIcon); + break; - case Session::PlayLoop: - b->setIcon(m_playModeLoopIcon); - break; + case Session::PlayLoop: + m_playModeAction->setIcon(m_playModeLoopIcon); + break; - case Session::PlayPingPong: - b->setIcon(m_playModePingPongIcon); - break; - } + case Session::PlayPingPong: + m_playModeAction->setIcon(m_playModePingPongIcon); + break; } } diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index 34a1d73c7..ef6ae723a 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -88,6 +90,9 @@ namespace Rv IPCore::Session* m_session; QString m_customCannotUseTooltip; QString m_customDisabledPrefix; + QWidget* m_leftBox; + QWidget* m_centerBox; + QWidget* m_rightBox; QAction* m_smAction; QAction* m_paintAction; QAction* m_infoAction; diff --git a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py index e5583c388..1253e24e7 100755 --- a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py +++ b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py @@ -126,9 +126,6 @@ class MultipleSourceMediaRepMode(rvtypes.MinorMode): _media_resolution_lbl = None _media_extension_lbl = None - # Media representation widgets' actions - _media_representation_action = None - # This is used to postponed received events until progressive loading # gets completed. _in_progressive_loading = False @@ -281,13 +278,15 @@ def _build_media_representation_widgets(self): # after the function call. self._bottomToolBar = qtutils.sessionBottomToolBar() - playback_style_action = None - for action in self._bottomToolBar.actions(): - if action.toolTip() == QtCore.QObject().tr("Select playback style"): - playback_style_action = action + right_box = self._bottomToolBar.findChild(QtWidgets.QWidget, "rightBox") + play_mode_btn = right_box.findChild(QtWidgets.QToolButton, "playModeButton") + right_layout = right_box.layout() + + def insert_before_play_mode(widget): + right_layout.insertWidget(right_layout.indexOf(play_mode_btn), widget) # Dropdown menu for the media reps. - self._media_representation_btn = QtWidgets.QToolButton(self._bottomToolBar) + self._media_representation_btn = QtWidgets.QToolButton(right_box) self._media_representation_btn.setToolTip("Select media playback type") self._media_representation_btn.setProperty("tbstyle", "solo_menu") self._media_representation_btn.setStyleSheet("color: gray") @@ -298,20 +297,18 @@ def _build_media_representation_widgets(self): menu.aboutToShow.connect(self._on_media_rep_about_to_show) self._media_representation_btn.setMenu(menu) - self._media_representation_action = self._bottomToolBar.insertWidget( - playback_style_action, self._media_representation_btn - ) - self._media_representation_action.setVisible(False) + insert_before_play_mode(self._media_representation_btn) + self._media_representation_btn.setVisible(False) # Media resolution. - self._media_resolution_lbl = QtWidgets.QLabel("", self._bottomToolBar) + self._media_resolution_lbl = QtWidgets.QLabel("", right_box) self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent; margin-right: 5px") - self._bottomToolBar.insertWidget(playback_style_action, self._media_resolution_lbl) + insert_before_play_mode(self._media_resolution_lbl) # Media extension. - self._media_extension_lbl = QtWidgets.QLabel("", self._bottomToolBar) + self._media_extension_lbl = QtWidgets.QLabel("", right_box) self._media_extension_lbl.setStyleSheet("color: gray; background-color: transparent") - self._bottomToolBar.insertWidget(playback_style_action, self._media_extension_lbl) + insert_before_play_mode(self._media_extension_lbl) def _populate_media_rep_menu(self, menu, switch_nodes): """ @@ -388,8 +385,8 @@ def _show_media_representation(self, show): """ Shows or hides the media rep drop down menu """ - if self._media_representation_action.isVisible() != show: - self._media_representation_action.setVisible(show) + if self._media_representation_btn.isVisible() != show: + self._media_representation_btn.setVisible(show) self._bottomToolBar.repaint() def _update_media_representation(self): From 48b7c74c1192cbc3bd6525d5d4f97393339fa261 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 11:19:17 -0400 Subject: [PATCH 02/13] clean up for building toolbar Signed-off-by: deltag0 --- src/lib/app/RvCommon/CMakeLists.txt | 1 + src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 225 +-------------- .../app/RvCommon/RvBottomViewToolBarBuild.cpp | 260 ++++++++++++++++++ .../RvCommon/RvCommon/RvBottomViewToolBar.h | 5 + 4 files changed, 269 insertions(+), 222 deletions(-) create mode 100644 src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp diff --git a/src/lib/app/RvCommon/CMakeLists.txt b/src/lib/app/RvCommon/CMakeLists.txt index dbe9b2f2d..1ac29f016 100644 --- a/src/lib/app/RvCommon/CMakeLists.txt +++ b/src/lib/app/RvCommon/CMakeLists.txt @@ -55,6 +55,7 @@ SET(_sources RvWebManager.cpp RvTopViewToolBar.cpp RvBottomViewToolBar.cpp + RvBottomViewToolBarBuild.cpp RvSourceEditor.cpp GLSLSyntaxHighlighter.cpp RvProfileManager.cpp diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 06a23aebe..34f0ec61b 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -71,24 +70,11 @@ namespace Rv setVisible(b); } - static QVariant enumCodeMap(int enumVal, QString codeVal) - { - QVariantMap m; - - m["enum"] = enumVal; - m["code"] = codeVal; - - return QVariant(m); - } - void RvBottomViewToolBar::build() { if (m_audioMenu) return; - Options& opts = Options::sharedOptions(); - - // Initialize QIcons m_playModeOnceIcon = QIcon(":/images/playmode_once_48x48.png"); m_playModeLoopIcon = QIcon(":/images/playmode_loop_48x48.png"); m_playModePingPongIcon = QIcon(":/images/playmode_pingpong_48x48.png"); @@ -104,216 +90,12 @@ namespace Rv constexpr int sideBoxPadding = 20; constexpr int sideBoxFixedWidth = 450; - auto makeBtn = [](QWidget* parent, QAction* action, const char* tbstyle, const char* tbsize = nullptr) { - QToolButton* btn = new QToolButton(parent); - btn->setDefaultAction(action); - btn->setProperty("tbstyle", QVariant(QString(tbstyle))); - if (tbsize) - btn->setProperty("tbsize", QVariant(QString(tbsize))); - btn->setToolButtonStyle(Qt::ToolButtonIconOnly); - return btn; - }; - - auto makeExpandingSpacer = [this]() { - QFrame* qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - return qf; - }; - - m_leftBox = new QWidget(this); - m_leftBox->setObjectName("leftBox"); - QHBoxLayout* leftLayout = new QHBoxLayout(m_leftBox); - leftLayout->setContentsMargins(sideBoxPadding, 0, sideBoxPadding, 0); - leftLayout->setSpacing(0); - m_leftBox->setFixedWidth(sideBoxFixedWidth); - - struct LeftActionDef - { - const char* iconPath; - const char* tooltip; - const char* tbstyle; - QAction** target; - }; - const LeftActionDef leftDefs[] = { - {":/images/smanager.png", "Toggle Session Manager", "left", &m_smAction}, - {":/images/paint_48x48.png", "Toggle Annotation tools", "interior", &m_paintAction}, - {":/images/about_48x48.png", "Toggle Image Info", "interior", &m_infoAction}, - {":/images/ntwrk_48x48.png", "Toggle RV Networking Dialog", "interior", &m_networkAction}, - {":/images/timeline_mag.png", "Toggle Timeline Magnifier", "interior", &m_timelineMagAction}, - {":/images/timeline.png", "Toggle Timeline", "right", &m_timelineAction}, - }; - for (const auto& def : leftDefs) - { - QAction* a = new QAction("", this); - a->setIcon(QIcon(def.iconPath)); - a->setToolTip(def.tooltip); - *def.target = a; - leftLayout->addWidget(makeBtn(m_leftBox, a, def.tbstyle)); - } - - connect(m_smAction, SIGNAL(triggered(bool)), this, SLOT(smActionTriggered(bool))); - connect(m_paintAction, SIGNAL(triggered(bool)), this, SLOT(paintActionTriggered(bool))); - connect(m_infoAction, SIGNAL(triggered(bool)), this, SLOT(infoActionTriggered(bool))); - connect(m_timelineAction, SIGNAL(triggered(bool)), this, SLOT(timelineActionTriggered(bool))); - connect(m_timelineMagAction, SIGNAL(triggered(bool)), this, SLOT(timelineMagActionTriggered(bool))); - connect(m_networkAction, SIGNAL(triggered(bool)), this, SLOT(networkActionTriggered(bool))); - - m_ghostAction = new QAction("", this); - m_ghostAction->setIcon(QIcon(":/images/ghost.png")); - m_ghostAction->setToolTip("Ghost"); - m_ghostAction->setCheckable(true); - leftLayout->addWidget(makeBtn(m_leftBox, m_ghostAction, "left")); - - m_holdAction = new QAction("", this); - m_holdAction->setIcon(QIcon(":/images/hold.png")); - m_holdAction->setToolTip("Hold"); - m_holdAction->setCheckable(true); - leftLayout->addWidget(makeBtn(m_leftBox, m_holdAction, "right")); - - connect(m_ghostAction, SIGNAL(triggered(bool)), this, SLOT(ghostTriggered(bool))); - connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); - - leftLayout->addStretch(); - addWidget(m_leftBox); - + buildLeft(sideBoxPadding, sideBoxFixedWidth); addWidget(makeExpandingSpacer()); - - m_centerBox = new QWidget(this); - m_centerBox->setObjectName("centerBox"); - QHBoxLayout* centerLayout = new QHBoxLayout(m_centerBox); - centerLayout->setContentsMargins(0, 0, 0, 0); - centerLayout->setSpacing(0); - - m_backStepAction = new QAction("", this); - m_backStepAction->setIcon(QIcon(":/images/control_bstep.png")); - m_backStepAction->setToolTip("Step back one frame"); - QToolButton* backStepBtn = makeBtn(m_centerBox, m_backStepAction, "left"); - backStepBtn->setObjectName("backStepButton"); - centerLayout->addWidget(backStepBtn); - - m_forwardStepAction = new QAction("", this); - m_forwardStepAction->setIcon(QIcon(":/images/control_fstep.png")); - m_forwardStepAction->setToolTip("Step forward one frame"); - QToolButton* fwdStepBtn = makeBtn(m_centerBox, m_forwardStepAction, "right"); - fwdStepBtn->setObjectName("forwardStepButton"); - centerLayout->addWidget(fwdStepBtn); - - m_backwardPlayAction = new QAction("", this); - m_backwardPlayAction->setIcon(QIcon(":/images/control_bplay.png")); - m_backwardPlayAction->setToolTip("Play backwards"); - centerLayout->addWidget(makeBtn(m_centerBox, m_backwardPlayAction, "left", "double")); - - m_forwardPlayAction = new QAction("", this); - m_forwardPlayAction->setIcon(QIcon(":/images/control_play.png")); - m_forwardPlayAction->setToolTip("Play forwards"); - centerLayout->addWidget(makeBtn(m_centerBox, m_forwardPlayAction, "right", "double")); - - m_backMarkAction = new QAction("", this); - m_backMarkAction->setIcon(QIcon(":/images/control_bmark.png")); - m_backMarkAction->setToolTip("Skip to start of sequence"); - QToolButton* backMarkBtn = makeBtn(m_centerBox, m_backMarkAction, "left"); - backMarkBtn->setObjectName("firstFrameButton"); - centerLayout->addWidget(backMarkBtn); - - m_forwardMarkAction = new QAction("", this); - m_forwardMarkAction->setIcon(QIcon(":/images/control_fmark.png")); - m_forwardMarkAction->setToolTip("Skip to end of sequence"); - QToolButton* fwdMarkBtn = makeBtn(m_centerBox, m_forwardMarkAction, "right"); - fwdMarkBtn->setObjectName("lastFrameButton"); - centerLayout->addWidget(fwdMarkBtn); - - connect(m_backStepAction, SIGNAL(triggered()), this, SLOT(backStepTriggered())); - connect(m_forwardStepAction, SIGNAL(triggered()), this, SLOT(forwardStepTriggered())); - connect(m_backwardPlayAction, SIGNAL(triggered()), this, SLOT(backPlayTriggered())); - connect(m_forwardPlayAction, SIGNAL(triggered()), this, SLOT(forwardPlayTriggered())); - connect(m_backMarkAction, SIGNAL(triggered()), this, SLOT(backMarkTriggered())); - connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); - - addWidget(m_centerBox); - + buildCenter(); addWidget(makeExpandingSpacer()); + buildRight(sideBoxPadding, sideBoxFixedWidth); - m_rightBox = new QWidget(this); - m_rightBox->setObjectName("rightBox"); - QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); - rightLayout->setContentsMargins(sideBoxPadding, 0, sideBoxPadding, 0); - rightLayout->setSpacing(0); - m_rightBox->setFixedWidth(sideBoxFixedWidth); - - rightLayout->addStretch(); - - m_playModeAction = new QAction("", this); - m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); - switch (static_cast(opts.loopMode)) - { - case Session::PlayOnce: - m_playModeAction->setIcon(m_playModeOnceIcon); - break; - case Session::PlayPingPong: - m_playModeAction->setIcon(m_playModePingPongIcon); - break; - default: - case Session::PlayLoop: - m_playModeAction->setIcon(m_playModeLoopIcon); - break; - } - - QToolButton* playModeBtn = makeBtn(m_rightBox, m_playModeAction, "left_menu"); - playModeBtn->setObjectName("playModeButton"); - playModeBtn->setPopupMode(QToolButton::InstantPopup); - - m_playModeMenu = new QMenu(playModeBtn); - m_playModeMenu->addAction("Playback")->setDisabled(true); - m_playModeOnceAction = m_playModeMenu->addAction(" Once"); - m_playModeOnceAction->setData(enumCodeMap(Session::PlayOnce, "commands.setPlayMode(PlayOnce)")); - m_playModeLoopAction = m_playModeMenu->addAction(" Loop"); - m_playModeLoopAction->setData(enumCodeMap(Session::PlayLoop, "commands.setPlayMode(PlayLoop)")); - m_playModePingPongAction = m_playModeMenu->addAction(" PingPong"); - m_playModePingPongAction->setData(enumCodeMap(Session::PlayPingPong, "commands.setPlayMode(PlayPingPong)")); - playModeBtn->setMenu(m_playModeMenu); - rightLayout->addWidget(playModeBtn); - - m_playModeMenu->installEventFilter(this); - connect(m_playModeMenu, SIGNAL(triggered(QAction*)), this, SLOT(playModeMenuTriggered(QAction*))); - connect(m_playModeMenu, SIGNAL(aboutToShow()), this, SLOT(playModeMenuUpdate())); - - int volumeLevel = (int)(100.0f * IPCore::SoundTrackIPNode::defaultVolume); - m_audioAction = new QAction("", this); - m_audioAction->setToolTip("Audio control"); - setVolumeLevel(*m_audioAction, volumeLevel); - - QToolButton* audioBtn = makeBtn(m_rightBox, m_audioAction, "right_menu"); - audioBtn->setPopupMode(QToolButton::InstantPopup); - - m_audioMenu = new QMenu(audioBtn); - m_audioMenu->setProperty("menuStyle", QVariant(QString("slim"))); - QAction* audioLabel = m_audioMenu->addAction("Volume"); - audioLabel->setDisabled(true); - QWidgetAction* wa = new QWidgetAction(audioBtn); - setVolumeLevel(*wa, volumeLevel); - m_audioSlider = new QSlider(audioBtn); - m_audioSlider->setProperty("sliderStyle", QVariant(QString("menu"))); - m_audioSlider->setTickInterval(10); - wa->setDefaultWidget(m_audioSlider); - m_audioMenu->addAction(wa); - m_audioMenu->addSeparator(); - m_muteAction = m_audioMenu->addAction("Mute"); - m_muteAction->setIcon(QIcon(":/images/mute_32x32.png")); - m_muteAction->setCheckable(true); - audioBtn->setMenu(m_audioMenu); - rightLayout->addWidget(audioBtn); - - connect(m_muteAction, SIGNAL(triggered(bool)), this, SLOT(audioMuteTriggered(bool))); - connect(m_audioMenu, SIGNAL(aboutToShow()), this, SLOT(audioMenuTriggered())); - connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(audioSliderChanged(int))); - connect(m_audioSlider, SIGNAL(sliderReleased()), this, SLOT(audioSliderReleased())); - - addWidget(m_rightBox); - - // Map toolbar actions to their corresponding event categories m_actionCategoryMappings = {{ {m_smAction, IPCore::EventCategories::sessionmanagerCategory, m_smAction->toolTip()}, {m_paintAction, IPCore::EventCategories::annotateCategory, m_paintAction->toolTip()}, @@ -324,7 +106,6 @@ namespace Rv {m_backwardPlayAction, IPCore::EventCategories::backwardplayCategory, m_backwardPlayAction->toolTip()}, {m_forwardPlayAction, IPCore::EventCategories::playcontrolCategory, m_forwardPlayAction->toolTip()}, {m_playModeAction, IPCore::EventCategories::playcontrolCategory, m_playModeAction->toolTip()}, - {m_backMarkAction, IPCore::EventCategories::playcontrolCategory, m_backMarkAction->toolTip()}, {m_forwardMarkAction, IPCore::EventCategories::playcontrolCategory, m_forwardMarkAction->toolTip()}, }}; diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp new file mode 100644 index 000000000..19d3f1578 --- /dev/null +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -0,0 +1,260 @@ +// +// Copyright (c) 2012 Tweak Software. +// All rights reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// +// +// Builders for the three sections of the bottom toolbar (left / center / +// right). Split out of RvBottomViewToolBar.cpp to keep build code separate +// from event handling and slot implementations. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Rv +{ + using namespace IPCore; + + namespace + { + constexpr std::string_view playModeDefaultTooltip = "Select playback style"; + + QToolButton* makeBtn(QWidget* parent, QAction* action, const char* tbstyle, const char* tbsize = nullptr) + { + QToolButton* btn = new QToolButton(parent); + btn->setDefaultAction(action); + btn->setProperty("tbstyle", QVariant(QString(tbstyle))); + if (tbsize) + btn->setProperty("tbsize", QVariant(QString(tbsize))); + btn->setToolButtonStyle(Qt::ToolButtonIconOnly); + return btn; + } + + QVariant enumCodeMap(int enumVal, QString codeVal) + { + QVariantMap m; + m["enum"] = enumVal; + m["code"] = codeVal; + return QVariant(m); + } + } // namespace + + QFrame* RvBottomViewToolBar::makeExpandingSpacer() + { + QFrame* qf = new QFrame(this); + qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + qf->setMinimumWidth(0); + qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); + qf->setStyleSheet("background-color: transparent"); + return qf; + } + + void RvBottomViewToolBar::buildLeft(int padding, int width) + { + m_leftBox = new QWidget(this); + m_leftBox->setObjectName("leftBox"); + QHBoxLayout* leftLayout = new QHBoxLayout(m_leftBox); + leftLayout->setContentsMargins(padding, 0, padding, 0); + leftLayout->setSpacing(0); + m_leftBox->setFixedWidth(width); + + struct LeftActionDef + { + const char* iconPath; + const char* tooltip; + const char* tbstyle; + QAction** target; + }; + const LeftActionDef leftDefs[] = { + {":/images/smanager.png", "Toggle Session Manager", "left", &m_smAction}, + {":/images/paint_48x48.png", "Toggle Annotation tools", "interior", &m_paintAction}, + {":/images/about_48x48.png", "Toggle Image Info", "interior", &m_infoAction}, + {":/images/ntwrk_48x48.png", "Toggle RV Networking Dialog", "interior", &m_networkAction}, + {":/images/timeline_mag.png", "Toggle Timeline Magnifier", "interior", &m_timelineMagAction}, + {":/images/timeline.png", "Toggle Timeline", "right", &m_timelineAction}, + }; + for (const auto& def : leftDefs) + { + QAction* a = new QAction("", this); + a->setIcon(QIcon(def.iconPath)); + a->setToolTip(def.tooltip); + *def.target = a; + leftLayout->addWidget(makeBtn(m_leftBox, a, def.tbstyle)); + } + + connect(m_smAction, SIGNAL(triggered(bool)), this, SLOT(smActionTriggered(bool))); + connect(m_paintAction, SIGNAL(triggered(bool)), this, SLOT(paintActionTriggered(bool))); + connect(m_infoAction, SIGNAL(triggered(bool)), this, SLOT(infoActionTriggered(bool))); + connect(m_timelineAction, SIGNAL(triggered(bool)), this, SLOT(timelineActionTriggered(bool))); + connect(m_timelineMagAction, SIGNAL(triggered(bool)), this, SLOT(timelineMagActionTriggered(bool))); + connect(m_networkAction, SIGNAL(triggered(bool)), this, SLOT(networkActionTriggered(bool))); + + m_ghostAction = new QAction("", this); + m_ghostAction->setIcon(QIcon(":/images/ghost.png")); + m_ghostAction->setToolTip("Ghost"); + m_ghostAction->setCheckable(true); + leftLayout->addWidget(makeBtn(m_leftBox, m_ghostAction, "left")); + + m_holdAction = new QAction("", this); + m_holdAction->setIcon(QIcon(":/images/hold.png")); + m_holdAction->setToolTip("Hold"); + m_holdAction->setCheckable(true); + leftLayout->addWidget(makeBtn(m_leftBox, m_holdAction, "right")); + + connect(m_ghostAction, SIGNAL(triggered(bool)), this, SLOT(ghostTriggered(bool))); + connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); + + leftLayout->addStretch(); + addWidget(m_leftBox); + } + + void RvBottomViewToolBar::buildCenter() + { + m_centerBox = new QWidget(this); + m_centerBox->setObjectName("centerBox"); + QHBoxLayout* centerLayout = new QHBoxLayout(m_centerBox); + centerLayout->setContentsMargins(0, 0, 0, 0); + centerLayout->setSpacing(0); + + m_backStepAction = new QAction("", this); + m_backStepAction->setIcon(QIcon(":/images/control_bstep.png")); + m_backStepAction->setToolTip("Step back one frame"); + QToolButton* backStepBtn = makeBtn(m_centerBox, m_backStepAction, "left"); + backStepBtn->setObjectName("backStepButton"); + centerLayout->addWidget(backStepBtn); + + m_forwardStepAction = new QAction("", this); + m_forwardStepAction->setIcon(QIcon(":/images/control_fstep.png")); + m_forwardStepAction->setToolTip("Step forward one frame"); + QToolButton* fwdStepBtn = makeBtn(m_centerBox, m_forwardStepAction, "right"); + fwdStepBtn->setObjectName("forwardStepButton"); + centerLayout->addWidget(fwdStepBtn); + + m_backwardPlayAction = new QAction("", this); + m_backwardPlayAction->setIcon(QIcon(":/images/control_bplay.png")); + m_backwardPlayAction->setToolTip("Play backwards"); + centerLayout->addWidget(makeBtn(m_centerBox, m_backwardPlayAction, "left", "double")); + + m_forwardPlayAction = new QAction("", this); + m_forwardPlayAction->setIcon(QIcon(":/images/control_play.png")); + m_forwardPlayAction->setToolTip("Play forwards"); + centerLayout->addWidget(makeBtn(m_centerBox, m_forwardPlayAction, "right", "double")); + + m_backMarkAction = new QAction("", this); + m_backMarkAction->setIcon(QIcon(":/images/control_bmark.png")); + m_backMarkAction->setToolTip("Skip to start of sequence"); + QToolButton* backMarkBtn = makeBtn(m_centerBox, m_backMarkAction, "left"); + backMarkBtn->setObjectName("firstFrameButton"); + centerLayout->addWidget(backMarkBtn); + + m_forwardMarkAction = new QAction("", this); + m_forwardMarkAction->setIcon(QIcon(":/images/control_fmark.png")); + m_forwardMarkAction->setToolTip("Skip to end of sequence"); + QToolButton* fwdMarkBtn = makeBtn(m_centerBox, m_forwardMarkAction, "right"); + fwdMarkBtn->setObjectName("lastFrameButton"); + centerLayout->addWidget(fwdMarkBtn); + + connect(m_backStepAction, SIGNAL(triggered()), this, SLOT(backStepTriggered())); + connect(m_forwardStepAction, SIGNAL(triggered()), this, SLOT(forwardStepTriggered())); + connect(m_backwardPlayAction, SIGNAL(triggered()), this, SLOT(backPlayTriggered())); + connect(m_forwardPlayAction, SIGNAL(triggered()), this, SLOT(forwardPlayTriggered())); + connect(m_backMarkAction, SIGNAL(triggered()), this, SLOT(backMarkTriggered())); + connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); + + addWidget(m_centerBox); + } + + void RvBottomViewToolBar::buildRight(int padding, int width) + { + Options& opts = Options::sharedOptions(); + + m_rightBox = new QWidget(this); + m_rightBox->setObjectName("rightBox"); + QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); + rightLayout->setContentsMargins(padding, 0, padding, 0); + rightLayout->setSpacing(0); + m_rightBox->setFixedWidth(width); + + rightLayout->addStretch(); + + m_playModeAction = new QAction("", this); + m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); + switch (static_cast(opts.loopMode)) + { + case Session::PlayOnce: + m_playModeAction->setIcon(m_playModeOnceIcon); + break; + case Session::PlayPingPong: + m_playModeAction->setIcon(m_playModePingPongIcon); + break; + default: + case Session::PlayLoop: + m_playModeAction->setIcon(m_playModeLoopIcon); + break; + } + + QToolButton* playModeBtn = makeBtn(m_rightBox, m_playModeAction, "left_menu"); + playModeBtn->setObjectName("playModeButton"); + playModeBtn->setPopupMode(QToolButton::InstantPopup); + + m_playModeMenu = new QMenu(playModeBtn); + m_playModeMenu->addAction("Playback")->setDisabled(true); + m_playModeOnceAction = m_playModeMenu->addAction(" Once"); + m_playModeOnceAction->setData(enumCodeMap(Session::PlayOnce, "commands.setPlayMode(PlayOnce)")); + m_playModeLoopAction = m_playModeMenu->addAction(" Loop"); + m_playModeLoopAction->setData(enumCodeMap(Session::PlayLoop, "commands.setPlayMode(PlayLoop)")); + m_playModePingPongAction = m_playModeMenu->addAction(" PingPong"); + m_playModePingPongAction->setData(enumCodeMap(Session::PlayPingPong, "commands.setPlayMode(PlayPingPong)")); + playModeBtn->setMenu(m_playModeMenu); + rightLayout->addWidget(playModeBtn); + + m_playModeMenu->installEventFilter(this); + connect(m_playModeMenu, SIGNAL(triggered(QAction*)), this, SLOT(playModeMenuTriggered(QAction*))); + connect(m_playModeMenu, SIGNAL(aboutToShow()), this, SLOT(playModeMenuUpdate())); + + int volumeLevel = (int)(100.0f * IPCore::SoundTrackIPNode::defaultVolume); + m_audioAction = new QAction("", this); + m_audioAction->setToolTip("Audio control"); + setVolumeLevel(*m_audioAction, volumeLevel); + + QToolButton* audioBtn = makeBtn(m_rightBox, m_audioAction, "right_menu"); + audioBtn->setPopupMode(QToolButton::InstantPopup); + + m_audioMenu = new QMenu(audioBtn); + m_audioMenu->setProperty("menuStyle", QVariant(QString("slim"))); + QAction* audioLabel = m_audioMenu->addAction("Volume"); + audioLabel->setDisabled(true); + QWidgetAction* wa = new QWidgetAction(audioBtn); + setVolumeLevel(*wa, volumeLevel); + m_audioSlider = new QSlider(audioBtn); + m_audioSlider->setProperty("sliderStyle", QVariant(QString("menu"))); + m_audioSlider->setTickInterval(10); + wa->setDefaultWidget(m_audioSlider); + m_audioMenu->addAction(wa); + m_audioMenu->addSeparator(); + m_muteAction = m_audioMenu->addAction("Mute"); + m_muteAction->setIcon(QIcon(":/images/mute_32x32.png")); + m_muteAction->setCheckable(true); + audioBtn->setMenu(m_audioMenu); + rightLayout->addWidget(audioBtn); + + connect(m_muteAction, SIGNAL(triggered(bool)), this, SLOT(audioMuteTriggered(bool))); + connect(m_audioMenu, SIGNAL(aboutToShow()), this, SLOT(audioMenuTriggered())); + connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(audioSliderChanged(int))); + connect(m_audioSlider, SIGNAL(sliderReleased()), this, SLOT(audioSliderReleased())); + + addWidget(m_rightBox); + } + +} // namespace Rv diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index ef6ae723a..55e269983 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,10 @@ namespace Rv virtual Result receiveEvent(const TwkApp::Event&); void build(); + void buildLeft(int padding, int width); + void buildCenter(); + void buildRight(int padding, int width); + QFrame* makeExpandingSpacer(); void makeActive(bool); void makeActiveFromSettings(); From 126461ffb73f80a51589fb5c7cf82d54a5f9d536 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 11:52:34 -0400 Subject: [PATCH 03/13] offset change for better UI --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 34f0ec61b..996864658 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -87,7 +87,7 @@ namespace Rv setProperty("tbstyle", QVariant(QString("play_controls"))); - constexpr int sideBoxPadding = 20; + constexpr int sideBoxPadding = 5; constexpr int sideBoxFixedWidth = 450; buildLeft(sideBoxPadding, sideBoxFixedWidth); From 2fad2bef826cb33dad2043119b2117320dd80033 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 14:52:16 -0400 Subject: [PATCH 04/13] fix for different tab sizes Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 24 +++++++++++++++---- .../app/RvCommon/RvBottomViewToolBarBuild.cpp | 18 ++++---------- .../RvCommon/RvCommon/RvBottomViewToolBar.h | 7 ++++-- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 996864658..6e9ca1eb4 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -5,6 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // // +#include +#include #include #include #include @@ -88,13 +90,25 @@ namespace Rv setProperty("tbstyle", QVariant(QString("play_controls"))); constexpr int sideBoxPadding = 5; - constexpr int sideBoxFixedWidth = 450; - buildLeft(sideBoxPadding, sideBoxFixedWidth); - addWidget(makeExpandingSpacer()); + buildLeft(sideBoxPadding); buildCenter(); - addWidget(makeExpandingSpacer()); - buildRight(sideBoxPadding, sideBoxFixedWidth); + buildRight(sideBoxPadding); + + barContainer = new QWidget(this); + barContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + grid = new QGridLayout(barContainer); + grid->setContentsMargins(0, 0, 0, 0); + grid->setSpacing(0); + + // All three sections share cell (0, 0); alignment positions each within + // the cell so the center button stays at the toolbar's geometric center + // regardless of left/right widths. + grid->addWidget(m_leftBox, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); + grid->addWidget(m_centerBox, 0, 0, Qt::AlignCenter); + grid->addWidget(m_rightBox, 0, 0, Qt::AlignRight | Qt::AlignVCenter); + + addWidget(barContainer); m_actionCategoryMappings = {{ {m_smAction, IPCore::EventCategories::sessionmanagerCategory, m_smAction->toolTip()}, diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index 19d3f1578..0f10c33c8 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -30,6 +30,9 @@ namespace Rv { constexpr std::string_view playModeDefaultTooltip = "Select playback style"; + /// + /// Make a button using an existing action and set it as the default action since we're no longer + /// QToolButton* makeBtn(QWidget* parent, QAction* action, const char* tbstyle, const char* tbsize = nullptr) { QToolButton* btn = new QToolButton(parent); @@ -60,14 +63,13 @@ namespace Rv return qf; } - void RvBottomViewToolBar::buildLeft(int padding, int width) + void RvBottomViewToolBar::buildLeft(int padding) { m_leftBox = new QWidget(this); m_leftBox->setObjectName("leftBox"); QHBoxLayout* leftLayout = new QHBoxLayout(m_leftBox); leftLayout->setContentsMargins(padding, 0, padding, 0); leftLayout->setSpacing(0); - m_leftBox->setFixedWidth(width); struct LeftActionDef { @@ -114,9 +116,6 @@ namespace Rv connect(m_ghostAction, SIGNAL(triggered(bool)), this, SLOT(ghostTriggered(bool))); connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); - - leftLayout->addStretch(); - addWidget(m_leftBox); } void RvBottomViewToolBar::buildCenter() @@ -171,11 +170,9 @@ namespace Rv connect(m_forwardPlayAction, SIGNAL(triggered()), this, SLOT(forwardPlayTriggered())); connect(m_backMarkAction, SIGNAL(triggered()), this, SLOT(backMarkTriggered())); connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); - - addWidget(m_centerBox); } - void RvBottomViewToolBar::buildRight(int padding, int width) + void RvBottomViewToolBar::buildRight(int padding) { Options& opts = Options::sharedOptions(); @@ -184,9 +181,6 @@ namespace Rv QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); rightLayout->setContentsMargins(padding, 0, padding, 0); rightLayout->setSpacing(0); - m_rightBox->setFixedWidth(width); - - rightLayout->addStretch(); m_playModeAction = new QAction("", this); m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); @@ -253,8 +247,6 @@ namespace Rv connect(m_audioMenu, SIGNAL(aboutToShow()), this, SLOT(audioMenuTriggered())); connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(audioSliderChanged(int))); connect(m_audioSlider, SIGNAL(sliderReleased()), this, SLOT(audioSliderReleased())); - - addWidget(m_rightBox); } } // namespace Rv diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index 55e269983..a0d12e96b 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -42,9 +43,9 @@ namespace Rv virtual Result receiveEvent(const TwkApp::Event&); void build(); - void buildLeft(int padding, int width); + void buildLeft(int padding); void buildCenter(); - void buildRight(int padding, int width); + void buildRight(int padding); QFrame* makeExpandingSpacer(); void makeActive(bool); void makeActiveFromSettings(); @@ -93,6 +94,8 @@ namespace Rv void updatePlayModeButtonState(); IPCore::Session* m_session; + QWidget* barContainer; + QGridLayout* grid; QString m_customCannotUseTooltip; QString m_customDisabledPrefix; QWidget* m_leftBox; From dd4c3d9e0660e787ea311fd0dc73448c6a87c707 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 15:15:03 -0400 Subject: [PATCH 05/13] docs Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 7 ++----- src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp | 14 +++++++++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 6e9ca1eb4..40eb114da 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -92,8 +92,8 @@ namespace Rv constexpr int sideBoxPadding = 5; buildLeft(sideBoxPadding); - buildCenter(); buildRight(sideBoxPadding); + buildCenter(); barContainer = new QWidget(this); barContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -101,12 +101,9 @@ namespace Rv grid->setContentsMargins(0, 0, 0, 0); grid->setSpacing(0); - // All three sections share cell (0, 0); alignment positions each within - // the cell so the center button stays at the toolbar's geometric center - // regardless of left/right widths. grid->addWidget(m_leftBox, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); - grid->addWidget(m_centerBox, 0, 0, Qt::AlignCenter); grid->addWidget(m_rightBox, 0, 0, Qt::AlignRight | Qt::AlignVCenter); + grid->addWidget(m_centerBox, 0, 0, Qt::AlignCenter); addWidget(barContainer); diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index 0f10c33c8..afb3a0330 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -31,7 +31,8 @@ namespace Rv constexpr std::string_view playModeDefaultTooltip = "Select playback style"; /// - /// Make a button using an existing action and set it as the default action since we're no longer + /// Make a button using an existing action and set it as the default action since + /// the action is not directly added to the toolbar /// QToolButton* makeBtn(QWidget* parent, QAction* action, const char* tbstyle, const char* tbsize = nullptr) { @@ -63,6 +64,9 @@ namespace Rv return qf; } + /// + /// Add all buttons belonging to the left side of the toolbar and the actions in a single Widget + /// void RvBottomViewToolBar::buildLeft(int padding) { m_leftBox = new QWidget(this); @@ -118,6 +122,10 @@ namespace Rv connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); } + + /// + /// Add all buttons belonging to the center (playback buttons) of the toolbar in a single widget + /// void RvBottomViewToolBar::buildCenter() { m_centerBox = new QWidget(this); @@ -172,6 +180,10 @@ namespace Rv connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); } + + /// + /// Add all buttons belonging to the right of the toolbar in a single widget + /// void RvBottomViewToolBar::buildRight(int padding) { Options& opts = Options::sharedOptions(); From 7f17d1bc79df7b6b7d1b5a80305b7674f849ed91 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 15:18:19 -0400 Subject: [PATCH 06/13] format Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 4 ++-- src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 40eb114da..9cbc41949 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -101,8 +101,8 @@ namespace Rv grid->setContentsMargins(0, 0, 0, 0); grid->setSpacing(0); - grid->addWidget(m_leftBox, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); - grid->addWidget(m_rightBox, 0, 0, Qt::AlignRight | Qt::AlignVCenter); + grid->addWidget(m_leftBox, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); + grid->addWidget(m_rightBox, 0, 0, Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(m_centerBox, 0, 0, Qt::AlignCenter); addWidget(barContainer); diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index afb3a0330..6eaae4b06 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -82,13 +82,14 @@ namespace Rv const char* tbstyle; QAction** target; }; + const LeftActionDef leftDefs[] = { - {":/images/smanager.png", "Toggle Session Manager", "left", &m_smAction}, - {":/images/paint_48x48.png", "Toggle Annotation tools", "interior", &m_paintAction}, - {":/images/about_48x48.png", "Toggle Image Info", "interior", &m_infoAction}, - {":/images/ntwrk_48x48.png", "Toggle RV Networking Dialog", "interior", &m_networkAction}, - {":/images/timeline_mag.png", "Toggle Timeline Magnifier", "interior", &m_timelineMagAction}, - {":/images/timeline.png", "Toggle Timeline", "right", &m_timelineAction}, + {":/images/smanager.png", "Toggle Session Manager", "left", &m_smAction}, + {":/images/paint_48x48.png", "Toggle Annotation tools", "interior", &m_paintAction}, + {":/images/about_48x48.png", "Toggle Image Info", "interior", &m_infoAction}, + {":/images/ntwrk_48x48.png", "Toggle RV Networking Dialog", "interior", &m_networkAction}, + {":/images/timeline_mag.png", "Toggle Timeline Magnifier", "interior", &m_timelineMagAction}, + {":/images/timeline.png", "Toggle Timeline", "right", &m_timelineAction}, }; for (const auto& def : leftDefs) { @@ -122,7 +123,6 @@ namespace Rv connect(m_holdAction, SIGNAL(triggered(bool)), this, SLOT(holdTriggered(bool))); } - /// /// Add all buttons belonging to the center (playback buttons) of the toolbar in a single widget /// @@ -180,7 +180,6 @@ namespace Rv connect(m_forwardMarkAction, SIGNAL(triggered()), this, SLOT(forwardMarkTriggered())); } - /// /// Add all buttons belonging to the right of the toolbar in a single widget /// From c96fb9f0d902fe5d0d247ff29789e35a429be523 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 15:37:51 -0400 Subject: [PATCH 07/13] overflow improvement Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 61 +++++++++++++++++++ .../RvCommon/RvCommon/RvBottomViewToolBar.h | 3 + 2 files changed, 64 insertions(+) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 9cbc41949..bca7893ea 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -536,6 +536,67 @@ namespace Rv return QToolBar::eventFilter(obj, event); } + void RvBottomViewToolBar::resizeEvent(QResizeEvent* event) + { + QToolBar::resizeEvent(event); + + if (!m_overflowUpdatePending) + { + m_overflowUpdatePending = true; + + QTimer::singleShot(0, this, [this]() { + m_overflowUpdatePending = false; + updateOverflow(); + }); + } + } + + void RvBottomViewToolBar::updateOverflow() + { + if (!m_leftBox || !m_centerBox || !m_rightBox) + return; + + const int centerWidth = m_centerBox->sizeHint().width(); + const int sideBudget = (width() - centerWidth) / 2; + + auto applyOverflow = [&](QWidget* box, bool reverse) { + QLayout* layout = box->layout(); + if (!layout) + return; + + box->setUpdatesEnabled(false); + + const QMargins margins = layout->contentsMargins(); + int remaining = sideBudget - margins.left() - margins.right(); + + const int n = layout->count(); + + for (int idx = 0; idx < n; ++idx) + { + const int i = reverse ? (n - 1 - idx) : idx; + + QWidget* w = layout->itemAt(i)->widget(); + if (!w) + continue; + + const int hint = w->sizeHint().width(); + const bool fits = hint <= remaining; + + if (w->isVisible() != fits) + w->setVisible(fits); + + if (fits) + remaining -= hint; + } + + box->setUpdatesEnabled(true); + box->updateGeometry(); + }; + + applyOverflow(m_leftBox, false); + applyOverflow(m_rightBox, true); + } + void RvBottomViewToolBar::updateActionAvailability() { if (!m_session) diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index a0d12e96b..3c7a9361f 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -78,6 +78,8 @@ namespace Rv protected: bool eventFilter(QObject* obj, QEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + void updateOverflow(); private: struct ActionCategoryMapping @@ -136,6 +138,7 @@ namespace Rv QIcon m_volumeHighMutedIcon; std::array m_actionCategoryMappings; + bool m_overflowUpdatePending = false; }; template void RvBottomViewToolBar::setVolumeLevel(T& inst, int level) From 85d2235c641b32d3298a73cfe821f777ea46b86c Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 16:05:28 -0400 Subject: [PATCH 08/13] fix plugin owned button appearing Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 19 ++++++++++++++++++- .../app/RvCommon/RvBottomViewToolBarBuild.cpp | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index bca7893ea..4ff067c34 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -568,9 +568,24 @@ namespace Rv const QMargins margins = layout->contentsMargins(); int remaining = sideBudget - margins.left() - margins.right(); - const int n = layout->count(); + // Subtract space taken by widgets we don't own (e.g. plugin-injected + // widgets). Their visibility is the plugin's responsibility; we + // only account for the space they occupy. + for (int i = 0; i < n; ++i) + { + QWidget* w = layout->itemAt(i)->widget(); + if (!w) + continue; + if (w->property("toolbarOwned").toBool()) + continue; + if (w->isVisible()) + remaining -= w->sizeHint().width(); + } + + // Walk toolbar-owned buttons from the outer edge inward, hiding + // those that don't fit in the remaining budget. for (int idx = 0; idx < n; ++idx) { const int i = reverse ? (n - 1 - idx) : idx; @@ -578,6 +593,8 @@ namespace Rv QWidget* w = layout->itemAt(i)->widget(); if (!w) continue; + if (!w->property("toolbarOwned").toBool()) + continue; const int hint = w->sizeHint().width(); const bool fits = hint <= remaining; diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index 6eaae4b06..2391fbb7b 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -39,6 +39,7 @@ namespace Rv QToolButton* btn = new QToolButton(parent); btn->setDefaultAction(action); btn->setProperty("tbstyle", QVariant(QString(tbstyle))); + btn->setProperty("toolbarOwned", true); if (tbsize) btn->setProperty("tbsize", QVariant(QString(tbsize))); btn->setToolButtonStyle(Qt::ToolButtonIconOnly); From ef1c819e4a2f20fe10ed3984c5012de7c6bdcb28 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Fri, 8 May 2026 17:07:59 -0400 Subject: [PATCH 09/13] overflow fixes Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 33 ++++++++++++++----- .../app/RvCommon/RvBottomViewToolBarBuild.cpp | 2 +- .../multiple_source_media_rep.py | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 4ff067c34..a9468f0ba 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -567,12 +567,13 @@ namespace Rv box->setUpdatesEnabled(false); const QMargins margins = layout->contentsMargins(); + const int spacing = layout->spacing(); int remaining = sideBudget - margins.left() - margins.right(); const int n = layout->count(); // Subtract space taken by widgets we don't own (e.g. plugin-injected - // widgets). Their visibility is the plugin's responsibility; we - // only account for the space they occupy. + // widgets). + int visibleCount = 0; for (int i = 0; i < n; ++i) { QWidget* w = layout->itemAt(i)->widget(); @@ -580,12 +581,19 @@ namespace Rv continue; if (w->property("toolbarOwned").toBool()) continue; - if (w->isVisible()) - remaining -= w->sizeHint().width(); + if (!w->isVisible()) + continue; + remaining -= w->sizeHint().width(); + if (visibleCount > 0) + remaining -= spacing; + ++visibleCount; } // Walk toolbar-owned buttons from the outer edge inward, hiding - // those that don't fit in the remaining budget. + // those that don't fit in the remaining budget. Once any button + // fails to fit, every button after it, closer to the center is + // not rendered. + bool hideRest = false; for (int idx = 0; idx < n; ++idx) { const int i = reverse ? (n - 1 - idx) : idx; @@ -596,14 +604,23 @@ namespace Rv if (!w->property("toolbarOwned").toBool()) continue; - const int hint = w->sizeHint().width(); - const bool fits = hint <= remaining; + int cost = w->sizeHint().width(); + if (visibleCount > 0) + cost += spacing; + + const bool fits = !hideRest && cost <= remaining; + + if (!fits) + hideRest = true; if (w->isVisible() != fits) w->setVisible(fits); if (fits) - remaining -= hint; + { + remaining -= cost; + ++visibleCount; + } } box->setUpdatesEnabled(true); diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index 2391fbb7b..63942de1f 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -192,7 +192,7 @@ namespace Rv m_rightBox->setObjectName("rightBox"); QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); rightLayout->setContentsMargins(padding, 0, padding, 0); - rightLayout->setSpacing(0); + rightLayout->setSpacing(5); m_playModeAction = new QAction("", this); m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); diff --git a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py index 1253e24e7..ccf8a40db 100755 --- a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py +++ b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py @@ -302,7 +302,7 @@ def insert_before_play_mode(widget): # Media resolution. self._media_resolution_lbl = QtWidgets.QLabel("", right_box) - self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent; margin-right: 5px") + self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent") insert_before_play_mode(self._media_resolution_lbl) # Media extension. From 525ca4731f8b7dcf2447e79d036abbeaf3f9fc94 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Mon, 11 May 2026 13:16:50 -0400 Subject: [PATCH 10/13] Overflow improvement with gaps Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 49 ++++++++++++++++--- .../app/RvCommon/RvBottomViewToolBarBuild.cpp | 25 +--------- .../RvCommon/RvCommon/RvBottomViewToolBar.h | 1 - .../multiple_source_media_rep.py | 4 ++ 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index a9468f0ba..00da55b87 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -5,12 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 // // -#include -#include #include #include #include #include +#include #include #include #include @@ -19,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -89,10 +90,11 @@ namespace Rv setProperty("tbstyle", QVariant(QString("play_controls"))); - constexpr int sideBoxPadding = 5; + constexpr int buttonPadding = 5; + - buildLeft(sideBoxPadding); - buildRight(sideBoxPadding); + buildLeft(buttonPadding); + buildRight(buttonPadding); buildCenter(); barContainer = new QWidget(this); @@ -544,6 +546,7 @@ namespace Rv { m_overflowUpdatePending = true; + // Only re-render once toolbar finished rendering other work QTimer::singleShot(0, this, [this]() { m_overflowUpdatePending = false; updateOverflow(); @@ -559,6 +562,11 @@ namespace Rv const int centerWidth = m_centerBox->sizeHint().width(); const int sideBudget = (width() - centerWidth) / 2; + qDebug() << "[overflow] toolbarW=" << width() + << " centerW=" << centerWidth + << " centerGeom=" << m_centerBox->geometry() + << " sideBudget=" << sideBudget; + auto applyOverflow = [&](QWidget* box, bool reverse) { QLayout* layout = box->layout(); if (!layout) @@ -568,9 +576,17 @@ namespace Rv const QMargins margins = layout->contentsMargins(); const int spacing = layout->spacing(); - int remaining = sideBudget - margins.left() - margins.right(); + int remaining = sideBudget - margins.left(); const int n = layout->count(); + qDebug() << "[overflow]" << (reverse ? "RIGHT" : "LEFT") + << " boxSizeHint=" << box->sizeHint().width() + << " boxGeom=" << box->geometry() + << " margins=" << margins + << " spacing=" << spacing + << " remaining_start=" << remaining + << " n=" << n; + // Subtract space taken by widgets we don't own (e.g. plugin-injected // widgets). int visibleCount = 0; @@ -583,6 +599,17 @@ namespace Rv continue; if (!w->isVisible()) continue; + + std::cout << "THIS IS BAD\n"; + qDebug() << "[overflow preload]" + << (reverse ? "R" : "L") + << "i=" << i + << "name=" << w->objectName() + << "class=" << w->metaObject()->className() + << "owned=" << w->property("toolbarOwned").toBool() + << "visible=" << w->isVisible() + << "sizeHintW=" << w->sizeHint().width() + << "remaining_before=" << remaining; remaining -= w->sizeHint().width(); if (visibleCount > 0) remaining -= spacing; @@ -610,6 +637,16 @@ namespace Rv const bool fits = !hideRest && cost <= remaining; + if (reverse) { + qDebug() << "[overflow] " << (reverse ? "R" : "L") + << " i=" << i + << " name=" << w->objectName() + << " sizeHint=" << w->sizeHint().width() + << " cost=" << cost + << " remaining=" << remaining + << " fits=" << fits; + } + if (!fits) hideRest = true; diff --git a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp index 63942de1f..ebacdbe0a 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBarBuild.cpp @@ -1,14 +1,3 @@ -// -// Copyright (c) 2012 Tweak Software. -// All rights reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// -// -// Builders for the three sections of the bottom toolbar (left / center / -// right). Split out of RvBottomViewToolBar.cpp to keep build code separate -// from event handling and slot implementations. -// #include #include #include @@ -55,16 +44,6 @@ namespace Rv } } // namespace - QFrame* RvBottomViewToolBar::makeExpandingSpacer() - { - QFrame* qf = new QFrame(this); - qf->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - qf->setMinimumWidth(0); - qf->setFrameStyle(QFrame::Plain | QFrame::NoFrame); - qf->setStyleSheet("background-color: transparent"); - return qf; - } - /// /// Add all buttons belonging to the left side of the toolbar and the actions in a single Widget /// @@ -191,8 +170,8 @@ namespace Rv m_rightBox = new QWidget(this); m_rightBox->setObjectName("rightBox"); QHBoxLayout* rightLayout = new QHBoxLayout(m_rightBox); - rightLayout->setContentsMargins(padding, 0, padding, 0); - rightLayout->setSpacing(5); + rightLayout->setContentsMargins(0, 0, 0, 0); + rightLayout->setSpacing(0); m_playModeAction = new QAction("", this); m_playModeAction->setToolTip(QString::fromUtf8(playModeDefaultTooltip.data(), playModeDefaultTooltip.size())); diff --git a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h index 3c7a9361f..0c010c40a 100644 --- a/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h +++ b/src/lib/app/RvCommon/RvCommon/RvBottomViewToolBar.h @@ -46,7 +46,6 @@ namespace Rv void buildLeft(int padding); void buildCenter(); void buildRight(int padding); - QFrame* makeExpandingSpacer(); void makeActive(bool); void makeActiveFromSettings(); diff --git a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py index ccf8a40db..55ccfdac3 100755 --- a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py +++ b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py @@ -303,11 +303,13 @@ def insert_before_play_mode(widget): # Media resolution. self._media_resolution_lbl = QtWidgets.QLabel("", right_box) self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent") + self._media_resolution_lbl.setVisible(False) insert_before_play_mode(self._media_resolution_lbl) # Media extension. self._media_extension_lbl = QtWidgets.QLabel("", right_box) self._media_extension_lbl.setStyleSheet("color: gray; background-color: transparent") + self._media_extension_lbl.setVisible(False) insert_before_play_mode(self._media_extension_lbl) def _populate_media_rep_menu(self, menu, switch_nodes): @@ -420,7 +422,9 @@ def _update_resolution_and_extension(self): common_source_media_infos = utils.get_common_source_media_infos(self._current_sources) self._media_resolution_lbl.setText(common_source_media_infos.resolution) + self._media_resolution_lbl.setVisible(bool(common_source_media_infos.resolution)) self._media_extension_lbl.setText(common_source_media_infos.extension) + self._media_extension_lbl.setVisible(bool(common_source_media_infos.extension)) def _update_media_info(self, event): """ From 69c44cc2ff4efcbca6c724567cb8bec119466250 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Mon, 11 May 2026 13:53:29 -0400 Subject: [PATCH 11/13] format fix Signed-off-by: deltag0 --- src/lib/app/RvCommon/RvBottomViewToolBar.cpp | 51 ++++---------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp index 00da55b87..7a847dfdf 100644 --- a/src/lib/app/RvCommon/RvBottomViewToolBar.cpp +++ b/src/lib/app/RvCommon/RvBottomViewToolBar.cpp @@ -92,7 +92,6 @@ namespace Rv constexpr int buttonPadding = 5; - buildLeft(buttonPadding); buildRight(buttonPadding); buildCenter(); @@ -547,10 +546,12 @@ namespace Rv m_overflowUpdatePending = true; // Only re-render once toolbar finished rendering other work - QTimer::singleShot(0, this, [this]() { - m_overflowUpdatePending = false; - updateOverflow(); - }); + QTimer::singleShot(0, this, + [this]() + { + m_overflowUpdatePending = false; + updateOverflow(); + }); } } @@ -562,12 +563,8 @@ namespace Rv const int centerWidth = m_centerBox->sizeHint().width(); const int sideBudget = (width() - centerWidth) / 2; - qDebug() << "[overflow] toolbarW=" << width() - << " centerW=" << centerWidth - << " centerGeom=" << m_centerBox->geometry() - << " sideBudget=" << sideBudget; - - auto applyOverflow = [&](QWidget* box, bool reverse) { + auto applyOverflow = [&](QWidget* box, bool reverse) + { QLayout* layout = box->layout(); if (!layout) return; @@ -579,16 +576,8 @@ namespace Rv int remaining = sideBudget - margins.left(); const int n = layout->count(); - qDebug() << "[overflow]" << (reverse ? "RIGHT" : "LEFT") - << " boxSizeHint=" << box->sizeHint().width() - << " boxGeom=" << box->geometry() - << " margins=" << margins - << " spacing=" << spacing - << " remaining_start=" << remaining - << " n=" << n; - // Subtract space taken by widgets we don't own (e.g. plugin-injected - // widgets). + // widgets). int visibleCount = 0; for (int i = 0; i < n; ++i) { @@ -600,16 +589,6 @@ namespace Rv if (!w->isVisible()) continue; - std::cout << "THIS IS BAD\n"; - qDebug() << "[overflow preload]" - << (reverse ? "R" : "L") - << "i=" << i - << "name=" << w->objectName() - << "class=" << w->metaObject()->className() - << "owned=" << w->property("toolbarOwned").toBool() - << "visible=" << w->isVisible() - << "sizeHintW=" << w->sizeHint().width() - << "remaining_before=" << remaining; remaining -= w->sizeHint().width(); if (visibleCount > 0) remaining -= spacing; @@ -619,7 +598,7 @@ namespace Rv // Walk toolbar-owned buttons from the outer edge inward, hiding // those that don't fit in the remaining budget. Once any button // fails to fit, every button after it, closer to the center is - // not rendered. + // not rendered. bool hideRest = false; for (int idx = 0; idx < n; ++idx) { @@ -637,16 +616,6 @@ namespace Rv const bool fits = !hideRest && cost <= remaining; - if (reverse) { - qDebug() << "[overflow] " << (reverse ? "R" : "L") - << " i=" << i - << " name=" << w->objectName() - << " sizeHint=" << w->sizeHint().width() - << " cost=" << cost - << " remaining=" << remaining - << " fits=" << fits; - } - if (!fits) hideRest = true; From cb731060ae709899dafd6e8dbcdcb1325f98b534 Mon Sep 17 00:00:00 2001 From: deltag0 Date: Mon, 11 May 2026 14:09:50 -0400 Subject: [PATCH 12/13] padding change for resolution and file type Signed-off-by: deltag0 --- .../multiple_source_media_rep/multiple_source_media_rep.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py index 55ccfdac3..8e1b513b2 100755 --- a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py +++ b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py @@ -302,13 +302,15 @@ def insert_before_play_mode(widget): # Media resolution. self._media_resolution_lbl = QtWidgets.QLabel("", right_box) - self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent") + self._media_resolution_lbl.setStyleSheet( + "color: gray; background-color: transparent; padding-right: 5px;" + ) self._media_resolution_lbl.setVisible(False) insert_before_play_mode(self._media_resolution_lbl) # Media extension. self._media_extension_lbl = QtWidgets.QLabel("", right_box) - self._media_extension_lbl.setStyleSheet("color: gray; background-color: transparent") + self._media_extension_lbl.setStyleSheet("color: gray; background-color: transparent; padding-right: 5px") self._media_extension_lbl.setVisible(False) insert_before_play_mode(self._media_extension_lbl) From 60939cf015651e7ace569b5e729d81c6c7e37a8e Mon Sep 17 00:00:00 2001 From: deltag0 Date: Mon, 11 May 2026 14:14:27 -0400 Subject: [PATCH 13/13] format fix Signed-off-by: deltag0 --- .../multiple_source_media_rep/multiple_source_media_rep.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py index 8e1b513b2..8487d192c 100755 --- a/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py +++ b/src/plugins/rv-packages/multiple_source_media_rep/multiple_source_media_rep.py @@ -302,9 +302,7 @@ def insert_before_play_mode(widget): # Media resolution. self._media_resolution_lbl = QtWidgets.QLabel("", right_box) - self._media_resolution_lbl.setStyleSheet( - "color: gray; background-color: transparent; padding-right: 5px;" - ) + self._media_resolution_lbl.setStyleSheet("color: gray; background-color: transparent; padding-right: 5px;") self._media_resolution_lbl.setVisible(False) insert_before_play_mode(self._media_resolution_lbl)