/*** Olive - Non-Linear Video Editor Copyright (C) 2019 Olive Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #ifndef PANELFOCUSMANAGER_H #define PANELFOCUSMANAGER_H #include #include #include "widget/panel/panel.h" OLIVE_NAMESPACE_ENTER /** * @brief The PanelFocusManager class * * This object keeps track of which panel is focused at any given time. * * Sometimes a function (specifically a keyboard-triggered one, e.g. Delete) may have different purposes depending on * which panel is "focused" at any given time. Pressing Delete on the Timeline is not the same as pressing Delete in * the Project panel, for example. This kind of "focus" is slightly different from standard QWidget focus, since it * aims to be less specific than a single QPushButton or QLineEdit, and rather specific to the panel widgets like * that belong to. * * PanelFocusManager's SLOT(FocusChanged()) connects to the QApplication instance's SIGNAL(focusChanged()) so that * it always knows when focus has changed within the application. */ class PanelManager : public QObject { Q_OBJECT public: PanelManager(QObject* parent = nullptr); /** * @brief Destroy all panels * * Should only be used on application exit to cleanly free all panels. */ void DeleteAllPanels(); /** * @brief Get a list of all existing panels * * Panels are ordered from most recently focused to least recently focused. */ const QList& panels(); /** * @brief Return the currently focused widget, or nullptr if nothing is focused * * This result == CurrentlyFocused() if HoverFocus is true */ PanelWidget* CurrentlyFocused() const; /** * @brief Return the widget that the mouse is currently hovering over, or nullptr if nothing is hovered over * * This result == CurrentlyFocused() if HoverFocus is true */ PanelWidget* CurrentlyHovered() const; template /** * @brief Get most recently focused panel of a certain type * * @return * * The most recently focused panel of the specified type, or nullptr if none exists */ T* MostRecentlyFocused(); template /** * @brief Create a panel */ T* CreatePanel(QWidget* parent); /** * @brief Get whether panels are currently prevented from moving */ bool ArePanelsLocked(); /** * @brief Create PanelManager singleton instance */ static void CreateInstance(); /** * @brief Destroy PanelManager singleton instance * * If no PanelManager was created, this is a no-op. */ static void DestroyInstance(); /** * @brief Access to PanelManager singleton instance */ static PanelManager* instance(); template /** * @brief Get a list of panels of a certain type */ QList GetPanelsOfType(); public slots: /** * @brief Connect this to a QApplication's SIGNAL(focusChanged()) * * Interprets focus information to determine the currently focused panel */ void FocusChanged(QWidget* old, QWidget* now); /** * @brief Sets whether panels should be prevented from moving */ void SetPanelsLocked(bool locked); signals: /** * @brief Signal emitted when the currently focused panel changes */ void FocusedPanelChanged(PanelWidget* panel); private: /** * @brief History array for traversing through (see MostRecentlyFocused()) */ QList focus_history_; /** * @brief Internal panel movement is locked value */ bool locked_; /** * @brief PanelManager singleton instance */ static PanelManager* instance_; /** * @brief The last panel that was focused * * Stored to prevent emitting FocusedPanelChanged() multiple times for the same panel */ PanelWidget* last_focused_panel_; private slots: /** * @brief Processing if a panel gets deleted */ void PanelDestroyed(); }; template T *PanelManager::CreatePanel(QWidget *parent) { T* panel = new T(parent); // Add panel to the bottom of the focus history focus_history_.append(panel); panel->SetMovementLocked(locked_); // Sane default for panel size panel->resize(parent->size() / 3); // We're about to center the panel relative to the parent (usually the main window), but for some // reason this requires the panel to be shown first. panel->show(); // Center the panel relative to the parent QPoint parent_center = panel->mapFromGlobal(parent->mapToGlobal(parent->rect().center())); QPoint panel_center = panel->rect().center(); panel->move(parent_center - panel_center); // Connect destroy signal so we can remove it from focus history connect(panel, &PanelWidget::destroyed, this, &PanelManager::PanelDestroyed, Qt::DirectConnection); return panel; } template T* PanelManager::MostRecentlyFocused() { T* cast_test; for (int i=0;i(focus_history_.at(i)); if (cast_test != nullptr) { return cast_test; } } return nullptr; } template QList PanelManager::GetPanelsOfType() { QList panels; T* cast_test; foreach (PanelWidget* panel, focus_history_) { cast_test = dynamic_cast(panel); if (cast_test) { panels.append(cast_test); } } return panels; } OLIVE_NAMESPACE_EXIT #endif // PANELFOCUSMANAGER_H