Pārlūkot izejas kodu

fix AttachmentPopup and TagPopup

Le Tan 5 dienas atpakaļ
vecāks
revīzija
db6a26b2f8

+ 2 - 0
src/data/core/core.qrc

@@ -65,6 +65,8 @@
         <file>icons/add.svg</file>
         <file>icons/clear.svg</file>
         <file>icons/open_folder.svg</file>
+        <file>icons/open_file.svg</file>
+        <file>icons/copy_path.svg</file>
         <file>icons/new_file.svg</file>
         <file>icons/new_folder.svg</file>
         <file>icons/decrease_outline_level.svg</file>

+ 1 - 0
src/data/core/icons/copy_path.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1761114436910" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8807" width="48" height="48" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M864 128l-64 0 0 64 32 0 0 512L576 704l0 256L192 960 192 192l32 0L224 128 160 128c-17.6 0-32 14.4-32 32l0 832c0 17.6 14.4 32 32 32l504 0 232-232L896 160C896 142.4 881.6 128 864 128zM640 960l0-192 192 0L640 960zM768 128l-128 0L640 64c0-35.2-28.8-64-64-64l-128 0c-35.2 0-64 28.8-64 64l0 64-128 0 0 128 512 0L768 128zM576 128l-128 0L448 64.128c0.032-0.032 0.064-0.064 0.128-0.128l127.776 0c0.032 0.032 0.096 0.064 0.128 0.128L576 128z" fill="#000000" p-id="8808"></path></svg>

+ 1 - 0
src/data/core/icons/open_file.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22 44L21 36" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M42 44V12H26L27 20L28 28L29 36L22 44H42Z" fill="none" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M28 28H33" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M27 20H33" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M6 4H25L26 12L27 20L28 28L29 36H21H6V4Z" fill="none" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 12H19" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 20H20" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 28H21" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>

+ 121 - 46
src/widgets/attachmentpopup.cpp

@@ -15,6 +15,7 @@
 #include <utils/iconutils.h>
 #include <utils/widgetutils.h>
 #include <utils/pathutils.h>
+#include <utils/clipboardutils.h>
 #include <core/vnotex.h>
 #include <core/thememgr.h>
 #include <buffer/buffer.h>
@@ -25,6 +26,7 @@
 #include <core/exception.h>
 #include <core/sessionconfig.h>
 #include <core/configmgr.h>
+#include "dialogs/filepropertiesdialog.h"
 
 using namespace vnotex;
 
@@ -148,59 +150,123 @@ void AttachmentPopup::setupUI()
 
     buttonsLayout->addStretch();
 
-    mainLayout->addLayout(buttonsLayout);
+    {
+        // Open files.
+        m_openBtn = createButton();
+        auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("open_file.svg"))),
+                               tr("Open"),
+                               m_openBtn);
+        connect(act, &QAction::triggered,
+                this, [this]() {
+                    hide();
+                    const auto paths = m_viewer->getSelectedPaths();
+                    for (const auto &file : paths) {
+                        auto paras = QSharedPointer<FileOpenParameters>::create();
+                        paras->m_nodeAttachedTo = m_buffer->getNode();
+                        Q_ASSERT(paras->m_nodeAttachedTo);
+                        emit VNoteX::getInst().openFileRequested(file, paras);
+                    }
+                });
+        m_openBtn->setDefaultAction(act);
+        buttonsLayout->addWidget(m_openBtn);
+    }
 
-    m_viewer = new FileSystemViewer(this);
-    connect(m_viewer, &FileSystemViewer::renameFile,
-            this, [this](const QString &p_path, const QString &p_name) {
-                try {
-                    m_buffer->renameAttachment(p_path, p_name);
-                    showPopupLater(QStringList() << PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_path), p_name));
-                } catch (Exception &p_e) {
-                    MessageBoxHelper::notify(MessageBoxHelper::Warning,
-                                             tr("Failed to rename attachment (%1) to (%2).").arg(p_path, p_name),
-                                             tr("Please try another name again."),
-                                             p_e.what(),
-                                             this);
-                }
-            });
-    connect(m_viewer, &FileSystemViewer::removeFiles,
-            this, [this](QStringList p_paths) {
-                if (p_paths.isEmpty()) {
-                    return;
-                }
+    {
+        // Delete files.
+        m_deleteBtn = createButton();
+        auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("delete.svg"))),
+                               tr("Delete"),
+                               m_deleteBtn);
+        connect(act, &QAction::triggered,
+                this, [this]() {
+                    auto selectedPaths = m_viewer->getSelectedPaths();
+                    if (selectedPaths.isEmpty()) {
+                        return;
+                    }
+                    // Filter out children paths.
+                    QStringList paths;
+                    std::sort(selectedPaths.begin(), selectedPaths.end());
+                    for (int i = selectedPaths.size() - 1; i >= 0; --i) {
+                        bool skip = false;
+                        for (int j = i - 1; j >= 0; --j) {
+                            // Check if [j] is parent of [i].
+                            if (selectedPaths[j].size() < selectedPaths[i].size()
+                                && selectedPaths[i].startsWith(selectedPaths[j]) && selectedPaths[i].at(selectedPaths[j].size()) == '/') {
+                                skip = true;
+                                break;
+                            }
+                        }
 
-                // Filter out children paths.
-                QStringList paths;
-                std::sort(p_paths.begin(), p_paths.end());
-                for (int i = p_paths.size() - 1; i >= 0; --i) {
-                    bool skip = false;
-                    for (int j = i - 1; j >= 0; --j) {
-                        // Check if [j] is parent of [i].
-                        if (p_paths[j].size() < p_paths[i].size()
-                            && p_paths[i].startsWith(p_paths[j]) && p_paths[i].at(p_paths[j].size()) == '/') {
-                            skip = true;
-                            break;
+                        if (!skip) {
+                            paths << selectedPaths[i];
                         }
                     }
 
-                    if (!skip) {
-                        paths << p_paths[i];
+                    m_buffer->removeAttachment(paths);
+                });
+        m_deleteBtn->setDefaultAction(act);
+        buttonsLayout->addWidget(m_deleteBtn);
+    }
+
+    {
+        // Copy path.
+        m_copyPathBtn = createButton();
+        auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("copy_path.svg"))),
+                               tr("Copy Path"),
+                               m_copyPathBtn);
+        connect(act, &QAction::triggered,
+                this, [this]() {
+                    hide();
+                    const auto paths = m_viewer->getSelectedPaths();
+                    ClipboardUtils::setTextToClipboard(paths.join('\n'));
+                });
+        m_copyPathBtn->setDefaultAction(act);
+        buttonsLayout->addWidget(m_copyPathBtn);
+    }
+
+    {
+        // Properties.
+        m_propertiesBtn = createButton();
+        auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("properties.svg"))),
+                               tr("Properties"),
+                               m_propertiesBtn);
+        connect(act, &QAction::triggered,
+                this, [this]() {
+                    hide();
+                    const auto paths = m_viewer->getSelectedPaths();
+                    Q_ASSERT(paths.size() == 1);
+                    const auto path = paths[0];
+                    FilePropertiesDialog dialog(path, this);
+                    int ret = dialog.exec();
+                    if (ret) {
+                        auto newName = dialog.getFileName();
+                        if (newName != PathUtils::fileName(path)) {
+                            // Rename.
+                            try {
+                                m_buffer->renameAttachment(path, newName);
+                                showPopupLater(QStringList() << PathUtils::concatenateFilePath(PathUtils::parentDirPath(path), newName));
+                            } catch (Exception &p_e) {
+                                MessageBoxHelper::notify(MessageBoxHelper::Warning,
+                                                        tr("Failed to rename attachment (%1) to (%2).").arg(path, newName),
+                                                        tr("Please try another name again."),
+                                                        p_e.what(),
+                                                        this);
+                            }
+                        }
                     }
-                }
+                });
+        m_propertiesBtn->setDefaultAction(act);
+        buttonsLayout->addWidget(m_propertiesBtn);
+    }
+
+    mainLayout->addLayout(buttonsLayout);
+
+    m_viewer = new FileSystemViewer(this);
+    connect(m_viewer, &FileSystemViewer::selectionChanged,
+            this, &AttachmentPopup::updateButtonsState);
+
+    updateButtonsState();
 
-                m_buffer->removeAttachment(paths);
-            });
-    connect(m_viewer, &FileSystemViewer::openFiles,
-            this, [this](const QStringList &p_paths) {
-                hide();
-                for (const auto &file : p_paths) {
-                    auto paras = QSharedPointer<FileOpenParameters>::create();
-                    paras->m_nodeAttachedTo = m_buffer->getNode();
-                    Q_ASSERT(paras->m_nodeAttachedTo);
-                    emit VNoteX::getInst().openFileRequested(file, paras);
-                }
-            });
     mainLayout->addWidget(m_viewer);
 
     widget->setMinimumSize(320, 384);
@@ -281,3 +347,12 @@ void AttachmentPopup::showPopupLater(const QStringList &p_pathsToSelect)
         m_button->showMenu();
     });
 }
+
+void AttachmentPopup::updateButtonsState()
+{
+    const int selectedCount = m_viewer->selectedCount();
+    m_openBtn->setEnabled(selectedCount > 0);
+    m_deleteBtn->setEnabled(selectedCount > 0);
+    m_copyPathBtn->setEnabled(selectedCount > 0);
+    m_propertiesBtn->setEnabled(selectedCount == 1);
+}

+ 8 - 0
src/widgets/attachmentpopup.h

@@ -16,6 +16,9 @@ namespace vnotex
 
         void setBuffer(Buffer *p_buffer);
 
+    private slots:
+        void updateButtonsState();
+
     private:
         void setupUI();
 
@@ -40,6 +43,11 @@ namespace vnotex
         // Managed by QObject.
         FileSystemViewer *m_viewer = nullptr;
 
+        QToolButton *m_openBtn = nullptr;
+        QToolButton *m_deleteBtn = nullptr;
+        QToolButton *m_copyPathBtn = nullptr;
+        QToolButton *m_propertiesBtn = nullptr;
+
         bool m_needUpdateAttachmentFolder = true;
     };
 }

+ 10 - 12
src/widgets/filesystemviewer.cpp

@@ -34,15 +34,18 @@ void FileSystemViewer::setupUI()
     m_viewer = new TreeView(this);
     m_viewer->setModel(fileModel);
     m_viewer->setSelectionMode(QAbstractItemView::ExtendedSelection);
-    m_viewer->setContextMenuPolicy(Qt::CustomContextMenu);
     m_viewer->setHeaderHidden(true);
     // Show only the Name column.
     for (int i = 1; i < fileModel->columnCount(); ++i) {
         m_viewer->hideColumn(i);
     }
 
-    connect(m_viewer, &QTreeView::customContextMenuRequested,
-            this, &FileSystemViewer::handleContextMenuRequested);
+    if (m_contextMenuEnabled) {
+        m_viewer->setContextMenuPolicy(Qt::CustomContextMenu);
+        connect(m_viewer, &QTreeView::customContextMenuRequested,
+                this, &FileSystemViewer::handleContextMenuRequested);
+    }
+
     connect(m_viewer, &QTreeView::activated,
             this, [this](const QModelIndex &p_index) {
                 if (!this->fileModel()->isDir(p_index)) {
@@ -51,6 +54,8 @@ void FileSystemViewer::setupUI()
                     emit openFiles(files);
                 }
             });
+    connect(m_viewer->selectionModel(), &QItemSelectionModel::selectionChanged,
+            this, &FileSystemViewer::selectionChanged);
 
     auto index = fileModel->setRootPath(QDir::homePath());
     m_viewer->setRootIndex(index);
@@ -214,16 +219,9 @@ void FileSystemViewer::scrollToAndSelect(const QStringList &p_paths)
 
 void FileSystemViewer::handleContextMenuRequested(const QPoint &p_pos)
 {
-    // @p_pos is the position in the coordinate of parent widget if parent is a popup.
-    auto pos = p_pos;
-    if (m_fixContextMenuPos) {
-        pos = mapFromParent(p_pos);
-        pos = m_viewer->mapFromParent(pos);
-    }
-
     QScopedPointer<QMenu> menu(WidgetsFactory::createMenu());
 
-    auto index = m_viewer->indexAt(pos);
+    auto index = m_viewer->indexAt(p_pos);
     if (index.isValid()) {
         auto selectionModel = m_viewer->selectionModel();
         if (!selectionModel->isSelected(index)) {
@@ -239,6 +237,6 @@ void FileSystemViewer::handleContextMenuRequested(const QPoint &p_pos)
     m_viewer->update();
 
     if (!menu->isEmpty()) {
-        menu->exec(m_viewer->mapToGlobal(pos));
+        menu->exec(m_viewer->mapToGlobal(p_pos));
     }
 }

+ 3 - 1
src/widgets/filesystemviewer.h

@@ -34,6 +34,8 @@ namespace vnotex
 
         void openFiles(const QStringList &p_paths);
 
+        void selectionChanged();
+
     private slots:
         // Resize the first column.
         void resizeTreeToContents();
@@ -62,7 +64,7 @@ namespace vnotex
         // Managed by QObject.
         QTreeView *m_viewer = nullptr;
 
-        bool m_fixContextMenuPos = true;
+        bool m_contextMenuEnabled = false;
     };
 }
 

+ 7 - 2
src/widgets/tagviewer.cpp

@@ -48,8 +48,6 @@ void TagViewer::setupUI()
     m_searchLineEdit->setToolTip(tr("[Shift+Enter] to add current selected tag in the list"));
     connect(m_searchLineEdit, &QLineEdit::textChanged,
             this, &TagViewer::searchAndFilter);
-    connect(m_searchLineEdit, &QLineEdit::returnPressed,
-            this, &TagViewer::handleSearchLineEditReturnPressed);
     mainLayout->addWidget(m_searchLineEdit);
 
     auto tagNameValidator = new QRegularExpressionValidator(QRegularExpression("[^>]*"), m_searchLineEdit);
@@ -90,6 +88,13 @@ bool TagViewer::eventFilter(QObject *p_obj, QEvent *p_event)
                 m_searchLineEdit->setFocus();
             }
             return true;
+        } else if (key == Qt::Key_Return || key == Qt::Key_Enter) {
+            if (p_obj == m_searchLineEdit) {
+                // Pressing twice will make the popup hide if we use the signal returnPressed,
+                // so we handle it here earlier.
+                handleSearchLineEditReturnPressed();
+                return true;
+            }
         }
     }