Browse Source

fix VOpenedListMenu with new theme

Le Tan 8 years ago
parent
commit
24349f4cc7

+ 9 - 0
src/resources/themes/v_white/v_white.qss

@@ -412,6 +412,15 @@ QLabel[ColorTealLabel="true"] {
     border-radius: 2px;
     background-color: #00796B;
 }
+
+QLabel[MenuSeparator="true"] {
+    padding-top: 5px;
+    padding-bottom: 5px;
+    margin-top: 3px;
+    font: italic;
+    border-top: 1px solid @menu_separator_bg
+}
+
 /* End QLabel */
 
 /* QLineEdit */

+ 1 - 0
src/utils/veditutils.cpp

@@ -851,6 +851,7 @@ void VEditUtils::insertTitleMark(QTextCursor &p_cursor,
                 // Remove all the prefix.
                 QRegExp prefixReg(VUtils::c_headerPrefixRegExp);
                 bool preMatched = prefixReg.exactMatch(text);
+                Q_UNUSED(preMatched);
                 Q_ASSERT(preMatched);
                 length = prefixReg.cap(1).length();
             }

+ 52 - 2
src/vbuttonmenuitem.cpp

@@ -1,15 +1,36 @@
 #include "vbuttonmenuitem.h"
 
 #include <QAction>
+#include <QPaintEvent>
+#include <QFontMetrics>
+#include <QPainter>
+#include <QRect>
 
 VButtonMenuItem::VButtonMenuItem(QAction *p_action, QWidget *p_parent)
-    : QPushButton(p_parent), m_action(p_action)
+    : QPushButton(p_parent),
+      m_action(p_action),
+      m_decorationWidth(0)
 {
     init();
 }
 
 VButtonMenuItem::VButtonMenuItem(QAction *p_action, const QString &p_text, QWidget *p_parent)
-    : QPushButton(p_text, p_parent), m_action(p_action)
+    : QPushButton(p_text, p_parent),
+      m_action(p_action),
+      m_decorationWidth(0)
+{
+    init();
+}
+
+VButtonMenuItem::VButtonMenuItem(QAction *p_action,
+                                 const QIcon &p_icon,
+                                 const QString &p_text,
+                                 const QString &p_decorationText,
+                                 QWidget *p_parent)
+    : QPushButton(p_icon, p_text, p_parent),
+      m_action(p_action),
+      m_decorationText(p_decorationText),
+      m_decorationWidth(0)
 {
     init();
 }
@@ -19,3 +40,32 @@ void VButtonMenuItem::init()
     connect(this, &QPushButton::clicked,
             m_action, &QAction::triggered);
 }
+
+void VButtonMenuItem::paintEvent(QPaintEvent *p_event)
+{
+    QPushButton::paintEvent(p_event);
+
+    if (m_decorationWidth > 0) {
+        Q_ASSERT(!m_decorationText.isEmpty());
+        QPainter painter(this);
+        painter.setRenderHint(QPainter::Antialiasing);
+        QFont font = painter.font();
+        font.setItalic(true);
+        painter.setFont(font);
+
+        QRect re = rect();
+        re.adjust(re.width() - m_decorationWidth, 0, 0, 0);
+        painter.drawText(re, Qt::AlignCenter, m_decorationText);
+    }
+}
+
+QSize VButtonMenuItem::sizeHint() const
+{
+    QSize size = QPushButton::sizeHint();
+    if (!m_decorationText.isEmpty()) {
+        const_cast<VButtonMenuItem *>(this)->m_decorationWidth = 5 + fontMetrics().width(m_decorationText);
+        size.rwidth() += m_decorationWidth;
+    }
+
+    return size;
+}

+ 18 - 0
src/vbuttonmenuitem.h

@@ -4,6 +4,7 @@
 #include <QPushButton>
 
 class QAction;
+class QPaintEvent;
 
 
 class VButtonMenuItem : public QPushButton
@@ -14,10 +15,27 @@ public:
 
     VButtonMenuItem(QAction *p_action, const QString &p_text, QWidget *p_parent = nullptr);
 
+    VButtonMenuItem(QAction *p_action,
+                    const QIcon &p_icon,
+                    const QString &p_text,
+                    const QString &p_decorationText = QString(),
+                    QWidget *p_parent = nullptr);
+
+    QSize sizeHint() const Q_DECL_OVERRIDE;
+
+protected:
+    void paintEvent(QPaintEvent *p_event) Q_DECL_OVERRIDE;
+
 private:
     void init();
 
     QAction *m_action;
+
+    // Decoration text drawn at the right end.
+    QString m_decorationText;
+
+    // Width in pixels of the decoration text.
+    int m_decorationWidth;
 };
 
 #endif // VBUTTONMENUITEM_H

+ 4 - 1
src/veditwindow.cpp

@@ -702,6 +702,7 @@ void VEditWindow::tabListJump(VFile *p_file)
     int idx = findTabByFile(p_file);
     Q_ASSERT(idx >= 0);
     setCurrentIndex(idx);
+    focusWindow();
     updateTabStatus(idx);
 }
 
@@ -1004,8 +1005,10 @@ bool VEditWindow::showOpenedFileList()
     if (count() == 0) {
         return false;
     }
+
     leftBtn->showMenu();
-    return true;
+    VOpenedListMenu *menu = dynamic_cast<VOpenedListMenu *>(leftBtn->menu());
+    return menu->isAccepted();
 }
 
 bool VEditWindow::activateTab(int p_sequence)

+ 55 - 120
src/vopenedlistmenu.cpp

@@ -6,12 +6,16 @@
 #include <QTimer>
 #include <QString>
 #include <QStyleFactory>
+#include <QWidgetAction>
+#include <QLabel>
 
 #include "veditwindow.h"
 #include "vnotefile.h"
 #include "vedittab.h"
 #include "vdirectory.h"
 #include "utils/vutils.h"
+#include "vbuttonmenuitem.h"
+#include "utils/vimnavigationforwidget.h"
 
 static const int c_cmdTime = 1 * 1000;
 
@@ -51,14 +55,11 @@ static bool fileComp(const VOpenedListMenu::ItemInfo &a,
 }
 
 VOpenedListMenu::VOpenedListMenu(VEditWindow *p_editWin)
-    : QMenu(p_editWin), m_editWin(p_editWin), m_cmdNum(0)
+    : QMenu(p_editWin),
+      m_editWin(p_editWin),
+      m_cmdNum(0),
+      m_accepted(false)
 {
-    // Force to display separator text on Windows and macOS.
-    setStyle(QStyleFactory::create("Fusion"));
-    int separatorHeight = 20 * VUtils::calculateScaleFactor();
-    QString style = QString("::separator { color: #009688; height: %1px; padding-top: 3px; }").arg(separatorHeight);
-    setStyleSheet(style);
-
     setToolTipsVisible(true);
 
     m_cmdTimer = new QTimer(this);
@@ -78,6 +79,7 @@ void VOpenedListMenu::updateOpenedList()
     // Regenerate the opened list.
     m_seqActionMap.clear();
     clear();
+    m_accepted = false;
 
     int curTab = m_editWin->currentIndex();
     int nrTab = m_editWin->count();
@@ -87,12 +89,12 @@ void VOpenedListMenu::updateOpenedList()
         files[i].index = i;
     }
 
+    Q_ASSERT(!files.isEmpty());
+
     std::sort(files.begin(), files.end(), fileComp);
 
     QString notebook;
     const VDirectory *directory = NULL;
-    QFont sepFont;
-    sepFont.setItalic(true);
     for (int i = 0; i < nrTab; ++i) {
         QPointer<VFile> file = files[i].file;
         int index = files[i].index;
@@ -108,6 +110,7 @@ void VOpenedListMenu::updateOpenedList()
             curNotebook = "EXTERNAL_FILES";
         }
 
+        QString separatorText;
         if (curNotebook != notebook
             || curDirectory != directory) {
             notebook = curNotebook;
@@ -117,28 +120,42 @@ void VOpenedListMenu::updateOpenedList()
                 dirName = directory->getName();
             }
 
-            QString text;
             if (dirName.isEmpty()) {
-                text = QString("[%1]").arg(notebook);
+                separatorText = QString("[%1]").arg(notebook);
             } else {
-                text = QString("[%1] %2").arg(notebook).arg(dirName);
+                separatorText = QString("[%1] %2").arg(notebook).arg(dirName);
             }
 
-            QAction *sepAct = addSection(text);
-            sepAct->setFont(sepFont);
+            // Add label as separator.
+            QWidgetAction *wact = new QWidgetAction(this);
+            QLabel *label = new QLabel(separatorText);
+            label->setProperty("MenuSeparator", true);
+            wact->setDefaultWidget(label);
+            wact->setSeparator(true);
+            addAction(wact);
         }
 
-        QAction *action = new QAction(m_editWin->tabIcon(index),
-                                      m_editWin->tabText(index));
-        action->setToolTip(generateDescription(file));
-        action->setData(QVariant::fromValue(file));
+        // Append the separator text to the end of the first item as well.
+        QWidgetAction *wact = new QWidgetAction(this);
+        wact->setData(QVariant::fromValue(file));
+        VButtonMenuItem *w = new VButtonMenuItem(wact,
+                                                 m_editWin->tabIcon(index),
+                                                 m_editWin->tabText(index),
+                                                 separatorText,
+                                                 this);
+        w->setToolTip(generateDescription(file));
+        wact->setDefaultWidget(w);
+
         if (index == curTab) {
-            QFont boldFont;
+            QFont boldFont = w->font();
             boldFont.setBold(true);
-            action->setFont(boldFont);
+            w->setFont(boldFont);
+
+            w->setFocus();
         }
-        addAction(action);
-        m_seqActionMap[index + c_tabSequenceBase] = action;
+
+        addAction(wact);
+        m_seqActionMap[index + c_tabSequenceBase] = wact;
     }
 }
 
@@ -159,17 +176,27 @@ QString VOpenedListMenu::generateDescription(const VFile *p_file) const
 
 void VOpenedListMenu::handleItemTriggered(QAction *p_action)
 {
-    if (!p_action) {
-        return;
+    if (p_action) {
+        QPointer<VFile> file = p_action->data().value<QPointer<VFile>>();
+        if (file) {
+            m_accepted = true;
+            emit fileTriggered(file);
+        }
     }
-    QPointer<VFile> file = p_action->data().value<QPointer<VFile>>();
-    emit fileTriggered(file);
+
+    hide();
 }
 
 void VOpenedListMenu::keyPressEvent(QKeyEvent *p_event)
 {
+    if (VimNavigationForWidget::injectKeyPressEventForVim(this,
+                                                          p_event)) {
+        m_cmdTimer->stop();
+        m_cmdNum = 0;
+        return;
+    }
+
     int key = p_event->key();
-    int modifiers = p_event->modifiers();
     switch (key) {
     case Qt::Key_0:
     case Qt::Key_1:
@@ -186,93 +213,6 @@ void VOpenedListMenu::keyPressEvent(QKeyEvent *p_event)
         return;
     }
 
-    case Qt::Key_BracketLeft:
-    {
-        m_cmdTimer->stop();
-        m_cmdNum = 0;
-        if (modifiers == Qt::ControlModifier) {
-            hide();
-            return;
-        }
-
-        break;
-    }
-
-    case Qt::Key_J:
-    {
-        m_cmdTimer->stop();
-        m_cmdNum = 0;
-        if (VUtils::isControlModifierForVim(modifiers)) {
-            QList<QAction *> acts = actions();
-            if (acts.size() == 0) {
-                return;
-            }
-            int idx = 0;
-            QAction *act = activeAction();
-            if (act) {
-                for (int i = 0; i < acts.size(); ++i) {
-                    if (acts.at(i) == act) {
-                        idx = i + 1;
-                        break;
-                    }
-                }
-            }
-            while (true) {
-                if (idx >= acts.size()) {
-                    idx = 0;
-                }
-                act = acts.at(idx);
-                if (act->isSeparator() || !act->isVisible()) {
-                    ++idx;
-                } else {
-                    break;
-                }
-            }
-            setActiveAction(act);
-            return;
-        }
-
-        break;
-    }
-
-    case Qt::Key_K:
-    {
-        m_cmdTimer->stop();
-        m_cmdNum = 0;
-        if (VUtils::isControlModifierForVim(modifiers)) {
-            QList<QAction *> acts = actions();
-            if (acts.size() == 0) {
-                return;
-            }
-
-            int idx = acts.size() - 1;
-            QAction *act = activeAction();
-            if (act) {
-                for (int i = 0; i < acts.size(); ++i) {
-                    if (acts.at(i) == act) {
-                        idx = i - 1;
-                        break;
-                    }
-                }
-            }
-            while (true) {
-                if (idx < 0) {
-                    idx = acts.size() - 1;
-                }
-                act = acts.at(idx);
-                if (act->isSeparator() || !act->isVisible()) {
-                    --idx;
-                } else {
-                    break;
-                }
-            }
-            setActiveAction(act);
-            return;
-        }
-
-        break;
-    }
-
     default:
         m_cmdTimer->stop();
         m_cmdNum = 0;
@@ -304,13 +244,8 @@ void VOpenedListMenu::addDigit(int p_digit)
             m_cmdNum = 0;
             return;
         }
-        // Set active action to the candidate.
-        auto it = m_seqActionMap.find(m_cmdNum);
-        if (it != m_seqActionMap.end()) {
-            QAction *act = it.value();
-            setActiveAction(act);
-        }
     }
+
     m_cmdTimer->start();
 }
 

+ 11 - 0
src/vopenedlistmenu.h

@@ -21,6 +21,8 @@ public:
 
     explicit VOpenedListMenu(VEditWindow *p_editWin);
 
+    bool isAccepted() const;
+
 protected:
     void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
 
@@ -39,10 +41,19 @@ private:
     void triggerItem(int p_seq);
 
     VEditWindow *m_editWin;
+
     // The number user pressed.
     int m_cmdNum;
+
     QTimer *m_cmdTimer;
     QMap<int, QAction*> m_seqActionMap;
+
+    // Whether the menu is accepted or rejected.
+    bool m_accepted;
 };
 
+inline bool VOpenedListMenu::isAccepted() const
+{
+    return m_accepted;
+}
 #endif // VOPENEDLISTMENU_H