Browse Source

VFileList: support specifying different view orders

Le Tan 7 years ago
parent
commit
a98757643f
7 changed files with 251 additions and 36 deletions
  1. 15 0
      src/resources/icons/view.svg
  2. 10 0
      src/resources/vnote.ini
  3. 1 0
      src/vconfigmanager.cpp
  4. 28 3
      src/vconfigmanager.h
  5. 173 30
      src/vfilelist.cpp
  6. 23 3
      src/vfilelist.h
  7. 1 0
      src/vnote.qrc

+ 15 - 0
src/resources/icons/view.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+	<path fill="#000000" d="M256,128c-81.9,0-145.7,48.8-224,128c67.4,67.7,124,128,224,128c99.9,0,173.4-76.4,224-126.6
+		C428.2,198.6,354.8,128,256,128z M256,347.3c-49.4,0-89.6-41-89.6-91.3c0-50.4,40.2-91.3,89.6-91.3s89.6,41,89.6,91.3
+		C345.6,306.4,305.4,347.3,256,347.3z"/>
+	<g>
+		<path fill="#000000" d="M256,224c0-7.9,2.9-15.1,7.6-20.7c-2.5-0.4-5-0.6-7.6-0.6c-28.8,0-52.3,23.9-52.3,53.3c0,29.4,23.5,53.3,52.3,53.3
+			s52.3-23.9,52.3-53.3c0-2.3-0.2-4.6-0.4-6.9c-5.5,4.3-12.3,6.9-19.8,6.9C270.3,256,256,241.7,256,224z"/>
+	</g>
+</g>
+</svg>

+ 10 - 0
src/resources/vnote.ini

@@ -213,6 +213,16 @@ search_options=4,2,7,0,0,""
 ; 0 to disable history
 history_size=50
 
+; View order of note list
+; 0 - configuration file
+; 1 - name
+; 2 - name reverse
+; 3 - created time
+; 4 - created time reverse
+; 5 - modified time
+; 6 - modified time reverse
+note_list_view_order=0
+
 [export]
 ; Path of the wkhtmltopdf tool
 wkhtmltopdf=wkhtmltopdf

+ 1 - 0
src/vconfigmanager.cpp

@@ -51,6 +51,7 @@ const QString VConfigManager::c_exportFolderName = QString("vnote_exports");
 
 VConfigManager::VConfigManager(QObject *p_parent)
     : QObject(p_parent),
+      m_noteListViewOrder(-1),
       m_hasReset(false),
       userSettings(NULL),
       defaultSettings(NULL),

+ 28 - 3
src/vconfigmanager.h

@@ -490,6 +490,9 @@ public:
     const QString &getGraphvizDot() const;
     void setGraphvizDot(const QString &p_dotPath);
 
+    int getNoteListViewOrder() const;
+    void setNoteListViewOrder(int p_order);
+
 private:
     // Look up a config from user and default settings.
     QVariant getConfigFromSettings(const QString &section, const QString &key) const;
@@ -870,9 +873,6 @@ private:
     // Whether close note before open it via external editor.
     bool m_closeBeforeExternalEditor;
 
-    // Whether user has reset the configurations.
-    bool m_hasReset;
-
     // The string containing styles to inline when copied in edit mode.
     QString m_stylesToInlineWhenCopied;
 
@@ -896,6 +896,12 @@ private:
     // Size of history.
     int m_historySize;
 
+    // View order of note list.
+    int m_noteListViewOrder;
+
+    // Whether user has reset the configurations.
+    bool m_hasReset;
+
     // The name of the config file in each directory, obsolete.
     // Use c_dirConfigFile instead.
     static const QString c_obsoleteDirConfigFile;
@@ -2301,4 +2307,23 @@ inline int VConfigManager::getHistorySize() const
 {
     return m_historySize;
 }
+
+inline int VConfigManager::getNoteListViewOrder() const
+{
+    if (m_noteListViewOrder == -1) {
+        const_cast<VConfigManager *>(this)->m_noteListViewOrder = getConfigFromSettings("global", "note_list_view_order").toInt();
+    }
+
+    return m_noteListViewOrder;
+}
+
+inline void VConfigManager::setNoteListViewOrder(int p_order)
+{
+    if (m_noteListViewOrder == p_order) {
+        return;
+    }
+
+    m_noteListViewOrder = p_order;
+    setConfigToSettings("global", "note_list_view_order", m_noteListViewOrder);
+}
 #endif // VCONFIGMANAGER_H

+ 173 - 30
src/vfilelist.cpp

@@ -66,10 +66,22 @@ void VFileList::setupUI()
     QLabel *titleLabel = new QLabel(tr("Notes"), this);
     titleLabel->setProperty("TitleLabel", true);
 
+    QPushButton *viewBtn = new QPushButton(VIconUtils::buttonIcon(":/resources/icons/view.svg"), "", this);
+    viewBtn->setToolTip(tr("View"));
+    viewBtn->setProperty("CornerBtn", true);
+
+    QMenu *viewMenu = new QMenu(this);
+    connect(viewMenu, &QMenu::aboutToShow,
+            this, [this, viewMenu]() {
+                updateViewMenu(viewMenu);
+            });
+    viewBtn->setMenu(viewMenu);
+
     m_numLabel = new QLabel(this);
 
     QHBoxLayout *titleLayout = new QHBoxLayout();
     titleLayout->addWidget(titleLabel);
+    titleLayout->addWidget(viewBtn);
     titleLayout->addStretch();
     titleLayout->addWidget(m_numLabel);
 
@@ -156,7 +168,9 @@ void VFileList::updateFileList()
         return;
     }
 
-    const QVector<VNoteFile *> &files = m_directory->getFiles();
+    QVector<VNoteFile *> files = m_directory->getFiles();
+    sortFiles(files, (ViewOrder)g_config->getNoteListViewOrder());
+
     for (int i = 0; i < files.size(); ++i) {
         VNoteFile *file = files[i];
         insertFileListItem(file);
@@ -359,11 +373,9 @@ void VFileList::newFile()
             }
         }
 
-        QVector<QListWidgetItem *> items = updateFileListAdded();
-        Q_ASSERT(items.size() == 1);
-        fileList->setCurrentItem(items[0], QItemSelectionModel::ClearAndSelect);
-        // Qt seems not to update the QListWidget correctly. Manually force it to repaint.
-        fileList->update();
+        updateFileList();
+
+        locateFile(file);
 
         // Open it in edit mode
         emit fileCreated(file, OpenFileMode::Edit, true);
@@ -383,27 +395,6 @@ void VFileList::newFile()
     }
 }
 
-QVector<QListWidgetItem *> VFileList::updateFileListAdded()
-{
-    QVector<QListWidgetItem *> ret;
-    const QVector<VNoteFile *> &files = m_directory->getFiles();
-    for (int i = 0; i < files.size(); ++i) {
-        VNoteFile *file = files[i];
-        if (i >= fileList->count()) {
-            QListWidgetItem *item = insertFileListItem(file, false);
-            ret.append(item);
-        } else {
-            VNoteFile *itemFile = getVFile(fileList->item(i));
-            if (itemFile != file) {
-                QListWidgetItem *item = insertFileListItem(file, false);
-                ret.append(item);
-            }
-        }
-    }
-
-    return ret;
-}
-
 void VFileList::deleteSelectedFiles()
 {
     QList<QListWidgetItem *> items = fileList->selectedItems();
@@ -500,6 +491,7 @@ void VFileList::deleteFiles(const QVector<VNoteFile *> &p_files)
             g_mainWin->showStatusMessage(tr("%1 %2 deleted")
                                            .arg(nrDeleted)
                                            .arg(nrDeleted > 1 ? tr("notes") : tr("note")));
+            updateNumberLabel();
         }
     }
 }
@@ -760,7 +752,7 @@ bool VFileList::importFiles(const QStringList &p_files, QString *p_errMsg)
     QString dirPath = m_directory->fetchPath();
     QDir dir(dirPath);
 
-    int nrImported = 0;
+    QVector<VNoteFile *> importedFiles;
     for (int i = 0; i < p_files.size(); ++i) {
         const QString &file = p_files[i];
 
@@ -799,7 +791,7 @@ bool VFileList::importFiles(const QStringList &p_files, QString *p_errMsg)
 
         VNoteFile *destFile = m_directory->addFile(name, -1);
         if (destFile) {
-            ++nrImported;
+            importedFiles.append(destFile);
             qDebug() << "imported" << file << "as" << targetFilePath;
         } else {
             VUtils::addErrMsg(p_errMsg, tr("Fail to add the note %1 to target folder's configuration.")
@@ -809,10 +801,12 @@ bool VFileList::importFiles(const QStringList &p_files, QString *p_errMsg)
         }
     }
 
-    qDebug() << "imported" << nrImported << "files";
+    qDebug() << "imported" << importedFiles.size() << "files";
 
     updateFileList();
 
+    selectFiles(importedFiles);
+
     return ret;
 }
 
@@ -1273,3 +1267,152 @@ void VFileList::updateNumberLabel() const
     m_numLabel->setText(tr("%1 %2").arg(cnt)
                                    .arg(cnt > 1 ? tr("Items") : tr("Item")));
 }
+
+void VFileList::updateViewMenu(QMenu *p_menu)
+{
+    if (p_menu->isEmpty()) {
+        QActionGroup *ag = new QActionGroup(p_menu);
+
+        QAction *act = new QAction(tr("View By Configuration File"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::Config);
+        act->setChecked(true);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Name"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::Name);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Name (Reverse)"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::NameReverse);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Created Time"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::CreatedTime);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Created Time (Reverse)"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::CreatedTimeReverse);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Modified Time"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::ModifiedTime);
+        p_menu->addAction(act);
+
+        act = new QAction(tr("View By Modified Time (Reverse)"), ag);
+        act->setCheckable(true);
+        act->setData(ViewOrder::ModifiedTimeReverse);
+        p_menu->addAction(act);
+
+        int config = g_config->getNoteListViewOrder();
+        for (auto act : ag->actions()) {
+            if (act->data().toInt() == config) {
+                act->setChecked(true);
+            }
+        }
+
+        connect(ag, &QActionGroup::triggered,
+                this, [this](QAction *p_action) {
+                    int order = p_action->data().toInt();
+                    g_config->setNoteListViewOrder(order);
+
+                    sortFileList((ViewOrder)order);
+                });
+    }
+}
+
+void VFileList::sortFileList(ViewOrder p_order)
+{
+    QVector<VNoteFile *> files = m_directory->getFiles();
+    sortFiles(files, p_order);
+
+    Q_ASSERT(files.size() == fileList->count());
+    int cnt = files.size();
+    for (int i = 0; i < cnt; ++i) {
+        int row = -1;
+        for (int j = i; j < cnt; ++j) {
+            QListWidgetItem *item = fileList->item(j);
+            if (files[i] == getVFile(item)) {
+                row = j;
+                break;
+            }
+        }
+
+        Q_ASSERT(row > -1);
+        QListWidgetItem *item = fileList->takeItem(row);
+        fileList->insertItem(i, item);
+    }
+}
+
+void VFileList::sortFiles(QVector<VNoteFile *> &p_files, ViewOrder p_order)
+{
+    bool reverse = false;
+
+    switch (p_order) {
+    case ViewOrder::Config:
+        break;
+
+    case ViewOrder::NameReverse:
+        reverse = true;
+        V_FALLTHROUGH
+    case ViewOrder::Name:
+        std::sort(p_files.begin(), p_files.end(), [reverse](const VNoteFile *p_a, const VNoteFile *p_b) {
+            if (reverse) {
+                return p_b->getName() < p_a->getName();
+            } else {
+                return p_a->getName() < p_b->getName();
+            }
+        });
+        break;
+
+    case ViewOrder::CreatedTimeReverse:
+        reverse = true;
+        V_FALLTHROUGH
+    case ViewOrder::CreatedTime:
+        std::sort(p_files.begin(), p_files.end(), [reverse](const VNoteFile *p_a, const VNoteFile *p_b) {
+            if (reverse) {
+                return p_b->getCreatedTimeUtc() < p_a->getCreatedTimeUtc();
+            } else {
+                return p_a->getCreatedTimeUtc() < p_b->getCreatedTimeUtc();
+            }
+        });
+        break;
+
+    case ViewOrder::ModifiedTimeReverse:
+        reverse = true;
+        V_FALLTHROUGH
+    case ViewOrder::ModifiedTime:
+        std::sort(p_files.begin(), p_files.end(), [reverse](const VNoteFile *p_a, const VNoteFile *p_b) {
+            if (reverse) {
+                return p_b->getModifiedTimeUtc() < p_a->getModifiedTimeUtc();
+            } else {
+                return p_a->getModifiedTimeUtc() < p_b->getModifiedTimeUtc();
+            }
+        });
+        break;
+
+    default:
+        break;
+    }
+}
+
+void VFileList::selectFiles(const QVector<VNoteFile *> &p_files)
+{
+    bool first = true;
+    for (auto const & file : p_files) {
+        QListWidgetItem *item = findItem(file);
+        if (item) {
+            if (first) {
+                first = false;
+                fileList->setCurrentItem(item, QItemSelectionModel::ClearAndSelect);
+            } else {
+                item->setSelected(true);
+            }
+        }
+    }
+}

+ 23 - 3
src/vfilelist.h

@@ -119,6 +119,19 @@ protected:
     void focusInEvent(QFocusEvent *p_event) Q_DECL_OVERRIDE;
 
 private:
+    // Should be aligned with note_list_view_order in vnote.ini.
+    enum ViewOrder
+    {
+        Config = 0,
+        Name,
+        NameReverse,
+        CreatedTime,
+        CreatedTimeReverse,
+        ModifiedTime,
+        ModifiedTimeReverse,
+        Max
+    };
+
     void setupUI();
 
     // Init shortcuts.
@@ -143,9 +156,6 @@ private:
                     const QVector<QString> &p_files,
                     bool p_isCut);
 
-    // New items have been added to direcotry. Update file list accordingly.
-    QVector<QListWidgetItem *> updateFileListAdded();
-
     inline QPointer<VNoteFile> getVFile(QListWidgetItem *p_item) const;
 
     // Fill the info of @p_item according to @p_file.
@@ -166,6 +176,16 @@ private:
 
     void updateNumberLabel() const;
 
+    // Update the View menu.
+    void updateViewMenu(QMenu *p_menu);
+
+    // Sort file list.
+    void sortFileList(ViewOrder p_order);
+
+    void sortFiles(QVector<VNoteFile *> &p_files, ViewOrder p_order);
+
+    void selectFiles(const QVector<VNoteFile *> &p_files);
+
     VEditArea *editArea;
 
     VListWidget *fileList;

+ 1 - 0
src/vnote.qrc

@@ -217,5 +217,6 @@
         <file>resources/icons/history.svg</file>
         <file>resources/icons/clear_history.svg</file>
         <file>resources/icons/pin.svg</file>
+        <file>resources/icons/view.svg</file>
     </qresource>
 </RCC>