Add open windows panel

This commit is contained in:
Le Tan 2022-08-11 19:10:28 +08:00
parent 12e18934df
commit 4f1959501d
19 changed files with 429 additions and 42 deletions

View File

@ -34,6 +34,7 @@ namespace vnotex
SnippetDock, SnippetDock,
LocationListDock, LocationListDock,
HistoryDock, HistoryDock,
WindowsDock,
TagDock, TagDock,
Search, Search,
NavigationMode, NavigationMode,

View File

@ -86,6 +86,7 @@
<file>icons/navigation_dock.svg</file> <file>icons/navigation_dock.svg</file>
<file>icons/history_dock.svg</file> <file>icons/history_dock.svg</file>
<file>icons/outline_dock.svg</file> <file>icons/outline_dock.svg</file>
<file>icons/windows_dock.svg</file>
<file>icons/search_dock.svg</file> <file>icons/search_dock.svg</file>
<file>icons/snippet_dock.svg</file> <file>icons/snippet_dock.svg</file>
<file>icons/location_list_dock.svg</file> <file>icons/location_list_dock.svg</file>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="4" y="6" width="40" height="36" rx="3" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M4 14H44" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M20 24H36" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M20 32H36" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 24H14" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 32H14" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>

After

Width:  |  Height:  |  Size: 779 B

View File

@ -26,6 +26,7 @@
"SnippetDock" : "Ctrl+G, S", "SnippetDock" : "Ctrl+G, S",
"LocationListDock" : "Ctrl+G, C", "LocationListDock" : "Ctrl+G, C",
"HistoryDock" : "", "HistoryDock" : "",
"WindowsDock" : "",
"TagDock" : "", "TagDock" : "",
"Search" : "Ctrl+Alt+F", "Search" : "Ctrl+Alt+F",
"NavigationMode" : "Ctrl+G, W", "NavigationMode" : "Ctrl+G, W",
@ -91,7 +92,7 @@
], ],
"shortcut_leader_key" : "Ctrl+G", "shortcut_leader_key" : "Ctrl+G",
"toolbar_icon_size" : 18, "toolbar_icon_size" : 18,
"docks_tabbar_icon_size" : 18, "docks_tabbar_icon_size" : 20,
"note_management" : { "note_management" : {
"external_node" : { "external_node" : {
"//comment" : "Wildcard patterns of files and folders to exclude as external files", "//comment" : "Wildcard patterns of files and folders to exclude as external files",
@ -492,7 +493,7 @@
"node_explorer_explore_mode" : 0, "node_explorer_explore_mode" : 0,
"search_panel_advanced_settings_visible" : true, "search_panel_advanced_settings_visible" : true,
"//comment" : "Docks to ignore when expanding content area of main window", "//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, "snippet_panel_builtin_snippets_visible" : true,
"tag_explorer_two_columns_enabled" : false, "tag_explorer_two_columns_enabled" : false,
"new_note_default_file_type" : 0, "new_note_default_file_type" : 0,

View File

@ -24,6 +24,7 @@
#include "searchpanel.h" #include "searchpanel.h"
#include "snippetpanel.h" #include "snippetpanel.h"
#include "historypanel.h" #include "historypanel.h"
#include "windowspanel.h"
#include "tagexplorer.h" #include "tagexplorer.h"
#include "consoleviewer.h" #include "consoleviewer.h"
@ -71,6 +72,8 @@ QString DockWidgetHelper::iconFileName(DockIndex p_dockIndex)
return "outline_dock.svg"; return "outline_dock.svg";
case DockIndex::HistoryDock: case DockIndex::HistoryDock:
return "history_dock.svg"; return "history_dock.svg";
case DockIndex::WindowsDock:
return "windows_dock.svg";
case DockIndex::TagDock: case DockIndex::TagDock:
return "tag_dock.svg"; return "tag_dock.svg";
case DockIndex::SearchDock: case DockIndex::SearchDock:
@ -116,6 +119,8 @@ void DockWidgetHelper::setupDocks()
setupOutlineDock(); setupOutlineDock();
setupWindowsDock();
setupConsoleDock(); setupConsoleDock();
setupLocationListDock(); setupLocationListDock();
@ -155,6 +160,17 @@ void DockWidgetHelper::setupOutlineDock()
m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); 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() void DockWidgetHelper::setupConsoleDock()
{ {
auto dock = createDockWidget(DockIndex::ConsoleDock, tr("Console"), m_mainWindow); auto dock = createDockWidget(DockIndex::ConsoleDock, tr("Console"), m_mainWindow);
@ -304,6 +320,10 @@ void DockWidgetHelper::setupShortcuts()
setupDockActivateShortcut(m_docks[DockIndex::SnippetDock], setupDockActivateShortcut(m_docks[DockIndex::SnippetDock],
coreConfig.getShortcut(CoreConfig::Shortcut::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) void DockWidgetHelper::setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys)

View File

@ -29,6 +29,7 @@ namespace vnotex
SearchDock, SearchDock,
SnippetDock, SnippetDock,
OutlineDock, OutlineDock,
WindowsDock,
ConsoleDock, ConsoleDock,
LocationListDock, LocationListDock,
MaxDock MaxDock
@ -100,6 +101,8 @@ namespace vnotex
void setupOutlineDock(); void setupOutlineDock();
void setupWindowsDock();
void setupConsoleDock(); void setupConsoleDock();
void setupSearchDock(); void setupSearchDock();

View File

@ -1,6 +1,8 @@
#include "listwidget.h" #include "listwidget.h"
#include <QKeyEvent> #include <QKeyEvent>
#include <QApplication>
#include <QTimer>
#include <core/vnotex.h> #include <core/vnotex.h>
#include <core/thememgr.h> #include <core/thememgr.h>
@ -9,20 +11,39 @@
using namespace vnotex; using namespace vnotex;
QBrush ListWidget::s_separatorForeground;
QBrush ListWidget::s_separatorBackground;
ListWidget::ListWidget(QWidget *p_parent) ListWidget::ListWidget(QWidget *p_parent)
: QListWidget(p_parent) : ListWidget(false, p_parent)
{ {
initialize();
} }
ListWidget::ListWidget(bool p_enhancedStyle, QWidget *p_parent) ListWidget::ListWidget(bool p_enhancedStyle, QWidget *p_parent)
: QListWidget(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) { if (p_enhancedStyle) {
auto delegate = new StyledItemDelegate(QSharedPointer<StyledItemDelegateListWidget>::create(this), auto delegate = new StyledItemDelegate(QSharedPointer<StyledItemDelegateListWidget>::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) void ListWidget::keyPressEvent(QKeyEvent *p_event)
{ {
if (WidgetUtils::processKeyEventLikeVi(this, p_event)) { if (WidgetUtils::processKeyEventLikeVi(this, p_event)) {
return; 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. // 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 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()) { if (auto item = currentItem()) {
emit itemActivated(item); emit itemActivated(item);
emit itemActivatedPlus(item, ActivateReason::Button);
} }
return; return;
} }
#endif
QListWidget::keyPressEvent(p_event); QListWidget::keyPressEvent(p_event);
} }
@ -86,11 +105,31 @@ QVector<QListWidgetItem *> ListWidget::getVisibleItems(const QListWidget *p_widg
return items; 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 *ListWidget::createSeparatorItem(const QString &p_text)
{ {
QListWidgetItem *item = new QListWidgetItem(p_text, nullptr, ItemTypeSeparator); QListWidgetItem *item = new QListWidgetItem(p_text, nullptr, ItemTypeSeparator);
item->setData(Qt::ForegroundRole, s_separatorForeground); item->setData(Qt::ForegroundRole, separatorForeground());
item->setData(Qt::BackgroundRole, s_separatorBackground); item->setData(Qt::BackgroundRole, separatorBackground());
item->setFlags(Qt::NoItemFlags); item->setFlags(Qt::NoItemFlags);
return item; return item;
} }
@ -124,3 +163,14 @@ void ListWidget::forEachItem(const QListWidget *p_widget, const std::function<bo
} }
} }
} }
void ListWidget::handleItemClick()
{
if (m_clickedItem) {
emit itemActivatedPlus(m_clickedItem,
m_isDoubleClick ? ActivateReason::DoubleClick
: ActivateReason::SingleClick);
m_isDoubleClick = false;
m_clickedItem = nullptr;
}
}

View File

@ -7,12 +7,21 @@
#include <QVector> #include <QVector>
class QTimer;
namespace vnotex namespace vnotex
{ {
class ListWidget : public QListWidget class ListWidget : public QListWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum ActivateReason
{
SingleClick = 0,
DoubleClick,
Button
};
explicit ListWidget(QWidget *p_parent = nullptr); explicit ListWidget(QWidget *p_parent = nullptr);
ListWidget(bool p_enhancedStyle, 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. // @p_func: return false to abort the iteration.
static void forEachItem(const QListWidget *p_widget, const std::function<bool(QListWidgetItem *p_item)> &p_func); static void forEachItem(const QListWidget *p_widget, const std::function<bool(QListWidgetItem *p_item)> &p_func);
signals:
// Item activated not by mouse clicking.
void itemActivatedPlus(QListWidgetItem *p_item, ActivateReason p_source);
protected: protected:
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
@ -37,11 +50,13 @@ namespace vnotex
ItemTypeSeparator = 2000 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;
}; };
} }

View File

@ -47,6 +47,8 @@
#include "searchpanel.h" #include "searchpanel.h"
#include "snippetpanel.h" #include "snippetpanel.h"
#include "historypanel.h" #include "historypanel.h"
#include "windowspanel.h"
#include "windowsprovider.h"
#include <notebook/notebook.h> #include <notebook/notebook.h>
#include "searchinfoprovider.h" #include "searchinfoprovider.h"
#include <vtextedit/spellchecker.h> #include <vtextedit/spellchecker.h>
@ -263,6 +265,8 @@ void MainWindow::setupDocks()
setupHistoryPanel(); setupHistoryPanel();
setupWindowsPanel();
setupSearchPanel(); setupSearchPanel();
setupSnippetPanel(); setupSnippetPanel();
@ -304,6 +308,12 @@ void MainWindow::setupHistoryPanel()
m_historyPanel->setObjectName("HistoryPanel.vnotex"); m_historyPanel->setObjectName("HistoryPanel.vnotex");
} }
void MainWindow::setupWindowsPanel()
{
m_windowsPanel = new WindowsPanel(QSharedPointer<WindowsProvider>::create(m_viewArea), this);
m_windowsPanel->setObjectName("WindowsPanel.vnotex");
}
void MainWindow::setupLocationList() void MainWindow::setupLocationList()
{ {
m_locationList = new LocationList(this); m_locationList = new LocationList(this);

View File

@ -27,6 +27,7 @@ namespace vnotex
class SearchPanel; class SearchPanel;
class SnippetPanel; class SnippetPanel;
class HistoryPanel; class HistoryPanel;
class WindowsPanel;
class ExportDialog; class ExportDialog;
class ConsoleViewer; class ConsoleViewer;
@ -121,6 +122,8 @@ namespace vnotex
void setupHistoryPanel(); void setupHistoryPanel();
void setupWindowsPanel();
void setupNotebookExplorer(); void setupNotebookExplorer();
void setupTagExplorer(); void setupTagExplorer();
@ -182,6 +185,8 @@ namespace vnotex
HistoryPanel *m_historyPanel = nullptr; HistoryPanel *m_historyPanel = nullptr;
WindowsPanel *m_windowsPanel = nullptr;
ExportDialog *m_exportDialog = nullptr; ExportDialog *m_exportDialog = nullptr;
QSystemTrayIcon *m_trayIcon = nullptr; QSystemTrayIcon *m_trayIcon = nullptr;

View File

@ -240,14 +240,17 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId)
connect(split, &ViewSplit::viewWindowCloseRequested, connect(split, &ViewSplit::viewWindowCloseRequested,
this, [this](ViewWindow *p_win) { this, [this](ViewWindow *p_win) {
closeViewWindow(p_win, false, true); closeViewWindow(p_win, false, true);
emit windowsChanged();
}); });
connect(split, &ViewSplit::verticalSplitRequested, connect(split, &ViewSplit::verticalSplitRequested,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
splitViewSplit(p_split, SplitType::Vertical); splitViewSplit(p_split, SplitType::Vertical);
emit windowsChanged();
}); });
connect(split, &ViewSplit::horizontalSplitRequested, connect(split, &ViewSplit::horizontalSplitRequested,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
splitViewSplit(p_split, SplitType::Horizontal); splitViewSplit(p_split, SplitType::Horizontal);
emit windowsChanged();
}); });
connect(split, &ViewSplit::maximizeSplitRequested, connect(split, &ViewSplit::maximizeSplitRequested,
this, &ViewArea::maximizeViewSplit); this, &ViewArea::maximizeViewSplit);
@ -256,16 +259,22 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId)
connect(split, &ViewSplit::removeSplitRequested, connect(split, &ViewSplit::removeSplitRequested,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
removeViewSplit(p_split, false); removeViewSplit(p_split, false);
emit windowsChanged();
}); });
connect(split, &ViewSplit::removeSplitAndWorkspaceRequested, connect(split, &ViewSplit::removeSplitAndWorkspaceRequested,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
removeViewSplit(p_split, true); removeViewSplit(p_split, true);
emit windowsChanged();
}); });
connect(split, &ViewSplit::newWorkspaceRequested, connect(split, &ViewSplit::newWorkspaceRequested,
this, &ViewArea::newWorkspaceInViewSplit); this, [this](ViewSplit *p_split) {
newWorkspaceInViewSplit(p_split);
emit windowsChanged();
});
connect(split, &ViewSplit::removeWorkspaceRequested, connect(split, &ViewSplit::removeWorkspaceRequested,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
removeWorkspaceInViewSplit(p_split, true); removeWorkspaceInViewSplit(p_split, true);
emit windowsChanged();
}); });
connect(split, &ViewSplit::focused, connect(split, &ViewSplit::focused,
this, [this](ViewSplit *p_split) { this, [this](ViewSplit *p_split) {
@ -287,9 +296,13 @@ ViewSplit *ViewArea::createViewSplit(QWidget *p_parent, ID p_viewSplitId)
p_win->setStatusWidgetVisible(true); p_win->setStatusWidgetVisible(true);
} }
} }
emit windowsChanged();
}); });
connect(split, &ViewSplit::moveViewWindowOneSplitRequested, 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; return split;
} }
@ -712,7 +725,7 @@ bool ViewArea::removeWorkspaceInViewSplit(ViewSplit *p_split, bool p_insertNew)
{ {
// Close all the ViewWindows. // Close all the ViewWindows.
setCurrentViewSplit(p_split, true); setCurrentViewSplit(p_split, true);
auto wins = getAllViewWindows(p_split); auto wins = p_split->getAllViewWindows();
for (const auto win : wins) { for (const auto win : wins) {
if (!closeViewWindow(win, false, false)) { if (!closeViewWindow(win, false, false)) {
return false; return false;
@ -1154,11 +1167,9 @@ QVector<ViewWindow *> ViewArea::getAllViewWindows(ViewSplit *p_split, const View
return wins; return wins;
} }
QVector<ViewWindow *> ViewArea::getAllViewWindows(ViewSplit *p_split) const const QVector<ViewSplit *>& ViewArea::getAllViewSplits() const
{ {
return getAllViewWindows(p_split, [](ViewWindow *) { return m_splits;
return true;
});
} }
QList<Buffer *> ViewArea::getAllBuffersInViewSplits() const QList<Buffer *> ViewArea::getAllBuffersInViewSplits() const
@ -1166,7 +1177,7 @@ QList<Buffer *> ViewArea::getAllBuffersInViewSplits() const
QSet<Buffer *> bufferSet; QSet<Buffer *> bufferSet;
for (auto split : m_splits) { for (auto split : m_splits) {
auto wins = getAllViewWindows(split); auto wins = split->getAllViewWindows();
for (auto win : wins) { for (auto win : wins) {
bufferSet.insert(win->getBuffer()); bufferSet.insert(win->getBuffer());
} }
@ -1542,3 +1553,23 @@ void ViewArea::closeFile(const QString &p_filePath, const QSharedPointer<Event>
p_event->m_response = done; p_event->m_response = done;
p_event->m_handled = !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;
}

View File

@ -74,6 +74,10 @@ namespace vnotex
ViewWindow *getCurrentViewWindow() const; ViewWindow *getCurrentViewWindow() const;
const QVector<ViewSplit *>& getAllViewSplits() const;
void setCurrentViewWindow(ID p_splitId, int p_windowIndex);
public slots: public slots:
void openBuffer(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras); void openBuffer(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras);
@ -103,7 +107,7 @@ namespace vnotex
// MainWindow should set the corresponding status widget accordingly. // MainWindow should set the corresponding status widget accordingly.
void statusWidgetChanged(QWidget *p_widget); void statusWidgetChanged(QWidget *p_widget);
// Count of ViewSplit is chagned. // Count of ViewSplit is changed.
// Used internally. // Used internally.
void viewSplitsCountChanged(); void viewSplitsCountChanged();
@ -112,6 +116,10 @@ namespace vnotex
// State of current view window has update. // State of current view window has update.
void currentViewWindowUpdated(); void currentViewWindowUpdated();
// ViewWindow reordered/added/removed/updated.
// ViewSplit added/removed/updated.
void windowsChanged();
private slots: private slots:
// Return true if @p_win is closed. // Return true if @p_win is closed.
// @p_removeSplitIfEmpty: whether remove the workspace and split if @p_win is that only ViewWindow left. // @p_removeSplitIfEmpty: whether remove the workspace and split if @p_win is that only ViewWindow left.
@ -212,8 +220,6 @@ namespace vnotex
QVector<ViewWindow *> getAllViewWindows(ViewSplit *p_split, const ViewSplit::ViewWindowSelector &p_func) const; QVector<ViewWindow *> getAllViewWindows(ViewSplit *p_split, const ViewSplit::ViewWindowSelector &p_func) const;
QVector<ViewWindow *> getAllViewWindows(ViewSplit *p_split) const;
void takeSnapshot(ViewAreaSession &p_session) const; void takeSnapshot(ViewAreaSession &p_session) const;
void postFirstViewSplit(); void postFirstViewSplit();
@ -226,6 +232,8 @@ namespace vnotex
ViewSplit *findSplitByDirection(ViewSplit *p_split, Direction p_direction); ViewSplit *findSplitByDirection(ViewSplit *p_split, Direction p_direction);
ViewSplit *findSplitById(ID p_splitId) const;
SplitType checkSplitType(const QSplitter *p_splitter) const; SplitType checkSplitType(const QSplitter *p_splitter) const;
void flashViewSplit(ViewSplit *p_split); void flashViewSplit(ViewSplit *p_split);

View File

@ -124,7 +124,7 @@ void ViewSplit::setupCornerWidget()
m_windowListButton->setPopupMode(QToolButton::InstantPopup); m_windowListButton->setPopupMode(QToolButton::InstantPopup);
m_windowListButton->setProperty(PropertyDefs::c_actionToolButton, true); 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); m_windowListButton->setDefaultAction(act);
auto menu = WidgetsFactory::createMenu(m_windowListButton); auto menu = WidgetsFactory::createMenu(m_windowListButton);
@ -315,6 +315,18 @@ ViewWindow *ViewSplit::getViewWindow(int p_idx) const
return dynamic_cast<ViewWindow *>(widget(p_idx)); return dynamic_cast<ViewWindow *>(widget(p_idx));
} }
QVector<ViewWindow *> ViewSplit::getAllViewWindows() const
{
QVector<ViewWindow *> 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 int ViewSplit::getViewWindowCount() const
{ {
return count(); return count();

View File

@ -49,6 +49,8 @@ namespace vnotex
void setCurrentViewWindow(int p_idx); void setCurrentViewWindow(int p_idx);
QVector<ViewWindow *> getAllViewWindows() const;
// @p_win is not deleted. // @p_win is not deleted.
void takeViewWindow(ViewWindow *p_win); void takeViewWindow(ViewWindow *p_win);

View File

@ -124,7 +124,9 @@ SOURCES += \
$$PWD/dialogs/deleteconfirmdialog.cpp \ $$PWD/dialogs/deleteconfirmdialog.cpp \
$$PWD/dialogs/importfolderutils.cpp \ $$PWD/dialogs/importfolderutils.cpp \
$$PWD/titletoolbar.cpp \ $$PWD/titletoolbar.cpp \
$$PWD/viewarea.cpp $$PWD/viewarea.cpp \
$$PWD/windowspanel.cpp \
$$PWD/windowsprovider.cpp
HEADERS += \ HEADERS += \
$$PWD/attachmentdragdropareaindicator.h \ $$PWD/attachmentdragdropareaindicator.h \
@ -256,4 +258,6 @@ HEADERS += \
$$PWD/statusbarhelper.h \ $$PWD/statusbarhelper.h \
$$PWD/dialogs/deleteconfirmdialog.h \ $$PWD/dialogs/deleteconfirmdialog.h \
$$PWD/titletoolbar.h \ $$PWD/titletoolbar.h \
$$PWD/viewarea.h $$PWD/viewarea.h \
$$PWD/windowspanel.h \
$$PWD/windowsprovider.h

View File

@ -0,0 +1,88 @@
#include "windowspanel.h"
#include <QVBoxLayout>
#include <QListWidgetItem>
#include <utils/widgetutils.h>
#include "windowsprovider.h"
#include "listwidget.h"
#include "navigationmodemgr.h"
using namespace vnotex;
WindowsPanel::WindowsPanel(const QSharedPointer<WindowsProvider> &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<QListWidget, QListWidgetItem>(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());
}

View File

@ -0,0 +1,43 @@
#ifndef WINDOWSPANEL_H
#define WINDOWSPANEL_H
#include <QFrame>
#include <QSharedPointer>
#include <QScopedPointer>
#include "navigationmodewrapper.h"
#include "windowsprovider.h"
class QListWidgetItem;
namespace vnotex
{
class ListWidget;
class WindowsPanel : public QFrame
{
Q_OBJECT
public:
WindowsPanel(const QSharedPointer<WindowsProvider> &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<WindowsProvider> m_provider;
ListWidget *m_windows = nullptr;
QScopedPointer<NavigationModeWrapper<QListWidget, QListWidgetItem>> m_navigationWrapper;
};
}
#endif // WINDOWSPANEL_H

View File

@ -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::ViewSplitWindows> WindowsProvider::getWindows() const
{
QVector<WindowsProvider::ViewSplitWindows> 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);
}

View File

@ -0,0 +1,46 @@
#ifndef WINDOWSPROVIDER_H
#define WINDOWSPROVIDER_H
#include <QObject>
#include <QVector>
#include <core/global.h>
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<WindowData> m_viewWindows;
};
explicit WindowsProvider(ViewArea *p_viewArea);
QVector<ViewSplitWindows> getWindows() const;
void setCurrentWindow(ID p_viewSplitId, int p_windowIndex);
signals:
void windowsChanged();
private:
ViewArea *m_viewArea = nullptr;
};
}
#endif // WINDOWSPROVIDER_H