From a98757643fe17d82d9aa6e6e34801b852b4adf0a Mon Sep 17 00:00:00 2001 From: Le Tan Date: Wed, 23 May 2018 20:09:27 +0800 Subject: [PATCH] VFileList: support specifying different view orders --- src/resources/icons/view.svg | 15 +++ src/resources/vnote.ini | 10 ++ src/vconfigmanager.cpp | 1 + src/vconfigmanager.h | 31 +++++- src/vfilelist.cpp | 203 +++++++++++++++++++++++++++++------ src/vfilelist.h | 26 ++++- src/vnote.qrc | 1 + 7 files changed, 251 insertions(+), 36 deletions(-) create mode 100644 src/resources/icons/view.svg diff --git a/src/resources/icons/view.svg b/src/resources/icons/view.svg new file mode 100644 index 00000000..176f2647 --- /dev/null +++ b/src/resources/icons/view.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index dee9bf79..2f3fdc24 100644 --- a/src/resources/vnote.ini +++ b/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 diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 7a5f12b5..55f19556 100644 --- a/src/vconfigmanager.cpp +++ b/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), diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index 6787c983..9dc016a1 100644 --- a/src/vconfigmanager.h +++ b/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 §ion, 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(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 diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index ab2a63b6..2ef94e00 100644 --- a/src/vfilelist.cpp +++ b/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 &files = m_directory->getFiles(); + QVector 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 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 VFileList::updateFileListAdded() -{ - QVector ret; - const QVector &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 items = fileList->selectedItems(); @@ -500,6 +491,7 @@ void VFileList::deleteFiles(const QVector &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 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 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 &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 &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); + } + } + } +} diff --git a/src/vfilelist.h b/src/vfilelist.h index c4cce227..ac702343 100644 --- a/src/vfilelist.h +++ b/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 &p_files, bool p_isCut); - // New items have been added to direcotry. Update file list accordingly. - QVector updateFileListAdded(); - inline QPointer 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 &p_files, ViewOrder p_order); + + void selectFiles(const QVector &p_files); + VEditArea *editArea; VListWidget *fileList; diff --git a/src/vnote.qrc b/src/vnote.qrc index b0470a78..32ba666f 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -217,5 +217,6 @@ resources/icons/history.svg resources/icons/clear_history.svg resources/icons/pin.svg + resources/icons/view.svg