register VFileList for Navigation Mode

Support Ctrl+J and Ctrl+K navigation in VFileList.
This commit is contained in:
Le Tan 2017-04-05 23:31:03 +08:00
parent 3ca968169f
commit 611a695cb1
8 changed files with 166 additions and 18 deletions

View File

@ -251,7 +251,9 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
case Qt::Key_Q: case Qt::Key_Q:
// Discard changes and exit edit mode. // Discard changes and exit edit mode.
if (m_mainWindow->m_curFile) {
m_mainWindow->discardExitAct->trigger(); m_mainWindow->discardExitAct->trigger();
}
break; break;
case Qt::Key_R: case Qt::Key_R:

View File

@ -726,9 +726,9 @@ void VDirectoryTree::showNavigation()
QChar key('a' + i); QChar key('a' + i);
m_keyMap[key] = items[i]; m_keyMap[key] = items[i];
qDebug() << key << items[i]; QString str = QString(m_majorKey) + key;
QLabel *label = new QLabel(QString(m_majorKey) + key, this); QLabel *label = new QLabel(str, this);
label->setStyleSheet(g_vnote->getNavigationLabelStyle()); label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
label->move(visualItemRect(items[i]).topLeft()); label->move(visualItemRect(items[i]).topLeft());
label->show(); label->show();
m_naviLabels.append(label); m_naviLabels.append(label);

View File

@ -9,6 +9,8 @@
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vfile.h" #include "vfile.h"
extern VNote *g_vnote;
VFileList::VFileList(QWidget *parent) VFileList::VFileList(QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
@ -461,11 +463,45 @@ bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VFile
void VFileList::keyPressEvent(QKeyEvent *event) void VFileList::keyPressEvent(QKeyEvent *event)
{ {
if (event->key() == Qt::Key_Return) { int key = event->key();
int modifiers = event->modifiers();
switch (key) {
case Qt::Key_Return:
{
QListWidgetItem *item = fileList->currentItem(); QListWidgetItem *item = fileList->currentItem();
if (item) { if (item) {
handleItemClicked(item); handleItemClicked(item);
} }
break;
}
case Qt::Key_J:
{
if (modifiers == Qt::ControlModifier) {
event->accept();
QKeyEvent *downEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down,
Qt::NoModifier);
QCoreApplication::postEvent(fileList, 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(fileList, upEvent);
return;
}
break;
}
default:
break;
} }
QWidget::keyPressEvent(event); QWidget::keyPressEvent(event);
} }
@ -512,3 +548,80 @@ bool VFileList::identicalListWithDirectory() const
} }
return true; return true;
} }
void VFileList::registerNavigation(QChar p_majorKey)
{
m_majorKey = p_majorKey;
V_ASSERT(m_keyMap.empty());
V_ASSERT(m_naviLabels.empty());
}
void VFileList::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];
QString str = QString(m_majorKey) + key;
QLabel *label = new QLabel(str, this);
label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
label->move(fileList->visualItemRect(items[i]).topLeft());
label->show();
m_naviLabels.append(label);
}
}
void VFileList::hideNavigation()
{
m_keyMap.clear();
for (auto label : m_naviLabels) {
delete label;
}
m_naviLabels.clear();
}
bool VFileList::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()) {
fileList->setCurrentItem(it.value());
fileList->setFocus();
p_succeed = true;
ret = true;
}
} else if (keyChar == m_majorKey) {
// Major key pressed.
// Need second key.
secondKey = true;
ret = true;
}
return ret;
}
QList<QListWidgetItem *> VFileList::getVisibleItems() const
{
QList<QListWidgetItem *> items;
for (int i = 0; i < fileList->count(); ++i) {
QListWidgetItem *item = fileList->item(i);
if (!item->isHidden()) {
items.append(item);
}
}
return items;
}

View File

@ -7,10 +7,12 @@
#include <QDir> #include <QDir>
#include <QPointer> #include <QPointer>
#include <QListWidgetItem> #include <QListWidgetItem>
#include <QMap>
#include "vnotebook.h" #include "vnotebook.h"
#include "vconstants.h" #include "vconstants.h"
#include "vdirectory.h" #include "vdirectory.h"
#include "vfile.h" #include "vfile.h"
#include "vnavigationmode.h"
class QAction; class QAction;
class VNote; class VNote;
@ -18,8 +20,9 @@ class QListWidget;
class QPushButton; class QPushButton;
class VEditArea; class VEditArea;
class QFocusEvent; class QFocusEvent;
class QLabel;
class VFileList : public QWidget class VFileList : public QWidget, public VNavigationMode
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -31,6 +34,12 @@ public:
bool locateFile(const VFile *p_file); bool locateFile(const VFile *p_file);
inline const VDirectory *currentDirectory() const; inline const VDirectory *currentDirectory() const;
// Implementations for VNavigationMode.
void registerNavigation(QChar p_majorKey);
void showNavigation();
void hideNavigation();
bool handleKeyNavigation(int p_key, bool &p_succeed);
signals: signals:
void fileClicked(VFile *p_file, OpenFileMode mode = OpenFileMode::Read); void fileClicked(VFile *p_file, OpenFileMode mode = OpenFileMode::Read);
void fileCreated(VFile *p_file, OpenFileMode mode = OpenFileMode::Read); void fileCreated(VFile *p_file, OpenFileMode mode = OpenFileMode::Read);
@ -70,6 +79,7 @@ private:
inline QPointer<VFile> getVFile(QListWidgetItem *p_item) const; inline QPointer<VFile> getVFile(QListWidgetItem *p_item) const;
// Check if the list items match exactly the contents of the directory. // Check if the list items match exactly the contents of the directory.
bool identicalListWithDirectory() const; bool identicalListWithDirectory() const;
QList<QListWidgetItem *> getVisibleItems() const;
VEditArea *editArea; VEditArea *editArea;
QListWidget *fileList; QListWidget *fileList;
@ -83,6 +93,11 @@ private:
QAction *copyAct; QAction *copyAct;
QAction *cutAct; QAction *cutAct;
QAction *pasteAct; QAction *pasteAct;
// Navigation Mode.
// Map second key to QListWidgetItem.
QMap<QChar, QListWidgetItem *> m_keyMap;
QVector<QLabel *> m_naviLabels;
}; };
inline void VFileList::setEditArea(VEditArea *editArea) inline void VFileList::setEditArea(VEditArea *editArea)

View File

@ -52,6 +52,7 @@ void VMainWindow::initCaptain()
m_captain->registerNavigationTarget(notebookSelector); m_captain->registerNavigationTarget(notebookSelector);
m_captain->registerNavigationTarget(directoryTree); m_captain->registerNavigationTarget(directoryTree);
m_captain->registerNavigationTarget(fileList);
} }
void VMainWindow::setupUI() void VMainWindow::setupUI()
@ -250,6 +251,7 @@ void VMainWindow::initFileToolBar()
deleteNoteAct->setEnabled(false); deleteNoteAct->setEnabled(false);
editNoteAct->setVisible(false); editNoteAct->setVisible(false);
saveExitAct->setVisible(false); saveExitAct->setVisible(false);
discardExitAct->setVisible(false);
saveNoteAct->setVisible(false); saveNoteAct->setVisible(false);
fileToolBar->addAction(newRootDirAct); fileToolBar->addAction(newRootDirAct);
@ -785,6 +787,7 @@ void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
if (p_file) { if (p_file) {
if (p_editMode) { if (p_editMode) {
editNoteAct->setVisible(false); editNoteAct->setVisible(false);
discardExitAct->setVisible(true);
saveExitAct->setVisible(true); saveExitAct->setVisible(true);
saveNoteAct->setVisible(true); saveNoteAct->setVisible(true);
deleteNoteAct->setEnabled(true); deleteNoteAct->setEnabled(true);
@ -792,6 +795,7 @@ void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
m_insertImageAct->setEnabled(true); m_insertImageAct->setEnabled(true);
} else { } else {
editNoteAct->setVisible(true); editNoteAct->setVisible(true);
discardExitAct->setVisible(false);
saveExitAct->setVisible(false); saveExitAct->setVisible(false);
saveNoteAct->setVisible(false); saveNoteAct->setVisible(false);
deleteNoteAct->setEnabled(true); deleteNoteAct->setEnabled(true);
@ -806,6 +810,7 @@ void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
m_findReplaceAct->setEnabled(true); m_findReplaceAct->setEnabled(true);
} else { } else {
editNoteAct->setVisible(false); editNoteAct->setVisible(false);
discardExitAct->setVisible(false);
saveExitAct->setVisible(false); saveExitAct->setVisible(false);
saveNoteAct->setVisible(false); saveNoteAct->setVisible(false);
deleteNoteAct->setEnabled(false); deleteNoteAct->setEnabled(false);

View File

@ -3,6 +3,8 @@
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include <QDir> #include <QDir>
#include <QFont>
#include <QFontMetrics>
#include "vnote.h" #include "vnote.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
@ -172,16 +174,27 @@ QVector<VNotebook *> &VNote::getNotebooks()
return m_notebooks; return m_notebooks;
} }
const QString &VNote::getNavigationLabelStyle() const QString VNote::getNavigationLabelStyle(const QString &p_str) const
{ {
static const QString stylesheet = QString("background-color: %1;" int fontPt = 15;
QString fontFamily("Monospace");
QFont font(fontFamily, fontPt);
font.setBold(true);
QFontMetrics fm(font);
int pxWidth = fm.width(p_str);
QString stylesheet = QString("background-color: %1;"
"color: %2;" "color: %2;"
"font-size: %3;" "font-size: %3pt;"
"font: bold;" "font: bold;"
"font-family: Monospace;" "font-family: %4;"
"border-radius: 3px;") "border-radius: 3px;"
"min-width: %5px;"
"max-width: %5px;")
.arg(getColorFromPalette("logo-base")) .arg(getColorFromPalette("logo-base"))
.arg(getColorFromPalette("logo-max")) .arg(getColorFromPalette("logo-max"))
.arg("18pt"); .arg(fontPt)
.arg(fontFamily)
.arg(pxWidth);
return stylesheet; return stylesheet;
} }

View File

@ -54,7 +54,7 @@ public:
QString getColorFromPalette(const QString &p_name) const; QString getColorFromPalette(const QString &p_name) const;
inline VMainWindow *getMainWindow() const; inline VMainWindow *getMainWindow() const;
const QString &getNavigationLabelStyle() const; QString getNavigationLabelStyle(const QString &p_str) const;
public slots: public slots:
void updateTemplate(); void updateTemplate();

View File

@ -403,7 +403,7 @@ void VNotebookSelector::registerNavigation(QChar p_majorKey)
m_majorKey = p_majorKey; m_majorKey = p_majorKey;
m_naviLabel = new QLabel(m_majorKey, this); m_naviLabel = new QLabel(m_majorKey, this);
m_naviLabel->setStyleSheet(g_vnote->getNavigationLabelStyle()); m_naviLabel->setStyleSheet(g_vnote->getNavigationLabelStyle(m_majorKey));
m_naviLabel->hide(); m_naviLabel->hide();
} }