mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
register VDirectoryTree for Navigation Mode
This commit is contained in:
parent
4bd05739c0
commit
6e0f1d38b4
@ -92,7 +92,7 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
|
|||||||
m_langCombo = new QComboBox(this);
|
m_langCombo = new QComboBox(this);
|
||||||
m_langCombo->addItem(tr("System"), "System");
|
m_langCombo->addItem(tr("System"), "System");
|
||||||
auto langs = VUtils::getAvailableLanguages();
|
auto langs = VUtils::getAvailableLanguages();
|
||||||
for (auto lang : langs) {
|
for (auto const &lang : langs) {
|
||||||
m_langCombo->addItem(lang.second, lang.first);
|
m_langCombo->addItem(lang.second, lang.first);
|
||||||
}
|
}
|
||||||
langLabel->setBuddy(m_langCombo);
|
langLabel->setBuddy(m_langCombo);
|
||||||
|
@ -319,7 +319,7 @@ const QVector<QPair<QString, QString>>& VUtils::getAvailableLanguages()
|
|||||||
|
|
||||||
bool VUtils::isValidLanguage(const QString &p_lang)
|
bool VUtils::isValidLanguage(const QString &p_lang)
|
||||||
{
|
{
|
||||||
for (auto lang : c_availableLanguages) {
|
for (auto const &lang : c_availableLanguages) {
|
||||||
if (lang.first == p_lang) {
|
if (lang.first == p_lang) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ const int c_pendingTime = 3 * 1000;
|
|||||||
|
|
||||||
VCaptain::VCaptain(VMainWindow *p_parent)
|
VCaptain::VCaptain(VMainWindow *p_parent)
|
||||||
: QWidget(p_parent), m_mainWindow(p_parent), m_mode(VCaptain::Normal),
|
: QWidget(p_parent), m_mainWindow(p_parent), m_mode(VCaptain::Normal),
|
||||||
m_widgetBeforeCaptain(NULL), m_nextMajorKey('a')
|
m_widgetBeforeCaptain(NULL), m_nextMajorKey('a'), m_ignoreFocusChange(false)
|
||||||
{
|
{
|
||||||
m_pendingTimer = new QTimer(this);
|
m_pendingTimer = new QTimer(this);
|
||||||
m_pendingTimer->setSingleShot(true);
|
m_pendingTimer->setSingleShot(true);
|
||||||
@ -62,7 +62,7 @@ void VCaptain::registerNavigationTarget(VNavigationMode *p_target)
|
|||||||
// In pending mode, if user click other widgets, we need to exit Captain mode.
|
// In pending mode, if user click other widgets, we need to exit Captain mode.
|
||||||
void VCaptain::handleFocusChanged(QWidget *p_old, QWidget * /* p_now */)
|
void VCaptain::handleFocusChanged(QWidget *p_old, QWidget * /* p_now */)
|
||||||
{
|
{
|
||||||
if (p_old == this) {
|
if (!m_ignoreFocusChange && p_old == this) {
|
||||||
exitCaptainMode();
|
exitCaptainMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,8 +124,12 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ignoreFocusChange = true;
|
||||||
|
|
||||||
if (m_mode == VCaptainMode::Navigation) {
|
if (m_mode == VCaptainMode::Navigation) {
|
||||||
return handleKeyPressNavigationMode(p_key, p_modifiers);
|
ret = handleKeyPressNavigationMode(p_key, p_modifiers);
|
||||||
|
m_ignoreFocusChange = false;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Captain mode, Ctrl key won't make a difference.
|
// In Captain mode, Ctrl key won't make a difference.
|
||||||
@ -303,25 +307,36 @@ bool VCaptain::handleKeyPressNavigationMode(int p_key,
|
|||||||
Qt::KeyboardModifiers /* p_modifiers */)
|
Qt::KeyboardModifiers /* p_modifiers */)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_mode == VCaptainMode::Navigation);
|
Q_ASSERT(m_mode == VCaptainMode::Navigation);
|
||||||
for (auto target : m_targets) {
|
bool hasConsumed = false;
|
||||||
|
bool pending = false;
|
||||||
|
for (auto &target : m_targets) {
|
||||||
|
if (hasConsumed) {
|
||||||
|
target.m_available = false;
|
||||||
|
target.m_target->hideNavigation();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (target.m_available) {
|
if (target.m_available) {
|
||||||
bool succeed = false;
|
bool succeed = false;
|
||||||
bool consumed = target.m_target->handleKeyNavigation(p_key, succeed);
|
bool consumed = target.m_target->handleKeyNavigation(p_key, succeed);
|
||||||
if (consumed) {
|
if (consumed) {
|
||||||
|
hasConsumed = true;
|
||||||
if (succeed) {
|
if (succeed) {
|
||||||
// Exit.
|
// Exit.
|
||||||
m_widgetBeforeCaptain = NULL;
|
m_widgetBeforeCaptain = NULL;
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
// Consumed but not succeed. Need more keys.
|
// Consumed but not succeed. Need more keys.
|
||||||
return true;
|
pending = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Do not ask this target any more.
|
// Do not ask this target any more.
|
||||||
target.m_available = false;
|
target.m_available = false;
|
||||||
|
target.m_target->hideNavigation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pending) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
exitCaptainMode();
|
exitCaptainMode();
|
||||||
restoreFocus();
|
restoreFocus();
|
||||||
return true;
|
return true;
|
||||||
@ -332,7 +347,7 @@ void VCaptain::triggerNavigationMode()
|
|||||||
m_pendingTimer->stop();
|
m_pendingTimer->stop();
|
||||||
m_mode = VCaptainMode::Navigation;
|
m_mode = VCaptainMode::Navigation;
|
||||||
|
|
||||||
for (auto target : m_targets) {
|
for (auto &target : m_targets) {
|
||||||
target.m_available = true;
|
target.m_available = true;
|
||||||
target.m_target->showNavigation();
|
target.m_target->showNavigation();
|
||||||
}
|
}
|
||||||
@ -342,7 +357,7 @@ void VCaptain::exitNavigationMode()
|
|||||||
{
|
{
|
||||||
m_mode = VCaptainMode::Normal;
|
m_mode = VCaptainMode::Normal;
|
||||||
|
|
||||||
for (auto target : m_targets) {
|
for (auto &target : m_targets) {
|
||||||
target.m_available = true;
|
target.m_available = true;
|
||||||
target.m_target->hideNavigation();
|
target.m_target->hideNavigation();
|
||||||
}
|
}
|
||||||
@ -383,6 +398,7 @@ void VCaptain::exitCaptainMode()
|
|||||||
}
|
}
|
||||||
m_mode = VCaptain::Normal;
|
m_mode = VCaptain::Normal;
|
||||||
m_pendingTimer->stop();
|
m_pendingTimer->stop();
|
||||||
|
m_ignoreFocusChange = false;
|
||||||
|
|
||||||
emit captainModeChanged(false);
|
emit captainModeChanged(false);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,9 @@ private:
|
|||||||
};
|
};
|
||||||
QList<NaviModeTarget> m_targets;
|
QList<NaviModeTarget> m_targets;
|
||||||
QChar m_nextMajorKey;
|
QChar m_nextMajorKey;
|
||||||
|
// Ignore focus change to avoid exiting Captain mode while handling key
|
||||||
|
// press.
|
||||||
|
bool m_ignoreFocusChange;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VCAPTAIN_H
|
#endif // VCAPTAIN_H
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
#include "veditarea.h"
|
#include "veditarea.h"
|
||||||
|
|
||||||
|
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), vnote(vnote), m_editArea(NULL)
|
||||||
{
|
{
|
||||||
@ -665,3 +667,99 @@ void VDirectoryTree::expandItemTree(QTreeWidgetItem *p_item)
|
|||||||
expandItem(p_item);
|
expandItem(p_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VDirectoryTree::registerNavigation(QChar p_majorKey)
|
||||||
|
{
|
||||||
|
m_majorKey = p_majorKey;
|
||||||
|
V_ASSERT(m_keyMap.empty());
|
||||||
|
V_ASSERT(m_naviLabels.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VDirectoryTree::showNavigation()
|
||||||
|
{
|
||||||
|
// Clean up.
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
|
||||||
|
qDebug() << key << items[i];
|
||||||
|
QLabel *label = new QLabel(QString(m_majorKey) + key, this);
|
||||||
|
label->setStyleSheet(g_vnote->getNavigationLabelStyle());
|
||||||
|
label->move(visualItemRect(items[i]).topLeft());
|
||||||
|
label->show();
|
||||||
|
m_naviLabels.append(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VDirectoryTree::hideNavigation()
|
||||||
|
{
|
||||||
|
m_keyMap.clear();
|
||||||
|
for (auto label : m_naviLabels) {
|
||||||
|
delete label;
|
||||||
|
}
|
||||||
|
m_naviLabels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VDirectoryTree::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;
|
||||||
|
auto it = m_keyMap.find(keyChar);
|
||||||
|
if (it != m_keyMap.end()) {
|
||||||
|
setCurrentItem(it.value());
|
||||||
|
setFocus();
|
||||||
|
p_succeed = true;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
} else if (keyChar == m_majorKey) {
|
||||||
|
// Major key pressed.
|
||||||
|
// Need second key.
|
||||||
|
secondKey = true;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTreeWidgetItem *> VDirectoryTree::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 *> VDirectoryTree::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;
|
||||||
|
}
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QList>
|
||||||
#include "vdirectory.h"
|
#include "vdirectory.h"
|
||||||
#include "vnotebook.h"
|
#include "vnotebook.h"
|
||||||
|
#include "vnavigationmode.h"
|
||||||
|
|
||||||
class VNote;
|
class VNote;
|
||||||
class VEditArea;
|
class VEditArea;
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
class VDirectoryTree : public QTreeWidget
|
class VDirectoryTree : public QTreeWidget, public VNavigationMode
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -20,6 +24,12 @@ public:
|
|||||||
bool locateDirectory(const VDirectory *p_directory);
|
bool locateDirectory(const VDirectory *p_directory);
|
||||||
inline const VNotebook *currentNotebook() const;
|
inline const VNotebook *currentNotebook() const;
|
||||||
|
|
||||||
|
// Implementations for VNavigationMode.
|
||||||
|
void registerNavigation(QChar p_majorKey);
|
||||||
|
void showNavigation();
|
||||||
|
void hideNavigation();
|
||||||
|
bool handleKeyNavigation(int p_key, bool &p_succeed);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentDirectoryChanged(VDirectory *p_directory);
|
void currentDirectoryChanged(VDirectory *p_directory);
|
||||||
void directoryUpdated(const VDirectory *p_directory);
|
void directoryUpdated(const VDirectory *p_directory);
|
||||||
@ -65,6 +75,8 @@ private:
|
|||||||
QTreeWidgetItem *expandToVDirectory(const VDirectory *p_directory);
|
QTreeWidgetItem *expandToVDirectory(const VDirectory *p_directory);
|
||||||
// Expand the tree under @p_item according to VDirectory.isOpened().
|
// Expand the tree under @p_item according to VDirectory.isOpened().
|
||||||
void expandItemTree(QTreeWidgetItem *p_item);
|
void expandItemTree(QTreeWidgetItem *p_item);
|
||||||
|
QList<QTreeWidgetItem *> getVisibleItems() const;
|
||||||
|
QList<QTreeWidgetItem *> getVisibleChildItems(const QTreeWidgetItem *p_item) const;
|
||||||
|
|
||||||
VNote *vnote;
|
VNote *vnote;
|
||||||
QPointer<VNotebook> m_notebook;
|
QPointer<VNotebook> m_notebook;
|
||||||
@ -80,6 +92,11 @@ private:
|
|||||||
QAction *copyAct;
|
QAction *copyAct;
|
||||||
QAction *cutAct;
|
QAction *cutAct;
|
||||||
QAction *pasteAct;
|
QAction *pasteAct;
|
||||||
|
|
||||||
|
// Navigation Mode.
|
||||||
|
// Map second key to QTreeWidgetItem.
|
||||||
|
QMap<QChar, QTreeWidgetItem *> m_keyMap;
|
||||||
|
QVector<QLabel *> m_naviLabels;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QPointer<VDirectory> VDirectoryTree::getVDirectory(QTreeWidgetItem *p_item)
|
inline QPointer<VDirectory> VDirectoryTree::getVDirectory(QTreeWidgetItem *p_item)
|
||||||
|
@ -51,6 +51,7 @@ void VMainWindow::initCaptain()
|
|||||||
this, &VMainWindow::handleCaptainModeChanged);
|
this, &VMainWindow::handleCaptainModeChanged);
|
||||||
|
|
||||||
m_captain->registerNavigationTarget(notebookSelector);
|
m_captain->registerNavigationTarget(notebookSelector);
|
||||||
|
m_captain->registerNavigationTarget(directoryTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMainWindow::setupUI()
|
void VMainWindow::setupUI()
|
||||||
|
@ -174,9 +174,14 @@ QVector<VNotebook *> &VNote::getNotebooks()
|
|||||||
|
|
||||||
const QString &VNote::getNavigationLabelStyle() const
|
const QString &VNote::getNavigationLabelStyle() const
|
||||||
{
|
{
|
||||||
static const QString stylesheet = QString("color: %1;"
|
static const QString stylesheet = QString("background-color: %1;"
|
||||||
"font-size: %2;"
|
"color: %2;"
|
||||||
"font: bold;").arg(getColorFromPalette("Red5"))
|
"font-size: %3;"
|
||||||
.arg("18pt");
|
"font: bold;"
|
||||||
|
"font-family: Monospace;"
|
||||||
|
"border-radius: 3px;")
|
||||||
|
.arg(getColorFromPalette("logo-base"))
|
||||||
|
.arg(getColorFromPalette("logo-max"))
|
||||||
|
.arg("18pt");
|
||||||
return stylesheet;
|
return stylesheet;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user