diff --git a/app/core.cpp b/app/core.cpp index 5daf4f25f..3243e754b 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -25,6 +25,7 @@ #include #include +#include "panel/panelfocusmanager.h" #include "ui/icons/icons.h" #include "ui/style/style.h" #include "widget/menu/menushared.h" @@ -42,6 +43,8 @@ void Core::Start() // Parse command line arguments // + QCoreApplication* app = QCoreApplication::instance(); + QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); @@ -55,7 +58,7 @@ void Core::Start() parser.addOption(fullscreen_option); // Parse options - parser.process(*QApplication::instance()); + parser.process(*app); QStringList args = parser.positionalArguments(); @@ -79,6 +82,12 @@ void Core::Start() // Set up shared menus olive::menu_shared.Initialize(); + // Since we're starting GUI mode, create a PanelFocusManager (auto-deletes with QObject) + olive::panel_focus_manager = new PanelFocusManager(this); + + // Connect the PanelFocusManager to the application's focus change signal + connect(app, SIGNAL(focusChanged(QWidget*, QWidget*)), olive::panel_focus_manager, SLOT(FocusChanged(QWidget*, QWidget*))); + // Create main window and open it main_window_ = new olive::MainWindow(); if (parser.isSet(fullscreen_option)) { diff --git a/app/panel/CMakeLists.txt b/app/panel/CMakeLists.txt index 492fa1607..4d4cd5d48 100644 --- a/app/panel/CMakeLists.txt +++ b/app/panel/CMakeLists.txt @@ -21,5 +21,7 @@ add_subdirectory(viewer) set(OLIVE_SOURCES ${OLIVE_SOURCES} + panel/panelfocusmanager.h + panel/panelfocusmanager.cpp PARENT_SCOPE ) diff --git a/app/panel/panelfocusmanager.cpp b/app/panel/panelfocusmanager.cpp new file mode 100644 index 000000000..61d5a273f --- /dev/null +++ b/app/panel/panelfocusmanager.cpp @@ -0,0 +1,60 @@ +#include "panelfocusmanager.h" + +#include + +PanelFocusManager* olive::panel_focus_manager; + +PanelFocusManager::PanelFocusManager(QObject *parent) : + QObject(parent) +{ + +} + +PanelWidget *PanelFocusManager::CurrentlyFocused() +{ + if (focus_history_.isEmpty()) { + return nullptr; + } + + return focus_history_.first(); +} + +void PanelFocusManager::FocusChanged(QWidget *old, QWidget *now) +{ + Q_UNUSED(old) + + QObject* parent = now; + PanelWidget* panel_cast_test; + + // Loop through widget's parent hierarchy + while (parent != nullptr) { + + // Use dynamic_cast to test if this object is a PanelWidget + panel_cast_test = dynamic_cast(parent); + + if (panel_cast_test != nullptr) { + // If so, bump this to the top of the focus history + + int panel_index = focus_history_.indexOf(panel_cast_test); + + // Force the old panel to repaint (if there is one) so it hides its border + if (!focus_history_.isEmpty()) { + focus_history_.first()->update(); + } + + // If it's not in the focus history, prepend it, otherwise move it + if (panel_index == -1) { + focus_history_.prepend(panel_cast_test); + } else { + focus_history_.move(panel_index, 0); + } + + // Force the panel to repaint so it shows a border + panel_cast_test->update(); + + break; + } + + parent = parent->parent(); + } +} diff --git a/app/panel/panelfocusmanager.h b/app/panel/panelfocusmanager.h new file mode 100644 index 000000000..618f5d0e7 --- /dev/null +++ b/app/panel/panelfocusmanager.h @@ -0,0 +1,28 @@ +#ifndef PANELFOCUSMANAGER_H +#define PANELFOCUSMANAGER_H + +#include +#include + +#include "widget/panel/panel.h" + +class PanelFocusManager : public QObject +{ + Q_OBJECT +public: + PanelFocusManager(QObject* parent); + + PanelWidget* CurrentlyFocused(); + +public slots: + void FocusChanged(QWidget* old, QWidget* now); + +private: + QList focus_history_; +}; + +namespace olive { +extern PanelFocusManager* panel_focus_manager; +} + +#endif // PANELFOCUSMANAGER_H diff --git a/app/widget/panel/panel.cpp b/app/widget/panel/panel.cpp index 1fe7f5fc6..47faac5db 100644 --- a/app/widget/panel/panel.cpp +++ b/app/widget/panel/panel.cpp @@ -20,9 +20,14 @@ #include "panel.h" +#include + +#include "panel/panelfocusmanager.h" + PanelWidget::PanelWidget(QWidget *parent) : QDockWidget(parent) { + setFocusPolicy(Qt::ClickFocus); } void PanelWidget::SetTitle(const QString &t) @@ -37,6 +42,29 @@ void PanelWidget::SetSubtitle(const QString &t) UpdateTitle(); } +void PanelWidget::paintEvent(QPaintEvent *event) +{ + // Perform default behavior + QDockWidget::paintEvent(event); + + // Check if this panel (or a child of it) has focus using PanelFocusManager + if (olive::panel_focus_manager->CurrentlyFocused() == this) { + + // Draw a highlight border if so + QPainter p(this); + + // We need to adjust the rect by 1 pixel since the bottom and right are "offscreen" + QRect highlight_border = rect(); + highlight_border.adjust(0, 0, -1, -1); + + // Set the color to the palette's highlight color + p.setPen(QPen(palette().highlight().color())); + + // Draw the highlight border + p.drawRect(highlight_border); + } +} + void PanelWidget::UpdateTitle() { if (subtitle_.isEmpty()) { diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index 0a20b9315..def33cbe5 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -69,6 +69,12 @@ protected: * String to set the subtitle to */ void SetSubtitle(const QString& t); + + /** + * @brief paintEvent + * @param event + */ + void paintEvent(QPaintEvent *event) override; private: /** * @brief Internal function that sets the QDockWidget's window title whenever the title/subtitle change. diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index 90aa5275a..308169f7e 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -20,6 +20,8 @@ #include "mainwindow.h" +#include + // Panel objects #include "panel/project/project.h" #include "panel/viewer/viewer.h" diff --git a/app/window/mainwindow/mainwindow.h b/app/window/mainwindow/mainwindow.h index 7da7f140e..e08747a50 100644 --- a/app/window/mainwindow/mainwindow.h +++ b/app/window/mainwindow/mainwindow.h @@ -35,7 +35,7 @@ namespace olive { class MainWindow : public QMainWindow { Q_OBJECT public: - MainWindow(QWidget* parent = nullptr); + MainWindow(QWidget *parent = nullptr); public slots: void ProjectOpen(Project *p);