From 5ebc7b824392f360fbe7ab6acb5f8bd0d761e2e8 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Wed, 4 Jul 2018 19:07:43 +0800 Subject: [PATCH] Outline: support increase/decrease the expanded level Add config [global]/outline_expanded_level (6 by default). --- .../icons/decrease_outline_level.svg | 9 + .../icons/increase_outline_level.svg | 9 + src/resources/vnote.ini | 4 + src/vconfigmanager.cpp | 3 + src/vconfigmanager.h | 21 ++ src/vnote.qrc | 2 + src/voutline.cpp | 203 +++++++++++++----- src/voutline.h | 25 ++- 8 files changed, 224 insertions(+), 52 deletions(-) create mode 100644 src/resources/icons/decrease_outline_level.svg create mode 100644 src/resources/icons/increase_outline_level.svg diff --git a/src/resources/icons/decrease_outline_level.svg b/src/resources/icons/decrease_outline_level.svg new file mode 100644 index 00000000..01f101f5 --- /dev/null +++ b/src/resources/icons/decrease_outline_level.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/resources/icons/increase_outline_level.svg b/src/resources/icons/increase_outline_level.svg new file mode 100644 index 00000000..7dc602b4 --- /dev/null +++ b/src/resources/icons/increase_outline_level.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index aa0deed8..f5c814dc 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -229,6 +229,10 @@ history_size=50 ; 6 - modified time reverse note_list_view_order=0 +; Level of the heading the outline should be expanded to +; 1 - 6 +outline_expanded_level=6 + [export] ; Path of the wkhtmltopdf tool wkhtmltopdf=wkhtmltopdf diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 64c16309..d16688fa 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -300,6 +300,9 @@ void VConfigManager::initialize() if (m_historySize < 0) { m_historySize = 0; } + + m_outlineExpandedLevel = getConfigFromSettings("global", + "outline_expanded_level").toInt(); } void VConfigManager::initSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index f195c899..5be2a1ba 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -519,6 +519,9 @@ public: int getNoteListViewOrder() const; void setNoteListViewOrder(int p_order); + int getOutlineExpandedLevel() const; + void setOutlineExpandedLevel(int p_level); + private: // Look up a config from user and default settings. QVariant getConfigFromSettings(const QString §ion, const QString &key) const; @@ -935,6 +938,9 @@ private: // Whether user has reset the configurations. bool m_hasReset; + // Expanded level of outline. + int m_outlineExpandedLevel; + // The name of the config file in each directory. static const QString c_dirConfigFile; @@ -2433,4 +2439,19 @@ inline QString VConfigManager::fetchDirConfigFilePath(const QString &p_path) { return QDir(p_path).filePath(c_dirConfigFile); } + +inline int VConfigManager::getOutlineExpandedLevel() const +{ + return m_outlineExpandedLevel; +} + +inline void VConfigManager::setOutlineExpandedLevel(int p_level) +{ + if (m_outlineExpandedLevel == p_level) { + return; + } + + m_outlineExpandedLevel = p_level; + setConfigToSettings("global", "outline_expanded_level", m_outlineExpandedLevel); +} #endif // VCONFIGMANAGER_H diff --git a/src/vnote.qrc b/src/vnote.qrc index 00bf6367..4d47895c 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -263,5 +263,7 @@ resources/icons/tag.svg resources/view_image.js resources/view_image.css + resources/icons/decrease_outline_level.svg + resources/icons/increase_outline_level.svg diff --git a/src/voutline.cpp b/src/voutline.cpp index 06a2af8e..6d159d97 100644 --- a/src/voutline.cpp +++ b/src/voutline.cpp @@ -1,27 +1,111 @@ -#include -#include -#include -#include -#include #include "voutline.h" + +#include +#include + #include "utils/vutils.h" #include "vnote.h" #include "vfile.h" +#include "vtreewidget.h" +#include "utils/viconutils.h" +#include "vconfigmanager.h" +#include "vmainwindow.h" extern VNote *g_vnote; +extern VConfigManager *g_config; + +extern VMainWindow *g_mainWin; + +#define STATIC_EXPANDED_LEVEL 6 + VOutline::VOutline(QWidget *parent) - : VTreeWidget(parent), + : QWidget(parent), VNavigationMode(), m_muted(false) { - setColumnCount(1); - setHeaderHidden(true); - setSelectionMode(QAbstractItemView::SingleSelection); + setupUI(); + m_expandTimer = new QTimer(this); + m_expandTimer->setSingleShot(true); + m_expandTimer->setInterval(1000); + connect(m_expandTimer, &QTimer::timeout, + this, [this]() { + // Auto adjust items after current header change. + int level = g_config->getOutlineExpandedLevel(); + if (level == STATIC_EXPANDED_LEVEL) { + return; + } + + expandTree(level); + + QTreeWidgetItem *curItem = m_tree->currentItem(); + if (curItem) { + m_tree->scrollToItem(curItem); + } + }); +} + +void VOutline::setupUI() +{ + m_deLevelBtn = new QPushButton(VIconUtils::buttonIcon(":/resources/icons/decrease_outline_level.svg"), + "", + this); + m_deLevelBtn->setToolTip(tr("Decrease Expanded Level")); + m_deLevelBtn->setProperty("FlatBtn", true); + m_deLevelBtn->setEnabled(false); + connect(m_deLevelBtn, &QPushButton::clicked, + this, [this]() { + int level = g_config->getOutlineExpandedLevel() - 1; + if (level <= 0) { + level = 1; + } else { + g_config->setOutlineExpandedLevel(level); + expandTree(level); + } + + g_mainWin->showStatusMessage(tr("Set Outline Expanded Level to %1").arg(level)); + }); + + m_inLevelBtn = new QPushButton(VIconUtils::buttonIcon(":/resources/icons/increase_outline_level.svg"), + "", + this); + m_inLevelBtn->setToolTip(tr("Increase Expanded Level")); + m_inLevelBtn->setProperty("FlatBtn", true); + m_inLevelBtn->setEnabled(false); + connect(m_inLevelBtn, &QPushButton::clicked, + this, [this]() { + int level = g_config->getOutlineExpandedLevel() + 1; + if (level >= 7) { + level = 6; + } else { + g_config->setOutlineExpandedLevel(level); + expandTree(level); + } + + g_mainWin->showStatusMessage(tr("Set Outline Expanded Level to %1").arg(level)); + }); + + QHBoxLayout *btnLayout = new QHBoxLayout(); + btnLayout->addStretch(); + btnLayout->addWidget(m_deLevelBtn); + btnLayout->addWidget(m_inLevelBtn); + btnLayout->setContentsMargins(0, 0, 0, 0); + + m_tree = new VTreeWidget(this); + m_tree->setColumnCount(1); + m_tree->setHeaderHidden(true); + m_tree->setSelectionMode(QAbstractItemView::SingleSelection); // TODO: jump to the header when user click the same item twice. - connect(this, &VOutline::currentItemChanged, + connect(m_tree, &QTreeWidget::currentItemChanged, this, &VOutline::handleCurrentItemChanged); + + QVBoxLayout *layout = new QVBoxLayout(); + layout->addLayout(btnLayout); + layout->addWidget(m_tree); + layout->setContentsMargins(3, 0, 3, 0); + + setLayout(layout); } void VOutline::updateOutline(const VTableOfContent &p_outline) @@ -35,9 +119,11 @@ void VOutline::updateOutline(const VTableOfContent &p_outline) m_outline = p_outline; - updateTreeFromOutline(this, m_outline); + updateTreeFromOutline(m_tree, m_outline); - expandTree(); + updateButtonsState(); + + expandTree(g_config->getOutlineExpandedLevel()); } void VOutline::updateTreeFromOutline(QTreeWidget *p_treeWidget, @@ -94,13 +180,42 @@ void VOutline::fillItem(QTreeWidgetItem *p_item, const VTableOfContentItem &p_he } } -void VOutline::expandTree() +void VOutline::expandTree(int p_expandedLevel) { - if (topLevelItemCount() == 0) { + int topCount = m_tree->topLevelItemCount(); + if (topCount == 0) { return; } - expandAll(); + m_tree->collapseAll(); + + // Get the base level. + const VTableOfContentItem *header = getHeaderFromItem(m_tree->topLevelItem(0), m_outline); + if (!header) { + return; + } + + int baseLevel = header->m_level; + int levelToBeExpanded = p_expandedLevel - baseLevel; + + for (int i = 0; i < topCount; ++i) { + expandTreeOne(m_tree->topLevelItem(i), levelToBeExpanded); + } +} + +void VOutline::expandTreeOne(QTreeWidgetItem *p_item, int p_levelToBeExpanded) +{ + if (p_levelToBeExpanded <= 0) { + return; + } + + // Expand this item. + p_item->setExpanded(true); + + int nrChild = p_item->childCount(); + for (int i = 0; i < nrChild; ++i) { + expandTreeOne(p_item->child(i), p_levelToBeExpanded - 1); + } } void VOutline::handleCurrentItemChanged(QTreeWidgetItem *p_curItem, @@ -131,8 +246,10 @@ void VOutline::updateCurrentHeader(const VHeaderPointer &p_header) // Item change should not emit the signal. m_muted = true; m_currentHeader = p_header; - selectHeader(this, m_outline, m_currentHeader); + selectHeader(m_tree, m_outline, m_currentHeader); m_muted = false; + + m_expandTimer->start(); } void VOutline::selectHeader(QTreeWidget *p_treeWidget, @@ -184,59 +301,35 @@ bool VOutline::selectHeaderOne(QTreeWidget *p_treeWidget, void VOutline::keyPressEvent(QKeyEvent *event) { - int key = event->key(); - int modifiers = event->modifiers(); - - switch (key) { + switch (event->key()) { case Qt::Key_Return: + V_FALLTHROUGH; + case Qt::Key_Enter: { - QTreeWidgetItem *item = currentItem(); + QTreeWidgetItem *item = m_tree->currentItem(); if (item) { item->setExpanded(!item->isExpanded()); } - break; - } - case Qt::Key_J: - { - if (modifiers == Qt::ControlModifier) { - event->accept(); - QKeyEvent *downEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, - Qt::NoModifier); - QCoreApplication::postEvent(this, downEvent); - return; - } - break; - } - - case Qt::Key_K: - { - if (modifiers == Qt::ControlModifier) { - event->accept(); - QKeyEvent *upEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, - Qt::NoModifier); - QCoreApplication::postEvent(this, upEvent); - return; - } - break; + return; } default: break; } - VTreeWidget::keyPressEvent(event); + QWidget::keyPressEvent(event); } void VOutline::showNavigation() { - VNavigationMode::showNavigation(this); + VNavigationMode::showNavigation(m_tree); } bool VOutline::handleKeyNavigation(int p_key, bool &p_succeed) { static bool secondKey = false; - return VNavigationMode::handleKeyNavigation(this, + return VNavigationMode::handleKeyNavigation(m_tree, secondKey, p_key, p_succeed); @@ -248,3 +341,17 @@ const VTableOfContentItem *VOutline::getHeaderFromItem(QTreeWidgetItem *p_item, int index = p_item->data(0, Qt::UserRole).toInt(); return p_outline.getItem(index); } + +void VOutline::focusInEvent(QFocusEvent *p_event) +{ + QWidget::focusInEvent(p_event); + + m_tree->setFocus(); +} + +void VOutline::updateButtonsState() +{ + bool empty = m_outline.isEmpty(); + m_deLevelBtn->setEnabled(!empty); + m_inLevelBtn->setEnabled(!empty); +} diff --git a/src/voutline.h b/src/voutline.h index d462fc93..9a41e3aa 100644 --- a/src/voutline.h +++ b/src/voutline.h @@ -1,19 +1,22 @@ #ifndef VOUTLINE_H #define VOUTLINE_H +#include #include #include #include -#include "vtreewidget.h" #include "vtableofcontent.h" #include "vnavigationmode.h" class QLabel; +class VTreeWidget; +class QPushButton; +class QTimer; // Display table of content as a tree and enable user to click an item to // jump to that header. -class VOutline : public VTreeWidget, public VNavigationMode +class VOutline : public QWidget, public VNavigationMode { Q_OBJECT public: @@ -52,12 +55,22 @@ public slots: protected: void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void focusInEvent(QFocusEvent *p_event) Q_DECL_OVERRIDE; + private slots: // Handle current item change even of the tree. // Do not response if m_muted is true. void handleCurrentItemChanged(QTreeWidgetItem *p_curItem, QTreeWidgetItem *p_preItem); private: + void setupUI(); + + void expandTree(int p_expandedLevel = 6); + + void expandTreeOne(QTreeWidgetItem *p_item, int p_levelToBeExpanded); + + void updateButtonsState(); + // @index: the index in @headers. static void updateTreeByLevel(QTreeWidget *p_treeWidget, const QVector &p_headers, @@ -69,8 +82,6 @@ private: // Fill the info of @p_item. static void fillItem(QTreeWidgetItem *p_item, const VTableOfContentItem &p_header); - void expandTree(); - static bool selectHeaderOne(QTreeWidget *p_treeWidget, QTreeWidgetItem *p_item, const VTableOfContent &p_outline, @@ -82,6 +93,12 @@ private: // When true, won't emit outlineItemActivated(). bool m_muted; + + QTimer *m_expandTimer; + + QPushButton *m_deLevelBtn; + QPushButton *m_inLevelBtn; + VTreeWidget *m_tree; }; #endif // VOUTLINE_H