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