mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
register VEditArea and VOutline for Navigation Mode
1. Register VEditArea and VOutline for Navigation mode; 2. Support Ctrl+J and Ctrl+K navigation in VOutline;
This commit is contained in:
parent
611a695cb1
commit
ab824946e8
@ -281,6 +281,7 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
|
|||||||
case Qt::Key_W:
|
case Qt::Key_W:
|
||||||
// Enter navigation mode.
|
// Enter navigation mode.
|
||||||
triggerNavigationMode();
|
triggerNavigationMode();
|
||||||
|
m_ignoreFocusChange = false;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
case Qt::Key_X:
|
case Qt::Key_X:
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
extern VNote *g_vnote;
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent)
|
VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent)
|
||||||
: QTreeWidget(parent), vnote(vnote), m_editArea(NULL)
|
: QTreeWidget(parent), VNavigationMode(),
|
||||||
|
vnote(vnote), m_editArea(NULL)
|
||||||
{
|
{
|
||||||
setColumnCount(1);
|
setColumnCount(1);
|
||||||
setHeaderHidden(true);
|
setHeaderHidden(true);
|
||||||
@ -720,6 +721,10 @@ void VDirectoryTree::showNavigation()
|
|||||||
}
|
}
|
||||||
m_naviLabels.clear();
|
m_naviLabels.clear();
|
||||||
|
|
||||||
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate labels for visible items.
|
// Generate labels for visible items.
|
||||||
auto items = getVisibleItems();
|
auto items = getVisibleItems();
|
||||||
for (int i = 0; i < 26 && i < items.size(); ++i) {
|
for (int i = 0; i < 26 && i < items.size(); ++i) {
|
||||||
@ -752,17 +757,21 @@ bool VDirectoryTree::handleKeyNavigation(int p_key, bool &p_succeed)
|
|||||||
QChar keyChar = VUtils::keyToChar(p_key);
|
QChar keyChar = VUtils::keyToChar(p_key);
|
||||||
if (secondKey && !keyChar.isNull()) {
|
if (secondKey && !keyChar.isNull()) {
|
||||||
secondKey = false;
|
secondKey = false;
|
||||||
|
p_succeed = true;
|
||||||
|
ret = true;
|
||||||
auto it = m_keyMap.find(keyChar);
|
auto it = m_keyMap.find(keyChar);
|
||||||
if (it != m_keyMap.end()) {
|
if (it != m_keyMap.end()) {
|
||||||
setCurrentItem(it.value());
|
setCurrentItem(it.value());
|
||||||
setFocus();
|
setFocus();
|
||||||
p_succeed = true;
|
|
||||||
ret = true;
|
|
||||||
}
|
}
|
||||||
} else if (keyChar == m_majorKey) {
|
} else if (keyChar == m_majorKey) {
|
||||||
// Major key pressed.
|
// Major key pressed.
|
||||||
// Need second key.
|
// Need second key if m_keyMap is not empty.
|
||||||
secondKey = true;
|
if (m_keyMap.isEmpty()) {
|
||||||
|
p_succeed = true;
|
||||||
|
} else {
|
||||||
|
secondKey = true;
|
||||||
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
#include "vfile.h"
|
#include "vfile.h"
|
||||||
#include "dialog/vfindreplacedialog.h"
|
#include "dialog/vfindreplacedialog.h"
|
||||||
|
#include "utils/vutils.h"
|
||||||
|
|
||||||
extern VConfigManager vconfig;
|
extern VConfigManager vconfig;
|
||||||
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
VEditArea::VEditArea(VNote *vnote, QWidget *parent)
|
VEditArea::VEditArea(VNote *vnote, QWidget *parent)
|
||||||
: QWidget(parent), vnote(vnote), curWindowIndex(-1)
|
: QWidget(parent), VNavigationMode(),
|
||||||
|
vnote(vnote), curWindowIndex(-1)
|
||||||
{
|
{
|
||||||
setupUI();
|
setupUI();
|
||||||
|
|
||||||
@ -570,3 +573,74 @@ VEditWindow *VEditArea::getCurrentWindow() const
|
|||||||
}
|
}
|
||||||
return getWindow(curWindowIndex);
|
return getWindow(curWindowIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VEditArea::registerNavigation(QChar p_majorKey)
|
||||||
|
{
|
||||||
|
m_majorKey = p_majorKey;
|
||||||
|
V_ASSERT(m_keyMap.empty());
|
||||||
|
V_ASSERT(m_naviLabels.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VEditArea::showNavigation()
|
||||||
|
{
|
||||||
|
// Clean up.
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
|
||||||
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate labels for VEditWindow.
|
||||||
|
for (int i = 0; i < 26 && i < splitter->count(); ++i) {
|
||||||
|
QChar key('a' + i);
|
||||||
|
m_keyMap[key] = getWindow(i);
|
||||||
|
|
||||||
|
QString str = QString(m_majorKey) + key;
|
||||||
|
QLabel *label = new QLabel(str, this);
|
||||||
|
label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
|
||||||
|
label->move(getWindow(i)->geometry().topLeft());
|
||||||
|
label->show();
|
||||||
|
m_naviLabels.append(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VEditArea::hideNavigation()
|
||||||
|
{
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VEditArea::handleKeyNavigation(int p_key, bool &p_succeed)
|
||||||
|
{
|
||||||
|
static bool secondKey = false;
|
||||||
|
bool ret = false;
|
||||||
|
p_succeed = false;
|
||||||
|
QChar keyChar = VUtils::keyToChar(p_key);
|
||||||
|
if (secondKey && !keyChar.isNull()) {
|
||||||
|
secondKey = false;
|
||||||
|
p_succeed = true;
|
||||||
|
ret = true;
|
||||||
|
auto it = m_keyMap.find(keyChar);
|
||||||
|
if (it != m_keyMap.end()) {
|
||||||
|
setCurrentWindow(splitter->indexOf(it.value()), true);
|
||||||
|
}
|
||||||
|
} else if (keyChar == m_majorKey) {
|
||||||
|
// Major key pressed.
|
||||||
|
// Need second key if m_keyMap is not empty.
|
||||||
|
if (m_keyMap.isEmpty()) {
|
||||||
|
p_succeed = true;
|
||||||
|
} else {
|
||||||
|
secondKey = true;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,14 @@
|
|||||||
#include "vnotebook.h"
|
#include "vnotebook.h"
|
||||||
#include "veditwindow.h"
|
#include "veditwindow.h"
|
||||||
#include "vtoc.h"
|
#include "vtoc.h"
|
||||||
|
#include "vnavigationmode.h"
|
||||||
|
|
||||||
class VNote;
|
class VNote;
|
||||||
class VFile;
|
class VFile;
|
||||||
class VDirectory;
|
class VDirectory;
|
||||||
class VFindReplaceDialog;
|
class VFindReplaceDialog;
|
||||||
|
|
||||||
class VEditArea : public QWidget
|
class VEditArea : public QWidget, public VNavigationMode
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -50,6 +51,12 @@ public:
|
|||||||
void moveCurrentTabOneSplit(bool p_right);
|
void moveCurrentTabOneSplit(bool p_right);
|
||||||
VEditWindow *getCurrentWindow() const;
|
VEditWindow *getCurrentWindow() const;
|
||||||
|
|
||||||
|
// Implementations for VNavigationMode.
|
||||||
|
void registerNavigation(QChar p_majorKey);
|
||||||
|
void showNavigation();
|
||||||
|
void hideNavigation();
|
||||||
|
bool handleKeyNavigation(int p_key, bool &p_succeed);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void curTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode);
|
void curTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode);
|
||||||
void outlineChanged(const VToc &toc);
|
void outlineChanged(const VToc &toc);
|
||||||
@ -101,6 +108,11 @@ private:
|
|||||||
// Splitter holding multiple split windows
|
// Splitter holding multiple split windows
|
||||||
QSplitter *splitter;
|
QSplitter *splitter;
|
||||||
VFindReplaceDialog *m_findReplace;
|
VFindReplaceDialog *m_findReplace;
|
||||||
|
|
||||||
|
// Navigation Mode.
|
||||||
|
// Map second key to VEditWindow.
|
||||||
|
QMap<QChar, VEditWindow *> m_keyMap;
|
||||||
|
QVector<QLabel *> m_naviLabels;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline VEditWindow* VEditArea::getWindow(int windowIndex) const
|
inline VEditWindow* VEditArea::getWindow(int windowIndex) const
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
extern VNote *g_vnote;
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
VFileList::VFileList(QWidget *parent)
|
VFileList::VFileList(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent), VNavigationMode()
|
||||||
{
|
{
|
||||||
setupUI();
|
setupUI();
|
||||||
initActions();
|
initActions();
|
||||||
@ -565,6 +565,10 @@ void VFileList::showNavigation()
|
|||||||
}
|
}
|
||||||
m_naviLabels.clear();
|
m_naviLabels.clear();
|
||||||
|
|
||||||
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate labels for visible items.
|
// Generate labels for visible items.
|
||||||
auto items = getVisibleItems();
|
auto items = getVisibleItems();
|
||||||
for (int i = 0; i < 26 && i < items.size(); ++i) {
|
for (int i = 0; i < 26 && i < items.size(); ++i) {
|
||||||
@ -597,17 +601,21 @@ bool VFileList::handleKeyNavigation(int p_key, bool &p_succeed)
|
|||||||
QChar keyChar = VUtils::keyToChar(p_key);
|
QChar keyChar = VUtils::keyToChar(p_key);
|
||||||
if (secondKey && !keyChar.isNull()) {
|
if (secondKey && !keyChar.isNull()) {
|
||||||
secondKey = false;
|
secondKey = false;
|
||||||
|
p_succeed = true;
|
||||||
|
ret = true;
|
||||||
auto it = m_keyMap.find(keyChar);
|
auto it = m_keyMap.find(keyChar);
|
||||||
if (it != m_keyMap.end()) {
|
if (it != m_keyMap.end()) {
|
||||||
fileList->setCurrentItem(it.value());
|
fileList->setCurrentItem(it.value());
|
||||||
fileList->setFocus();
|
fileList->setFocus();
|
||||||
p_succeed = true;
|
|
||||||
ret = true;
|
|
||||||
}
|
}
|
||||||
} else if (keyChar == m_majorKey) {
|
} else if (keyChar == m_majorKey) {
|
||||||
// Major key pressed.
|
// Major key pressed.
|
||||||
// Need second key.
|
// Need second key if m_keyMap is not empty.
|
||||||
secondKey = true;
|
if (m_keyMap.isEmpty()) {
|
||||||
|
p_succeed = true;
|
||||||
|
} else {
|
||||||
|
secondKey = true;
|
||||||
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -53,6 +53,8 @@ void VMainWindow::initCaptain()
|
|||||||
m_captain->registerNavigationTarget(notebookSelector);
|
m_captain->registerNavigationTarget(notebookSelector);
|
||||||
m_captain->registerNavigationTarget(directoryTree);
|
m_captain->registerNavigationTarget(directoryTree);
|
||||||
m_captain->registerNavigationTarget(fileList);
|
m_captain->registerNavigationTarget(fileList);
|
||||||
|
m_captain->registerNavigationTarget(editArea);
|
||||||
|
m_captain->registerNavigationTarget(outline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMainWindow::setupUI()
|
void VMainWindow::setupUI()
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QFontDatabase>
|
||||||
#include "vnote.h"
|
#include "vnote.h"
|
||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
@ -176,25 +178,56 @@ QVector<VNotebook *> &VNote::getNotebooks()
|
|||||||
|
|
||||||
QString VNote::getNavigationLabelStyle(const QString &p_str) const
|
QString VNote::getNavigationLabelStyle(const QString &p_str) const
|
||||||
{
|
{
|
||||||
|
static int lastLen = -1;
|
||||||
|
static int pxWidth = 24;
|
||||||
int fontPt = 15;
|
int fontPt = 15;
|
||||||
QString fontFamily("Monospace");
|
QString fontFamily = getMonospacedFont();
|
||||||
QFont font(fontFamily, fontPt);
|
|
||||||
font.setBold(true);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
int pxWidth = fm.width(p_str);
|
|
||||||
|
|
||||||
QString stylesheet = QString("background-color: %1;"
|
if (p_str.size() != lastLen) {
|
||||||
"color: %2;"
|
QFont font(fontFamily, fontPt);
|
||||||
"font-size: %3pt;"
|
font.setBold(true);
|
||||||
"font: bold;"
|
QFontMetrics fm(font);
|
||||||
"font-family: %4;"
|
pxWidth = fm.width(p_str);
|
||||||
"border-radius: 3px;"
|
lastLen = p_str.size();
|
||||||
"min-width: %5px;"
|
}
|
||||||
"max-width: %5px;")
|
|
||||||
.arg(getColorFromPalette("logo-base"))
|
return QString("background-color: %1;"
|
||||||
.arg(getColorFromPalette("logo-max"))
|
"color: %2;"
|
||||||
.arg(fontPt)
|
"font-size: %3pt;"
|
||||||
.arg(fontFamily)
|
"font: bold;"
|
||||||
.arg(pxWidth);
|
"font-family: %4;"
|
||||||
return stylesheet;
|
"border-radius: 3px;"
|
||||||
|
"min-width: %5px;"
|
||||||
|
"max-width: %5px;")
|
||||||
|
.arg(getColorFromPalette("logo-base"))
|
||||||
|
.arg(getColorFromPalette("logo-max"))
|
||||||
|
.arg(fontPt)
|
||||||
|
.arg(fontFamily)
|
||||||
|
.arg(pxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &VNote::getMonospacedFont() const
|
||||||
|
{
|
||||||
|
static QString font;
|
||||||
|
if (font.isNull()) {
|
||||||
|
QStringList candidates;
|
||||||
|
candidates << "Consolas" << "Monaco" << "Andale Mono" << "Monospace" << "Courier New";
|
||||||
|
QStringList availFamilies = QFontDatabase().families();
|
||||||
|
|
||||||
|
for (int i = 0; i < candidates.size(); ++i) {
|
||||||
|
QString family = candidates[i].trimmed().toLower();
|
||||||
|
for (int j = 0; j < availFamilies.size(); ++j) {
|
||||||
|
QString availFamily = availFamilies[j];
|
||||||
|
availFamily.remove(QRegExp("\\[.*\\]"));
|
||||||
|
if (family == availFamily.trimmed().toLower()) {
|
||||||
|
font = availFamily;
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to current font.
|
||||||
|
font = QFont().family();
|
||||||
|
}
|
||||||
|
return font;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,8 @@ public slots:
|
|||||||
void updateTemplate();
|
void updateTemplate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const QString &getMonospacedFont() const;
|
||||||
|
|
||||||
// Maintain all the notebooks. Other holder should use QPointer.
|
// Maintain all the notebooks. Other holder should use QPointer.
|
||||||
QVector<VNotebook *> m_notebooks;
|
QVector<VNotebook *> m_notebooks;
|
||||||
QVector<QPair<QString, QString> > m_palette;
|
QVector<QPair<QString, QString> > m_palette;
|
||||||
|
@ -399,37 +399,41 @@ void VNotebookSelector::resizeListWidgetToContent()
|
|||||||
void VNotebookSelector::registerNavigation(QChar p_majorKey)
|
void VNotebookSelector::registerNavigation(QChar p_majorKey)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_naviLabel);
|
Q_ASSERT(!m_naviLabel);
|
||||||
qDebug() << "VNotebookSelector register for navigation key" << p_majorKey;
|
|
||||||
m_majorKey = p_majorKey;
|
m_majorKey = p_majorKey;
|
||||||
|
|
||||||
m_naviLabel = new QLabel(m_majorKey, this);
|
|
||||||
m_naviLabel->setStyleSheet(g_vnote->getNavigationLabelStyle(m_majorKey));
|
|
||||||
m_naviLabel->hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNotebookSelector::showNavigation()
|
void VNotebookSelector::showNavigation()
|
||||||
{
|
{
|
||||||
qDebug() << "VNotebookSelector show navigation";
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
V_ASSERT(!m_naviLabel);
|
||||||
|
m_naviLabel = new QLabel(m_majorKey, this);
|
||||||
|
m_naviLabel->setStyleSheet(g_vnote->getNavigationLabelStyle(m_majorKey));
|
||||||
m_naviLabel->show();
|
m_naviLabel->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNotebookSelector::hideNavigation()
|
void VNotebookSelector::hideNavigation()
|
||||||
{
|
{
|
||||||
qDebug() << "VNotebookSelector hide navigation";
|
if (m_naviLabel) {
|
||||||
m_naviLabel->hide();
|
delete m_naviLabel;
|
||||||
|
m_naviLabel = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VNotebookSelector::handleKeyNavigation(int p_key, bool &p_succeed)
|
bool VNotebookSelector::handleKeyNavigation(int p_key, bool &p_succeed)
|
||||||
{
|
{
|
||||||
qDebug() << "VNotebookSelector handle key navigation" << p_key;
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
p_succeed = false;
|
p_succeed = false;
|
||||||
QChar keyChar = VUtils::keyToChar(p_key);
|
QChar keyChar = VUtils::keyToChar(p_key);
|
||||||
if (keyChar == m_majorKey) {
|
if (keyChar == m_majorKey) {
|
||||||
// Hit.
|
// Hit.
|
||||||
p_succeed = true;
|
p_succeed = true;
|
||||||
showPopup();
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
if (m_naviLabel) {
|
||||||
|
showPopup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
149
src/voutline.cpp
149
src/voutline.cpp
@ -3,11 +3,17 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include "voutline.h"
|
#include "voutline.h"
|
||||||
#include "vtoc.h"
|
#include "vtoc.h"
|
||||||
|
#include "utils/vutils.h"
|
||||||
|
#include "vnote.h"
|
||||||
|
|
||||||
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
VOutline::VOutline(QWidget *parent)
|
VOutline::VOutline(QWidget *parent)
|
||||||
: QTreeWidget(parent)
|
: QTreeWidget(parent), VNavigationMode()
|
||||||
{
|
{
|
||||||
setColumnCount(1);
|
setColumnCount(1);
|
||||||
setHeaderHidden(true);
|
setHeaderHidden(true);
|
||||||
@ -178,11 +184,150 @@ bool VOutline::selectLineNumberOne(QTreeWidgetItem *item, int lineNumber)
|
|||||||
|
|
||||||
void VOutline::keyPressEvent(QKeyEvent *event)
|
void VOutline::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key() == Qt::Key_Return) {
|
int key = event->key();
|
||||||
|
int modifiers = event->modifiers();
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case Qt::Key_Return:
|
||||||
|
{
|
||||||
QTreeWidgetItem *item = currentItem();
|
QTreeWidgetItem *item = currentItem();
|
||||||
if (item) {
|
if (item) {
|
||||||
item->setExpanded(!item->isExpanded());
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidget::keyPressEvent(event);
|
QTreeWidget::keyPressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VOutline::registerNavigation(QChar p_majorKey)
|
||||||
|
{
|
||||||
|
m_majorKey = p_majorKey;
|
||||||
|
V_ASSERT(m_keyMap.empty());
|
||||||
|
V_ASSERT(m_naviLabels.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VOutline::showNavigation()
|
||||||
|
{
|
||||||
|
// Clean up.
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
|
||||||
|
if (!isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate labels for visible items.
|
||||||
|
auto items = getVisibleItems();
|
||||||
|
for (int i = 0; i < 26 && i < items.size(); ++i) {
|
||||||
|
QChar key('a' + i);
|
||||||
|
m_keyMap[key] = items[i];
|
||||||
|
|
||||||
|
QString str = QString(m_majorKey) + key;
|
||||||
|
QLabel *label = new QLabel(str, this);
|
||||||
|
label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
|
||||||
|
label->move(visualItemRect(items[i]).topLeft());
|
||||||
|
label->show();
|
||||||
|
m_naviLabels.append(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VOutline::hideNavigation()
|
||||||
|
{
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VOutline::handleKeyNavigation(int p_key, bool &p_succeed)
|
||||||
|
{
|
||||||
|
static bool secondKey = false;
|
||||||
|
bool ret = false;
|
||||||
|
p_succeed = false;
|
||||||
|
QChar keyChar = VUtils::keyToChar(p_key);
|
||||||
|
if (secondKey && !keyChar.isNull()) {
|
||||||
|
secondKey = false;
|
||||||
|
p_succeed = true;
|
||||||
|
ret = true;
|
||||||
|
auto it = m_keyMap.find(keyChar);
|
||||||
|
if (it != m_keyMap.end()) {
|
||||||
|
setCurrentItem(it.value());
|
||||||
|
setFocus();
|
||||||
|
}
|
||||||
|
} else if (keyChar == m_majorKey) {
|
||||||
|
// Major key pressed.
|
||||||
|
// Need second key if m_keyMap is not empty.
|
||||||
|
if (m_keyMap.isEmpty()) {
|
||||||
|
p_succeed = true;
|
||||||
|
} else {
|
||||||
|
secondKey = true;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem *> VOutline::getVisibleItems() const
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem *> items;
|
||||||
|
for (int i = 0; i < topLevelItemCount(); ++i) {
|
||||||
|
QTreeWidgetItem *item = topLevelItem(i);
|
||||||
|
if (!item->isHidden()) {
|
||||||
|
items.append(item);
|
||||||
|
if (item->isExpanded()) {
|
||||||
|
items.append(getVisibleChildItems(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem *> VOutline::getVisibleChildItems(const QTreeWidgetItem *p_item) const
|
||||||
|
{
|
||||||
|
QList<QTreeWidgetItem *> items;
|
||||||
|
if (p_item && !p_item->isHidden() && p_item->isExpanded()) {
|
||||||
|
for (int i = 0; i < p_item->childCount(); ++i) {
|
||||||
|
QTreeWidgetItem *child = p_item->child(i);
|
||||||
|
if (!child->isHidden()) {
|
||||||
|
items.append(child);
|
||||||
|
if (child->isExpanded()) {
|
||||||
|
items.append(getVisibleChildItems(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
@ -2,14 +2,26 @@
|
|||||||
#define VOUTLINE_H
|
#define VOUTLINE_H
|
||||||
|
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QChar>
|
||||||
#include "vtoc.h"
|
#include "vtoc.h"
|
||||||
|
#include "vnavigationmode.h"
|
||||||
|
|
||||||
class VOutline : public QTreeWidget
|
class QLabel;
|
||||||
|
|
||||||
|
class VOutline : public QTreeWidget, public VNavigationMode
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
VOutline(QWidget *parent = 0);
|
VOutline(QWidget *parent = 0);
|
||||||
|
|
||||||
|
// Implementations for VNavigationMode.
|
||||||
|
void registerNavigation(QChar p_majorKey);
|
||||||
|
void showNavigation();
|
||||||
|
void hideNavigation();
|
||||||
|
bool handleKeyNavigation(int p_key, bool &p_succeed);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void outlineItemActivated(const VAnchor &anchor);
|
void outlineItemActivated(const VAnchor &anchor);
|
||||||
|
|
||||||
@ -32,9 +44,16 @@ private:
|
|||||||
bool selectAnchorOne(QTreeWidgetItem *item, const QString &anchor);
|
bool selectAnchorOne(QTreeWidgetItem *item, const QString &anchor);
|
||||||
void selectLineNumber(int lineNumber);
|
void selectLineNumber(int lineNumber);
|
||||||
bool selectLineNumberOne(QTreeWidgetItem *item, int lineNumber);
|
bool selectLineNumberOne(QTreeWidgetItem *item, int lineNumber);
|
||||||
|
QList<QTreeWidgetItem *> getVisibleItems() const;
|
||||||
|
QList<QTreeWidgetItem *> getVisibleChildItems(const QTreeWidgetItem *p_item) const;
|
||||||
|
|
||||||
VToc outline;
|
VToc outline;
|
||||||
VAnchor curHeader;
|
VAnchor curHeader;
|
||||||
|
|
||||||
|
// Navigation Mode.
|
||||||
|
// Map second key to QTreeWidgetItem.
|
||||||
|
QMap<QChar, QTreeWidgetItem *> m_keyMap;
|
||||||
|
QVector<QLabel *> m_naviLabels;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VOUTLINE_H
|
#endif // VOUTLINE_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user