Преглед на файлове

register VFileList for Navigation Mode

Support Ctrl+J and Ctrl+K navigation in VFileList.
Le Tan преди 8 години
родител
ревизия
611a695cb1
променени са 8 файла, в които са добавени 166 реда и са изтрити 18 реда
  1. 3 1
      src/vcaptain.cpp
  2. 3 3
      src/vdirectorytree.cpp
  3. 114 1
      src/vfilelist.cpp
  4. 16 1
      src/vfilelist.h
  5. 5 0
      src/vmainwindow.cpp
  6. 23 10
      src/vnote.cpp
  7. 1 1
      src/vnote.h
  8. 1 1
      src/vnotebookselector.cpp

+ 3 - 1
src/vcaptain.cpp

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

+ 3 - 3
src/vdirectorytree.cpp

@@ -726,9 +726,9 @@ void VDirectoryTree::showNavigation()
         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());
+        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);

+ 114 - 1
src/vfilelist.cpp

@@ -9,6 +9,8 @@
 #include "utils/vutils.h"
 #include "vfile.h"
 
+extern VNote *g_vnote;
+
 VFileList::VFileList(QWidget *parent)
     : QWidget(parent)
 {
@@ -461,11 +463,45 @@ bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VFile
 
 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();
         if (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);
 }
@@ -512,3 +548,80 @@ bool VFileList::identicalListWithDirectory() const
     }
     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;
+}
+

+ 16 - 1
src/vfilelist.h

@@ -7,10 +7,12 @@
 #include <QDir>
 #include <QPointer>
 #include <QListWidgetItem>
+#include <QMap>
 #include "vnotebook.h"
 #include "vconstants.h"
 #include "vdirectory.h"
 #include "vfile.h"
+#include "vnavigationmode.h"
 
 class QAction;
 class VNote;
@@ -18,8 +20,9 @@ class QListWidget;
 class QPushButton;
 class VEditArea;
 class QFocusEvent;
+class QLabel;
 
-class VFileList : public QWidget
+class VFileList : public QWidget, public VNavigationMode
 {
     Q_OBJECT
 public:
@@ -31,6 +34,12 @@ public:
     bool locateFile(const VFile *p_file);
     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:
     void fileClicked(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;
     // Check if the list items match exactly the contents of the directory.
     bool identicalListWithDirectory() const;
+    QList<QListWidgetItem *> getVisibleItems() const;
 
     VEditArea *editArea;
     QListWidget *fileList;
@@ -83,6 +93,11 @@ private:
     QAction *copyAct;
     QAction *cutAct;
     QAction *pasteAct;
+
+    // Navigation Mode.
+    // Map second key to QListWidgetItem.
+    QMap<QChar, QListWidgetItem *> m_keyMap;
+    QVector<QLabel *> m_naviLabels;
 };
 
 inline void VFileList::setEditArea(VEditArea *editArea)

+ 5 - 0
src/vmainwindow.cpp

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

+ 23 - 10
src/vnote.cpp

@@ -3,6 +3,8 @@
 #include <QJsonObject>
 #include <QJsonArray>
 #include <QDir>
+#include <QFont>
+#include <QFontMetrics>
 #include "vnote.h"
 #include "utils/vutils.h"
 #include "vconfigmanager.h"
@@ -172,16 +174,27 @@ QVector<VNotebook *> &VNote::getNotebooks()
     return m_notebooks;
 }
 
-const QString &VNote::getNavigationLabelStyle() const
+QString VNote::getNavigationLabelStyle(const QString &p_str) const
 {
-    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");
+    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;"
+                                 "font-size: %3pt;"
+                                 "font: bold;"
+                                 "font-family: %4;"
+                                 "border-radius: 3px;"
+                                 "min-width: %5px;"
+                                 "max-width: %5px;")
+                                 .arg(getColorFromPalette("logo-base"))
+                                 .arg(getColorFromPalette("logo-max"))
+                                 .arg(fontPt)
+                                 .arg(fontFamily)
+                                 .arg(pxWidth);
     return stylesheet;
 }

+ 1 - 1
src/vnote.h

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

+ 1 - 1
src/vnotebookselector.cpp

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