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->addItem(tr("System"), "System");
|
||||
auto langs = VUtils::getAvailableLanguages();
|
||||
for (auto lang : langs) {
|
||||
for (auto const &lang : langs) {
|
||||
m_langCombo->addItem(lang.second, lang.first);
|
||||
}
|
||||
langLabel->setBuddy(m_langCombo);
|
||||
|
@ -319,7 +319,7 @@ const QVector<QPair<QString, QString>>& VUtils::getAvailableLanguages()
|
||||
|
||||
bool VUtils::isValidLanguage(const QString &p_lang)
|
||||
{
|
||||
for (auto lang : c_availableLanguages) {
|
||||
for (auto const &lang : c_availableLanguages) {
|
||||
if (lang.first == p_lang) {
|
||||
return true;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ const int c_pendingTime = 3 * 1000;
|
||||
|
||||
VCaptain::VCaptain(VMainWindow *p_parent)
|
||||
: 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->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.
|
||||
void VCaptain::handleFocusChanged(QWidget *p_old, QWidget * /* p_now */)
|
||||
{
|
||||
if (p_old == this) {
|
||||
if (!m_ignoreFocusChange && p_old == this) {
|
||||
exitCaptainMode();
|
||||
}
|
||||
}
|
||||
@ -124,8 +124,12 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
m_ignoreFocusChange = true;
|
||||
|
||||
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.
|
||||
@ -303,25 +307,36 @@ bool VCaptain::handleKeyPressNavigationMode(int p_key,
|
||||
Qt::KeyboardModifiers /* p_modifiers */)
|
||||
{
|
||||
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) {
|
||||
bool succeed = false;
|
||||
bool consumed = target.m_target->handleKeyNavigation(p_key, succeed);
|
||||
if (consumed) {
|
||||
hasConsumed = true;
|
||||
if (succeed) {
|
||||
// Exit.
|
||||
m_widgetBeforeCaptain = NULL;
|
||||
break;
|
||||
} else {
|
||||
// Consumed but not succeed. Need more keys.
|
||||
return true;
|
||||
pending = true;
|
||||
}
|
||||
} else {
|
||||
// Do not ask this target any more.
|
||||
target.m_available = false;
|
||||
target.m_target->hideNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pending) {
|
||||
return true;
|
||||
}
|
||||
exitCaptainMode();
|
||||
restoreFocus();
|
||||
return true;
|
||||
@ -332,7 +347,7 @@ void VCaptain::triggerNavigationMode()
|
||||
m_pendingTimer->stop();
|
||||
m_mode = VCaptainMode::Navigation;
|
||||
|
||||
for (auto target : m_targets) {
|
||||
for (auto &target : m_targets) {
|
||||
target.m_available = true;
|
||||
target.m_target->showNavigation();
|
||||
}
|
||||
@ -342,7 +357,7 @@ void VCaptain::exitNavigationMode()
|
||||
{
|
||||
m_mode = VCaptainMode::Normal;
|
||||
|
||||
for (auto target : m_targets) {
|
||||
for (auto &target : m_targets) {
|
||||
target.m_available = true;
|
||||
target.m_target->hideNavigation();
|
||||
}
|
||||
@ -383,6 +398,7 @@ void VCaptain::exitCaptainMode()
|
||||
}
|
||||
m_mode = VCaptain::Normal;
|
||||
m_pendingTimer->stop();
|
||||
m_ignoreFocusChange = false;
|
||||
|
||||
emit captainModeChanged(false);
|
||||
}
|
||||
|
@ -69,6 +69,9 @@ private:
|
||||
};
|
||||
QList<NaviModeTarget> m_targets;
|
||||
QChar m_nextMajorKey;
|
||||
// Ignore focus change to avoid exiting Captain mode while handling key
|
||||
// press.
|
||||
bool m_ignoreFocusChange;
|
||||
};
|
||||
|
||||
#endif // VCAPTAIN_H
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "utils/vutils.h"
|
||||
#include "veditarea.h"
|
||||
|
||||
extern VNote *g_vnote;
|
||||
|
||||
VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent)
|
||||
: QTreeWidget(parent), vnote(vnote), m_editArea(NULL)
|
||||
{
|
||||
@ -665,3 +667,99 @@ void VDirectoryTree::expandItemTree(QTreeWidgetItem *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 <QPointer>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
#include "vdirectory.h"
|
||||
#include "vnotebook.h"
|
||||
#include "vnavigationmode.h"
|
||||
|
||||
class VNote;
|
||||
class VEditArea;
|
||||
class QLabel;
|
||||
|
||||
class VDirectoryTree : public QTreeWidget
|
||||
class VDirectoryTree : public QTreeWidget, public VNavigationMode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -20,6 +24,12 @@ public:
|
||||
bool locateDirectory(const VDirectory *p_directory);
|
||||
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:
|
||||
void currentDirectoryChanged(VDirectory *p_directory);
|
||||
void directoryUpdated(const VDirectory *p_directory);
|
||||
@ -65,6 +75,8 @@ private:
|
||||
QTreeWidgetItem *expandToVDirectory(const VDirectory *p_directory);
|
||||
// Expand the tree under @p_item according to VDirectory.isOpened().
|
||||
void expandItemTree(QTreeWidgetItem *p_item);
|
||||
QList<QTreeWidgetItem *> getVisibleItems() const;
|
||||
QList<QTreeWidgetItem *> getVisibleChildItems(const QTreeWidgetItem *p_item) const;
|
||||
|
||||
VNote *vnote;
|
||||
QPointer<VNotebook> m_notebook;
|
||||
@ -80,6 +92,11 @@ private:
|
||||
QAction *copyAct;
|
||||
QAction *cutAct;
|
||||
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)
|
||||
|
@ -51,6 +51,7 @@ void VMainWindow::initCaptain()
|
||||
this, &VMainWindow::handleCaptainModeChanged);
|
||||
|
||||
m_captain->registerNavigationTarget(notebookSelector);
|
||||
m_captain->registerNavigationTarget(directoryTree);
|
||||
}
|
||||
|
||||
void VMainWindow::setupUI()
|
||||
|
@ -174,9 +174,14 @@ QVector<VNotebook *> &VNote::getNotebooks()
|
||||
|
||||
const QString &VNote::getNavigationLabelStyle() const
|
||||
{
|
||||
static const QString stylesheet = QString("color: %1;"
|
||||
"font-size: %2;"
|
||||
"font: bold;").arg(getColorFromPalette("Red5"))
|
||||
.arg("18pt");
|
||||
static const QString stylesheet = QString("background-color: %1;"
|
||||
"color: %2;"
|
||||
"font-size: %3;"
|
||||
"font: bold;"
|
||||
"font-family: Monospace;"
|
||||
"border-radius: 3px;")
|
||||
.arg(getColorFromPalette("logo-base"))
|
||||
.arg(getColorFromPalette("logo-max"))
|
||||
.arg("18pt");
|
||||
return stylesheet;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user