Browse Source

MainWindow: use icon only in docks' tab bar

Le Tan 4 years ago
parent
commit
bcec79fe17

+ 17 - 0
src/core/coreconfig.cpp

@@ -48,6 +48,11 @@ void CoreConfig::init(const QJsonObject &p_app,
         m_toolBarIconSize = 16;
     }
 
+    m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size"));
+    if (m_docksTabBarIconSize <= 0) {
+        m_docksTabBarIconSize = 20;
+    }
+
     loadNoteManagement(appObj, userObj);
 
     m_recoverLastSessionOnStartEnabled = READBOOL(QStringLiteral("recover_last_session_on_start"));
@@ -65,6 +70,7 @@ QJsonObject CoreConfig::toJson() const
     obj[QStringLiteral("locale")] = m_locale;
     obj[QStringLiteral("shortcuts")] = saveShortcuts();
     obj[QStringLiteral("toolbar_icon_size")] = m_toolBarIconSize;
+    obj[QStringLiteral("docks_tabbar_icon_size")] = m_docksTabBarIconSize;
     obj[QStringLiteral("recover_last_session_on_start")] = m_recoverLastSessionOnStartEnabled;
     obj[QStringLiteral("history_max_count")] = m_historyMaxCount;
     return obj;
@@ -154,6 +160,17 @@ void CoreConfig::setToolBarIconSize(int p_size)
     updateConfig(m_toolBarIconSize, p_size, this);
 }
 
+int CoreConfig::getDocksTabBarIconSize() const
+{
+    return m_docksTabBarIconSize;
+}
+
+void CoreConfig::setDocksTabBarIconSize(int p_size)
+{
+    Q_ASSERT(p_size > 0);
+    updateConfig(m_docksTabBarIconSize, p_size, this);
+}
+
 const QStringList &CoreConfig::getExternalNodeExcludePatterns() const
 {
     return m_externalNodeExcludePatterns;

+ 6 - 0
src/core/coreconfig.h

@@ -87,6 +87,9 @@ namespace vnotex
         int getToolBarIconSize() const;
         void setToolBarIconSize(int p_size);
 
+        int getDocksTabBarIconSize() const;
+        void setDocksTabBarIconSize(int p_size);
+
         const QStringList &getExternalNodeExcludePatterns() const;
 
         static const QStringList &getAvailableLocales();
@@ -117,6 +120,9 @@ namespace vnotex
         // Icon size of MainWindow tool bar.
         int m_toolBarIconSize = 16;
 
+        // Icon size of MainWindow QDockWidgets tab bar.
+        int m_docksTabBarIconSize = 20;
+
         QStringList m_externalNodeExcludePatterns;
 
         // Whether recover last session on start.

+ 6 - 1
src/data/core/core.qrc

@@ -15,7 +15,6 @@
         <file>icons/read_editor.svg</file>
         <file>icons/expand.svg</file>
         <file>icons/fullscreen.svg</file>
-        <file>icons/history_explorer.svg</file>
         <file>icons/tag_explorer.svg</file>
         <file>icons/help.svg</file>
         <file>icons/menu.svg</file>
@@ -81,6 +80,12 @@
         <file>icons/cancel.svg</file>
         <file>icons/section_number_editor.svg</file>
         <file>icons/sort.svg</file>
+        <file>icons/navigation_dock.svg</file>
+        <file>icons/history_dock.svg</file>
+        <file>icons/outline_dock.svg</file>
+        <file>icons/search_dock.svg</file>
+        <file>icons/snippet_dock.svg</file>
+        <file>icons/location_list_dock.svg</file>
         <file>logo/vnote.svg</file>
         <file>logo/vnote.png</file>
         <file>logo/256x256/vnote.png</file>

+ 0 - 0
src/data/core/icons/history_explorer.svg → src/data/core/icons/history_dock.svg


+ 1 - 0
src/data/core/icons/location_list_dock.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="1618368321416" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2001" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M128 256 64 256 64 192l64 0L128 256zM320 384 256 384l0 64 64 0L320 384zM320 576 256 576l0 64 64 0L320 576zM320 768 256 768l0 64 64 0L320 768zM896 224C896 206.336 881.664 192 864 192l-640 0C206.336 192 192 206.336 192 224l0 0C192 241.664 206.336 256 224 256l640 0C881.664 256 896 241.664 896 224L896 224zM896 416C896 398.336 881.664 384 864 384l-448 0C398.336 384 384 398.336 384 416l0 0C384 433.664 398.336 448 416 448l448 0C881.664 448 896 433.664 896 416L896 416zM896 608C896 590.336 881.664 576 864 576l-448 0C398.336 576 384 590.336 384 608l0 0C384 625.664 398.336 640 416 640l448 0C881.664 640 896 625.664 896 608L896 608zM896 800c0-17.664-14.336-32-32-32l-448 0C398.336 768 384 782.336 384 800l0 0C384 817.664 398.336 832 416 832l448 0C881.664 832 896 817.664 896 800L896 800z" p-id="2002" fill="#000000"></path></svg>

+ 1 - 0
src/data/core/icons/navigation_dock.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="1629376644691" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4940" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M917.792 357.088c-22.208-30.304-53.184-65.696-87.168-99.712s-69.408-64.96-99.712-87.168c-51.584-37.824-76.576-42.208-90.912-42.208l-368 0c-44.128 0-80 35.904-80 80l0 736c0 44.096 35.872 80 80 80l608 0c44.096 0 80-35.904 80-80l0-496c0-14.336-4.384-39.36-42.208-90.912zM785.376 302.624c30.688 30.688 54.784 58.4 72.576 81.376l-153.952 0 0-153.952c22.976 17.792 50.688 41.888 81.376 72.576l0 0zM896 944c0 8.672-7.328 16-16 16l-608 0c-8.672 0-16-7.328-16-16l0-736c0-8.672 7.328-16 16-16 0 0 367.968 0 368 0l0 224c0 17.664 14.336 32 32 32l224 0 0 496z" p-id="4941" fill="#000000"></path><path d="M602.912 42.208c-51.584-37.824-76.576-42.208-90.912-42.208l-368 0c-44.096 0-80 35.872-80 80l0 736c0 38.624 27.52 70.944 64 78.4l0-814.4c0-8.672 7.328-16 16-16l486.88 0c-9.632-7.936-19.04-15.264-27.936-21.792z" p-id="4942" fill="#000000"></path></svg>

+ 1 - 0
src/data/core/icons/outline_dock.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="1606090006454" class="icon" viewBox="0 0 1057 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1135" width="528.5" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M924.903226 1024H132.129032a132.129032 132.129032 0 0 1-132.129032-132.129032V132.129032a132.129032 132.129032 0 0 1 132.129032-132.129032h792.774194a132.129032 132.129032 0 0 1 132.129032 132.129032v759.741936a132.129032 132.129032 0 0 1-132.129032 132.129032z m66.064516-891.870968a66.064516 66.064516 0 0 0-66.064516-66.064516H132.129032a66.064516 66.064516 0 0 0-66.064516 66.064516v759.741936a66.064516 66.064516 0 0 0 66.064516 66.064516h792.774194a66.064516 66.064516 0 0 0 66.064516-66.064516V132.129032z m-132.129032 660.645162H297.290323a33.032258 33.032258 0 0 1 0-66.064517h561.548387a33.032258 33.032258 0 0 1 0 66.064517z m0-165.161291H297.290323a33.032258 33.032258 0 0 1 0-66.064516h561.548387a33.032258 33.032258 0 0 1 0 66.064516z m0-165.16129H297.290323a33.032258 33.032258 0 0 1 0-66.064516h561.548387a33.032258 33.032258 0 0 1 0 66.064516z m0-165.16129H297.290323a33.032258 33.032258 0 0 1 0-66.064517h561.548387a33.032258 33.032258 0 0 1 0 66.064517zM165.16129 726.709677h66.064516v66.064517H165.16129v-66.064517z m0-165.16129h66.064516v66.064516H165.16129v-66.064516z m0-165.16129h66.064516v66.064516H165.16129v-66.064516z m0-165.161291h66.064516v66.064517H165.16129V231.225806z" p-id="1136" fill="#000000"></path></svg>

+ 10 - 0
src/data/core/icons/search_dock.svg

@@ -0,0 +1,10 @@
+<?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">
+<path style="fill:#000000" d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
+	c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
+	C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
+	C125.8,169.4,169.2,125.9,222.6,125.9z"/>
+</svg>

File diff suppressed because it is too large
+ 0 - 0
src/data/core/icons/snippet_dock.svg


+ 1 - 0
src/data/core/vnotex.json

@@ -59,6 +59,7 @@
             "OpenLastClosedFile" : "Ctrl+Shift+T"
         },
         "toolbar_icon_size" : 16,
+        "docks_tabbar_icon_size" : 20,
         "note_management" : {
             "external_node" : {
                 "//comment" : "Wildcard patterns of files and folders to exclude as external files",

+ 16 - 0
src/data/extra/themes/moonlight/interface.qss

@@ -511,6 +511,22 @@ QTabBar::tab:left {
     min-width: 20px;
 }
 
+/* Tabified QDockWidget */
+QMainWindow > QTabBar::tab:right {
+    border-right: 3px solid transparent;
+    border-bottom: none;
+    margin: 0px;
+    padding: -10px 2px 5px 2px;
+}
+
+/* Tabified QDockWidget */
+QMainWindow > QTabBar::tab:left {
+    border-left: 3px solid transparent;
+    border-bottom: none;
+    margin: 0px;
+    padding: -10px 2px 5px 2px;
+}
+
 QTabBar::tab:hover {
     color: @widgets#qtabbar#tab#hover#fg;
     background-color: @widgets#qtabbar#tab#hover#bg;

+ 13 - 0
src/data/extra/themes/moonlight/palette.json

@@ -164,6 +164,9 @@
             },
             "danger" : {
                 "fg": "@base#danger#fg"
+            },
+            "selected" : {
+                "fg" : "@base#master#bg"
             }
         }
     },
@@ -627,6 +630,16 @@
                 "fg" : "@base#master#fg",
                 "bg" : "@base#master#bg"
             }
+        },
+        "mainwindow" : {
+            "dockwidget_tabbar" : {
+                "icon" : {
+                    "fg" : "@base#icon#fg",
+                    "selected" : {
+                        "fg" : "@base#icon#selected#fg"
+                    }
+                }
+            }
         }
     }
 }

+ 13 - 0
src/data/extra/themes/native/palette.json

@@ -43,6 +43,9 @@
             },
             "danger" : {
                 "fg": "@base#danger#fg"
+            },
+            "selected" : {
+                "fg": "@base#info#fg"
             }
         },
         "master" : {
@@ -140,6 +143,16 @@
                 "fg" : "@base#master#fg",
                 "bg" : "@base#master#bg"
             }
+        },
+        "mainwindow" : {
+            "dockwidget_tabbar" : {
+                "icon" : {
+                    "fg" : "@base#icon#fg",
+                    "selected" : {
+                        "fg" : "@base#icon#selected#fg"
+                    }
+                }
+            }
         }
     }
 }

+ 16 - 0
src/data/extra/themes/pure/interface.qss

@@ -511,6 +511,22 @@ QTabBar::tab:left {
     min-width: 20px;
 }
 
+/* Tabified QDockWidget */
+QMainWindow > QTabBar::tab:right {
+    border-right: 3px solid transparent;
+    border-bottom: none;
+    margin: 0px;
+    padding: -10px 2px 5px 2px;
+}
+
+/* Tabified QDockWidget */
+QMainWindow > QTabBar::tab:left {
+    border-left: 3px solid transparent;
+    border-bottom: none;
+    margin: 0px;
+    padding: -10px 2px 5px 2px;
+}
+
 QTabBar::tab:hover {
     color: @widgets#qtabbar#tab#hover#fg;
     background-color: @widgets#qtabbar#tab#hover#bg;

+ 13 - 0
src/data/extra/themes/pure/palette.json

@@ -160,6 +160,9 @@
             },
             "danger" : {
                 "fg": "@base#danger#fg"
+            },
+            "selected" : {
+                "fg" : "@base#master#bg"
             }
         }
     },
@@ -623,6 +626,16 @@
                 "fg" : "@base#master#fg",
                 "bg" : "@base#master#bg"
             }
+        },
+        "mainwindow" : {
+            "dockwidget_tabbar" : {
+                "icon" : {
+                    "fg" : "@base#icon#fg",
+                    "selected" : {
+                        "fg" : "@base#icon#selected#fg"
+                    }
+                }
+            }
         }
     }
 }

+ 5 - 1
src/utils/iconutils.cpp

@@ -15,7 +15,8 @@ QString IconUtils::s_defaultIconForeground;
 QString IconUtils::s_defaultIconDisabledForeground;
 
 QIcon IconUtils::fetchIcon(const QString &p_iconFile,
-                           const QVector<OverriddenColor> &p_overriddenColors)
+                           const QVector<OverriddenColor> &p_overriddenColors,
+                           qreal p_angle)
 {
     const auto suffix = QFileInfo(p_iconFile).suffix().toLower().toStdString();
     if (p_overriddenColors.isEmpty() || suffix != "svg") {
@@ -33,6 +34,9 @@ QIcon IconUtils::fetchIcon(const QString &p_iconFile,
         auto data = overriddenContent.toLocal8Bit();
         QPixmap pixmap;
         pixmap.loadFromData(data, suffix.c_str());
+        if (p_angle > 0) {
+            pixmap = pixmap.transformed(QTransform().rotate(p_angle));
+        }
         icon.addPixmap(pixmap, color.m_mode, color.m_state);
     }
 

+ 2 - 1
src/utils/iconutils.h

@@ -37,7 +37,8 @@ namespace vnotex
         static void setDefaultIconForeground(const QString &p_fg, const QString &p_disabledFg);
 
         static QIcon fetchIcon(const QString &p_iconFile,
-                               const QVector<OverriddenColor> &p_overriddenColors);
+                               const QVector<OverriddenColor> &p_overriddenColors,
+                               qreal p_angle = -1);
 
         static QIcon fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground);
 

+ 6 - 0
src/widgets/dialogs/dialog.cpp

@@ -176,3 +176,9 @@ bool Dialog::isCompleted() const
 {
     return m_completed;
 }
+
+QSize Dialog::sizeHint() const
+{
+    auto sz = QDialog::sizeHint();
+    return sz * 1.2;
+}

+ 2 - 0
src/widgets/dialogs/dialog.h

@@ -40,6 +40,8 @@ namespace vnotex
 
         bool isCompleted() const;
 
+        QSize sizeHint() const Q_DECL_OVERRIDE;
+
     protected:
         virtual void acceptedButtonClicked();
 

+ 7 - 1
src/widgets/dialogs/importfolderutils.cpp

@@ -48,7 +48,13 @@ void ImportFolderUtils::importFolderContentsByLegacyConfig(Notebook *p_notebook,
 {
     auto rootDir = p_node->toDir();
 
-    const auto config = LegacyNotebookUtils::getFolderConfig(rootDir.absolutePath());
+    QJsonObject config;
+    try {
+        config = LegacyNotebookUtils::getFolderConfig(rootDir.absolutePath());
+    } catch (Exception &p_e) {
+        Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to read folder config (%1).").arg(rootDir.absolutePath()));
+        return;
+    }
 
     // Remove the config file.
     LegacyNotebookUtils::removeFolderConfigFile(rootDir.absolutePath());

+ 35 - 14
src/widgets/dialogs/importlegacynotebookdialog.cpp

@@ -19,7 +19,7 @@ using namespace vnotex;
 ImportLegacyNotebookDialog::ImportLegacyNotebookDialog(QWidget *p_parent)
     : NewNotebookDialog(p_parent)
 {
-    setWindowTitle(tr("Import Legacy Notebook"));
+    setWindowTitle(tr("Open Legacy Notebook"));
 
     m_infoWidget->setMode(NotebookInfoWidget::Mode::CreateFromLegacy);
     m_infoWidget->getRootFolderPathLineEdit()->setFocus();
@@ -34,8 +34,8 @@ void ImportLegacyNotebookDialog::acceptedButtonClicked()
 
     // Warn user about the transformation.
     int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
-                                                 tr("Once imported, the legacy notebook could no longer be recognized by legacy VNote!"),
-                                                 tr("This operation is irreversible. Please make sure the new VNote already meets all your needs before continue."),
+                                                 tr("Once opened, the legacy notebook could no longer be recognized by legacy VNote!"),
+                                                 QString(),
                                                  tr("Welcome to VNoteX and the new VNote!"),
                                                  this);
     if (ret == QMessageBox::Ok && importLegacyNotebook()) {
@@ -48,7 +48,7 @@ bool ImportLegacyNotebookDialog::validateRootFolderInput(QString &p_msg)
 {
     const auto rootFolderPath = m_infoWidget->getRootFolderPath();
     if (!QFileInfo::exists(rootFolderPath) || !PathUtils::isLegalPath(rootFolderPath)) {
-        Utils::appendMsg(p_msg, tr("Please specify a valid root folder to import."));
+        Utils::appendMsg(p_msg, tr("Please specify a valid root folder to open."));
         return false;
     }
 
@@ -76,14 +76,30 @@ bool ImportLegacyNotebookDialog::importLegacyNotebook()
     const auto rootFolderPath = m_infoWidget->getRootFolderPath();
 
     auto &notebookMgr = VNoteX::getInst().getNotebookMgr();
-    auto imageFolder = LegacyNotebookUtils::getImageFolderOfNotebook(rootFolderPath);
-    if (imageFolder.isEmpty()) {
-        imageFolder = Notebook::c_defaultImageFolder;
-    }
-    auto attachmentFolder = LegacyNotebookUtils::getAttachmentFolderOfNotebook(rootFolderPath);
-    if (attachmentFolder.isEmpty()) {
-        attachmentFolder = Notebook::c_defaultAttachmentFolder;
+
+    QString imageFolder;
+    QString attachmentFolder;
+    QDateTime createdTimeUtc;
+
+    try {
+        imageFolder = LegacyNotebookUtils::getImageFolderOfNotebook(rootFolderPath);
+        if (imageFolder.isEmpty()) {
+            imageFolder = Notebook::c_defaultImageFolder;
+        }
+
+        attachmentFolder = LegacyNotebookUtils::getAttachmentFolderOfNotebook(rootFolderPath);
+        if (attachmentFolder.isEmpty()) {
+            attachmentFolder = Notebook::c_defaultAttachmentFolder;
+        }
+
+        createdTimeUtc = LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootFolderPath);
+    } catch (Exception &p_e) {
+        QString msg = tr("Failed to read legacy notebook configuration in (%1) (%2).").arg(rootFolderPath, p_e.what());
+        qCritical() << msg;
+        setInformationText(msg, ScrollDialog::InformationLevel::Error);
+        return false;
     }
+
     auto paras = NotebookParameters::createNotebookParameters(notebookMgr,
                                                               m_infoWidget->getType(),
                                                               m_infoWidget->getName(),
@@ -92,7 +108,7 @@ bool ImportLegacyNotebookDialog::importLegacyNotebook()
                                                               m_infoWidget->getIcon(),
                                                               imageFolder,
                                                               attachmentFolder,
-                                                              LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootFolderPath),
+                                                              createdTimeUtc,
                                                               m_infoWidget->getBackend(),
                                                               m_infoWidget->getVersionController(),
                                                               m_infoWidget->getConfigMgr());
@@ -101,7 +117,7 @@ bool ImportLegacyNotebookDialog::importLegacyNotebook()
     try {
         nb = notebookMgr.newNotebook(paras);
     } catch (Exception &p_e) {
-        QString msg = tr("Failed to create notebook in %1 (%2).").arg(rootFolderPath, p_e.what());
+        QString msg = tr("Failed to create notebook in (%1) (%2).").arg(rootFolderPath, p_e.what());
         qCritical() << msg;
         setInformationText(msg, ScrollDialog::InformationLevel::Error);
         return false;
@@ -123,7 +139,12 @@ bool ImportLegacyNotebookDialog::importLegacyNotebook()
     }
 
     auto rootNode = nb->getRootNode();
-    ImportFolderUtils::importFolderContentsByLegacyConfig(nb.data(), rootNode.data(), errMsg);
+
+    try {
+        ImportFolderUtils::importFolderContentsByLegacyConfig(nb.data(), rootNode.data(), errMsg);
+    } catch (Exception &p_e) {
+        errMsg = tr("Failed to import folder contents by legacy config in (%1) (%2).").arg(rootFolderPath, p_e.what());
+    }
 
     emit nb->nodeUpdated(rootNode.data());
 

+ 3 - 3
src/widgets/dialogs/importnotebookdialog.cpp

@@ -34,7 +34,7 @@ void ImportNotebookDialog::setupUI()
     setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
     setButtonEnabled(QDialogButtonBox::Ok, false);
 
-    setWindowTitle(tr("Import Notebook"));
+    setWindowTitle(tr("Open Notebook"));
 }
 
 void ImportNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent)
@@ -135,7 +135,7 @@ bool ImportNotebookDialog::createNotebookToImport(QString &p_msg)
 bool ImportNotebookDialog::importNotebook()
 {
     if (!m_notebookToImport) {
-        QString msg = tr("Failed to import notebook.");
+        QString msg = tr("Failed to open notebook.");
         qCritical() << msg;
         setInformationText(msg, ScrollDialog::InformationLevel::Error);
         return false;
@@ -145,7 +145,7 @@ bool ImportNotebookDialog::importNotebook()
         auto &notebookMgr = VNoteX::getInst().getNotebookMgr();
         notebookMgr.importNotebook(m_notebookToImport);
     } catch (Exception &p_e) {
-        QString msg = tr("Failed to import notebook (%1).").arg(p_e.what());
+        QString msg = tr("Failed to open notebook (%1).").arg(p_e.what());
         qCritical() << msg;
         setInformationText(msg, ScrollDialog::InformationLevel::Error);
         return false;

+ 1 - 1
src/widgets/dialogs/settings/appearancepage.cpp

@@ -59,7 +59,7 @@ void AppearancePage::setupUI()
         auto layout = new QVBoxLayout();
 
         for (int i = 0; i < docks.size(); ++i) {
-            m_keepDocksExpandingContentArea[i].first = WidgetsFactory::createCheckBox(docks[i]->windowTitle(), this);
+            m_keepDocksExpandingContentArea[i].first = WidgetsFactory::createCheckBox(docks[i]->property(MainWindow::c_propertyDockTitle).toString(), this);
             m_keepDocksExpandingContentArea[i].second = docks[i]->objectName();
             layout->addWidget(m_keepDocksExpandingContentArea[i].first);
             connect(m_keepDocksExpandingContentArea[i].first, &QCheckBox::stateChanged,

+ 0 - 11
src/widgets/dialogs/settings/settingsdialog.cpp

@@ -267,14 +267,3 @@ QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetIte
     setupPage(subItem, p_page);
     return subItem;
 }
-
-void SettingsDialog::showEvent(QShowEvent *p_event)
-{
-    Dialog::showEvent(p_event);
-
-    if (m_firstShown) {
-        m_firstShown = false;
-        const auto sz = size();
-        resize(sz * 1.2);
-    }
-}

+ 0 - 4
src/widgets/dialogs/settings/settingsdialog.h

@@ -28,8 +28,6 @@ namespace vnotex
 
         void appliedButtonClicked() Q_DECL_OVERRIDE;
 
-        void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
-
     private:
         void setupUI();
 
@@ -63,8 +61,6 @@ namespace vnotex
         bool m_changesUnsaved = false;
 
         bool m_ready = false;
-
-        bool m_firstShown = true;
     };
 }
 

+ 101 - 24
src/widgets/mainwindow.cpp

@@ -4,8 +4,8 @@
 #include <QDebug>
 #include <QResizeEvent>
 #include <QSplitter>
-#include <QVariant>
 #include <QDockWidget>
+#include <QVariant>
 #include <QTextEdit>
 #include <QStatusBar>
 #include <QCloseEvent>
@@ -18,6 +18,7 @@
 #include <QSystemTrayIcon>
 #include <QWindowStateChangeEvent>
 #include <QTimer>
+#include <QBitArray>
 
 #include "toolbox.h"
 #include "notebookexplorer.h"
@@ -48,9 +49,14 @@
 #include "searchinfoprovider.h"
 #include <vtextedit/spellchecker.h>
 #include <utils/docsutils.h>
+#include <utils/iconutils.h>
+#include <core/thememgr.h>
 
 using namespace vnotex;
 
+const char *MainWindow::c_propertyDockIndex = "DockIndex";
+const char *MainWindow::c_propertyDockTitle = "DockTitle";
+
 MainWindow::MainWindow(QWidget *p_parent)
     : QMainWindow(p_parent)
 {
@@ -64,6 +70,15 @@ MainWindow::MainWindow(QWidget *p_parent)
 
     loadStateAndGeometry();
 
+    {
+        updateDockWidgetTabBar();
+
+        for (auto dock : m_docks) {
+            connect(dock, &QDockWidget::visibilityChanged,
+                    this, &MainWindow::updateDockWidgetTabBar);
+        }
+    }
+
     // The signal is particularly useful if your application has to do some last-second cleanup.
     // Note that no user interaction is possible in this state.
     connect(qApp, &QCoreApplication::aboutToQuit,
@@ -213,6 +228,38 @@ void MainWindow::setupDocks()
     setTabPosition(Qt::BottomDockWidgetArea, QTabWidget::North);
     setDockNestingEnabled(true);
 
+    // Init docks icon.
+    {
+        m_dockIcons.resize(DockIndex::MaxDock);
+
+        const auto &themeMgr = VNoteX::getInst().getThemeMgr();
+        const auto fg = themeMgr.paletteColor("widgets#mainwindow#dockwidget_tabbar#icon#fg");
+        const auto selectedFg = themeMgr.paletteColor("widgets#mainwindow#dockwidget_tabbar#icon#selected#fg");
+
+        QVector<IconUtils::OverriddenColor> colors;
+        colors.push_back(IconUtils::OverriddenColor(fg, QIcon::Normal));
+        // FIXME: the Selected Mode is not used by the selected tab of a QTabBar.
+        colors.push_back(IconUtils::OverriddenColor(selectedFg, QIcon::Selected));
+
+        auto iconFile = themeMgr.getIconFile("navigation_dock.svg");
+        m_dockIcons[DockIndex::NavigationDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+
+        iconFile = themeMgr.getIconFile("outline_dock.svg");
+        m_dockIcons[DockIndex::OutlineDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+
+        iconFile = themeMgr.getIconFile("history_dock.svg");
+        m_dockIcons[DockIndex::HistoryDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+
+        iconFile = themeMgr.getIconFile("search_dock.svg");
+        m_dockIcons[DockIndex::SearchDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+
+        iconFile = themeMgr.getIconFile("snippet_dock.svg");
+        m_dockIcons[DockIndex::SnippetDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+
+        iconFile = themeMgr.getIconFile("location_list_dock.svg");
+        m_dockIcons[DockIndex::LocationListDock] = IconUtils::fetchIcon(iconFile, colors, 90);
+    }
+
     // The order of m_docks should be identical with enum DockIndex.
     setupNavigationDock();
 
@@ -230,16 +277,6 @@ void MainWindow::setupDocks()
 
     // Following are non-tabfieid docks.
     setupLocationListDock();
-
-    for (auto dock : m_docks) {
-        connect(dock, &QDockWidget::visibilityChanged,
-                this, [this]() {
-                    updateTabBarStyle();
-                    emit layoutChanged();
-                });
-    }
-
-    activateDock(m_docks[DockIndex::NavigationDock]);
 }
 
 void MainWindow::activateDock(QDockWidget *p_dock)
@@ -264,8 +301,7 @@ void MainWindow::activateDock(QDockWidget *p_dock)
 
 void MainWindow::setupNavigationDock()
 {
-    auto dock = new QDockWidget(tr("Navigation"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::NavigationDock, tr("Navigation"), this);
 
     dock->setObjectName(QStringLiteral("NavigationDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -278,8 +314,7 @@ void MainWindow::setupNavigationDock()
 
 void MainWindow::setupOutlineDock()
 {
-    auto dock = new QDockWidget(tr("Outline"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::OutlineDock, tr("Outline"), this);
 
     dock->setObjectName(QStringLiteral("OutlineDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -292,8 +327,7 @@ void MainWindow::setupOutlineDock()
 
 void MainWindow::setupSearchDock()
 {
-    auto dock = new QDockWidget(tr("Search"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::SearchDock, tr("Search"), this);
 
     dock->setObjectName(QStringLiteral("SearchDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -316,8 +350,7 @@ void MainWindow::setupSearchPanel()
 
 void MainWindow::setupSnippetDock()
 {
-    auto dock = new QDockWidget(tr("Snippets"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::SnippetDock, tr("Snippets"), this);
 
     dock->setObjectName(QStringLiteral("SnippetDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -344,8 +377,7 @@ void MainWindow::setupSnippetPanel()
 
 void MainWindow::setupHistoryDock()
 {
-    auto dock = new QDockWidget(tr("History"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::HistoryDock, tr("History"), this);
 
     dock->setObjectName(QStringLiteral("HistoryDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -364,8 +396,7 @@ void MainWindow::setupHistoryPanel()
 
 void MainWindow::setupLocationListDock()
 {
-    auto dock = new QDockWidget(tr("Location List"), this);
-    m_docks.push_back(dock);
+    auto dock = createDockWidget(DockIndex::LocationListDock, tr("Location List"), this);
 
     dock->setObjectName(QStringLiteral("LocationListDock.vnotex"));
     dock->setAllowedAreas(Qt::AllDockWidgetAreas);
@@ -766,11 +797,47 @@ void MainWindow::quitApp()
     close();
 }
 
-void MainWindow::updateTabBarStyle()
+void MainWindow::updateDockWidgetTabBar()
 {
+    QBitArray tabifiedDocks(m_docks.size(), false);
     Q_FOREACH(QTabBar* tabBar, this->findChildren<QTabBar*>(QString(), Qt::FindDirectChildrenOnly)) {
         tabBar->setDrawBase(false);
+
+        const int sz = ConfigMgr::getInst().getCoreConfig().getDocksTabBarIconSize();
+        tabBar->setIconSize(QSize(sz, sz));
+
+        auto tabShape = tabBar->shape();
+        bool iconOnly = tabShape == QTabBar::RoundedWest || tabShape == QTabBar::RoundedEast
+                        || tabShape == QTabBar::TriangularWest || tabShape == QTabBar::TriangularEast;
+        const int cnt = tabBar->count();
+        if (cnt == 1) {
+            iconOnly = false;
+        }
+        for (int i = 0; i < cnt; ++i) {
+            auto dock = reinterpret_cast<QDockWidget *>(tabBar->tabData(i).toULongLong());
+            if (!dock) {
+                continue;
+            }
+            int dockIdx = dock->property(c_propertyDockIndex).toInt();
+            tabifiedDocks.setBit(dockIdx);
+            if (iconOnly) {
+                dock->setWindowTitle(QString());
+                tabBar->setTabIcon(i, m_dockIcons[dockIdx]);
+            } else if (dock->windowTitle().isEmpty()) {
+                dock->setWindowTitle(dock->property(c_propertyDockTitle).toString());
+                tabBar->setTabIcon(i, QIcon());
+            }
+        }
+    }
+
+    // Non-tabified docks.
+    for (int i = 0; i < m_docks.size(); ++i) {
+        if (!tabifiedDocks[i] && m_docks[i]->windowTitle().isEmpty()) {
+            m_docks[i]->setWindowTitle(m_docks[i]->property(c_propertyDockTitle).toString());
+        }
     }
+
+    emit layoutChanged();
 }
 
 void MainWindow::exportNotes()
@@ -860,3 +927,13 @@ void MainWindow::setupSpellCheck()
     vte::SpellChecker::addDictionaryCustomSearchPaths(
         QStringList() << configMgr.getUserDictsFolder() << configMgr.getAppDictsFolder());
 }
+
+QDockWidget *MainWindow::createDockWidget(DockIndex p_dockIndex, const QString &p_title, QWidget *p_parent)
+{
+    auto dock = new QDockWidget(p_title, p_parent);
+    dock->setToolTip(p_title);
+    dock->setProperty(c_propertyDockIndex, p_dockIndex);
+    dock->setProperty(c_propertyDockTitle, p_title);
+    m_docks.push_back(dock);
+    return dock;
+}

+ 12 - 3
src/widgets/mainwindow.h

@@ -66,6 +66,12 @@ namespace vnotex
 
         void toggleLocationListVisible();
 
+        void updateDockWidgetTabBar();
+
+        static const char *c_propertyDockIndex;
+
+        static const char *c_propertyDockTitle;
+
     signals:
         void mainWindowStarted();
 
@@ -85,8 +91,6 @@ namespace vnotex
     private slots:
         void closeOnQuit();
 
-        void updateTabBarStyle();
-
         void exportNotes();
 
         void showTips(const QString &p_message, int p_timeoutMilliseconds);
@@ -100,7 +104,8 @@ namespace vnotex
             HistoryDock,
             SearchDock,
             SnippetDock,
-            LocationListDock
+            LocationListDock,
+            MaxDock
         };
 
         void setupUI();
@@ -162,6 +167,8 @@ namespace vnotex
 
         void setupSpellCheck();
 
+        QDockWidget *createDockWidget(DockIndex p_dockIndex, const QString &p_title, QWidget *p_parent);
+
         ToolBarHelper m_toolBarHelper;
 
         StatusBarHelper m_statusBarHelper;
@@ -186,6 +193,8 @@ namespace vnotex
 
         QVector<QDockWidget *> m_docks;
 
+        QVector<QIcon> m_dockIcons;
+
         bool m_layoutReset = false;
 
         // -1: do not request to quit;

+ 21 - 4
src/widgets/toolbarhelper.cpp

@@ -77,7 +77,7 @@ QToolBar *ToolBarHelper::setupFileToolBar(MainWindow *p_win, QToolBar *p_toolBar
 
         // Import notebook.
         btnMenu->addAction(generateIcon("import_notebook.svg"),
-                           MainWindow::tr("Import Notebook"),
+                           MainWindow::tr("Open Other Notebooks"),
                            btnMenu,
                            []() {
                                emit VNoteX::getInst().importNotebookRequested();
@@ -85,7 +85,7 @@ QToolBar *ToolBarHelper::setupFileToolBar(MainWindow *p_win, QToolBar *p_toolBar
 
         // Import notebook of VNote 2.
         btnMenu->addAction(generateIcon("import_notebook_of_vnote2.svg"),
-                           MainWindow::tr("Import Legacy Notebook Of VNote 2"),
+                           MainWindow::tr("Open Legacy Notebooks Of VNote 2"),
                            btnMenu,
                            []() {
                                emit VNoteX::getInst().importLegacyNotebookRequested();
@@ -174,7 +174,7 @@ QToolBar *ToolBarHelper::setupFileToolBar(MainWindow *p_win, QToolBar *p_toolBar
 
         newMenu->addSeparator();
 
-        auto exportAct = newMenu->addAction(MainWindow::tr("Export"),
+        auto exportAct = newMenu->addAction(MainWindow::tr("Export (Convert Format)"),
                                             newMenu,
                                             []() {
                                                 emit VNoteX::getInst().exportRequested();
@@ -337,9 +337,26 @@ QToolBar *ToolBarHelper::setupSettingsToolBar(MainWindow *p_win, QToolBar *p_too
 
         {
             // Windows.
+            // MainWindow will clear the title of the dock widget for the tab bar, so we need to use
+            // another action to wrap the no-text action.
             auto subMenu = menu->addMenu(MainWindow::tr("Windows"));
             for (auto dock : p_win->getDocks()) {
-                subMenu->addAction(dock->toggleViewAction());
+                // @act is owned by the QDockWidget.
+                auto act = dock->toggleViewAction();
+                auto actWrapper = subMenu->addAction(act->text());
+                actWrapper->setCheckable(act->isCheckable());
+                actWrapper->setChecked(act->isChecked());
+                MainWindow::connect(act, &QAction::toggled,
+                                    actWrapper, [actWrapper](bool checked) {
+                                        if (actWrapper->isChecked() != checked) {
+                                            actWrapper->setChecked(checked);
+                                        }
+                                    });
+                MainWindow::connect(actWrapper, &QAction::triggered,
+                                    act, [p_win, act]() {
+                                        act->trigger();
+                                        p_win->updateDockWidgetTabBar();
+                                    });
             }
         }
 

Some files were not shown because too many files changed in this diff