diff --git a/app/core.cpp b/app/core.cpp index 1935335af..a668bec2d 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -170,7 +170,7 @@ void Core::DialogImportShow() if (!files.isEmpty()) { // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = olive::panel_focus_manager->MostRecentlyFocused(); + ProjectPanel* active_project_panel = olive::panel_manager->MostRecentlyFocused(); Project* active_project; if (active_project_panel == nullptr // Check that we found a Project panel @@ -189,7 +189,7 @@ void Core::DialogImportShow() void Core::CreateNewFolder() { // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = olive::panel_focus_manager->MostRecentlyFocused(); + ProjectPanel* active_project_panel = olive::panel_manager->MostRecentlyFocused(); Project* active_project; if (active_project_panel == nullptr // Check that we found a Project panel @@ -234,7 +234,7 @@ void Core::CreateNewFolder() void Core::CreateNewSequence() { // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = olive::panel_focus_manager->MostRecentlyFocused(); + ProjectPanel* active_project_panel = olive::panel_manager->MostRecentlyFocused(); Project* active_project; if (active_project_panel == nullptr // Check that we found a Project panel @@ -311,9 +311,9 @@ void Core::CreateNewSequence() // Connect timeline end point to renderer NodeParam::ConnectEdge(tb->length_output(), rp->length_input()); - olive::panel_focus_manager->MostRecentlyFocused()->ConnectViewerNode(vo); - olive::panel_focus_manager->MostRecentlyFocused()->ConnectTimelineNode(tb); - olive::panel_focus_manager->MostRecentlyFocused()->SetGraph(new_sequence.get()); + olive::panel_manager->MostRecentlyFocused()->ConnectViewerNode(vo); + olive::panel_manager->MostRecentlyFocused()->ConnectTimelineNode(tb); + olive::panel_manager->MostRecentlyFocused()->SetGraph(new_sequence.get()); olive::undo_stack.push(aic); } @@ -343,12 +343,12 @@ void Core::StartGUI(bool full_screen) olive::menu_shared.Initialize(); // Since we're starting GUI mode, create a PanelFocusManager (auto-deletes with QObject) - olive::panel_focus_manager = new PanelManager(this); + olive::panel_manager = new PanelManager(this); // Connect the PanelFocusManager to the application's focus change signal connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), - olive::panel_focus_manager, + olive::panel_manager, SLOT(FocusChanged(QWidget*, QWidget*))); // Create main window and open it @@ -369,7 +369,7 @@ void Core::StartGUI(bool full_screen) Project *Core::GetActiveProject() { // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = olive::panel_focus_manager->MostRecentlyFocused(); + ProjectPanel* active_project_panel = olive::panel_manager->MostRecentlyFocused(); // If we couldn't find one, return nullptr if (active_project_panel == nullptr) { diff --git a/app/panel/panelmanager.cpp b/app/panel/panelmanager.cpp index b7b837327..899f86e87 100644 --- a/app/panel/panelmanager.cpp +++ b/app/panel/panelmanager.cpp @@ -20,10 +20,11 @@ #include "panelmanager.h" -PanelManager* olive::panel_focus_manager = nullptr; +PanelManager* olive::panel_manager = nullptr; PanelManager::PanelManager(QObject *parent) : - QObject(parent) + QObject(parent), + locked_(false) { } @@ -44,6 +45,11 @@ PanelWidget *PanelManager::CurrentlyFocused() const return focus_history_.first(); } +bool PanelManager::ArePanelsLocked() +{ + return locked_; +} + void PanelManager::FocusChanged(QWidget *old, QWidget *now) { Q_UNUSED(old) @@ -83,3 +89,12 @@ void PanelManager::FocusChanged(QWidget *old, QWidget *now) parent = parent->parent(); } } + +void PanelManager::SetPanelsLocked(bool locked) +{ + foreach (PanelWidget* panel, focus_history_) { + panel->SetMovementLocked(locked); + } + + locked_ = locked; +} diff --git a/app/panel/panelmanager.h b/app/panel/panelmanager.h index d70528b99..9093ed6de 100644 --- a/app/panel/panelmanager.h +++ b/app/panel/panelmanager.h @@ -72,6 +72,11 @@ public: */ T* CreatePanel(QWidget* parent); + /** + * @brief Get whether panels are currently prevented from moving + */ + bool ArePanelsLocked(); + public slots: /** * @brief Connect this to a QApplication's SIGNAL(focusChanged()) @@ -80,11 +85,21 @@ public slots: */ void FocusChanged(QWidget* old, QWidget* now); + /** + * @brief Sets whether panels should be prevented from moving + */ + void SetPanelsLocked(bool locked); + private: /** * @brief History array for traversing through (see MostRecentlyFocused()) */ QList focus_history_; + + /** + * @brief Internal panel movement is locked value + */ + bool locked_; }; template @@ -92,6 +107,8 @@ T *PanelManager::CreatePanel(QWidget *parent) { T* panel = new T(parent); + panel->SetMovementLocked(locked_); + // Add panel to the bottom of the focus history focus_history_.append(panel); @@ -115,7 +132,7 @@ T* PanelManager::MostRecentlyFocused() } namespace olive { -extern PanelManager* panel_focus_manager; +extern PanelManager* panel_manager; } #endif // PANELFOCUSMANAGER_H diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 26cb72479..7dbe90eb8 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -171,7 +171,7 @@ void NodeParamViewWidgetBridge::CreateWidgets() // FIXME: Test code // Pretty hacky way of getting the root folder for this node's sequence - ProjectPanel* pp = olive::panel_focus_manager->MostRecentlyFocused(); + ProjectPanel* pp = olive::panel_manager->MostRecentlyFocused(); footage_combobox->SetRoot(pp->project()->root()); // Use multiple values diff --git a/app/widget/panel/panel.cpp b/app/widget/panel/panel.cpp index 5998f2313..1303da216 100644 --- a/app/widget/panel/panel.cpp +++ b/app/widget/panel/panel.cpp @@ -32,6 +32,23 @@ PanelWidget::PanelWidget(QWidget *parent) : setFocusPolicy(Qt::ClickFocus); } +void PanelWidget::SetMovementLocked(bool locked) +{ + if (locked) { + // Disable moving on QDockWidget + setFeatures(features() & ~QDockWidget::DockWidgetMovable); + + // Hide the title bar (only real way to do this is to replace it with an empty QWidget) + setTitleBarWidget(new QWidget(this)); + } else { + // Re-enable moving on QDockWidget + setFeatures(features() | QDockWidget::DockWidgetMovable); + + // Set the "custom" titlebar to null so the default gets restored + setTitleBarWidget(nullptr); + } +} + void PanelWidget::SetBorderVisible(bool enabled) { border_visible_ = enabled; diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index 62b5d706e..a5971fe8c 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -40,6 +40,11 @@ public: */ PanelWidget(QWidget* parent); + /** + * @brief Set whether panel movement is locked or not + */ + void SetMovementLocked(bool locked); + /** * @brief Set visibility of panel's highlighted border, mostly used for showing panel focus * diff --git a/app/window/mainwindow/mainmenu.cpp b/app/window/mainwindow/mainmenu.cpp index 0c80caf79..98a2f7473 100644 --- a/app/window/mainwindow/mainmenu.cpp +++ b/app/window/mainwindow/mainmenu.cpp @@ -191,11 +191,10 @@ MainMenu::MainMenu(QMainWindow *parent) : // // WINDOW MENU // - window_menu_ = new Menu(this); - window_menu_->addAction("No window support"); - window_menu_->addSeparator(); + window_menu_ = new Menu(this, this, SLOT(WindowMenuAboutToShow())); + window_menu_separator_ = window_menu_->addSeparator(); window_maximize_panel_item_ = window_menu_->AddItem("maximizepanel", nullptr, nullptr, "`"); - window_lock_layout_item_ = window_menu_->AddItem("lockpanels", nullptr, nullptr); + window_lock_layout_item_ = window_menu_->AddItem("lockpanels", olive::panel_manager, SLOT(SetPanelsLocked(bool))); window_lock_layout_item_->setCheckable(true); window_menu_->addSeparator(); window_reset_layout_item_ = window_menu_->AddItem("resetdefaultlayout", nullptr, nullptr); @@ -345,49 +344,67 @@ void MainMenu::ToolsMenuAboutToShow() tools_snapping_item_->setChecked(olive::core.snapping()); } +void MainMenu::WindowMenuAboutToShow() +{ + // QMainWindow generates a perfectly usable menu for this purpose, we just need to copy it to the window menu + QMenu* panel_menu = static_cast(parentWidget())->createPopupMenu(); + QList panel_menu_actions = panel_menu->actions(); + + // Make sure when we delete the panel_menu, it doesn't delete the actions + foreach (QAction* panel_action, panel_menu_actions) { + panel_action->setParent(window_menu_); + } + + delete panel_menu; + + window_menu_->insertActions(window_menu_separator_, panel_menu_actions); + + window_lock_layout_item_->setChecked(olive::panel_manager->ArePanelsLocked()); +} + void MainMenu::ZoomInTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->ZoomIn(); + olive::panel_manager->CurrentlyFocused()->ZoomIn(); } void MainMenu::ZoomOutTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->ZoomOut(); + olive::panel_manager->CurrentlyFocused()->ZoomOut(); } void MainMenu::GoToStartTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->GoToStart(); + olive::panel_manager->CurrentlyFocused()->GoToStart(); } void MainMenu::PrevFrameTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->PrevFrame(); + olive::panel_manager->CurrentlyFocused()->PrevFrame(); } void MainMenu::PlayPauseTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->PlayPause(); + olive::panel_manager->CurrentlyFocused()->PlayPause(); } void MainMenu::NextFrameTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->NextFrame(); + olive::panel_manager->CurrentlyFocused()->NextFrame(); } void MainMenu::GoToEndTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->GoToEnd(); + olive::panel_manager->CurrentlyFocused()->GoToEnd(); } void MainMenu::SelectAllTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->SelectAll(); + olive::panel_manager->CurrentlyFocused()->SelectAll(); } void MainMenu::DeselectAllTriggered() { - olive::panel_focus_manager->CurrentlyFocused()->DeselectAll(); + olive::panel_manager->CurrentlyFocused()->DeselectAll(); } void MainMenu::Retranslate() diff --git a/app/window/mainwindow/mainmenu.h b/app/window/mainwindow/mainmenu.h index 008e91f22..3a567fa8b 100644 --- a/app/window/mainwindow/mainmenu.h +++ b/app/window/mainwindow/mainmenu.h @@ -66,6 +66,11 @@ private slots: */ void ToolsMenuAboutToShow(); + /** + * @brief Slot triggered just before the Window menu shows + */ + void WindowMenuAboutToShow(); + /** * @brief Slot for zooming in * @@ -163,6 +168,7 @@ private: QAction* playback_loop_item_; Menu* window_menu_; + QAction* window_menu_separator_; QAction* window_maximize_panel_item_; QAction* window_lock_layout_item_; QAction* window_reset_layout_item_; diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index d189c26b7..5f154e308 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -67,23 +67,23 @@ void olive::MainWindow::SetFullscreen(bool fullscreen) void olive::MainWindow::ProjectOpen(Project* p) { // FIXME Use settings data to create panels and restore state if they exist - NodePanel* node_panel = olive::panel_focus_manager->CreatePanel(this); + NodePanel* node_panel = olive::panel_manager->CreatePanel(this); addDockWidget(Qt::TopDockWidgetArea, node_panel); - ParamPanel* param_panel = olive::panel_focus_manager->CreatePanel(this); + ParamPanel* param_panel = olive::panel_manager->CreatePanel(this); addDockWidget(Qt::TopDockWidgetArea, param_panel); - ViewerPanel* viewer_panel2 = olive::panel_focus_manager->CreatePanel(this); + ViewerPanel* viewer_panel2 = olive::panel_manager->CreatePanel(this); addDockWidget(Qt::TopDockWidgetArea, viewer_panel2); - ProjectPanel* project_panel = olive::panel_focus_manager->CreatePanel(this); + ProjectPanel* project_panel = olive::panel_manager->CreatePanel(this); project_panel->set_project(p); addDockWidget(Qt::BottomDockWidgetArea, project_panel); - ToolPanel* tool_panel = olive::panel_focus_manager->CreatePanel(this); + ToolPanel* tool_panel = olive::panel_manager->CreatePanel(this); addDockWidget(Qt::BottomDockWidgetArea, tool_panel); - TimelinePanel* timeline_panel = olive::panel_focus_manager->CreatePanel(this); + TimelinePanel* timeline_panel = olive::panel_manager->CreatePanel(this); addDockWidget(Qt::BottomDockWidgetArea, timeline_panel); connect(node_panel, SIGNAL(SelectionChanged(QList)), param_panel, SLOT(SetNodes(QList))); @@ -96,7 +96,7 @@ void olive::MainWindow::ProjectOpen(Project* p) void olive::MainWindow::closeEvent(QCloseEvent *e) { - olive::panel_focus_manager->DeleteAllPanels(); + olive::panel_manager->DeleteAllPanels(); // FIXME: Test code - We have no cache management and the cache is very much testing only, so we delete it on close // as to not clog up HDD space