From 4f1959501dda7ec3195dcce1bf9f86b45670d262 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Thu, 11 Aug 2022 19:10:28 +0800 Subject: [PATCH] Add open windows panel --- src/core/coreconfig.h | 1 + src/data/core/core.qrc | 1 + src/data/core/icons/windows_dock.svg | 1 + src/data/core/vnotex.json | 5 +- src/widgets/dockwidgethelper.cpp | 20 ++++++ src/widgets/dockwidgethelper.h | 3 + src/widgets/listwidget.cpp | 96 +++++++++++++++++++++------- src/widgets/listwidget.h | 21 +++++- src/widgets/mainwindow.cpp | 10 +++ src/widgets/mainwindow.h | 5 ++ src/widgets/viewarea.cpp | 47 +++++++++++--- src/widgets/viewarea.h | 14 +++- src/widgets/viewsplit.cpp | 14 +++- src/widgets/viewsplit.h | 2 + src/widgets/widgets.pri | 8 ++- src/widgets/windowspanel.cpp | 88 +++++++++++++++++++++++++ src/widgets/windowspanel.h | 43 +++++++++++++ src/widgets/windowsprovider.cpp | 46 +++++++++++++ src/widgets/windowsprovider.h | 46 +++++++++++++ 19 files changed, 429 insertions(+), 42 deletions(-) create mode 100644 src/data/core/icons/windows_dock.svg create mode 100644 src/widgets/windowspanel.cpp create mode 100644 src/widgets/windowspanel.h create mode 100644 src/widgets/windowsprovider.cpp create mode 100644 src/widgets/windowsprovider.h diff --git a/src/core/coreconfig.h b/src/core/coreconfig.h index ded4f9d2..ad15a85f 100644 --- a/src/core/coreconfig.h +++ b/src/core/coreconfig.h @@ -34,6 +34,7 @@ namespace vnotex SnippetDock, LocationListDock, HistoryDock, + WindowsDock, TagDock, Search, NavigationMode, diff --git a/src/data/core/core.qrc b/src/data/core/core.qrc index 2aa95117..cf27d264 100644 --- a/src/data/core/core.qrc +++ b/src/data/core/core.qrc @@ -86,6 +86,7 @@ icons/navigation_dock.svg icons/history_dock.svg icons/outline_dock.svg + icons/windows_dock.svg icons/search_dock.svg icons/snippet_dock.svg icons/location_list_dock.svg diff --git a/src/data/core/icons/windows_dock.svg b/src/data/core/icons/windows_dock.svg new file mode 100644 index 00000000..1377d4e9 --- /dev/null +++ b/src/data/core/icons/windows_dock.svg @@ -0,0 +1 @@ + diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index f3435f31..6c45a7dc 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -26,6 +26,7 @@ "SnippetDock" : "Ctrl+G, S", "LocationListDock" : "Ctrl+G, C", "HistoryDock" : "", + "WindowsDock" : "", "TagDock" : "", "Search" : "Ctrl+Alt+F", "NavigationMode" : "Ctrl+G, W", @@ -91,7 +92,7 @@ ], "shortcut_leader_key" : "Ctrl+G", "toolbar_icon_size" : 18, - "docks_tabbar_icon_size" : 18, + "docks_tabbar_icon_size" : 20, "note_management" : { "external_node" : { "//comment" : "Wildcard patterns of files and folders to exclude as external files", @@ -492,7 +493,7 @@ "node_explorer_explore_mode" : 0, "search_panel_advanced_settings_visible" : true, "//comment" : "Docks to ignore when expanding content area of main window", - "main_window_keep_docks_expanding_content_area": ["OutlineDock.vnotex"], + "main_window_keep_docks_expanding_content_area": ["OutlineDock.vnotex", "WindowsDock.vnotex"], "snippet_panel_builtin_snippets_visible" : true, "tag_explorer_two_columns_enabled" : false, "new_note_default_file_type" : 0, diff --git a/src/widgets/dockwidgethelper.cpp b/src/widgets/dockwidgethelper.cpp index 451be3b6..84847878 100644 --- a/src/widgets/dockwidgethelper.cpp +++ b/src/widgets/dockwidgethelper.cpp @@ -24,6 +24,7 @@ #include "searchpanel.h" #include "snippetpanel.h" #include "historypanel.h" +#include "windowspanel.h" #include "tagexplorer.h" #include "consoleviewer.h" @@ -71,6 +72,8 @@ QString DockWidgetHelper::iconFileName(DockIndex p_dockIndex) return "outline_dock.svg"; case DockIndex::HistoryDock: return "history_dock.svg"; + case DockIndex::WindowsDock: + return "windows_dock.svg"; case DockIndex::TagDock: return "tag_dock.svg"; case DockIndex::SearchDock: @@ -116,6 +119,8 @@ void DockWidgetHelper::setupDocks() setupOutlineDock(); + setupWindowsDock(); + setupConsoleDock(); setupLocationListDock(); @@ -155,6 +160,17 @@ void DockWidgetHelper::setupOutlineDock() m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); } +void DockWidgetHelper::setupWindowsDock() +{ + auto dock = createDockWidget(DockIndex::WindowsDock, tr("Open Windows"), m_mainWindow); + + dock->setObjectName(QStringLiteral("WindowsDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); + + addWidgetToDock(dock, m_mainWindow->m_windowsPanel); + m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); +} + void DockWidgetHelper::setupConsoleDock() { auto dock = createDockWidget(DockIndex::ConsoleDock, tr("Console"), m_mainWindow); @@ -304,6 +320,10 @@ void DockWidgetHelper::setupShortcuts() setupDockActivateShortcut(m_docks[DockIndex::SnippetDock], coreConfig.getShortcut(CoreConfig::Shortcut::SnippetDock)); + + setupDockActivateShortcut(m_docks[DockIndex::WindowsDock], + coreConfig.getShortcut(CoreConfig::Shortcut::WindowsDock)); + } void DockWidgetHelper::setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys) diff --git a/src/widgets/dockwidgethelper.h b/src/widgets/dockwidgethelper.h index 7920fb92..4579fd1c 100644 --- a/src/widgets/dockwidgethelper.h +++ b/src/widgets/dockwidgethelper.h @@ -29,6 +29,7 @@ namespace vnotex SearchDock, SnippetDock, OutlineDock, + WindowsDock, ConsoleDock, LocationListDock, MaxDock @@ -100,6 +101,8 @@ namespace vnotex void setupOutlineDock(); + void setupWindowsDock(); + void setupConsoleDock(); void setupSearchDock(); diff --git a/src/widgets/listwidget.cpp b/src/widgets/listwidget.cpp index 7c0711c7..5b65720d 100644 --- a/src/widgets/listwidget.cpp +++ b/src/widgets/listwidget.cpp @@ -1,6 +1,8 @@ #include "listwidget.h" #include +#include +#include #include #include @@ -9,20 +11,39 @@ using namespace vnotex; -QBrush ListWidget::s_separatorForeground; - -QBrush ListWidget::s_separatorBackground; - ListWidget::ListWidget(QWidget *p_parent) - : QListWidget(p_parent) + : ListWidget(false, p_parent) { - initialize(); } ListWidget::ListWidget(bool p_enhancedStyle, QWidget *p_parent) : QListWidget(p_parent) { - initialize(); + m_clickTimer = new QTimer(this); + m_clickTimer->setSingleShot(true); + connect(m_clickTimer, &QTimer::timeout, + this, &ListWidget::handleItemClick); + + connect(this, &QListWidget::itemClicked, + this, [this](QListWidgetItem *item) { + if (m_isDoubleClick && m_clickedItem == item) { + // There will be a single click right after double click. + m_clickTimer->stop(); + handleItemClick(); + return; + } + + m_isDoubleClick = false; + m_clickedItem = item; + m_clickTimer->start(QApplication::doubleClickInterval()); + }); + + connect(this, &QListWidget::itemDoubleClicked, + this, [this](QListWidgetItem *item) { + m_clickTimer->stop(); + m_isDoubleClick = true; + m_clickedItem = item; + }); if (p_enhancedStyle) { auto delegate = new StyledItemDelegate(QSharedPointer::create(this), @@ -32,33 +53,31 @@ ListWidget::ListWidget(bool p_enhancedStyle, QWidget *p_parent) } } -void ListWidget::initialize() -{ - static bool initialized = false; - if (!initialized) { - initialized = true; - - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - s_separatorForeground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#fg"))); - s_separatorBackground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#bg"))); - } -} - void ListWidget::keyPressEvent(QKeyEvent *p_event) { if (WidgetUtils::processKeyEventLikeVi(this, p_event)) { return; } + bool activateItem = false; + const int key = p_event->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter) { + activateItem = true; + } // On Mac OS X, it is `Command+O` to activate an item, instead of Return. #if defined(Q_OS_MACOS) || defined(Q_OS_MAC) - if (p_event->key() == Qt::Key_Return) { + if (key == Qt::Key_O && p_event->modifiers() == Qt::ControlModifier) { + activateItem = true; + } +#endif + + if (activateItem) { if (auto item = currentItem()) { emit itemActivated(item); + emit itemActivatedPlus(item, ActivateReason::Button); } return; } -#endif QListWidget::keyPressEvent(p_event); } @@ -86,11 +105,31 @@ QVector ListWidget::getVisibleItems(const QListWidget *p_widg return items; } +static const QBrush &separatorForeground() +{ + static QBrush fg; + if (fg == QBrush()) { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + fg = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#fg"))); + } + return fg; +} + +static const QBrush &separatorBackground() +{ + static QBrush bg; + if (bg == QBrush()) { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + bg = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#bg"))); + } + return bg; +} + QListWidgetItem *ListWidget::createSeparatorItem(const QString &p_text) { QListWidgetItem *item = new QListWidgetItem(p_text, nullptr, ItemTypeSeparator); - item->setData(Qt::ForegroundRole, s_separatorForeground); - item->setData(Qt::BackgroundRole, s_separatorBackground); + item->setData(Qt::ForegroundRole, separatorForeground()); + item->setData(Qt::BackgroundRole, separatorBackground()); item->setFlags(Qt::NoItemFlags); return item; } @@ -124,3 +163,14 @@ void ListWidget::forEachItem(const QListWidget *p_widget, const std::function +class QTimer; + namespace vnotex { class ListWidget : public QListWidget { Q_OBJECT public: + enum ActivateReason + { + SingleClick = 0, + DoubleClick, + Button + }; + explicit ListWidget(QWidget *p_parent = nullptr); ListWidget(bool p_enhancedStyle, QWidget *p_parent = nullptr); @@ -28,6 +37,10 @@ namespace vnotex // @p_func: return false to abort the iteration. static void forEachItem(const QListWidget *p_widget, const std::function &p_func); + signals: + // Item activated not by mouse clicking. + void itemActivatedPlus(QListWidgetItem *p_item, ActivateReason p_source); + protected: void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; @@ -37,11 +50,13 @@ namespace vnotex ItemTypeSeparator = 2000 }; - void initialize(); + void handleItemClick(); - static QBrush s_separatorForeground; + QTimer *m_clickTimer = nullptr; - static QBrush s_separatorBackground; + QListWidgetItem *m_clickedItem = nullptr; + + bool m_isDoubleClick = false; }; } diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp index 06c766af..73b8f797 100644 --- a/src/widgets/mainwindow.cpp +++ b/src/widgets/mainwindow.cpp @@ -47,6 +47,8 @@ #include "searchpanel.h" #include "snippetpanel.h" #include "historypanel.h" +#include "windowspanel.h" +#include "windowsprovider.h" #include #include "searchinfoprovider.h" #include @@ -263,6 +265,8 @@ void MainWindow::setupDocks() setupHistoryPanel(); + setupWindowsPanel(); + setupSearchPanel(); setupSnippetPanel(); @@ -304,6 +308,12 @@ void MainWindow::setupHistoryPanel() m_historyPanel->setObjectName("HistoryPanel.vnotex"); } +void MainWindow::setupWindowsPanel() +{ + m_windowsPanel = new WindowsPanel(QSharedPointer::create(m_viewArea), this); + m_windowsPanel->setObjectName("WindowsPanel.vnotex"); +} + void MainWindow::setupLocationList() { m_locationList = new LocationList(this); diff --git a/src/widgets/mainwindow.h b/src/widgets/mainwindow.h index 5b6ef2af..38ba88af 100644 --- a/src/widgets/mainwindow.h +++ b/src/widgets/mainwindow.h @@ -27,6 +27,7 @@ namespace vnotex class SearchPanel; class SnippetPanel; class HistoryPanel; + class WindowsPanel; class ExportDialog; class ConsoleViewer; @@ -121,6 +122,8 @@ namespace vnotex void setupHistoryPanel(); + void setupWindowsPanel(); + void setupNotebookExplorer(); void setupTagExplorer(); @@ -182,6 +185,8 @@ namespace vnotex HistoryPanel *m_historyPanel = nullptr; + WindowsPanel *m_windowsPanel = nullptr; + ExportDialog *m_exportDialog = nullptr; QSystemTrayIcon *m_trayIcon = nullptr; diff --git a/src/widgets/viewarea.cpp b/src/widgets/viewarea.cpp index c94f9d3e..3ec35ccb 100644 --- a/src/widgets/viewarea.cpp +++ b/src/widgets/viewarea.cpp @@ -240,14 +240,17 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId) connect(split, &ViewSplit::viewWindowCloseRequested, this, [this](ViewWindow *p_win) { closeViewWindow(p_win, false, true); + emit windowsChanged(); }); connect(split, &ViewSplit::verticalSplitRequested, this, [this](ViewSplit *p_split) { splitViewSplit(p_split, SplitType::Vertical); + emit windowsChanged(); }); connect(split, &ViewSplit::horizontalSplitRequested, this, [this](ViewSplit *p_split) { splitViewSplit(p_split, SplitType::Horizontal); + emit windowsChanged(); }); connect(split, &ViewSplit::maximizeSplitRequested, this, &ViewArea::maximizeViewSplit); @@ -256,16 +259,22 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId) connect(split, &ViewSplit::removeSplitRequested, this, [this](ViewSplit *p_split) { removeViewSplit(p_split, false); + emit windowsChanged(); }); connect(split, &ViewSplit::removeSplitAndWorkspaceRequested, this, [this](ViewSplit *p_split) { removeViewSplit(p_split, true); + emit windowsChanged(); }); connect(split, &ViewSplit::newWorkspaceRequested, - this, &ViewArea::newWorkspaceInViewSplit); + this, [this](ViewSplit *p_split) { + newWorkspaceInViewSplit(p_split); + emit windowsChanged(); + }); connect(split, &ViewSplit::removeWorkspaceRequested, this, [this](ViewSplit *p_split) { removeWorkspaceInViewSplit(p_split, true); + emit windowsChanged(); }); connect(split, &ViewSplit::focused, this, [this](ViewSplit *p_split) { @@ -287,9 +296,13 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId) p_win->setStatusWidgetVisible(true); } } + emit windowsChanged(); }); connect(split, &ViewSplit::moveViewWindowOneSplitRequested, - this, &ViewArea::moveViewWindowOneSplit); + this, [this](ViewSplit *p_split, ViewWindow *p_win, Direction p_direction) { + moveViewWindowOneSplit(p_split, p_win, p_direction); + emit windowsChanged(); + }); return split; } @@ -712,7 +725,7 @@ bool ViewArea::removeWorkspaceInViewSplit(ViewSplit *p_split, bool p_insertNew) { // Close all the ViewWindows. setCurrentViewSplit(p_split, true); - auto wins = getAllViewWindows(p_split); + auto wins = p_split->getAllViewWindows(); for (const auto win : wins) { if (!closeViewWindow(win, false, false)) { return false; @@ -1154,11 +1167,9 @@ QVector ViewArea::getAllViewWindows(ViewSplit *p_split, const View return wins; } -QVector ViewArea::getAllViewWindows(ViewSplit *p_split) const +const QVector& ViewArea::getAllViewSplits() const { - return getAllViewWindows(p_split, [](ViewWindow *) { - return true; - }); + return m_splits; } QList ViewArea::getAllBuffersInViewSplits() const @@ -1166,7 +1177,7 @@ QList ViewArea::getAllBuffersInViewSplits() const QSet bufferSet; for (auto split : m_splits) { - auto wins = getAllViewWindows(split); + auto wins = split->getAllViewWindows(); for (auto win : wins) { bufferSet.insert(win->getBuffer()); } @@ -1542,3 +1553,23 @@ void ViewArea::closeFile(const QString &p_filePath, const QSharedPointer p_event->m_response = done; p_event->m_handled = !done; } + +void ViewArea::setCurrentViewWindow(ID p_splitId, int p_windowIndex) +{ + auto split = findSplitById(p_splitId); + if (split) { + setCurrentViewSplit(split, true); + split->setCurrentViewWindow(p_windowIndex); + } +} + +ViewSplit *ViewArea::findSplitById(ID p_splitId) const +{ + for (auto split : m_splits) { + if (split->getId() == p_splitId) { + return split; + } + } + + return nullptr; +} diff --git a/src/widgets/viewarea.h b/src/widgets/viewarea.h index faeb37fd..2982ee92 100644 --- a/src/widgets/viewarea.h +++ b/src/widgets/viewarea.h @@ -74,6 +74,10 @@ namespace vnotex ViewWindow *getCurrentViewWindow() const; + const QVector& getAllViewSplits() const; + + void setCurrentViewWindow(ID p_splitId, int p_windowIndex); + public slots: void openBuffer(Buffer *p_buffer, const QSharedPointer &p_paras); @@ -103,7 +107,7 @@ namespace vnotex // MainWindow should set the corresponding status widget accordingly. void statusWidgetChanged(QWidget *p_widget); - // Count of ViewSplit is chagned. + // Count of ViewSplit is changed. // Used internally. void viewSplitsCountChanged(); @@ -112,6 +116,10 @@ namespace vnotex // State of current view window has update. void currentViewWindowUpdated(); + // ViewWindow reordered/added/removed/updated. + // ViewSplit added/removed/updated. + void windowsChanged(); + private slots: // Return true if @p_win is closed. // @p_removeSplitIfEmpty: whether remove the workspace and split if @p_win is that only ViewWindow left. @@ -212,8 +220,6 @@ namespace vnotex QVector getAllViewWindows(ViewSplit *p_split, const ViewSplit::ViewWindowSelector &p_func) const; - QVector getAllViewWindows(ViewSplit *p_split) const; - void takeSnapshot(ViewAreaSession &p_session) const; void postFirstViewSplit(); @@ -226,6 +232,8 @@ namespace vnotex ViewSplit *findSplitByDirection(ViewSplit *p_split, Direction p_direction); + ViewSplit *findSplitById(ID p_splitId) const; + SplitType checkSplitType(const QSplitter *p_splitter) const; void flashViewSplit(ViewSplit *p_split); diff --git a/src/widgets/viewsplit.cpp b/src/widgets/viewsplit.cpp index 5e5ef409..d400e714 100644 --- a/src/widgets/viewsplit.cpp +++ b/src/widgets/viewsplit.cpp @@ -124,7 +124,7 @@ void ViewSplit::setupCornerWidget() m_windowListButton->setPopupMode(QToolButton::InstantPopup); m_windowListButton->setProperty(PropertyDefs::c_actionToolButton, true); - auto act = new QAction(s_windowListIcon, tr("Windows List"), m_windowListButton); + auto act = new QAction(s_windowListIcon, tr("Open Windows"), m_windowListButton); m_windowListButton->setDefaultAction(act); auto menu = WidgetsFactory::createMenu(m_windowListButton); @@ -315,6 +315,18 @@ ViewWindow *ViewSplit::getViewWindow(int p_idx) const return dynamic_cast(widget(p_idx)); } +QVector ViewSplit::getAllViewWindows() const +{ + QVector wins; + int cnt = getViewWindowCount(); + for (int i = 0; i < cnt; ++i) { + auto win = getViewWindow(i); + wins.push_back(win); + } + + return wins; +} + int ViewSplit::getViewWindowCount() const { return count(); diff --git a/src/widgets/viewsplit.h b/src/widgets/viewsplit.h index 1c44f604..7ea03930 100644 --- a/src/widgets/viewsplit.h +++ b/src/widgets/viewsplit.h @@ -49,6 +49,8 @@ namespace vnotex void setCurrentViewWindow(int p_idx); + QVector getAllViewWindows() const; + // @p_win is not deleted. void takeViewWindow(ViewWindow *p_win); diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index d7fada38..561121c8 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -124,7 +124,9 @@ SOURCES += \ $$PWD/dialogs/deleteconfirmdialog.cpp \ $$PWD/dialogs/importfolderutils.cpp \ $$PWD/titletoolbar.cpp \ - $$PWD/viewarea.cpp + $$PWD/viewarea.cpp \ + $$PWD/windowspanel.cpp \ + $$PWD/windowsprovider.cpp HEADERS += \ $$PWD/attachmentdragdropareaindicator.h \ @@ -256,4 +258,6 @@ HEADERS += \ $$PWD/statusbarhelper.h \ $$PWD/dialogs/deleteconfirmdialog.h \ $$PWD/titletoolbar.h \ - $$PWD/viewarea.h + $$PWD/viewarea.h \ + $$PWD/windowspanel.h \ + $$PWD/windowsprovider.h diff --git a/src/widgets/windowspanel.cpp b/src/widgets/windowspanel.cpp new file mode 100644 index 00000000..86c0a6f7 --- /dev/null +++ b/src/widgets/windowspanel.cpp @@ -0,0 +1,88 @@ +#include "windowspanel.h" + +#include +#include + +#include + +#include "windowsprovider.h" +#include "listwidget.h" +#include "navigationmodemgr.h" + +using namespace vnotex; + +WindowsPanel::WindowsPanel(const QSharedPointer &p_provider, QWidget *p_parent) + : QFrame(p_parent), + m_provider(p_provider) +{ + Q_ASSERT(m_provider); + setupUI(); + + connect(m_provider.data(), &WindowsProvider::windowsChanged, + this, &WindowsPanel::updateWindowsList); +} + +void WindowsPanel::setupUI() +{ + auto mainLayout = new QVBoxLayout(this); + WidgetUtils::setContentsMargins(mainLayout); + + m_windows = new ListWidget(true, this); + mainLayout->addWidget(m_windows); + + connect(m_windows, &ListWidget::itemActivatedPlus, + this, [this](QListWidgetItem *item, ListWidget::ActivateReason reason) { + if (reason == ListWidget::ActivateReason::Button) { + activateItem(item); + } + }); + connect(m_windows, &QListWidget::itemClicked, + this, [this](QListWidgetItem *item) { + // It is fine to trigger multiple times. + activateItem(item); + }); + + m_navigationWrapper.reset(new NavigationModeWrapper(m_windows)); + NavigationModeMgr::getInst().registerNavigationTarget(m_navigationWrapper.data()); + + setFocusProxy(m_windows); +} + +void WindowsPanel::updateWindowsList() +{ + m_windows->clear(); + if (!isVisible()) { + return; + } + + const auto wins = m_provider->getWindows(); + for (const auto &splitWins : wins) { + for (const auto &win : splitWins.m_viewWindows) { + addItem(splitWins.m_viewSplitId, win); + } + } +} + +void WindowsPanel::addItem(ID p_viewSplitId, const WindowsProvider::WindowData &p_data) +{ + auto item = new QListWidgetItem(m_windows); + + item->setText(p_data.m_name); + item->setToolTip(p_data.m_name); + item->setData(Qt::UserRole, p_viewSplitId); + item->setData(Role::UserRole2, p_data.m_index); +} + +void WindowsPanel::showEvent(QShowEvent *p_event) +{ + QFrame::showEvent(p_event); + + updateWindowsList(); +} + +void WindowsPanel::activateItem(QListWidgetItem *p_item) +{ + Q_ASSERT(p_item); + m_provider->setCurrentWindow(p_item->data(Qt::UserRole).toULongLong(), + p_item->data(Role::UserRole2).toInt()); +} diff --git a/src/widgets/windowspanel.h b/src/widgets/windowspanel.h new file mode 100644 index 00000000..27a5b4fc --- /dev/null +++ b/src/widgets/windowspanel.h @@ -0,0 +1,43 @@ +#ifndef WINDOWSPANEL_H +#define WINDOWSPANEL_H + +#include +#include +#include + +#include "navigationmodewrapper.h" +#include "windowsprovider.h" + +class QListWidgetItem; + +namespace vnotex +{ + class ListWidget; + + class WindowsPanel : public QFrame + { + Q_OBJECT + public: + WindowsPanel(const QSharedPointer &p_provider, QWidget *p_parent = nullptr); + + protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; + + private: + void setupUI(); + + void updateWindowsList(); + + void addItem(ID p_viewSplitId, const WindowsProvider::WindowData &p_data); + + void activateItem(QListWidgetItem *p_item); + + QSharedPointer m_provider; + + ListWidget *m_windows = nullptr; + + QScopedPointer> m_navigationWrapper; + }; +} + +#endif // WINDOWSPANEL_H diff --git a/src/widgets/windowsprovider.cpp b/src/widgets/windowsprovider.cpp new file mode 100644 index 00000000..39e4f261 --- /dev/null +++ b/src/widgets/windowsprovider.cpp @@ -0,0 +1,46 @@ +#include "windowsprovider.h" + +#include "viewarea.h" +#include "viewsplit.h" +#include "viewwindow.h" + +using namespace vnotex; + +WindowsProvider::WindowsProvider(ViewArea *p_viewArea) + : QObject(nullptr), + m_viewArea(p_viewArea) +{ + Q_ASSERT(m_viewArea); + connect(m_viewArea, &ViewArea::windowsChanged, + this, &WindowsProvider::windowsChanged); +} + +QVector WindowsProvider::getWindows() const +{ + QVector windows; + + const auto& splits = m_viewArea->getAllViewSplits(); + for (auto split : splits) { + auto wins = split->getAllViewWindows(); + if (wins.empty()) { + continue; + } + + windows.push_back(ViewSplitWindows()); + auto& tmp = windows.back(); + tmp.m_viewSplitId = split->getId(); + for (int idx = 0; idx < wins.size(); ++idx) { + WindowData data; + data.m_index = idx; + data.m_name = wins[idx]->getName(); + tmp.m_viewWindows.push_back(data); + } + } + + return windows; +} + +void WindowsProvider::setCurrentWindow(ID p_viewSplitId, int p_windowIndex) +{ + m_viewArea->setCurrentViewWindow(p_viewSplitId, p_windowIndex); +} diff --git a/src/widgets/windowsprovider.h b/src/widgets/windowsprovider.h new file mode 100644 index 00000000..47320e1e --- /dev/null +++ b/src/widgets/windowsprovider.h @@ -0,0 +1,46 @@ +#ifndef WINDOWSPROVIDER_H +#define WINDOWSPROVIDER_H + +#include + +#include + +#include + +namespace vnotex +{ + class ViewArea; + + class WindowsProvider : public QObject + { + Q_OBJECT + public: + struct WindowData + { + int m_index = -1; + + QString m_name; + }; + + struct ViewSplitWindows + { + ID m_viewSplitId = 0; + + QVector m_viewWindows; + }; + + explicit WindowsProvider(ViewArea *p_viewArea); + + QVector getWindows() const; + + void setCurrentWindow(ID p_viewSplitId, int p_windowIndex); + + signals: + void windowsChanged(); + + private: + ViewArea *m_viewArea = nullptr; + }; +} + +#endif // WINDOWSPROVIDER_H