diff --git a/src/core/coreconfig.cpp b/src/core/coreconfig.cpp
index ecba94e1..b7271ca8 100644
--- a/src/core/coreconfig.cpp
+++ b/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;
diff --git a/src/core/coreconfig.h b/src/core/coreconfig.h
index 41e81161..d1d03d2a 100644
--- a/src/core/coreconfig.h
+++ b/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.
diff --git a/src/data/core/core.qrc b/src/data/core/core.qrc
index 74756f66..285fa0e3 100644
--- a/src/data/core/core.qrc
+++ b/src/data/core/core.qrc
@@ -15,7 +15,6 @@
icons/read_editor.svg
icons/expand.svg
icons/fullscreen.svg
- icons/history_explorer.svg
icons/tag_explorer.svg
icons/help.svg
icons/menu.svg
@@ -81,6 +80,12 @@
icons/cancel.svg
icons/section_number_editor.svg
icons/sort.svg
+ icons/navigation_dock.svg
+ icons/history_dock.svg
+ icons/outline_dock.svg
+ icons/search_dock.svg
+ icons/snippet_dock.svg
+ icons/location_list_dock.svg
logo/vnote.svg
logo/vnote.png
logo/256x256/vnote.png
diff --git a/src/data/core/icons/history_explorer.svg b/src/data/core/icons/history_dock.svg
similarity index 100%
rename from src/data/core/icons/history_explorer.svg
rename to src/data/core/icons/history_dock.svg
diff --git a/src/data/core/icons/location_list_dock.svg b/src/data/core/icons/location_list_dock.svg
new file mode 100644
index 00000000..5b303164
--- /dev/null
+++ b/src/data/core/icons/location_list_dock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/data/core/icons/navigation_dock.svg b/src/data/core/icons/navigation_dock.svg
new file mode 100644
index 00000000..6557edbe
--- /dev/null
+++ b/src/data/core/icons/navigation_dock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/data/core/icons/outline_dock.svg b/src/data/core/icons/outline_dock.svg
new file mode 100644
index 00000000..7bf1d5b2
--- /dev/null
+++ b/src/data/core/icons/outline_dock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/data/core/icons/search_dock.svg b/src/data/core/icons/search_dock.svg
new file mode 100644
index 00000000..0927bfb2
--- /dev/null
+++ b/src/data/core/icons/search_dock.svg
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/src/data/core/icons/snippet_dock.svg b/src/data/core/icons/snippet_dock.svg
new file mode 100644
index 00000000..339038eb
--- /dev/null
+++ b/src/data/core/icons/snippet_dock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json
index 9d56db6d..eca78743 100644
--- a/src/data/core/vnotex.json
+++ b/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",
diff --git a/src/data/extra/themes/moonlight/interface.qss b/src/data/extra/themes/moonlight/interface.qss
index f5b5641a..a02ec2e0 100644
--- a/src/data/extra/themes/moonlight/interface.qss
+++ b/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;
diff --git a/src/data/extra/themes/moonlight/palette.json b/src/data/extra/themes/moonlight/palette.json
index 26994e32..5cb570c8 100644
--- a/src/data/extra/themes/moonlight/palette.json
+++ b/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"
+ }
+ }
+ }
}
}
}
diff --git a/src/data/extra/themes/native/palette.json b/src/data/extra/themes/native/palette.json
index a3f545de..cdd94883 100644
--- a/src/data/extra/themes/native/palette.json
+++ b/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"
+ }
+ }
+ }
}
}
}
diff --git a/src/data/extra/themes/pure/interface.qss b/src/data/extra/themes/pure/interface.qss
index f5b5641a..a02ec2e0 100644
--- a/src/data/extra/themes/pure/interface.qss
+++ b/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;
diff --git a/src/data/extra/themes/pure/palette.json b/src/data/extra/themes/pure/palette.json
index 5b370a7f..006761b1 100644
--- a/src/data/extra/themes/pure/palette.json
+++ b/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"
+ }
+ }
+ }
}
}
}
diff --git a/src/utils/iconutils.cpp b/src/utils/iconutils.cpp
index 82256eba..cc871d7d 100644
--- a/src/utils/iconutils.cpp
+++ b/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 &p_overriddenColors)
+ const QVector &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);
}
diff --git a/src/utils/iconutils.h b/src/utils/iconutils.h
index ef4e93ed..cf951915 100644
--- a/src/utils/iconutils.h
+++ b/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 &p_overriddenColors);
+ const QVector &p_overriddenColors,
+ qreal p_angle = -1);
static QIcon fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground);
diff --git a/src/widgets/dialogs/dialog.cpp b/src/widgets/dialogs/dialog.cpp
index c3609bfc..a28524f3 100644
--- a/src/widgets/dialogs/dialog.cpp
+++ b/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;
+}
diff --git a/src/widgets/dialogs/dialog.h b/src/widgets/dialogs/dialog.h
index 423c2f5b..5f07d0a4 100644
--- a/src/widgets/dialogs/dialog.h
+++ b/src/widgets/dialogs/dialog.h
@@ -40,6 +40,8 @@ namespace vnotex
bool isCompleted() const;
+ QSize sizeHint() const Q_DECL_OVERRIDE;
+
protected:
virtual void acceptedButtonClicked();
diff --git a/src/widgets/dialogs/importfolderutils.cpp b/src/widgets/dialogs/importfolderutils.cpp
index d5b766ed..96056b19 100644
--- a/src/widgets/dialogs/importfolderutils.cpp
+++ b/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());
diff --git a/src/widgets/dialogs/importlegacynotebookdialog.cpp b/src/widgets/dialogs/importlegacynotebookdialog.cpp
index 1e6d5f4d..0a459bfb 100644
--- a/src/widgets/dialogs/importlegacynotebookdialog.cpp
+++ b/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 ¬ebookMgr = 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());
diff --git a/src/widgets/dialogs/importnotebookdialog.cpp b/src/widgets/dialogs/importnotebookdialog.cpp
index 783f99c9..4d6ceab9 100644
--- a/src/widgets/dialogs/importnotebookdialog.cpp
+++ b/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 ¬ebookMgr = 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;
diff --git a/src/widgets/dialogs/settings/appearancepage.cpp b/src/widgets/dialogs/settings/appearancepage.cpp
index 55c57878..2eb28c7d 100644
--- a/src/widgets/dialogs/settings/appearancepage.cpp
+++ b/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,
diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp
index 50003566..edd12087 100644
--- a/src/widgets/dialogs/settings/settingsdialog.cpp
+++ b/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);
- }
-}
diff --git a/src/widgets/dialogs/settings/settingsdialog.h b/src/widgets/dialogs/settings/settingsdialog.h
index 681f50f5..0b1d74c5 100644
--- a/src/widgets/dialogs/settings/settingsdialog.h
+++ b/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;
};
}
diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp
index d3b7ce84..7ce9ac8f 100644
--- a/src/widgets/mainwindow.cpp
+++ b/src/widgets/mainwindow.cpp
@@ -4,8 +4,8 @@
#include
#include
#include
-#include
#include
+#include
#include
#include
#include
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include "toolbox.h"
#include "notebookexplorer.h"
@@ -48,9 +49,14 @@
#include "searchinfoprovider.h"
#include
#include
+#include
+#include
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 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(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(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;
+}
diff --git a/src/widgets/mainwindow.h b/src/widgets/mainwindow.h
index ac68a1ac..4e710cff 100644
--- a/src/widgets/mainwindow.h
+++ b/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 m_docks;
+ QVector m_dockIcons;
+
bool m_layoutReset = false;
// -1: do not request to quit;
diff --git a/src/widgets/toolbarhelper.cpp b/src/widgets/toolbarhelper.cpp
index 3d1bd887..ddbdd479 100644
--- a/src/widgets/toolbarhelper.cpp
+++ b/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();
+ });
}
}