From 16ba3cf26c10ad38e5beaeec595bac4c4049e83d Mon Sep 17 00:00:00 2001 From: Le Tan Date: Mon, 27 Oct 2025 22:20:48 +0800 Subject: [PATCH 1/4] introduce auto formatting with clang-format --- .clang-format | 297 ++ libs/vtextedit | 2 +- scripts/pre-commit | 45 + src/application.cpp | 99 +- src/application.h | 48 +- src/commandlineoptions.cpp | 140 +- src/commandlineoptions.h | 29 +- src/core/buffer/buffer.cpp | 784 ++- src/core/buffer/buffer.h | 291 +- src/core/buffer/bufferprovider.cpp | 25 +- src/core/buffer/bufferprovider.h | 92 +- src/core/buffer/filebufferprovider.cpp | 240 +- src/core/buffer/filebufferprovider.h | 87 +- src/core/buffer/filetypehelper.cpp | 267 +- src/core/buffer/filetypehelper.h | 88 +- src/core/buffer/ibufferfactory.h | 27 +- src/core/buffer/markdownbuffer.cpp | 143 +- src/core/buffer/markdownbuffer.h | 55 +- src/core/buffer/markdownbufferfactory.cpp | 10 +- src/core/buffer/markdownbufferfactory.h | 19 +- src/core/buffer/mindmapbuffer.cpp | 18 +- src/core/buffer/mindmapbuffer.h | 23 +- src/core/buffer/mindmapbufferfactory.cpp | 10 +- src/core/buffer/mindmapbufferfactory.h | 19 +- src/core/buffer/nodebufferprovider.cpp | 195 +- src/core/buffer/nodebufferprovider.h | 86 +- src/core/buffer/pdfbuffer.cpp | 15 +- src/core/buffer/pdfbuffer.h | 23 +- src/core/buffer/pdfbufferfactory.cpp | 15 +- src/core/buffer/pdfbufferfactory.h | 19 +- src/core/buffer/textbuffer.cpp | 15 +- src/core/buffer/textbuffer.h | 22 +- src/core/buffer/textbufferfactory.cpp | 11 +- src/core/buffer/textbufferfactory.h | 19 +- src/core/buffer/urlbasedbufferprovider.h | 216 +- src/core/buffermgr.cpp | 457 +- src/core/buffermgr.h | 70 +- src/core/clipboarddata.cpp | 261 +- src/core/clipboarddata.h | 96 +- src/core/configmgr.cpp | 838 ++- src/core/configmgr.h | 209 +- src/core/coreconfig.cpp | 493 +- src/core/coreconfig.h | 316 +- src/core/editorconfig.cpp | 445 +- src/core/editorconfig.h | 270 +- src/core/events.h | 31 +- src/core/exception.h | 172 +- src/core/externalfile.cpp | 84 +- src/core/externalfile.h | 55 +- src/core/file.cpp | 10 +- src/core/file.h | 76 +- src/core/filelocator.h | 69 +- src/core/fileopenparameters.h | 66 +- src/core/global.h | 311 +- src/core/historyitem.cpp | 32 +- src/core/historyitem.h | 34 +- src/core/historymgr.cpp | 319 +- src/core/historymgr.h | 102 +- src/core/htmltemplatehelper.cpp | 599 ++- src/core/htmltemplatehelper.h | 185 +- src/core/iconfig.h | 420 +- src/core/location.h | 123 +- src/core/logger.cpp | 177 +- src/core/logger.h | 28 +- src/core/mainconfig.cpp | 130 +- src/core/mainconfig.h | 66 +- src/core/markdowneditorconfig.cpp | 740 ++- src/core/markdowneditorconfig.h | 333 +- src/core/mindmapeditorconfig.cpp | 65 +- src/core/mindmapeditorconfig.h | 30 +- src/core/namebasedserver.h | 75 +- src/core/noncopyable.h | 20 +- src/core/notebook/bundlenotebook.cpp | 332 +- src/core/notebook/bundlenotebook.h | 105 +- src/core/notebook/bundlenotebookfactory.cpp | 131 +- src/core/notebook/bundlenotebookfactory.h | 45 +- src/core/notebook/externalnode.cpp | 27 +- src/core/notebook/externalnode.h | 46 +- src/core/notebook/historyi.h | 24 +- src/core/notebook/inotebookfactory.h | 74 +- src/core/notebook/node.cpp | 679 +-- src/core/notebook/node.h | 288 +- src/core/notebook/nodeparameters.cpp | 5 +- src/core/notebook/nodeparameters.h | 30 +- src/core/notebook/nodevisual.cpp | 24 +- src/core/notebook/nodevisual.h | 69 +- src/core/notebook/notebook.cpp | 493 +- src/core/notebook/notebook.h | 269 +- src/core/notebook/notebookdatabaseaccess.cpp | 1350 +++-- src/core/notebook/notebookdatabaseaccess.h | 170 +- src/core/notebook/notebookparameters.cpp | 80 +- src/core/notebook/notebookparameters.h | 111 +- src/core/notebook/notebooktagmgr.cpp | 464 +- src/core/notebook/notebooktagmgr.h | 79 +- src/core/notebook/tag.cpp | 45 +- src/core/notebook/tag.h | 38 +- src/core/notebook/tagi.h | 36 +- src/core/notebook/vxnode.cpp | 137 +- src/core/notebook/vxnode.h | 44 +- src/core/notebook/vxnodefile.cpp | 100 +- src/core/notebook/vxnodefile.h | 57 +- src/core/notebookbackend/inotebookbackend.cpp | 27 +- src/core/notebookbackend/inotebookbackend.h | 136 +- .../notebookbackend/inotebookbackendfactory.h | 30 +- .../notebookbackend/localnotebookbackend.cpp | 265 +- .../notebookbackend/localnotebookbackend.h | 105 +- .../localnotebookbackendfactory.cpp | 29 +- .../localnotebookbackendfactory.h | 23 +- .../bundlenotebookconfigmgr.cpp | 112 +- .../bundlenotebookconfigmgr.h | 67 +- .../notebookconfigmgr/inotebookconfigmgr.cpp | 24 +- .../notebookconfigmgr/inotebookconfigmgr.h | 117 +- .../inotebookconfigmgrfactory.h | 34 +- src/core/notebookconfigmgr/notebookconfig.cpp | 177 +- src/core/notebookconfigmgr/notebookconfig.h | 68 +- src/core/notebookconfigmgr/vxnodeconfig.cpp | 391 +- src/core/notebookconfigmgr/vxnodeconfig.h | 144 +- .../notebookconfigmgr/vxnotebookconfigmgr.cpp | 1689 +++--- .../notebookconfigmgr/vxnotebookconfigmgr.h | 214 +- .../vxnotebookconfigmgrfactory.cpp | 33 +- .../vxnotebookconfigmgrfactory.h | 31 +- src/core/notebookmgr.cpp | 545 +- src/core/notebookmgr.h | 149 +- src/core/pdfviewerconfig.cpp | 65 +- src/core/pdfviewerconfig.h | 30 +- src/core/quickaccesshelper.cpp | 21 +- src/core/quickaccesshelper.h | 18 +- src/core/sessionconfig.cpp | 903 ++-- src/core/sessionconfig.h | 294 +- src/core/singleinstanceguard.cpp | 343 +- src/core/singleinstanceguard.h | 99 +- src/core/templatemgr.cpp | 38 +- src/core/templatemgr.h | 45 +- src/core/texteditorconfig.cpp | 345 +- src/core/texteditorconfig.h | 129 +- src/core/theme.cpp | 753 ++- src/core/theme.h | 159 +- src/core/thememgr.cpp | 337 +- src/core/thememgr.h | 123 +- .../dummyversioncontroller.cpp | 27 +- .../dummyversioncontroller.h | 38 +- .../dummyversioncontrollerfactory.cpp | 27 +- .../dummyversioncontrollerfactory.h | 23 +- .../versioncontroller/iversioncontroller.h | 31 +- .../iversioncontrollerfactory.h | 30 +- .../versioncontrollerserver.cpp | 47 +- .../versioncontrollerserver.h | 32 +- src/core/vnotex.cpp | 169 +- src/core/vnotex.h | 196 +- src/core/webresource.h | 178 +- src/core/widgetconfig.cpp | 259 +- src/core/widgetconfig.h | 114 +- src/export/exportdata.cpp | 366 +- src/export/exportdata.h | 175 +- src/export/exporter.cpp | 1034 ++-- src/export/exporter.h | 117 +- src/export/webviewexporter.cpp | 916 ++-- src/export/webviewexporter.h | 117 +- src/fakeaccessible.cpp | 101 +- src/fakeaccessible.h | 53 +- src/imagehost/giteeimagehost.cpp | 276 +- src/imagehost/giteeimagehost.h | 49 +- src/imagehost/githubimagehost.cpp | 302 +- src/imagehost/githubimagehost.h | 53 +- src/imagehost/imagehost.cpp | 36 +- src/imagehost/imagehost.h | 63 +- src/imagehost/imagehostmgr.cpp | 258 +- src/imagehost/imagehostmgr.h | 61 +- src/imagehost/imagehostutils.cpp | 29 +- src/imagehost/imagehostutils.h | 20 +- src/imagehost/repoimagehost.cpp | 78 +- src/imagehost/repoimagehost.h | 41 +- src/main.cpp | 434 +- src/search/filesearchengine.cpp | 343 +- src/search/filesearchengine.h | 102 +- src/search/isearchengine.h | 61 +- src/search/isearchinfoprovider.h | 30 +- src/search/searchdata.cpp | 65 +- src/search/searchdata.h | 176 +- src/search/searcher.cpp | 792 ++- src/search/searcher.h | 124 +- src/search/searchhelper.cpp | 148 +- src/search/searchhelper.h | 28 +- src/search/searchresultitem.cpp | 92 +- src/search/searchresultitem.h | 75 +- src/search/searchtoken.cpp | 438 +- src/search/searchtoken.h | 92 +- src/snippet/dynamicsnippet.cpp | 31 +- src/snippet/dynamicsnippet.h | 31 +- src/snippet/snippet.cpp | 223 +- src/snippet/snippet.h | 118 +- src/snippet/snippetmgr.cpp | 653 ++- src/snippet/snippetmgr.h | 130 +- src/task/shellexecution.cpp | 90 +- src/task/shellexecution.h | 35 +- src/task/task.cpp | 870 ++-- src/task/task.h | 210 +- src/task/taskmgr.cpp | 137 +- src/task/taskmgr.h | 62 +- src/task/taskvariablemgr.cpp | 697 ++- src/task/taskvariablemgr.h | 120 +- src/unitedentry/entrypopup.cpp | 59 +- src/unitedentry/entrypopup.h | 28 +- src/unitedentry/entrywidgetfactory.cpp | 30 +- src/unitedentry/entrywidgetfactory.h | 18 +- src/unitedentry/findunitedentry.cpp | 528 +- src/unitedentry/findunitedentry.h | 75 +- src/unitedentry/helpunitedentry.cpp | 63 +- src/unitedentry/helpunitedentry.h | 40 +- src/unitedentry/iunitedentry.cpp | 193 +- src/unitedentry/iunitedentry.h | 94 +- src/unitedentry/unitedentry.cpp | 790 ++- src/unitedentry/unitedentry.h | 98 +- src/unitedentry/unitedentryalias.cpp | 126 +- src/unitedentry/unitedentryalias.h | 61 +- src/unitedentry/unitedentryhelper.cpp | 88 +- src/unitedentry/unitedentryhelper.h | 53 +- src/unitedentry/unitedentrymgr.cpp | 91 +- src/unitedentry/unitedentrymgr.h | 59 +- src/utils/asyncworker.cpp | 37 +- src/utils/asyncworker.h | 52 +- src/utils/callbackpool.cpp | 33 +- src/utils/callbackpool.h | 28 +- src/utils/clipboardutils.cpp | 316 +- src/utils/clipboardutils.h | 58 +- src/utils/contentmediautils.cpp | 328 +- src/utils/contentmediautils.h | 88 +- src/utils/docsutils.cpp | 66 +- src/utils/docsutils.h | 28 +- src/utils/fileutils.cpp | 545 +- src/utils/fileutils.h | 99 +- src/utils/htmlutils.cpp | 35 +- src/utils/htmlutils.h | 20 +- src/utils/iconutils.cpp | 279 +- src/utils/iconutils.h | 111 +- src/utils/imageutils.cpp | 16 +- src/utils/imageutils.h | 18 +- src/utils/pathutils.cpp | 325 +- src/utils/pathutils.h | 96 +- src/utils/printutils.cpp | 24 +- src/utils/printutils.h | 18 +- src/utils/processutils.cpp | 265 +- src/utils/processutils.h | 85 +- src/utils/urldragdroputils.cpp | 51 +- src/utils/urldragdroputils.h | 20 +- src/utils/utils.cpp | 308 +- src/utils/utils.h | 64 +- src/utils/vxurlutils.cpp | 241 +- src/utils/vxurlutils.h | 42 +- src/utils/webutils.cpp | 154 +- src/utils/webutils.h | 22 +- src/utils/widgetutils.cpp | 719 ++- src/utils/widgetutils.h | 101 +- .../attachmentdragdropareaindicator.cpp | 45 +- src/widgets/attachmentdragdropareaindicator.h | 26 +- src/widgets/attachmentpopup.cpp | 573 +-- src/widgets/attachmentpopup.h | 62 +- src/widgets/biaction.cpp | 127 +- src/widgets/biaction.h | 67 +- src/widgets/buttonpopup.cpp | 41 +- src/widgets/buttonpopup.h | 28 +- src/widgets/combobox.cpp | 24 +- src/widgets/combobox.h | 18 +- src/widgets/consoleviewer.cpp | 67 +- src/widgets/consoleviewer.h | 32 +- src/widgets/dialogs/deleteconfirmdialog.cpp | 310 +- src/widgets/dialogs/deleteconfirmdialog.h | 158 +- src/widgets/dialogs/dialog.cpp | 254 +- src/widgets/dialogs/dialog.h | 74 +- src/widgets/dialogs/exportdialog.cpp | 1502 +++--- src/widgets/dialogs/exportdialog.h | 212 +- src/widgets/dialogs/filepropertiesdialog.cpp | 58 +- src/widgets/dialogs/filepropertiesdialog.h | 28 +- .../dialogs/folderfilesfilterwidget.cpp | 297 +- src/widgets/dialogs/folderfilesfilterwidget.h | 58 +- .../dialogs/folderpropertiesdialog.cpp | 127 +- src/widgets/dialogs/folderpropertiesdialog.h | 40 +- src/widgets/dialogs/imageinsertdialog.cpp | 539 +- src/widgets/dialogs/imageinsertdialog.h | 128 +- src/widgets/dialogs/importfolderdialog.cpp | 167 +- src/widgets/dialogs/importfolderdialog.h | 46 +- src/widgets/dialogs/importfolderutils.cpp | 196 +- src/widgets/dialogs/importfolderutils.h | 54 +- .../dialogs/importlegacynotebookdialog.cpp | 238 +- .../dialogs/importlegacynotebookdialog.h | 26 +- src/widgets/dialogs/importnotebookdialog.cpp | 211 +- src/widgets/dialogs/importnotebookdialog.h | 44 +- src/widgets/dialogs/legacynotebookutils.cpp | 122 +- src/widgets/dialogs/legacynotebookutils.h | 57 +- .../dialogs/levellabelwithupbutton.cpp | 100 +- src/widgets/dialogs/levellabelwithupbutton.h | 55 +- src/widgets/dialogs/linkinsertdialog.cpp | 144 +- src/widgets/dialogs/linkinsertdialog.h | 45 +- src/widgets/dialogs/managenotebooksdialog.cpp | 464 +- src/widgets/dialogs/managenotebooksdialog.h | 72 +- src/widgets/dialogs/newfolderdialog.cpp | 120 +- src/widgets/dialogs/newfolderdialog.h | 44 +- src/widgets/dialogs/newnotebookdialog.cpp | 209 +- src/widgets/dialogs/newnotebookdialog.h | 44 +- .../dialogs/newnotebookfromfolderdialog.cpp | 254 +- .../dialogs/newnotebookfromfolderdialog.h | 54 +- src/widgets/dialogs/newnotedialog.cpp | 232 +- src/widgets/dialogs/newnotedialog.h | 62 +- src/widgets/dialogs/newsnippetdialog.cpp | 110 +- src/widgets/dialogs/newsnippetdialog.h | 36 +- src/widgets/dialogs/newtagdialog.cpp | 138 +- src/widgets/dialogs/newtagdialog.h | 48 +- src/widgets/dialogs/nodeinfowidget.cpp | 303 +- src/widgets/dialogs/nodeinfowidget.h | 76 +- src/widgets/dialogs/notebookinfowidget.cpp | 537 +- src/widgets/dialogs/notebookinfowidget.h | 116 +- src/widgets/dialogs/notepropertiesdialog.cpp | 129 +- src/widgets/dialogs/notepropertiesdialog.h | 40 +- src/widgets/dialogs/notetemplateselector.cpp | 142 +- src/widgets/dialogs/notetemplateselector.h | 40 +- src/widgets/dialogs/renametagdialog.cpp | 101 +- src/widgets/dialogs/renametagdialog.h | 40 +- src/widgets/dialogs/scrolldialog.cpp | 50 +- src/widgets/dialogs/scrolldialog.h | 30 +- src/widgets/dialogs/selectdialog.cpp | 202 +- src/widgets/dialogs/selectdialog.h | 62 +- src/widgets/dialogs/selectionitemwidget.cpp | 93 +- src/widgets/dialogs/selectionitemwidget.h | 59 +- .../dialogs/settings/appearancepage.cpp | 181 +- src/widgets/dialogs/settings/appearancepage.h | 38 +- src/widgets/dialogs/settings/editorpage.cpp | 276 +- src/widgets/dialogs/settings/editorpage.h | 40 +- .../dialogs/settings/fileassociationpage.cpp | 171 +- .../dialogs/settings/fileassociationpage.h | 40 +- src/widgets/dialogs/settings/generalpage.cpp | 218 +- src/widgets/dialogs/settings/generalpage.h | 38 +- .../dialogs/settings/imagehostpage.cpp | 470 +- src/widgets/dialogs/settings/imagehostpage.h | 58 +- .../dialogs/settings/markdowneditorpage.cpp | 1059 ++-- .../dialogs/settings/markdowneditorpage.h | 92 +- src/widgets/dialogs/settings/miscpage.cpp | 29 +- src/widgets/dialogs/settings/miscpage.h | 28 +- .../dialogs/settings/newimagehostdialog.cpp | 114 +- .../dialogs/settings/newimagehostdialog.h | 38 +- .../dialogs/settings/notemanagementpage.cpp | 165 +- .../dialogs/settings/notemanagementpage.h | 34 +- .../dialogs/settings/quickaccesspage.cpp | 524 +- .../dialogs/settings/quickaccesspage.h | 74 +- .../dialogs/settings/settingsdialog.cpp | 492 +- src/widgets/dialogs/settings/settingsdialog.h | 70 +- src/widgets/dialogs/settings/settingspage.cpp | 145 +- src/widgets/dialogs/settings/settingspage.h | 89 +- .../dialogs/settings/texteditorpage.cpp | 392 +- src/widgets/dialogs/settings/texteditorpage.h | 48 +- src/widgets/dialogs/settings/themepage.cpp | 254 +- src/widgets/dialogs/settings/themepage.h | 40 +- src/widgets/dialogs/settings/vipage.cpp | 61 +- src/widgets/dialogs/settings/vipage.h | 30 +- src/widgets/dialogs/snippetinfowidget.cpp | 291 +- src/widgets/dialogs/snippetinfowidget.h | 72 +- .../dialogs/snippetpropertiesdialog.cpp | 124 +- src/widgets/dialogs/snippetpropertiesdialog.h | 40 +- src/widgets/dialogs/sortdialog.cpp | 393 +- src/widgets/dialogs/sortdialog.h | 74 +- src/widgets/dialogs/tableinsertdialog.cpp | 140 +- src/widgets/dialogs/tableinsertdialog.h | 32 +- src/widgets/dialogs/updater.cpp | 148 +- src/widgets/dialogs/updater.h | 36 +- src/widgets/dialogs/viewtagsdialog.cpp | 72 +- src/widgets/dialogs/viewtagsdialog.h | 38 +- src/widgets/dockwidgethelper.cpp | 856 ++-- src/widgets/dockwidgethelper.h | 159 +- src/widgets/dragdropareaindicator.cpp | 59 +- src/widgets/dragdropareaindicator.h | 50 +- src/widgets/editors/graphhelper.cpp | 308 +- src/widgets/editors/graphhelper.h | 107 +- src/widgets/editors/graphvizhelper.cpp | 93 +- src/widgets/editors/graphvizhelper.h | 29 +- src/widgets/editors/markdowneditor.cpp | 2876 +++++------ src/widgets/editors/markdowneditor.h | 275 +- src/widgets/editors/markdowntable.cpp | 1218 +++-- src/widgets/editors/markdowntable.h | 189 +- src/widgets/editors/markdowntablehelper.cpp | 162 +- src/widgets/editors/markdowntablehelper.h | 47 +- src/widgets/editors/markdownviewer.cpp | 662 ++- src/widgets/editors/markdownviewer.h | 103 +- src/widgets/editors/markdownvieweradapter.cpp | 601 +-- src/widgets/editors/markdownvieweradapter.h | 313 +- src/widgets/editors/mindmapeditor.cpp | 50 +- src/widgets/editors/mindmapeditor.h | 52 +- src/widgets/editors/mindmapeditoradapter.cpp | 84 +- src/widgets/editors/mindmapeditoradapter.h | 64 +- src/widgets/editors/pdfviewer.cpp | 21 +- src/widgets/editors/pdfviewer.h | 30 +- src/widgets/editors/pdfvieweradapter.cpp | 22 +- src/widgets/editors/pdfvieweradapter.h | 32 +- src/widgets/editors/plantumlhelper.cpp | 135 +- src/widgets/editors/plantumlhelper.h | 43 +- src/widgets/editors/previewhelper.cpp | 777 ++- src/widgets/editors/previewhelper.h | 293 +- src/widgets/editors/statuswidget.cpp | 94 +- src/widgets/editors/statuswidget.h | 46 +- src/widgets/editors/texteditor.cpp | 36 +- src/widgets/editors/texteditor.h | 28 +- src/widgets/editors/webviewadapter.cpp | 124 +- src/widgets/editors/webviewadapter.h | 82 +- src/widgets/editreaddiscardaction.cpp | 73 +- src/widgets/editreaddiscardaction.h | 57 +- src/widgets/filesystemviewer.cpp | 363 +- src/widgets/filesystemviewer.h | 75 +- src/widgets/findandreplacewidget.cpp | 556 +- src/widgets/findandreplacewidget.h | 87 +- src/widgets/floatingwidget.cpp | 30 +- src/widgets/floatingwidget.h | 36 +- .../framelessmainwindow.cpp | 51 +- .../framelessmainwindow/framelessmainwindow.h | 48 +- .../framelessmainwindowimpl.h | 11 +- .../framelessmainwindowlinux.cpp | 199 +- .../framelessmainwindowlinux.h | 84 +- .../framelessmainwindowwin.cpp | 372 +- .../framelessmainwindowwin.h | 58 +- src/widgets/fullscreentoggleaction.cpp | 68 +- src/widgets/fullscreentoggleaction.h | 32 +- src/widgets/historypanel.cpp | 315 +- src/widgets/historypanel.h | 69 +- src/widgets/itemproxystyle.cpp | 442 +- src/widgets/itemproxystyle.h | 49 +- src/widgets/labelwithbuttonswidget.cpp | 99 +- src/widgets/labelwithbuttonswidget.h | 47 +- src/widgets/lineedit.cpp | 184 +- src/widgets/lineedit.h | 42 +- src/widgets/lineeditdelegate.cpp | 46 +- src/widgets/lineeditdelegate.h | 33 +- src/widgets/lineeditwithsnippet.cpp | 25 +- src/widgets/lineeditwithsnippet.h | 28 +- src/widgets/listwidget.cpp | 246 +- src/widgets/listwidget.h | 63 +- src/widgets/locationinputwithbrowsebutton.cpp | 54 +- src/widgets/locationinputwithbrowsebutton.h | 36 +- src/widgets/locationlist.cpp | 358 +- src/widgets/locationlist.h | 71 +- src/widgets/mainwindow.cpp | 1263 +++-- src/widgets/mainwindow.h | 226 +- src/widgets/markdownviewwindow.cpp | 2339 ++++----- src/widgets/markdownviewwindow.h | 275 +- src/widgets/messageboxhelper.cpp | 238 +- src/widgets/messageboxhelper.h | 101 +- src/widgets/mindmapviewwindow.cpp | 851 ++- src/widgets/mindmapviewwindow.h | 113 +- src/widgets/navigationmode.cpp | 324 +- src/widgets/navigationmode.h | 88 +- src/widgets/navigationmodemgr.cpp | 218 +- src/widgets/navigationmodemgr.h | 72 +- src/widgets/navigationmodewrapper.h | 153 +- src/widgets/notebookexplorer.cpp | 1085 ++-- src/widgets/notebookexplorer.h | 104 +- src/widgets/notebookexplorersession.cpp | 46 +- src/widgets/notebookexplorersession.h | 45 +- src/widgets/notebooknodeexplorer.cpp | 4557 ++++++++--------- src/widgets/notebooknodeexplorer.h | 491 +- src/widgets/notebookselector.cpp | 403 +- src/widgets/notebookselector.h | 74 +- src/widgets/outlinepopup.cpp | 44 +- src/widgets/outlinepopup.h | 34 +- src/widgets/outlineprovider.cpp | 130 +- src/widgets/outlineprovider.h | 144 +- src/widgets/outlineviewer.cpp | 542 +- src/widgets/outlineviewer.h | 97 +- src/widgets/pdfviewwindow.cpp | 196 +- src/widgets/pdfviewwindow.h | 77 +- src/widgets/propertydefs.h | 46 +- src/widgets/qtreewidgetstatecache.h | 149 +- src/widgets/quickselector.cpp | 340 +- src/widgets/quickselector.h | 77 +- src/widgets/searchinfoprovider.cpp | 56 +- src/widgets/searchinfoprovider.h | 43 +- src/widgets/searchpanel.cpp | 749 ++- src/widgets/searchpanel.h | 126 +- src/widgets/simplesegmenthighlighter.cpp | 36 +- src/widgets/simplesegmenthighlighter.h | 32 +- src/widgets/snippetpanel.cpp | 375 +- src/widgets/snippetpanel.h | 54 +- src/widgets/statusbarhelper.cpp | 7 +- src/widgets/statusbarhelper.h | 18 +- src/widgets/styleditemdelegate.cpp | 209 +- src/widgets/styleditemdelegate.h | 99 +- src/widgets/systemtrayhelper.cpp | 66 +- src/widgets/systemtrayhelper.h | 18 +- src/widgets/tagexplorer.cpp | 875 ++-- src/widgets/tagexplorer.h | 111 +- src/widgets/tagpopup.cpp | 48 +- src/widgets/tagpopup.h | 32 +- src/widgets/tagviewer.cpp | 484 +- src/widgets/tagviewer.h | 80 +- src/widgets/textviewwindow.cpp | 435 +- src/widgets/textviewwindow.h | 119 +- src/widgets/textviewwindowhelper.h | 686 ++- src/widgets/titlebar.cpp | 260 +- src/widgets/titlebar.h | 144 +- src/widgets/titletoolbar.cpp | 78 +- src/widgets/titletoolbar.h | 42 +- src/widgets/toolbarhelper.cpp | 1309 +++-- src/widgets/toolbarhelper.h | 61 +- src/widgets/toolbox.cpp | 235 +- src/widgets/toolbox.h | 92 +- src/widgets/treeview.cpp | 16 +- src/widgets/treeview.h | 20 +- src/widgets/treewidget.cpp | 449 +- src/widgets/treewidget.h | 96 +- src/widgets/treewidgetitem.cpp | 43 +- src/widgets/treewidgetitem.h | 21 +- src/widgets/viewarea.cpp | 2500 +++++---- src/widgets/viewarea.h | 328 +- src/widgets/viewareasession.cpp | 119 +- src/widgets/viewareasession.h | 67 +- src/widgets/viewsplit.cpp | 1867 ++++--- src/widgets/viewsplit.h | 199 +- src/widgets/viewwindow.cpp | 2131 ++++---- src/widgets/viewwindow.h | 499 +- src/widgets/viewwindowsession.cpp | 40 +- src/widgets/viewwindowsession.h | 24 +- src/widgets/viewwindowtoolbarhelper.cpp | 812 ++- src/widgets/viewwindowtoolbarhelper.h | 101 +- src/widgets/webpage.cpp | 67 +- src/widgets/webpage.h | 29 +- src/widgets/webviewer.cpp | 77 +- src/widgets/webviewer.h | 26 +- src/widgets/widgetsfactory.cpp | 124 +- src/widgets/widgetsfactory.h | 47 +- src/widgets/windowspanel.cpp | 114 +- src/widgets/windowspanel.h | 40 +- src/widgets/windowsprovider.cpp | 56 +- src/widgets/windowsprovider.h | 48 +- src/widgets/wordcountpopup.cpp | 91 +- src/widgets/wordcountpopup.h | 63 +- 530 files changed, 50054 insertions(+), 57257 deletions(-) create mode 100644 .clang-format create mode 100644 scripts/pre-commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..7e15438194 --- /dev/null +++ b/.clang-format @@ -0,0 +1,297 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: true + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AllowShortNamespacesOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AttributeMacros: + - __capability +BinPackArguments: true +BinPackLongBracedList: true +BinPackParameters: BinPack +BitFieldColonSpacing: Both +BracedInitializerIndentWidth: -1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: None +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTemplateCloser: false +BreakBeforeTernaryOperators: true +BreakBinaryOperations: Never +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: MultiLine +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +EnumTrailingComma: Leave +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +KeepFormFeed: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +OneLineFormatOffRegex: '' +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakBeforeMemberAccess: 150 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: Always +RemoveBracesLLVM: false +RemoveEmptyLinesInUnwrappedLines: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: + Enabled: true + IgnoreCase: false +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterOperatorKeyword: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterNot: false + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +WrapNamespaceBodyWithEmptyLines: Leave +... + diff --git a/libs/vtextedit b/libs/vtextedit index c8fe95efd4..b4a773a41c 160000 --- a/libs/vtextedit +++ b/libs/vtextedit @@ -1 +1 @@ -Subproject commit c8fe95efd4ee7ddbe3c1e4b517c32b293ff15d79 +Subproject commit b4a773a41c692469d2132dc78aeb12b98168b59d diff --git a/scripts/pre-commit b/scripts/pre-commit new file mode 100644 index 0000000000..40669d3815 --- /dev/null +++ b/scripts/pre-commit @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Pre-commit hook to format C++ files with clang-format +# Excludes third-party library folders + +# Folders to exclude (third-party sources) +EXCLUDE_DIRS="libs" + +# Get list of staged C++ files +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(cpp|h|c|cc|cxx|hpp)$') + +if [ -z "$STAGED_FILES" ]; then + exit 0 +fi + +# Check if clang-format is available +if ! command -v clang-format >/dev/null 2>&1; then + echo "Warning: clang-format not found. Skipping formatting." + echo "Install clang-format to enable automatic formatting." + exit 0 +fi + +# Format each file that is not in excluded directories +for FILE in $STAGED_FILES; do + # Check if file is in excluded directory + EXCLUDED=0 + for EXCLUDE_DIR in $EXCLUDE_DIRS; do + case "$FILE" in + $EXCLUDE_DIR/*) + EXCLUDED=1 + break + ;; + esac + done + + if [ $EXCLUDED -eq 0 ]; then + echo "Formatting: $FILE" + clang-format -i "$FILE" + git add "$FILE" + else + echo "Skipping (third-party): $FILE" + fi +done + +exit 0 diff --git a/src/application.cpp b/src/application.cpp index 6585accf1d..10386c0f96 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,75 +1,68 @@ #include "application.h" -#include #include #include -#include +#include #include +#include #include #include using namespace vnotex; -Application::Application(int &p_argc, char **p_argv) - : QApplication(p_argc, p_argv) -{ -} +Application::Application(int &p_argc, char **p_argv) : QApplication(p_argc, p_argv) {} -void Application::watchThemeFolder(const QString &p_themeFolderPath) -{ - if (p_themeFolderPath.isEmpty()) { - return; - } +void Application::watchThemeFolder(const QString &p_themeFolderPath) { + if (p_themeFolderPath.isEmpty()) { + return; + } - // Initialize watchers only when needed - if (!m_styleWatcher) { - m_styleWatcher = new QFileSystemWatcher(this); - } - if (!m_reloadTimer) { - m_reloadTimer = new QTimer(this); - m_reloadTimer->setSingleShot(true); - m_reloadTimer->setInterval(500); // 500ms debounce delay - connect(m_reloadTimer, &QTimer::timeout, - this, &Application::reloadThemeResources); + // Initialize watchers only when needed + if (!m_styleWatcher) { + m_styleWatcher = new QFileSystemWatcher(this); + } + if (!m_reloadTimer) { + m_reloadTimer = new QTimer(this); + m_reloadTimer->setSingleShot(true); + m_reloadTimer->setInterval(500); // 500ms debounce delay + connect(m_reloadTimer, &QTimer::timeout, this, &Application::reloadThemeResources); - // Connect file watcher to timer - connect(m_styleWatcher, &QFileSystemWatcher::directoryChanged, - m_reloadTimer, qOverload<>(&QTimer::start)); - connect(m_styleWatcher, &QFileSystemWatcher::fileChanged, - m_reloadTimer, qOverload<>(&QTimer::start)); - } + // Connect file watcher to timer + connect(m_styleWatcher, &QFileSystemWatcher::directoryChanged, m_reloadTimer, + qOverload<>(&QTimer::start)); + connect(m_styleWatcher, &QFileSystemWatcher::fileChanged, m_reloadTimer, + qOverload<>(&QTimer::start)); + } - // Watch the theme folder and its files - m_styleWatcher->addPath(p_themeFolderPath); + // Watch the theme folder and its files + m_styleWatcher->addPath(p_themeFolderPath); - // Also watch individual files in the theme folder - QDir themeDir(p_themeFolderPath); - QStringList files = themeDir.entryList(QDir::Files); - for (const QString &file : files) { - m_styleWatcher->addPath(themeDir.filePath(file)); - } + // Also watch individual files in the theme folder + QDir themeDir(p_themeFolderPath); + QStringList files = themeDir.entryList(QDir::Files); + for (const QString &file : files) { + m_styleWatcher->addPath(themeDir.filePath(file)); + } } -void Application::reloadThemeResources() -{ - VNoteX::getInst().getThemeMgr().refreshCurrentTheme(); +void Application::reloadThemeResources() { + VNoteX::getInst().getThemeMgr().refreshCurrentTheme(); - auto stylesheet = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet(); - if (!stylesheet.isEmpty()) { - setStyleSheet(stylesheet); - style()->unpolish(this); - style()->polish(this); - } + auto stylesheet = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet(); + if (!stylesheet.isEmpty()) { + setStyleSheet(stylesheet); + style()->unpolish(this); + style()->polish(this); + } } -bool Application::event(QEvent *p_event) -{ - // On macOS, we need this to open file from Finder. - if (p_event->type() == QEvent::FileOpen) { - QFileOpenEvent *openEvent = static_cast(p_event); - qDebug() << "request to open file" << openEvent->file(); - emit openFileRequested(openEvent->file()); - } +bool Application::event(QEvent *p_event) { + // On macOS, we need this to open file from Finder. + if (p_event->type() == QEvent::FileOpen) { + QFileOpenEvent *openEvent = static_cast(p_event); + qDebug() << "request to open file" << openEvent->file(); + emit openFileRequested(openEvent->file()); + } - return QApplication::event(p_event); + return QApplication::event(p_event); } diff --git a/src/application.h b/src/application.h index 74060bf237..1477f1c3ff 100644 --- a/src/application.h +++ b/src/application.h @@ -5,30 +5,28 @@ class QFileSystemWatcher; class QTimer; -namespace vnotex -{ - class Application : public QApplication - { - Q_OBJECT - public: - Application(int &p_argc, char **p_argv); - - // Set up theme folder watcher for hot-reload - void watchThemeFolder(const QString &p_themeFolderPath); - - // Reload the theme resources (stylesheet, icons, etc) - void reloadThemeResources(); - - signals: - void openFileRequested(const QString &p_filePath); - - protected: - bool event(QEvent *p_event) Q_DECL_OVERRIDE; - - private: - QFileSystemWatcher *m_styleWatcher = nullptr; - QTimer *m_reloadTimer = nullptr; - }; -} +namespace vnotex { +class Application : public QApplication { + Q_OBJECT +public: + Application(int &p_argc, char **p_argv); + + // Set up theme folder watcher for hot-reload + void watchThemeFolder(const QString &p_themeFolderPath); + + // Reload the theme resources (stylesheet, icons, etc) + void reloadThemeResources(); + +signals: + void openFileRequested(const QString &p_filePath); + +protected: + bool event(QEvent *p_event) Q_DECL_OVERRIDE; + +private: + QFileSystemWatcher *m_styleWatcher = nullptr; + QTimer *m_reloadTimer = nullptr; +}; +} // namespace vnotex #endif // APPLICATION_H diff --git a/src/commandlineoptions.cpp b/src/commandlineoptions.cpp index e0449ed066..8736432f47 100644 --- a/src/commandlineoptions.cpp +++ b/src/commandlineoptions.cpp @@ -1,7 +1,7 @@ #include "commandlineoptions.h" -#include #include +#include #include #include @@ -9,73 +9,73 @@ using vnotex::MainWindow; -CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_arguments) -{ - QCommandLineParser parser; - parser.setApplicationDescription(MainWindow::tr("A pleasant note-taking platform.")); - const auto helpOpt = parser.addHelpOption(); - const auto versionOpt = parser.addVersionOption(); - - // Positional arguments. - parser.addPositionalArgument("paths", MainWindow::tr("Files or folders to open.")); - - const QCommandLineOption verboseOpt("verbose", MainWindow::tr("Print more logs.")); - parser.addOption(verboseOpt); - - const QCommandLineOption logStderrOpt("log-stderr", MainWindow::tr("Log to stderr.")); - parser.addOption(logStderrOpt); - - const QCommandLineOption watchThemesOpt("watch-themes", MainWindow::tr("Watch theme folder for changes.")); - parser.addOption(watchThemesOpt); - - // WebEngine options. - // No need to handle them. Just add them to the parser to avoid parse error. - { - QCommandLineOption webRemoteDebuggingPortOpt("remote-debugging-port", - MainWindow::tr("WebEngine remote debugging port."), - MainWindow::tr("port_number")); - webRemoteDebuggingPortOpt.setFlags(QCommandLineOption::HiddenFromHelp); - parser.addOption(webRemoteDebuggingPortOpt); - - QCommandLineOption webNoSandboxOpt("no-sandbox", MainWindow::tr("WebEngine without sandbox.")); - webNoSandboxOpt.setFlags(QCommandLineOption::HiddenFromHelp); - parser.addOption(webNoSandboxOpt); - - QCommandLineOption webDisableGpu("disable-gpu", MainWindow::tr("WebEngine with GPU disabled.")); - webDisableGpu.setFlags(QCommandLineOption::HiddenFromHelp); - parser.addOption(webDisableGpu); - } - - if (!parser.parse(p_arguments)) { - m_errorMsg = parser.errorText(); - return ParseResult::Error; - } - - // Handle results. - m_helpText = parser.helpText(); - if (parser.isSet(helpOpt)) { - return ParseResult::HelpRequested; - } - - if (parser.isSet(versionOpt)) { - return ParseResult::VersionRequested; - } - - // Position arguments. - const auto args = parser.positionalArguments(); - m_pathsToOpen = args; - - if (parser.isSet(verboseOpt)) { - m_verbose = true; - } - - if (parser.isSet(logStderrOpt)) { - m_logToStderr = true; - } - - if (parser.isSet(watchThemesOpt)) { - m_watchThemes = true; - } - - return ParseResult::Ok; +CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_arguments) { + QCommandLineParser parser; + parser.setApplicationDescription(MainWindow::tr("A pleasant note-taking platform.")); + const auto helpOpt = parser.addHelpOption(); + const auto versionOpt = parser.addVersionOption(); + + // Positional arguments. + parser.addPositionalArgument("paths", MainWindow::tr("Files or folders to open.")); + + const QCommandLineOption verboseOpt("verbose", MainWindow::tr("Print more logs.")); + parser.addOption(verboseOpt); + + const QCommandLineOption logStderrOpt("log-stderr", MainWindow::tr("Log to stderr.")); + parser.addOption(logStderrOpt); + + const QCommandLineOption watchThemesOpt("watch-themes", + MainWindow::tr("Watch theme folder for changes.")); + parser.addOption(watchThemesOpt); + + // WebEngine options. + // No need to handle them. Just add them to the parser to avoid parse error. + { + QCommandLineOption webRemoteDebuggingPortOpt("remote-debugging-port", + MainWindow::tr("WebEngine remote debugging port."), + MainWindow::tr("port_number")); + webRemoteDebuggingPortOpt.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(webRemoteDebuggingPortOpt); + + QCommandLineOption webNoSandboxOpt("no-sandbox", MainWindow::tr("WebEngine without sandbox.")); + webNoSandboxOpt.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(webNoSandboxOpt); + + QCommandLineOption webDisableGpu("disable-gpu", MainWindow::tr("WebEngine with GPU disabled.")); + webDisableGpu.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(webDisableGpu); + } + + if (!parser.parse(p_arguments)) { + m_errorMsg = parser.errorText(); + return ParseResult::Error; + } + + // Handle results. + m_helpText = parser.helpText(); + if (parser.isSet(helpOpt)) { + return ParseResult::HelpRequested; + } + + if (parser.isSet(versionOpt)) { + return ParseResult::VersionRequested; + } + + // Position arguments. + const auto args = parser.positionalArguments(); + m_pathsToOpen = args; + + if (parser.isSet(verboseOpt)) { + m_verbose = true; + } + + if (parser.isSet(logStderrOpt)) { + m_logToStderr = true; + } + + if (parser.isSet(watchThemesOpt)) { + m_watchThemes = true; + } + + return ParseResult::Ok; } diff --git a/src/commandlineoptions.h b/src/commandlineoptions.h index 3ec4b4190b..405b415438 100644 --- a/src/commandlineoptions.h +++ b/src/commandlineoptions.h @@ -3,33 +3,26 @@ #include -class CommandLineOptions -{ +class CommandLineOptions { public: - enum ParseResult - { - Ok, - Error, - VersionRequested, - HelpRequested - }; + enum ParseResult { Ok, Error, VersionRequested, HelpRequested }; - CommandLineOptions() = default; + CommandLineOptions() = default; - ParseResult parse(const QStringList &p_arguments); + ParseResult parse(const QStringList &p_arguments); - QString m_errorMsg; + QString m_errorMsg; - QString m_helpText; + QString m_helpText; - QStringList m_pathsToOpen; + QStringList m_pathsToOpen; - bool m_verbose = false; + bool m_verbose = false; - bool m_logToStderr = false; + bool m_logToStderr = false; - // Whether to watch theme folder for changes - bool m_watchThemes = false; + // Whether to watch theme folder for changes + bool m_watchThemes = false; }; #endif // COMMANDLINEOPTIONS_H diff --git a/src/core/buffer/buffer.cpp b/src/core/buffer/buffer.cpp index b166c53577..bea1c32ba5 100644 --- a/src/core/buffer/buffer.cpp +++ b/src/core/buffer/buffer.cpp @@ -4,8 +4,8 @@ #include #include -#include #include +#include #include #include @@ -15,563 +15,469 @@ using namespace vnotex; -static vnotex::ID generateBufferID() -{ - static vnotex::ID id = 0; - return ++id; -} - -Buffer::Buffer(const BufferParameters &p_parameters, - QObject *p_parent) - : QObject(p_parent), - m_provider(p_parameters.m_provider), - m_id(generateBufferID()), - m_readOnly(m_provider->isReadOnly()) -{ - m_autoSaveTimer = new QTimer(this); - m_autoSaveTimer->setSingleShot(true); - m_autoSaveTimer->setInterval(1000); - connect(m_autoSaveTimer, &QTimer::timeout, - this, &Buffer::autoSave); +static vnotex::ID generateBufferID() { + static vnotex::ID id = 0; + return ++id; +} - readContent(); +Buffer::Buffer(const BufferParameters &p_parameters, QObject *p_parent) + : QObject(p_parent), m_provider(p_parameters.m_provider), m_id(generateBufferID()), + m_readOnly(m_provider->isReadOnly()) { + m_autoSaveTimer = new QTimer(this); + m_autoSaveTimer->setSingleShot(true); + m_autoSaveTimer->setInterval(1000); + connect(m_autoSaveTimer, &QTimer::timeout, this, &Buffer::autoSave); - checkBackupFileOfPreviousSession(); -} + readContent(); -Buffer::~Buffer() -{ - Q_ASSERT(m_attachedViewWindowCount == 0); - Q_ASSERT(!m_viewWindowToSync); - Q_ASSERT(!isModified()); - Q_ASSERT(m_backupFilePath.isEmpty()); + checkBackupFileOfPreviousSession(); } -int Buffer::getAttachViewWindowCount() const -{ - return m_attachedViewWindowCount; +Buffer::~Buffer() { + Q_ASSERT(m_attachedViewWindowCount == 0); + Q_ASSERT(!m_viewWindowToSync); + Q_ASSERT(!isModified()); + Q_ASSERT(m_backupFilePath.isEmpty()); } -void Buffer::attachViewWindow(ViewWindow *p_win) -{ - Q_UNUSED(p_win); - Q_ASSERT(!(m_state & StateFlag::Discarded)); - ++m_attachedViewWindowCount; +int Buffer::getAttachViewWindowCount() const { return m_attachedViewWindowCount; } + +void Buffer::attachViewWindow(ViewWindow *p_win) { + Q_UNUSED(p_win); + Q_ASSERT(!(m_state & StateFlag::Discarded)); + ++m_attachedViewWindowCount; } -void Buffer::detachViewWindow(ViewWindow *p_win) -{ - Q_UNUSED(p_win); - Q_ASSERT(p_win != m_viewWindowToSync); +void Buffer::detachViewWindow(ViewWindow *p_win) { + Q_UNUSED(p_win); + Q_ASSERT(p_win != m_viewWindowToSync); - --m_attachedViewWindowCount; - Q_ASSERT(m_attachedViewWindowCount >= 0); + --m_attachedViewWindowCount; + Q_ASSERT(m_attachedViewWindowCount >= 0); - if (m_attachedViewWindowCount == 0) { - emit attachedViewWindowEmpty(); - } + if (m_attachedViewWindowCount == 0) { + emit attachedViewWindowEmpty(); + } } -ViewWindow *Buffer::createViewWindow(const QSharedPointer &p_paras, QWidget *p_parent) -{ - auto window = createViewWindowInternal(p_paras, p_parent); - Q_ASSERT(window); - window->attachToBuffer(this, p_paras); - return window; +ViewWindow *Buffer::createViewWindow(const QSharedPointer &p_paras, + QWidget *p_parent) { + auto window = createViewWindowInternal(p_paras, p_parent); + Q_ASSERT(window); + window->attachToBuffer(this, p_paras); + return window; } -bool Buffer::match(const Node *p_node) const -{ - Q_ASSERT(p_node); - return m_provider->match(p_node); +bool Buffer::match(const Node *p_node) const { + Q_ASSERT(p_node); + return m_provider->match(p_node); } -bool Buffer::match(const QString &p_filePath) const -{ - return m_provider->match(p_filePath); -} +bool Buffer::match(const QString &p_filePath) const { return m_provider->match(p_filePath); } -QString Buffer::getName() const -{ - return m_provider->getName(); -} +QString Buffer::getName() const { return m_provider->getName(); } -QString Buffer::getPath() const -{ - return m_provider->getPath(); -} +QString Buffer::getPath() const { return m_provider->getPath(); } -QString Buffer::getContentPath() const -{ - return m_provider->getContentPath(); -} +QString Buffer::getContentPath() const { return m_provider->getContentPath(); } -QString Buffer::getResourcePath() const -{ - return m_provider->getResourcePath(); -} +QString Buffer::getResourcePath() const { return m_provider->getResourcePath(); } -ID Buffer::getId() const -{ - return m_id; -} +ID Buffer::getId() const { return m_id; } -const QString &Buffer::getContent() const -{ - const_cast(this)->syncContent(); - return m_content; +const QString &Buffer::getContent() const { + const_cast(this)->syncContent(); + return m_content; } -void Buffer::setContent(const QString &p_content, int &p_revision) -{ - m_viewWindowToSync = nullptr; - m_content = p_content; - p_revision = ++m_revision; - setModified(true); - m_autoSaveTimer->start(); - emit contentsChanged(); +void Buffer::setContent(const QString &p_content, int &p_revision) { + m_viewWindowToSync = nullptr; + m_content = p_content; + p_revision = ++m_revision; + setModified(true); + m_autoSaveTimer->start(); + emit contentsChanged(); } void Buffer::invalidateContent(const ViewWindow *p_win, - const std::function &p_setRevision) -{ - Q_ASSERT(!m_viewWindowToSync || m_viewWindowToSync == p_win); - ++m_revision; - p_setRevision(m_revision); - m_viewWindowToSync = p_win; - m_autoSaveTimer->start(); - emit contentsChanged(); + const std::function &p_setRevision) { + Q_ASSERT(!m_viewWindowToSync || m_viewWindowToSync == p_win); + ++m_revision; + p_setRevision(m_revision); + m_viewWindowToSync = p_win; + m_autoSaveTimer->start(); + emit contentsChanged(); } -int Buffer::getRevision() const -{ - return m_revision; -} +int Buffer::getRevision() const { return m_revision; } -void Buffer::syncContent(const ViewWindow *p_win) -{ - if (m_viewWindowToSync == p_win) { - syncContent(); - } +void Buffer::syncContent(const ViewWindow *p_win) { + if (m_viewWindowToSync == p_win) { + syncContent(); + } } -void Buffer::syncContent() -{ - if (m_viewWindowToSync) { - // Need to sync content. - m_content = m_viewWindowToSync->getLatestContent(); - m_viewWindowToSync = nullptr; - } +void Buffer::syncContent() { + if (m_viewWindowToSync) { + // Need to sync content. + m_content = m_viewWindowToSync->getLatestContent(); + m_viewWindowToSync = nullptr; + } } -bool Buffer::isModified() const -{ - return m_modified; -} +bool Buffer::isModified() const { return m_modified; } -void Buffer::setModified(bool p_modified) -{ - if (m_modified == p_modified) { - return; - } +void Buffer::setModified(bool p_modified) { + if (m_modified == p_modified) { + return; + } - m_modified = p_modified; - emit modified(m_modified); + m_modified = p_modified; + emit modified(m_modified); } -bool Buffer::isReadOnly() const -{ - return m_readOnly; -} +bool Buffer::isReadOnly() const { return m_readOnly; } -Buffer::OperationCode Buffer::save(bool p_force) -{ - Q_ASSERT(!m_readOnly); - if (m_readOnly) { - return OperationCode::Failed; - } +Buffer::OperationCode Buffer::save(bool p_force) { + Q_ASSERT(!m_readOnly); + if (m_readOnly) { + return OperationCode::Failed; + } - if (m_modified - || p_force - || m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { - syncContent(); - - // We do not involve user here to handle file missing and changed outside cases. - // The active ViewWindow will check this periodically. - // Check if file still exists. - if (!p_force && !checkFileExistsOnDisk()) { - qWarning() << "failed to save buffer due to file missing on disk" << getPath(); - return OperationCode::FileMissingOnDisk; - } - - // Check if file is modified outside. - if (!p_force && checkFileChangedOutside()) { - qWarning() << "failed to save buffer due to file changed from outside" << getPath(); - return OperationCode::FileChangedOutside; - } - - try { - m_provider->write(m_content); - } catch (Exception &p_e) { - qWarning() << "failed to write the buffer content" << getPath() << p_e.what(); - return OperationCode::Failed; - } - - setModified(false); - m_state &= ~(StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside); - } - return OperationCode::Success; -} + if (m_modified || p_force || + m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { + syncContent(); -Buffer::OperationCode Buffer::reload() -{ - // Check if file is missing. - if (!checkFileExistsOnDisk()) { - qWarning() << "failed to save buffer due to file missing on disk" << getPath(); - return OperationCode::FileMissingOnDisk; + // We do not involve user here to handle file missing and changed outside cases. + // The active ViewWindow will check this periodically. + // Check if file still exists. + if (!p_force && !checkFileExistsOnDisk()) { + qWarning() << "failed to save buffer due to file missing on disk" << getPath(); + return OperationCode::FileMissingOnDisk; } - if (m_modified - || m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { - readContent(); + // Check if file is modified outside. + if (!p_force && checkFileChangedOutside()) { + qWarning() << "failed to save buffer due to file changed from outside" << getPath(); + return OperationCode::FileChangedOutside; + } - emit modified(m_modified); - emit contentsChanged(); + try { + m_provider->write(m_content); + } catch (Exception &p_e) { + qWarning() << "failed to write the buffer content" << getPath() << p_e.what(); + return OperationCode::Failed; } - return OperationCode::Success; + + setModified(false); + m_state &= ~(StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside); + } + return OperationCode::Success; } -void Buffer::readContent() -{ - m_content = m_provider->read(); - ++m_revision; +Buffer::OperationCode Buffer::reload() { + // Check if file is missing. + if (!checkFileExistsOnDisk()) { + qWarning() << "failed to save buffer due to file missing on disk" << getPath(); + return OperationCode::FileMissingOnDisk; + } - // Reset state. - m_viewWindowToSync = nullptr; - m_modified = false; + if (m_modified || m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { + readContent(); + + emit modified(m_modified); + emit contentsChanged(); + } + return OperationCode::Success; } -void Buffer::discard() -{ - Q_ASSERT(!(m_state & StateFlag::Discarded)); - Q_ASSERT(m_attachedViewWindowCount == 1); - m_autoSaveTimer->stop(); - m_content.clear(); - m_state |= StateFlag::Discarded; - ++m_revision; +void Buffer::readContent() { + m_content = m_provider->read(); + ++m_revision; - m_viewWindowToSync = nullptr; - m_modified = false; + // Reset state. + m_viewWindowToSync = nullptr; + m_modified = false; } -void Buffer::close() -{ - // Delete the backup file if exists. - m_autoSaveTimer->stop(); - if (!m_backupFilePath.isEmpty()) { - FileUtils::removeFile(m_backupFilePath); - m_backupFilePath.clear(); - } -} +void Buffer::discard() { + Q_ASSERT(!(m_state & StateFlag::Discarded)); + Q_ASSERT(m_attachedViewWindowCount == 1); + m_autoSaveTimer->stop(); + m_content.clear(); + m_state |= StateFlag::Discarded; + ++m_revision; -QString Buffer::getImageFolderPath() const -{ - return const_cast(this)->m_provider->fetchImageFolderPath(); + m_viewWindowToSync = nullptr; + m_modified = false; } -QString Buffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - Q_UNUSED(p_srcImagePath); - Q_UNUSED(p_imageFileName); - Q_ASSERT_X(false, "insertImage", "image insert is not supported"); - return QString(); +void Buffer::close() { + // Delete the backup file if exists. + m_autoSaveTimer->stop(); + if (!m_backupFilePath.isEmpty()) { + FileUtils::removeFile(m_backupFilePath); + m_backupFilePath.clear(); + } } -QString Buffer::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - Q_UNUSED(p_image); - Q_UNUSED(p_imageFileName); - Q_ASSERT_X(false, "insertImage", "image insert is not supported"); - return QString(); +QString Buffer::getImageFolderPath() const { + return const_cast(this)->m_provider->fetchImageFolderPath(); } -void Buffer::removeImage(const QString &p_imagePath) -{ - Q_UNUSED(p_imagePath); - Q_ASSERT_X(false, "removeImage", "image remove is not supported"); +QString Buffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) { + Q_UNUSED(p_srcImagePath); + Q_UNUSED(p_imageFileName); + Q_ASSERT_X(false, "insertImage", "image insert is not supported"); + return QString(); } -void Buffer::autoSave() -{ - if (m_readOnly) { - m_autoSaveTimer->stop(); - return; - } +QString Buffer::insertImage(const QImage &p_image, const QString &p_imageFileName) { + Q_UNUSED(p_image); + Q_UNUSED(p_imageFileName); + Q_ASSERT_X(false, "insertImage", "image insert is not supported"); + return QString(); +} - if (m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { - qDebug() << "disable AutoSave due to file missing on disk or changed outside"; - return; - } - Q_ASSERT(!(m_state & StateFlag::Discarded)); - auto policy = ConfigMgr::getInst().getEditorConfig().getAutoSavePolicy(); - switch (policy) { - case EditorConfig::AutoSavePolicy::None: - return; - - case EditorConfig::AutoSavePolicy::AutoSave: - if (save(false) != OperationCode::Success) { - qWarning() << "AutoSave failed to save buffer, retry later"; - } else { - emit autoSaved(); - } - break; - - case EditorConfig::AutoSavePolicy::BackupFile: - try { - writeBackupFile(); - } catch (Exception &p_e) { - qWarning() << "AutoSave failed to write backup file, retry later" << p_e.what(); - } - break; - } +void Buffer::removeImage(const QString &p_imagePath) { + Q_UNUSED(p_imagePath); + Q_ASSERT_X(false, "removeImage", "image remove is not supported"); } -void Buffer::writeBackupFile() -{ - if (m_backupFilePath.isEmpty()) { - const auto &config = ConfigMgr::getInst().getEditorConfig(); - QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory())); - backupDirPath = QDir::cleanPath(backupDirPath); - auto backupFileName = FileUtils::generateFileNameWithSequence(backupDirPath, - getName(), - config.getBackupFileExtension()); - QDir backupDir(backupDirPath); - backupDir.mkpath(backupDirPath); - m_backupFilePath = backupDir.filePath(backupFileName); +void Buffer::autoSave() { + if (m_readOnly) { + m_autoSaveTimer->stop(); + return; + } + + if (m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) { + qDebug() << "disable AutoSave due to file missing on disk or changed outside"; + return; + } + Q_ASSERT(!(m_state & StateFlag::Discarded)); + auto policy = ConfigMgr::getInst().getEditorConfig().getAutoSavePolicy(); + switch (policy) { + case EditorConfig::AutoSavePolicy::None: + return; + + case EditorConfig::AutoSavePolicy::AutoSave: + if (save(false) != OperationCode::Success) { + qWarning() << "AutoSave failed to save buffer, retry later"; + } else { + emit autoSaved(); } + break; - Q_ASSERT(m_backupFilePathOfPreviousSession.isEmpty()); - - // Just use FileUtils instead of notebook backend. - FileUtils::writeFile(m_backupFilePath, generateBackupFileHead() + getContent()); -} - -QString Buffer::generateBackupFileHead() const -{ - return QStringLiteral("vnotex_backup_file %1|").arg(getContentPath()); + case EditorConfig::AutoSavePolicy::BackupFile: + try { + writeBackupFile(); + } catch (Exception &p_e) { + qWarning() << "AutoSave failed to write backup file, retry later" << p_e.what(); + } + break; + } } -void Buffer::checkBackupFileOfPreviousSession() -{ +void Buffer::writeBackupFile() { + if (m_backupFilePath.isEmpty()) { const auto &config = ConfigMgr::getInst().getEditorConfig(); - if (config.getAutoSavePolicy() != EditorConfig::AutoSavePolicy::BackupFile) { - return; - } - QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory())); backupDirPath = QDir::cleanPath(backupDirPath); + auto backupFileName = FileUtils::generateFileNameWithSequence(backupDirPath, getName(), + config.getBackupFileExtension()); QDir backupDir(backupDirPath); - QStringList backupFiles; - { - const QString nameFilter = QStringLiteral("%1*%2").arg(getName(), config.getBackupFileExtension()); - backupFiles = backupDir.entryList(QStringList(nameFilter), - QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot); - } - - if (backupFiles.isEmpty()) { - return; - } - - for (const auto &file : backupFiles) { - const auto filePath = backupDir.filePath(file); - if (isBackupFileOfBuffer(filePath)) { - const auto backupContent = readBackupFile(filePath); - if (backupContent == getContent()) { - // Found backup file with identical content. - // Just discard the backup file. - FileUtils::removeFile(filePath); - qInfo() << "delete identical backup file of previous session" << filePath; - } else { - m_backupFilePathOfPreviousSession = filePath; - qInfo() << "found backup file of previous session" << filePath; - } - break; - } + backupDir.mkpath(backupDirPath); + m_backupFilePath = backupDir.filePath(backupFileName); + } + + Q_ASSERT(m_backupFilePathOfPreviousSession.isEmpty()); + + // Just use FileUtils instead of notebook backend. + FileUtils::writeFile(m_backupFilePath, generateBackupFileHead() + getContent()); +} + +QString Buffer::generateBackupFileHead() const { + return QStringLiteral("vnotex_backup_file %1|").arg(getContentPath()); +} + +void Buffer::checkBackupFileOfPreviousSession() { + const auto &config = ConfigMgr::getInst().getEditorConfig(); + if (config.getAutoSavePolicy() != EditorConfig::AutoSavePolicy::BackupFile) { + return; + } + + QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory())); + backupDirPath = QDir::cleanPath(backupDirPath); + QDir backupDir(backupDirPath); + QStringList backupFiles; + { + const QString nameFilter = + QStringLiteral("%1*%2").arg(getName(), config.getBackupFileExtension()); + backupFiles = + backupDir.entryList(QStringList(nameFilter), + QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot); + } + + if (backupFiles.isEmpty()) { + return; + } + + for (const auto &file : backupFiles) { + const auto filePath = backupDir.filePath(file); + if (isBackupFileOfBuffer(filePath)) { + const auto backupContent = readBackupFile(filePath); + if (backupContent == getContent()) { + // Found backup file with identical content. + // Just discard the backup file. + FileUtils::removeFile(filePath); + qInfo() << "delete identical backup file of previous session" << filePath; + } else { + m_backupFilePathOfPreviousSession = filePath; + qInfo() << "found backup file of previous session" << filePath; + } + break; } + } } -bool Buffer::isBackupFileOfBuffer(const QString &p_file) const -{ - QFile file(p_file); - if (!file.open(QFile::ReadOnly | QIODevice::Text)) { - return false; - } +bool Buffer::isBackupFileOfBuffer(const QString &p_file) const { + QFile file(p_file); + if (!file.open(QFile::ReadOnly | QIODevice::Text)) { + return false; + } - QTextStream st(&file); - const auto head = st.readLine(); - return head.startsWith(generateBackupFileHead()); + QTextStream st(&file); + const auto head = st.readLine(); + return head.startsWith(generateBackupFileHead()); } -const QString &Buffer::getBackupFileOfPreviousSession() const -{ - return m_backupFilePathOfPreviousSession; +const QString &Buffer::getBackupFileOfPreviousSession() const { + return m_backupFilePathOfPreviousSession; } -QString Buffer::readBackupFile(const QString &p_filePath) -{ - auto content = FileUtils::readTextFile(p_filePath); - return content.mid(content.indexOf(QLatin1Char('|')) + 1); +QString Buffer::readBackupFile(const QString &p_filePath) { + auto content = FileUtils::readTextFile(p_filePath); + return content.mid(content.indexOf(QLatin1Char('|')) + 1); } -void Buffer::discardBackupFileOfPreviousSession() -{ - Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty()); +void Buffer::discardBackupFileOfPreviousSession() { + Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty()); - FileUtils::removeFile(m_backupFilePathOfPreviousSession); - qInfo() << "discard backup file of previous session" << m_backupFilePathOfPreviousSession; - m_backupFilePathOfPreviousSession.clear(); + FileUtils::removeFile(m_backupFilePathOfPreviousSession); + qInfo() << "discard backup file of previous session" << m_backupFilePathOfPreviousSession; + m_backupFilePathOfPreviousSession.clear(); } -void Buffer::recoverFromBackupFileOfPreviousSession() -{ - Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty()); +void Buffer::recoverFromBackupFileOfPreviousSession() { + Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty()); - m_content = readBackupFile(m_backupFilePathOfPreviousSession); - m_provider->write(m_content); - ++m_revision; + m_content = readBackupFile(m_backupFilePathOfPreviousSession); + m_provider->write(m_content); + ++m_revision; - FileUtils::removeFile(m_backupFilePathOfPreviousSession); - qInfo() << "recover from backup file of previous session" << m_backupFilePathOfPreviousSession; - m_backupFilePathOfPreviousSession.clear(); + FileUtils::removeFile(m_backupFilePathOfPreviousSession); + qInfo() << "recover from backup file of previous session" << m_backupFilePathOfPreviousSession; + m_backupFilePathOfPreviousSession.clear(); - // Reset state. - m_viewWindowToSync = nullptr; - m_modified = false; + // Reset state. + m_viewWindowToSync = nullptr; + m_modified = false; - emit modified(m_modified); - emit contentsChanged(); + emit modified(m_modified); + emit contentsChanged(); } -bool Buffer::isChildOf(const Node *p_node) const -{ - return m_provider->isChildOf(p_node); -} +bool Buffer::isChildOf(const Node *p_node) const { return m_provider->isChildOf(p_node); } -bool Buffer::isAttachmentSupported() const -{ - return !m_readOnly && m_provider->isAttachmentSupported(); +bool Buffer::isAttachmentSupported() const { + return !m_readOnly && m_provider->isAttachmentSupported(); } -bool Buffer::hasAttachment() const -{ - if (!isAttachmentSupported()) { - return false; - } - - if (m_provider->getAttachmentFolder().isEmpty()) { - return false; - } +bool Buffer::hasAttachment() const { + if (!isAttachmentSupported()) { + return false; + } - QDir dir(getAttachmentFolderPath()); - return !dir.isEmpty(); -} + if (m_provider->getAttachmentFolder().isEmpty()) { + return false; + } -QString Buffer::getAttachmentFolderPath() const -{ - Q_ASSERT(isAttachmentSupported()); - return const_cast(this)->m_provider->fetchAttachmentFolderPath(); + QDir dir(getAttachmentFolderPath()); + return !dir.isEmpty(); } -QStringList Buffer::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) -{ - if (p_files.isEmpty()) { - return QStringList(); - } - auto destFolderPath = p_destFolderPath.isEmpty() ? getAttachmentFolderPath() : p_destFolderPath; - Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), destFolderPath)); - auto files = m_provider->addAttachment(destFolderPath, p_files); - if (!files.isEmpty()) { - emit attachmentChanged(); - } - return files; +QString Buffer::getAttachmentFolderPath() const { + Q_ASSERT(isAttachmentSupported()); + return const_cast(this)->m_provider->fetchAttachmentFolderPath(); } -QString Buffer::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath)); - auto filePath = m_provider->newAttachmentFile(p_destFolderPath, p_name); +QStringList Buffer::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) { + if (p_files.isEmpty()) { + return QStringList(); + } + auto destFolderPath = p_destFolderPath.isEmpty() ? getAttachmentFolderPath() : p_destFolderPath; + Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), destFolderPath)); + auto files = m_provider->addAttachment(destFolderPath, p_files); + if (!files.isEmpty()) { emit attachmentChanged(); - return filePath; + } + return files; } -QString Buffer::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath)); - auto folderPath = m_provider->newAttachmentFolder(p_destFolderPath, p_name); - emit attachmentChanged(); - return folderPath; +QString Buffer::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath)); + auto filePath = m_provider->newAttachmentFile(p_destFolderPath, p_name); + emit attachmentChanged(); + return filePath; } -QString Buffer::renameAttachment(const QString &p_path, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_path)); - return m_provider->renameAttachment(p_path, p_name); +QString Buffer::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath)); + auto folderPath = m_provider->newAttachmentFolder(p_destFolderPath, p_name); + emit attachmentChanged(); + return folderPath; } -void Buffer::removeAttachment(const QStringList &p_paths) -{ - m_provider->removeAttachment(p_paths); - emit attachmentChanged(); +QString Buffer::renameAttachment(const QString &p_path, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_path)); + return m_provider->renameAttachment(p_path, p_name); } -bool Buffer::isAttachment(const QString &p_path) const -{ - return PathUtils::pathContains(getAttachmentFolderPath(), p_path); +void Buffer::removeAttachment(const QStringList &p_paths) { + m_provider->removeAttachment(p_paths); + emit attachmentChanged(); } -bool Buffer::isTagSupported() const -{ - return m_provider->isTagSupported(); +bool Buffer::isAttachment(const QString &p_path) const { + return PathUtils::pathContains(getAttachmentFolderPath(), p_path); } -Buffer::ProviderType Buffer::getProviderType() const -{ - return m_provider->getType(); -} +bool Buffer::isTagSupported() const { return m_provider->isTagSupported(); } -Node *Buffer::getNode() const -{ - return m_provider->getNode(); -} +Buffer::ProviderType Buffer::getProviderType() const { return m_provider->getType(); } -bool Buffer::checkFileExistsOnDisk() -{ - if (m_provider->checkFileExistsOnDisk()) { - m_state &= ~StateFlag::FileMissingOnDisk; - return true; - } else { - m_state |= StateFlag::FileMissingOnDisk; - return false; - } -} +Node *Buffer::getNode() const { return m_provider->getNode(); } -bool Buffer::checkFileChangedOutside() -{ - if (m_provider->checkFileChangedOutside()) { - m_state |= StateFlag::FileChangedOutside; - return true; - } else { - m_state &= ~StateFlag::FileChangedOutside; - return false; - } +bool Buffer::checkFileExistsOnDisk() { + if (m_provider->checkFileExistsOnDisk()) { + m_state &= ~StateFlag::FileMissingOnDisk; + return true; + } else { + m_state |= StateFlag::FileMissingOnDisk; + return false; + } } -Buffer::StateFlags Buffer::state() const -{ - return m_state; +bool Buffer::checkFileChangedOutside() { + if (m_provider->checkFileChangedOutside()) { + m_state |= StateFlag::FileChangedOutside; + return true; + } else { + m_state &= ~StateFlag::FileChangedOutside; + return false; + } } -QSharedPointer Buffer::getFile() const -{ - return m_provider->getFile(); -} +Buffer::StateFlags Buffer::state() const { return m_state; } + +QSharedPointer Buffer::getFile() const { return m_provider->getFile(); } diff --git a/src/core/buffer/buffer.h b/src/core/buffer/buffer.h index 7b6b2267da..4bf39ad607 100644 --- a/src/core/buffer/buffer.h +++ b/src/core/buffer/buffer.h @@ -11,239 +11,220 @@ class QWidget; class QTimer; -namespace vnotex -{ - class Node; - class Buffer; - class ViewWindow; - struct FileOpenParameters; - class BufferProvider; - class File; +namespace vnotex { +class Node; +class Buffer; +class ViewWindow; +struct FileOpenParameters; +class BufferProvider; +class File; - struct BufferParameters - { - QSharedPointer m_provider; - }; +struct BufferParameters { + QSharedPointer m_provider; +}; - class Buffer : public QObject - { - Q_OBJECT - public: - enum class ProviderType - { - Internal, - External - }; +class Buffer : public QObject { + Q_OBJECT +public: + enum class ProviderType { Internal, External }; - enum class OperationCode - { - Success, - FileMissingOnDisk, - FileChangedOutside, - Failed - }; + enum class OperationCode { Success, FileMissingOnDisk, FileChangedOutside, Failed }; - enum StateFlag - { - Normal = 0, - FileMissingOnDisk = 0x1, - FileChangedOutside = 0x2, - Discarded = 0x4 - }; - Q_DECLARE_FLAGS(StateFlags, StateFlag); + enum StateFlag { Normal = 0, FileMissingOnDisk = 0x1, FileChangedOutside = 0x2, Discarded = 0x4 }; + Q_DECLARE_FLAGS(StateFlags, StateFlag); - Buffer(const BufferParameters &p_parameters, - QObject *p_parent = nullptr); + Buffer(const BufferParameters &p_parameters, QObject *p_parent = nullptr); - virtual ~Buffer(); + virtual ~Buffer(); - int getAttachViewWindowCount() const; + int getAttachViewWindowCount() const; - void attachViewWindow(ViewWindow *p_win); - void detachViewWindow(ViewWindow *p_win); + void attachViewWindow(ViewWindow *p_win); + void detachViewWindow(ViewWindow *p_win); - // Create a view window to show the content of this buffer. - // Attach the created view window to this buffer. - ViewWindow *createViewWindow(const QSharedPointer &p_paras, QWidget *p_parent); + // Create a view window to show the content of this buffer. + // Attach the created view window to this buffer. + ViewWindow *createViewWindow(const QSharedPointer &p_paras, + QWidget *p_parent); - // Whether this buffer matches @p_node. - bool match(const Node *p_node) const; + // Whether this buffer matches @p_node. + bool match(const Node *p_node) const; - // Whether this buffer matches @p_filePath. - bool match(const QString &p_filePath) const; + // Whether this buffer matches @p_filePath. + bool match(const QString &p_filePath) const; - // Buffer name. - QString getName() const; + // Buffer name. + QString getName() const; - QString getPath() const; + QString getPath() const; - // In some cases, getPath() may point to a container containting all the stuffs. - // getContentPath() will return the real path to the file providing the content. - QString getContentPath() const; + // In some cases, getPath() may point to a container containting all the stuffs. + // getContentPath() will return the real path to the file providing the content. + QString getContentPath() const; - // Get the base path to resolve resources. - QString getResourcePath() const; + // Get the base path to resolve resources. + QString getResourcePath() const; - // Return nullptr if not available. - QSharedPointer getFile() const; + // Return nullptr if not available. + QSharedPointer getFile() const; - ID getId() const; + ID getId() const; - // Get buffer content. - // It may differ from the content on disk. - // For performance, we need to sync the content with ViewWindow before returning - // the latest content. - const QString &getContent() const; + // Get buffer content. + // It may differ from the content on disk. + // For performance, we need to sync the content with ViewWindow before returning + // the latest content. + const QString &getContent() const; - // @p_revision will be set before contentsChanged is emitted. - void setContent(const QString &p_content, int &p_revision); + // @p_revision will be set before contentsChanged is emitted. + void setContent(const QString &p_content, int &p_revision); - // Invalidate the content of buffer. - // Need to sync with @p_win to get the latest content. - // @p_setRevision will be called to set revision before contentsChanged is emitted. - void invalidateContent(const ViewWindow *p_win, - const std::function &p_setRevision); + // Invalidate the content of buffer. + // Need to sync with @p_win to get the latest content. + // @p_setRevision will be called to set revision before contentsChanged is emitted. + void invalidateContent(const ViewWindow *p_win, const std::function &p_setRevision); - // Sync content with @p_win if @p_win is the window needed to sync. - void syncContent(const ViewWindow *p_win); + // Sync content with @p_win if @p_win is the window needed to sync. + void syncContent(const ViewWindow *p_win); - int getRevision() const; + int getRevision() const; - bool isModified() const; - void setModified(bool p_modified); + bool isModified() const; + void setModified(bool p_modified); - bool isReadOnly() const; + bool isReadOnly() const; - // Save buffer content to file. - OperationCode save(bool p_force); + // Save buffer content to file. + OperationCode save(bool p_force); - // Discard changes and reload file. - OperationCode reload(); + // Discard changes and reload file. + OperationCode reload(); - // Discard the buffer which will invalidate the buffer. - void discard(); + // Discard the buffer which will invalidate the buffer. + void discard(); - // Buffer is about to be deleted. - void close(); + // Buffer is about to be deleted. + void close(); - // Insert image from @p_srcImagePath. - // Return inserted image file path. - virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName); + // Insert image from @p_srcImagePath. + // Return inserted image file path. + virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName); - virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName); + virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName); - virtual void removeImage(const QString &p_imagePath); + virtual void removeImage(const QString &p_imagePath); - const QString &getBackupFileOfPreviousSession() const; + const QString &getBackupFileOfPreviousSession() const; - void discardBackupFileOfPreviousSession(); + void discardBackupFileOfPreviousSession(); - void recoverFromBackupFileOfPreviousSession(); + void recoverFromBackupFileOfPreviousSession(); - // Whether this buffer's provider is a child of @p_node or an attachment of @p_node. - bool isChildOf(const Node *p_node) const; + // Whether this buffer's provider is a child of @p_node or an attachment of @p_node. + bool isChildOf(const Node *p_node) const; - Node *getNode() const; + Node *getNode() const; - bool isAttachmentSupported() const; + bool isAttachmentSupported() const; - bool hasAttachment() const; + bool hasAttachment() const; - QString getAttachmentFolderPath() const; + QString getAttachmentFolderPath() const; - // @p_destFolderPath: folder path locating in attachment folder. Use the root folder if empty. - QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files); + // @p_destFolderPath: folder path locating in attachment folder. Use the root folder if empty. + QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files); - QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name); + QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name); - QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name); + QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name); - QString renameAttachment(const QString &p_path, const QString &p_name); + QString renameAttachment(const QString &p_path, const QString &p_name); - void removeAttachment(const QStringList &p_paths); + void removeAttachment(const QStringList &p_paths); - // Judge whether file @p_path is attachment. - bool isAttachment(const QString &p_path) const; + // Judge whether file @p_path is attachment. + bool isAttachment(const QString &p_path) const; - bool isTagSupported() const; + bool isTagSupported() const; - ProviderType getProviderType() const; + ProviderType getProviderType() const; - bool checkFileExistsOnDisk(); + bool checkFileExistsOnDisk(); - bool checkFileChangedOutside(); + bool checkFileChangedOutside(); - StateFlags state() const; + StateFlags state() const; - static QString readBackupFile(const QString &p_filePath); + static QString readBackupFile(const QString &p_filePath); - signals: - void attachedViewWindowEmpty(); +signals: + void attachedViewWindowEmpty(); - void modified(bool p_modified); + void modified(bool p_modified); - void contentsChanged(); + void contentsChanged(); - void nameChanged(); + void nameChanged(); - void attachmentChanged(); + void attachmentChanged(); - // This buffer is AutoSavePolicy::AutoSave. - void autoSaved(); + // This buffer is AutoSavePolicy::AutoSave. + void autoSaved(); - protected: - virtual ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) = 0; +protected: + virtual ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) = 0; - QSharedPointer m_provider; + QSharedPointer m_provider; - private slots: - void autoSave(); +private slots: + void autoSave(); - private: - void syncContent(); +private: + void syncContent(); - void readContent(); + void readContent(); - // Get the path of the image folder. - QString getImageFolderPath() const; + // Get the path of the image folder. + QString getImageFolderPath() const; - void writeBackupFile(); + void writeBackupFile(); - // Generate backup file head. - QString generateBackupFileHead() const; + // Generate backup file head. + QString generateBackupFileHead() const; - void checkBackupFileOfPreviousSession(); + void checkBackupFileOfPreviousSession(); - bool isBackupFileOfBuffer(const QString &p_file) const; + bool isBackupFileOfBuffer(const QString &p_file) const; - // Will be assigned uniquely once created. - const ID m_id = 0; + // Will be assigned uniquely once created. + const ID m_id = 0; - // Revision of contents. - int m_revision = 0; + // Revision of contents. + int m_revision = 0; - // If the buffer is modified, m_content reflect the latest changes instead - // of the file content. - QString m_content; + // If the buffer is modified, m_content reflect the latest changes instead + // of the file content. + QString m_content; - bool m_readOnly = false; + bool m_readOnly = false; - bool m_modified = false; + bool m_modified = false; - int m_attachedViewWindowCount = 0; + int m_attachedViewWindowCount = 0; - const ViewWindow *m_viewWindowToSync = nullptr; + const ViewWindow *m_viewWindowToSync = nullptr; - // Managed by QObject. - QTimer *m_autoSaveTimer = nullptr; + // Managed by QObject. + QTimer *m_autoSaveTimer = nullptr; - QString m_backupFilePath; + QString m_backupFilePath; - QString m_backupFilePathOfPreviousSession; + QString m_backupFilePathOfPreviousSession; - StateFlags m_state = StateFlag::Normal; - }; -} // ns vnotex + StateFlags m_state = StateFlag::Normal; +}; +} // namespace vnotex Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::Buffer::StateFlags) diff --git a/src/core/buffer/bufferprovider.cpp b/src/core/buffer/bufferprovider.cpp index cc2d0f1450..5c23ed2307 100644 --- a/src/core/buffer/bufferprovider.cpp +++ b/src/core/buffer/bufferprovider.cpp @@ -4,22 +4,17 @@ using namespace vnotex; -bool BufferProvider::checkFileExistsOnDisk() const -{ - return QFileInfo::exists(getContentPath()); -} +bool BufferProvider::checkFileExistsOnDisk() const { return QFileInfo::exists(getContentPath()); } -QDateTime BufferProvider::getLastModifiedFromFile() const -{ - return QFileInfo(getContentPath()).lastModified(); +QDateTime BufferProvider::getLastModifiedFromFile() const { + return QFileInfo(getContentPath()).lastModified(); } -bool BufferProvider::checkFileChangedOutside() const -{ - // TODO: support non-local URLs. - QFileInfo info(getContentPath()); - if (!info.exists() || m_lastModified != info.lastModified()) { - return true; - } - return false; +bool BufferProvider::checkFileChangedOutside() const { + // TODO: support non-local URLs. + QFileInfo info(getContentPath()); + if (!info.exists() || m_lastModified != info.lastModified()) { + return true; + } + return false; } diff --git a/src/core/buffer/bufferprovider.h b/src/core/buffer/bufferprovider.h index 5c4bf398ac..9d9cffd244 100644 --- a/src/core/buffer/bufferprovider.h +++ b/src/core/buffer/bufferprovider.h @@ -1,89 +1,85 @@ #ifndef BUFFERPROVIDER_H #define BUFFERPROVIDER_H -#include #include +#include #include "buffer.h" -namespace vnotex -{ - class Node; +namespace vnotex { +class Node; - // Content provider for Buffer. - class BufferProvider : public QObject - { - Q_OBJECT - public: - BufferProvider(QObject *p_parent = nullptr) - : QObject(p_parent) - { - } +// Content provider for Buffer. +class BufferProvider : public QObject { + Q_OBJECT +public: + BufferProvider(QObject *p_parent = nullptr) : QObject(p_parent) {} - virtual ~BufferProvider() {} + virtual ~BufferProvider() {} - virtual Buffer::ProviderType getType() const = 0; + virtual Buffer::ProviderType getType() const = 0; - virtual bool match(const Node *p_node) const = 0; + virtual bool match(const Node *p_node) const = 0; - virtual bool match(const QString &p_filePath) const = 0; + virtual bool match(const QString &p_filePath) const = 0; - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getPath() const = 0; + virtual QString getPath() const = 0; - virtual QString getContentPath() const = 0; + virtual QString getContentPath() const = 0; - virtual QString getResourcePath() const = 0; + virtual QString getResourcePath() const = 0; - virtual void write(const QString &p_content) = 0; + virtual void write(const QString &p_content) = 0; - virtual QString read() const = 0; + virtual QString read() const = 0; - virtual QString fetchImageFolderPath() = 0; + virtual QString fetchImageFolderPath() = 0; - virtual bool isChildOf(const Node *p_node) const = 0; + virtual bool isChildOf(const Node *p_node) const = 0; - virtual Node *getNode() const = 0; + virtual Node *getNode() const = 0; - virtual QString getAttachmentFolder() const = 0; + virtual QString getAttachmentFolder() const = 0; - virtual QString fetchAttachmentFolderPath() = 0; + virtual QString fetchAttachmentFolderPath() = 0; - virtual QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) = 0; + virtual QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) = 0; - virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0; + virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0; - virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0; + virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0; - virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0; + virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0; - virtual void removeAttachment(const QStringList &p_paths) = 0; + virtual void removeAttachment(const QStringList &p_paths) = 0; - virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0; + virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0; - virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0; + virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0; - virtual void removeImage(const QString &p_imagePath) = 0; + virtual void removeImage(const QString &p_imagePath) = 0; - virtual bool isAttachmentSupported() const = 0; + virtual bool isAttachmentSupported() const = 0; - virtual bool isTagSupported() const = 0; + virtual bool isTagSupported() const = 0; - virtual bool checkFileExistsOnDisk() const; + virtual bool checkFileExistsOnDisk() const; - virtual bool checkFileChangedOutside() const; + virtual bool checkFileChangedOutside() const; - virtual bool isReadOnly() const = 0; + virtual bool isReadOnly() const = 0; - // Return nullptr if not available. - virtual QSharedPointer getFile() const = 0; + // Return nullptr if not available. + virtual QSharedPointer getFile() const = 0; - protected: - virtual QDateTime getLastModifiedFromFile() const; +protected: + virtual QDateTime getLastModifiedFromFile() const; - QDateTime m_lastModified; - }; -} + QDateTime m_lastModified; +}; +} // namespace vnotex #endif // BUFFERPROVIDER_H diff --git a/src/core/buffer/filebufferprovider.cpp b/src/core/buffer/filebufferprovider.cpp index 765397d06d..9b96ed6e97 100644 --- a/src/core/buffer/filebufferprovider.cpp +++ b/src/core/buffer/filebufferprovider.cpp @@ -2,194 +2,146 @@ #include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace vnotex; -FileBufferProvider::FileBufferProvider(const QSharedPointer &p_file, - Node *p_nodeAttachedTo, - bool p_readOnly, - QObject *p_parent) - : BufferProvider(p_parent), - m_file(p_file), - c_nodeAttachedTo(p_nodeAttachedTo), - m_readOnly(p_readOnly) -{ -} +FileBufferProvider::FileBufferProvider(const QSharedPointer &p_file, Node *p_nodeAttachedTo, + bool p_readOnly, QObject *p_parent) + : BufferProvider(p_parent), m_file(p_file), c_nodeAttachedTo(p_nodeAttachedTo), + m_readOnly(p_readOnly) {} -Buffer::ProviderType FileBufferProvider::getType() const -{ - return Buffer::ProviderType::External; -} +Buffer::ProviderType FileBufferProvider::getType() const { return Buffer::ProviderType::External; } -bool FileBufferProvider::match(const Node *p_node) const -{ - Q_UNUSED(p_node); - return false; +bool FileBufferProvider::match(const Node *p_node) const { + Q_UNUSED(p_node); + return false; } -bool FileBufferProvider::match(const QString &p_filePath) const -{ - return PathUtils::areSamePaths(m_file->getFilePath(), p_filePath); +bool FileBufferProvider::match(const QString &p_filePath) const { + return PathUtils::areSamePaths(m_file->getFilePath(), p_filePath); } -QString FileBufferProvider::getName() const -{ - return m_file->getName(); -} +QString FileBufferProvider::getName() const { return m_file->getName(); } -QString FileBufferProvider::getPath() const -{ - return m_file->getFilePath(); -} +QString FileBufferProvider::getPath() const { return m_file->getFilePath(); } -QString FileBufferProvider::getContentPath() const -{ - return m_file->getContentPath(); -} +QString FileBufferProvider::getContentPath() const { return m_file->getContentPath(); } -QString FileBufferProvider::getResourcePath() const -{ - return m_file->getResourcePath(); -} +QString FileBufferProvider::getResourcePath() const { return m_file->getResourcePath(); } -void FileBufferProvider::write(const QString &p_content) -{ - m_file->write(p_content); - m_lastModified = getLastModifiedFromFile(); +void FileBufferProvider::write(const QString &p_content) { + m_file->write(p_content); + m_lastModified = getLastModifiedFromFile(); } -QString FileBufferProvider::read() const -{ - const_cast(this)->m_lastModified = getLastModifiedFromFile(); - return m_file->read(); +QString FileBufferProvider::read() const { + const_cast(this)->m_lastModified = getLastModifiedFromFile(); + return m_file->read(); } -QString FileBufferProvider::fetchImageFolderPath() -{ - auto file = m_file->getImageInterface(); - if (file) { - return file->fetchImageFolderPath(); - } else { - return QString(); - } +QString FileBufferProvider::fetchImageFolderPath() { + auto file = m_file->getImageInterface(); + if (file) { + return file->fetchImageFolderPath(); + } else { + return QString(); + } } -bool FileBufferProvider::isChildOf(const Node *p_node) const -{ - if (c_nodeAttachedTo) { - return c_nodeAttachedTo == p_node || Node::isAncestor(p_node, c_nodeAttachedTo); - } - return false; +bool FileBufferProvider::isChildOf(const Node *p_node) const { + if (c_nodeAttachedTo) { + return c_nodeAttachedTo == p_node || Node::isAncestor(p_node, c_nodeAttachedTo); + } + return false; } -QString FileBufferProvider::getAttachmentFolder() const -{ - Q_ASSERT(false); - return QString(); +QString FileBufferProvider::getAttachmentFolder() const { + Q_ASSERT(false); + return QString(); } -QString FileBufferProvider::fetchAttachmentFolderPath() -{ - Q_ASSERT(false); - return QString(); +QString FileBufferProvider::fetchAttachmentFolderPath() { + Q_ASSERT(false); + return QString(); } -QStringList FileBufferProvider::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) -{ - Q_UNUSED(p_destFolderPath); - Q_UNUSED(p_files); - Q_ASSERT(false); - return QStringList(); +QStringList FileBufferProvider::addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) { + Q_UNUSED(p_destFolderPath); + Q_UNUSED(p_files); + Q_ASSERT(false); + return QStringList(); } -QString FileBufferProvider::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) -{ - Q_UNUSED(p_destFolderPath); - Q_UNUSED(p_name); - Q_ASSERT(false); - return QString(); +QString FileBufferProvider::newAttachmentFile(const QString &p_destFolderPath, + const QString &p_name) { + Q_UNUSED(p_destFolderPath); + Q_UNUSED(p_name); + Q_ASSERT(false); + return QString(); } -QString FileBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) -{ - Q_UNUSED(p_destFolderPath); - Q_UNUSED(p_name); - Q_ASSERT(false); - return QString(); +QString FileBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) { + Q_UNUSED(p_destFolderPath); + Q_UNUSED(p_name); + Q_ASSERT(false); + return QString(); } -QString FileBufferProvider::renameAttachment(const QString &p_path, const QString &p_name) -{ - Q_UNUSED(p_path); - Q_UNUSED(p_name); - Q_ASSERT(false); - return QString(); +QString FileBufferProvider::renameAttachment(const QString &p_path, const QString &p_name) { + Q_UNUSED(p_path); + Q_UNUSED(p_name); + Q_ASSERT(false); + return QString(); } -void FileBufferProvider::removeAttachment(const QStringList &p_paths) -{ - Q_UNUSED(p_paths); - Q_ASSERT(false); +void FileBufferProvider::removeAttachment(const QStringList &p_paths) { + Q_UNUSED(p_paths); + Q_ASSERT(false); } -QString FileBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - auto file = m_file->getImageInterface(); - if (file) { - return file->insertImage(p_srcImagePath, p_imageFileName); - } else { - return QString(); - } +QString FileBufferProvider::insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) { + auto file = m_file->getImageInterface(); + if (file) { + return file->insertImage(p_srcImagePath, p_imageFileName); + } else { + return QString(); + } } -QString FileBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - auto file = m_file->getImageInterface(); - if (file) { - return file->insertImage(p_image, p_imageFileName); - } else { - return QString(); - } +QString FileBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) { + auto file = m_file->getImageInterface(); + if (file) { + return file->insertImage(p_image, p_imageFileName); + } else { + return QString(); + } } -void FileBufferProvider::removeImage(const QString &p_imagePath) -{ - auto file = m_file->getImageInterface(); - if (file) { - try { - file->removeImage(p_imagePath); - } catch (Exception &e) { - qWarning() << "failed to remove image" << p_imagePath << e.what(); - } +void FileBufferProvider::removeImage(const QString &p_imagePath) { + auto file = m_file->getImageInterface(); + if (file) { + try { + file->removeImage(p_imagePath); + } catch (Exception &e) { + qWarning() << "failed to remove image" << p_imagePath << e.what(); } + } } -bool FileBufferProvider::isAttachmentSupported() const -{ - return false; -} +bool FileBufferProvider::isAttachmentSupported() const { return false; } -bool FileBufferProvider::isTagSupported() const -{ - return false; -} +bool FileBufferProvider::isTagSupported() const { return false; } -Node *FileBufferProvider::getNode() const -{ - return c_nodeAttachedTo; -} +Node *FileBufferProvider::getNode() const { return c_nodeAttachedTo; } -bool FileBufferProvider::isReadOnly() const -{ - return m_readOnly; -} +bool FileBufferProvider::isReadOnly() const { return m_readOnly; } -QSharedPointer FileBufferProvider::getFile() const -{ - return m_file; -} +QSharedPointer FileBufferProvider::getFile() const { return m_file; } diff --git a/src/core/buffer/filebufferprovider.h b/src/core/buffer/filebufferprovider.h index 16111679f5..75d0534c3b 100644 --- a/src/core/buffer/filebufferprovider.h +++ b/src/core/buffer/filebufferprovider.h @@ -3,79 +3,78 @@ #include "bufferprovider.h" -namespace vnotex -{ - class File; +namespace vnotex { +class File; - // Buffer provider based on external file. - class FileBufferProvider : public BufferProvider - { - Q_OBJECT - public: - FileBufferProvider(const QSharedPointer &m_file, - Node *p_nodeAttachedTo, - bool p_readOnly, - QObject *p_parent = nullptr); +// Buffer provider based on external file. +class FileBufferProvider : public BufferProvider { + Q_OBJECT +public: + FileBufferProvider(const QSharedPointer &m_file, Node *p_nodeAttachedTo, bool p_readOnly, + QObject *p_parent = nullptr); - Buffer::ProviderType getType() const Q_DECL_OVERRIDE; + Buffer::ProviderType getType() const Q_DECL_OVERRIDE; - bool match(const Node *p_node) const Q_DECL_OVERRIDE; + bool match(const Node *p_node) const Q_DECL_OVERRIDE; - bool match(const QString &p_filePath) const Q_DECL_OVERRIDE; + bool match(const QString &p_filePath) const Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getPath() const Q_DECL_OVERRIDE; + QString getPath() const Q_DECL_OVERRIDE; - QString getContentPath() const Q_DECL_OVERRIDE; + QString getContentPath() const Q_DECL_OVERRIDE; - QString getResourcePath() const Q_DECL_OVERRIDE; + QString getResourcePath() const Q_DECL_OVERRIDE; - void write(const QString &p_content) Q_DECL_OVERRIDE; + void write(const QString &p_content) Q_DECL_OVERRIDE; - QString read() const Q_DECL_OVERRIDE; + QString read() const Q_DECL_OVERRIDE; - QString fetchImageFolderPath() Q_DECL_OVERRIDE; + QString fetchImageFolderPath() Q_DECL_OVERRIDE; - bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE; + bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE; - Node *getNode() const Q_DECL_OVERRIDE; + Node *getNode() const Q_DECL_OVERRIDE; - QString getAttachmentFolder() const Q_DECL_OVERRIDE; + QString getAttachmentFolder() const Q_DECL_OVERRIDE; - QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE; + QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE; - QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE; + QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) Q_DECL_OVERRIDE; - QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; - QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) Q_DECL_OVERRIDE; - QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; + QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; - void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; + void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE; - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; - bool isAttachmentSupported() const Q_DECL_OVERRIDE; + bool isAttachmentSupported() const Q_DECL_OVERRIDE; - bool isTagSupported() const Q_DECL_OVERRIDE; + bool isTagSupported() const Q_DECL_OVERRIDE; - bool isReadOnly() const Q_DECL_OVERRIDE; + bool isReadOnly() const Q_DECL_OVERRIDE; - QSharedPointer getFile() const Q_DECL_OVERRIDE; + QSharedPointer getFile() const Q_DECL_OVERRIDE; - private: - QSharedPointer m_file; +private: + QSharedPointer m_file; - Node *c_nodeAttachedTo = nullptr; + Node *c_nodeAttachedTo = nullptr; - bool m_readOnly = false; - }; -} + bool m_readOnly = false; +}; +} // namespace vnotex #endif // FILEBUFFERPROVIDER_H diff --git a/src/core/buffer/filetypehelper.cpp b/src/core/buffer/filetypehelper.cpp index 0beb6b33cd..bfd48e5a44 100644 --- a/src/core/buffer/filetypehelper.cpp +++ b/src/core/buffer/filetypehelper.cpp @@ -1,197 +1,176 @@ #include "filetypehelper.h" -#include #include +#include -#include #include "buffer.h" #include #include +#include using namespace vnotex; -QString FileType::preferredSuffix() const -{ - return m_suffixes.isEmpty() ? QString() : m_suffixes.first(); +QString FileType::preferredSuffix() const { + return m_suffixes.isEmpty() ? QString() : m_suffixes.first(); } -bool FileType::isMarkdown() const -{ - return m_type == Type::Markdown; -} +bool FileType::isMarkdown() const { return m_type == Type::Markdown; } QString FileTypeHelper::s_systemDefaultProgram = QStringLiteral("System"); -FileTypeHelper::FileTypeHelper() -{ - reload(); -} +FileTypeHelper::FileTypeHelper() { reload(); } -void FileTypeHelper::reload() -{ - setupBuiltInTypes(); +void FileTypeHelper::reload() { + setupBuiltInTypes(); - setupSuffixTypeMap(); + setupSuffixTypeMap(); } -void FileTypeHelper::setupBuiltInTypes() -{ - m_fileTypes.clear(); - - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - - { - FileType type; - type.m_type = FileType::Markdown; - type.m_typeName = QStringLiteral("Markdown"); - type.m_displayName = Buffer::tr("Markdown"); - - auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); - if (suffixes && !suffixes->isEmpty()) { - type.m_suffixes = *suffixes; - } else { - type.m_suffixes << QStringLiteral("md") - << QStringLiteral("mkd") - << QStringLiteral("rmd") - << QStringLiteral("markdown"); - } - - m_fileTypes.push_back(type); - } +void FileTypeHelper::setupBuiltInTypes() { + m_fileTypes.clear(); - { - FileType type; - type.m_type = FileType::Text; - type.m_typeName = QStringLiteral("Text"); - type.m_displayName = Buffer::tr("Text"); + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); - if (suffixes && !suffixes->isEmpty()) { - type.m_suffixes = *suffixes; - } else { - type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log"); - } + { + FileType type; + type.m_type = FileType::Markdown; + type.m_typeName = QStringLiteral("Markdown"); + type.m_displayName = Buffer::tr("Markdown"); - m_fileTypes.push_back(type); + auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); + if (suffixes && !suffixes->isEmpty()) { + type.m_suffixes = *suffixes; + } else { + type.m_suffixes << QStringLiteral("md") << QStringLiteral("mkd") << QStringLiteral("rmd") + << QStringLiteral("markdown"); } - { - FileType type; - type.m_type = FileType::Pdf; - type.m_typeName = QStringLiteral("PDF"); - type.m_displayName = Buffer::tr("Portable Document Format"); - type.m_isNewable = false; - - auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); - if (suffixes && !suffixes->isEmpty()) { - type.m_suffixes = *suffixes; - } else { - type.m_suffixes << QStringLiteral("pdf"); - } - - m_fileTypes.push_back(type); + m_fileTypes.push_back(type); + } + + { + FileType type; + type.m_type = FileType::Text; + type.m_typeName = QStringLiteral("Text"); + type.m_displayName = Buffer::tr("Text"); + + auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); + if (suffixes && !suffixes->isEmpty()) { + type.m_suffixes = *suffixes; + } else { + type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log"); } - { - FileType type; - type.m_type = FileType::MindMap; - type.m_typeName = QStringLiteral("MindMap"); - type.m_displayName = Buffer::tr("Mind Map"); + m_fileTypes.push_back(type); + } - auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); - if (suffixes && !suffixes->isEmpty()) { - type.m_suffixes = *suffixes; - } else { - type.m_suffixes << QStringLiteral("emind"); - } + { + FileType type; + type.m_type = FileType::Pdf; + type.m_typeName = QStringLiteral("PDF"); + type.m_displayName = Buffer::tr("Portable Document Format"); + type.m_isNewable = false; - m_fileTypes.push_back(type); + auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); + if (suffixes && !suffixes->isEmpty()) { + type.m_suffixes = *suffixes; + } else { + type.m_suffixes << QStringLiteral("pdf"); } - { - FileType type; - type.m_type = FileType::Others; - type.m_typeName = QStringLiteral("Others"); - type.m_displayName = Buffer::tr("Others"); - m_fileTypes.push_back(type); + m_fileTypes.push_back(type); + } + + { + FileType type; + type.m_type = FileType::MindMap; + type.m_typeName = QStringLiteral("MindMap"); + type.m_displayName = Buffer::tr("Mind Map"); + + auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName); + if (suffixes && !suffixes->isEmpty()) { + type.m_suffixes = *suffixes; + } else { + type.m_suffixes << QStringLiteral("emind"); } + + m_fileTypes.push_back(type); + } + + { + FileType type; + type.m_type = FileType::Others; + type.m_typeName = QStringLiteral("Others"); + type.m_displayName = Buffer::tr("Others"); + m_fileTypes.push_back(type); + } } -const FileType &FileTypeHelper::getFileType(const QString &p_filePath) const -{ - Q_ASSERT(!p_filePath.isEmpty()); +const FileType &FileTypeHelper::getFileType(const QString &p_filePath) const { + Q_ASSERT(!p_filePath.isEmpty()); - QFileInfo fi(p_filePath); - auto suffix = fi.suffix().toLower(); - auto it = m_suffixTypeMap.find(suffix); - if (it != m_suffixTypeMap.end()) { - return m_fileTypes.at(it.value()); - } + QFileInfo fi(p_filePath); + auto suffix = fi.suffix().toLower(); + auto it = m_suffixTypeMap.find(suffix); + if (it != m_suffixTypeMap.end()) { + return m_fileTypes.at(it.value()); + } - // Treat all unknown text files as plain text files. - if (FileUtils::isText(p_filePath)) { - return m_fileTypes[FileType::Text]; - } + // Treat all unknown text files as plain text files. + if (FileUtils::isText(p_filePath)) { + return m_fileTypes[FileType::Text]; + } - return m_fileTypes[FileType::Others]; + return m_fileTypes[FileType::Others]; } -const FileType &FileTypeHelper::getFileTypeBySuffix(const QString &p_suffix) const -{ - auto it = m_suffixTypeMap.find(p_suffix.toLower()); - if (it != m_suffixTypeMap.end()) { - return m_fileTypes.at(it.value()); - } else { - return m_fileTypes[FileType::Others]; - } +const FileType &FileTypeHelper::getFileTypeBySuffix(const QString &p_suffix) const { + auto it = m_suffixTypeMap.find(p_suffix.toLower()); + if (it != m_suffixTypeMap.end()) { + return m_fileTypes.at(it.value()); + } else { + return m_fileTypes[FileType::Others]; + } } -void FileTypeHelper::setupSuffixTypeMap() -{ - m_suffixTypeMap.clear(); - - for (int i = 0; i < m_fileTypes.size(); ++i) { - for (const auto &suffix : m_fileTypes[i].m_suffixes) { - if (m_suffixTypeMap.contains(suffix)) { - qWarning() << "suffix conflicts detected" << suffix << m_fileTypes[i].m_type; - } - m_suffixTypeMap.insert(suffix, i); - } +void FileTypeHelper::setupSuffixTypeMap() { + m_suffixTypeMap.clear(); + + for (int i = 0; i < m_fileTypes.size(); ++i) { + for (const auto &suffix : m_fileTypes[i].m_suffixes) { + if (m_suffixTypeMap.contains(suffix)) { + qWarning() << "suffix conflicts detected" << suffix << m_fileTypes[i].m_type; + } + m_suffixTypeMap.insert(suffix, i); } + } } -const QVector &FileTypeHelper::getAllFileTypes() const -{ - return m_fileTypes; -} +const QVector &FileTypeHelper::getAllFileTypes() const { return m_fileTypes; } -const FileType &FileTypeHelper::getFileType(int p_type) const -{ - if (p_type >= m_fileTypes.size()) { - p_type = FileType::Others; - } - return m_fileTypes[p_type]; +const FileType &FileTypeHelper::getFileType(int p_type) const { + if (p_type >= m_fileTypes.size()) { + p_type = FileType::Others; + } + return m_fileTypes[p_type]; } -FileTypeHelper &FileTypeHelper::getInst() -{ - static FileTypeHelper helper; - return helper; +FileTypeHelper &FileTypeHelper::getInst() { + static FileTypeHelper helper; + return helper; } -bool FileTypeHelper::checkFileType(const QString &p_filePath, int p_type) const -{ - return getFileType(p_filePath).m_type == p_type; +bool FileTypeHelper::checkFileType(const QString &p_filePath, int p_type) const { + return getFileType(p_filePath).m_type == p_type; } -const FileType &FileTypeHelper::getFileTypeByName(const QString &p_typeName) const -{ - for (const auto &ft : m_fileTypes) { - if (ft.m_typeName == p_typeName) { - return ft; - } +const FileType &FileTypeHelper::getFileTypeByName(const QString &p_typeName) const { + for (const auto &ft : m_fileTypes) { + if (ft.m_typeName == p_typeName) { + return ft; } + } - Q_ASSERT(false); - return m_fileTypes[FileType::Others]; + Q_ASSERT(false); + return m_fileTypes[FileType::Others]; } diff --git a/src/core/buffer/filetypehelper.h b/src/core/buffer/filetypehelper.h index 47433dbe5f..2d0e2164cd 100644 --- a/src/core/buffer/filetypehelper.h +++ b/src/core/buffer/filetypehelper.h @@ -1,78 +1,68 @@ #ifndef FILETYPEHELPER_H #define FILETYPEHELPER_H -#include #include +#include #include -namespace vnotex -{ - class FileType - { - public: - // There may be other types after Others. - enum Type - { - Markdown = 0, - Text, - Pdf, - MindMap, - Others - }; +namespace vnotex { +class FileType { +public: + // There may be other types after Others. + enum Type { Markdown = 0, Text, Pdf, MindMap, Others }; - QString preferredSuffix() const; + QString preferredSuffix() const; - bool isMarkdown() const; + bool isMarkdown() const; - // Type. - int m_type = -1; + // Type. + int m_type = -1; - QString m_typeName; + QString m_typeName; - QString m_displayName; + QString m_displayName; - QStringList m_suffixes; + QStringList m_suffixes; - // Whether we can new this type of file. - bool m_isNewable = true; - }; + // Whether we can new this type of file. + bool m_isNewable = true; +}; - // Only handle built-in editors. - class FileTypeHelper - { - public: - const FileType &getFileType(const QString &p_filePath) const; +// Only handle built-in editors. +class FileTypeHelper { +public: + const FileType &getFileType(const QString &p_filePath) const; - const FileType &getFileType(int p_type) const; + const FileType &getFileType(int p_type) const; - const FileType &getFileTypeByName(const QString &p_typeName) const; + const FileType &getFileTypeByName(const QString &p_typeName) const; - const FileType &getFileTypeBySuffix(const QString &p_suffix) const; + const FileType &getFileTypeBySuffix(const QString &p_suffix) const; - const QVector &getAllFileTypes() const; + const QVector &getAllFileTypes() const; - bool checkFileType(const QString &p_filePath, int p_type) const; + bool checkFileType(const QString &p_filePath, int p_type) const; - void reload(); + void reload(); - static FileTypeHelper &getInst(); + static FileTypeHelper &getInst(); - static QString s_systemDefaultProgram; + static QString s_systemDefaultProgram; - private: - FileTypeHelper(); +private: + FileTypeHelper(); - void setupBuiltInTypes(); + void setupBuiltInTypes(); - void setupSuffixTypeMap(); + void setupSuffixTypeMap(); - // Built-in Type could be accessed via enum Type. - QVector m_fileTypes; + // Built-in Type could be accessed via enum Type. + QVector m_fileTypes; - // suffix -> index of m_fileTypes. - // TODO: handle suffix conflicts. - QMap m_suffixTypeMap; - }; -} // ns vnotex + // suffix -> index of m_fileTypes. + // TODO: handle suffix conflicts. + QMap m_suffixTypeMap; +}; +} // namespace vnotex #endif // FILETYPEHELPER_H diff --git a/src/core/buffer/ibufferfactory.h b/src/core/buffer/ibufferfactory.h index b6cbdda7b7..c95ccc04d4 100644 --- a/src/core/buffer/ibufferfactory.h +++ b/src/core/buffer/ibufferfactory.h @@ -3,24 +3,19 @@ #include -namespace vnotex -{ - class Buffer; - struct BufferParameters; +namespace vnotex { +class Buffer; +struct BufferParameters; - // Abstract factory to create buffer. - class IBufferFactory - { - public: - virtual ~IBufferFactory() - { - } +// Abstract factory to create buffer. +class IBufferFactory { +public: + virtual ~IBufferFactory() {} - virtual Buffer *createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) = 0; + virtual Buffer *createBuffer(const BufferParameters &p_parameters, QObject *p_parent) = 0; - virtual bool isBufferCreatedByFactory(const Buffer *p_buffer) const = 0; - }; -} // ns vnotex + virtual bool isBufferCreatedByFactory(const Buffer *p_buffer) const = 0; +}; +} // namespace vnotex #endif // IBUFFERFACTORY_H diff --git a/src/core/buffer/markdownbuffer.cpp b/src/core/buffer/markdownbuffer.cpp index 025a61cf15..22019268c2 100644 --- a/src/core/buffer/markdownbuffer.cpp +++ b/src/core/buffer/markdownbuffer.cpp @@ -2,106 +2,101 @@ #include -#include +#include #include #include -#include +#include using namespace vnotex; -MarkdownBuffer::MarkdownBuffer(const BufferParameters &p_parameters, - QObject *p_parent) - : Buffer(p_parameters, p_parent) -{ - fetchInitialImages(); +MarkdownBuffer::MarkdownBuffer(const BufferParameters &p_parameters, QObject *p_parent) + : Buffer(p_parameters, p_parent) { + fetchInitialImages(); } -ViewWindow *MarkdownBuffer::createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) -{ - Q_UNUSED(p_paras); - return new MarkdownViewWindow(p_parent); +ViewWindow * +MarkdownBuffer::createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) { + Q_UNUSED(p_paras); + return new MarkdownViewWindow(p_parent); } -QString MarkdownBuffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - return m_provider->insertImage(p_srcImagePath, p_imageFileName); +QString MarkdownBuffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) { + return m_provider->insertImage(p_srcImagePath, p_imageFileName); } -QString MarkdownBuffer::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - return m_provider->insertImage(p_image, p_imageFileName); +QString MarkdownBuffer::insertImage(const QImage &p_image, const QString &p_imageFileName) { + return m_provider->insertImage(p_image, p_imageFileName); } -void MarkdownBuffer::fetchInitialImages() -{ - Q_ASSERT(m_initialImages.isEmpty()); - // There is compilation error on Linux and macOS using TypeFlags directly. - int linkFlags = vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote; - m_initialImages = vte::MarkdownUtils::fetchImagesFromMarkdownText(getContent(), - getResourcePath(), - static_cast(linkFlags)); +void MarkdownBuffer::fetchInitialImages() { + Q_ASSERT(m_initialImages.isEmpty()); + // There is compilation error on Linux and macOS using TypeFlags directly. + int linkFlags = + vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote; + m_initialImages = vte::MarkdownUtils::fetchImagesFromMarkdownText( + getContent(), getResourcePath(), static_cast(linkFlags)); } -void MarkdownBuffer::addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink) -{ - vte::MarkdownLink link; - link.m_path = p_imagePath; - link.m_urlInLink = p_urlInLink; - // There are two types: local internal and remote for image host. - link.m_type = PathUtils::isLocalFile(p_imagePath) ? vte::MarkdownLink::TypeFlag::LocalRelativeInternal : vte::MarkdownLink::TypeFlag::Remote; - m_insertedImages.append(link); +void MarkdownBuffer::addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink) { + vte::MarkdownLink link; + link.m_path = p_imagePath; + link.m_urlInLink = p_urlInLink; + // There are two types: local internal and remote for image host. + link.m_type = PathUtils::isLocalFile(p_imagePath) + ? vte::MarkdownLink::TypeFlag::LocalRelativeInternal + : vte::MarkdownLink::TypeFlag::Remote; + m_insertedImages.append(link); } -QHash MarkdownBuffer::clearObsoleteImages() -{ - QHash obsoleteImages; - - Q_ASSERT(!isModified()); - const bool discarded = state() & StateFlag::Discarded; - const int linkFlags = vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote; - const auto latestImages = - vte::MarkdownUtils::fetchImagesFromMarkdownText(!discarded ? getContent() : m_provider->read(), - getResourcePath(), - static_cast(linkFlags)); - QSet latestImagesPath; - for (const auto &link : latestImages) { - if (link.m_type & vte::MarkdownLink::TypeFlag::Remote) { - latestImagesPath.insert(link.m_path); - } else { - latestImagesPath.insert(PathUtils::normalizePath(link.m_path)); - } +QHash MarkdownBuffer::clearObsoleteImages() { + QHash obsoleteImages; + + Q_ASSERT(!isModified()); + const bool discarded = state() & StateFlag::Discarded; + const int linkFlags = + vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote; + const auto latestImages = vte::MarkdownUtils::fetchImagesFromMarkdownText( + !discarded ? getContent() : m_provider->read(), getResourcePath(), + static_cast(linkFlags)); + QSet latestImagesPath; + for (const auto &link : latestImages) { + if (link.m_type & vte::MarkdownLink::TypeFlag::Remote) { + latestImagesPath.insert(link.m_path); + } else { + latestImagesPath.insert(PathUtils::normalizePath(link.m_path)); } + } - for (const auto &link : m_insertedImages) { - if (!(link.m_type & linkFlags)) { - continue; - } + for (const auto &link : m_insertedImages) { + if (!(link.m_type & linkFlags)) { + continue; + } - const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote; - const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path); - if (!latestImagesPath.contains(linkPath)) { - obsoleteImages.insert(link.m_path, isRemote); - } + const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote; + const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path); + if (!latestImagesPath.contains(linkPath)) { + obsoleteImages.insert(link.m_path, isRemote); } + } - m_insertedImages.clear(); + m_insertedImages.clear(); - for (const auto &link : m_initialImages) { - Q_ASSERT(link.m_type & linkFlags); - const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote; - const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path); - if (!latestImagesPath.contains(linkPath)) { - obsoleteImages.insert(link.m_path, isRemote); - } + for (const auto &link : m_initialImages) { + Q_ASSERT(link.m_type & linkFlags); + const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote; + const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path); + if (!latestImagesPath.contains(linkPath)) { + obsoleteImages.insert(link.m_path, isRemote); } + } - m_initialImages = latestImages; + m_initialImages = latestImages; - return obsoleteImages; + return obsoleteImages; } -void MarkdownBuffer::removeImage(const QString &p_imagePath) -{ - qDebug() << "remove obsolete image" << p_imagePath; - m_provider->removeImage(p_imagePath); +void MarkdownBuffer::removeImage(const QString &p_imagePath) { + qDebug() << "remove obsolete image" << p_imagePath; + m_provider->removeImage(p_imagePath); } diff --git a/src/core/buffer/markdownbuffer.h b/src/core/buffer/markdownbuffer.h index 7eda4dbb42..59288ac3da 100644 --- a/src/core/buffer/markdownbuffer.h +++ b/src/core/buffer/markdownbuffer.h @@ -3,46 +3,45 @@ #include "buffer.h" -#include #include +#include #include -namespace vnotex -{ - class MarkdownBuffer : public Buffer - { - Q_OBJECT - public: - MarkdownBuffer(const BufferParameters &p_parameters, - QObject *p_parent = nullptr); +namespace vnotex { +class MarkdownBuffer : public Buffer { + Q_OBJECT +public: + MarkdownBuffer(const BufferParameters &p_parameters, QObject *p_parent = nullptr); - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE; - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; - void addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink); + void addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink); - // Clear obsolete images. - // Won't delete images, just return a list of obsolete images path. - // Will re-init m_initialImages and clear m_insertedImages. - // Return [ImagePath] -> IsRemote. - QHash clearObsoleteImages(); + // Clear obsolete images. + // Won't delete images, just return a list of obsolete images path. + // Will re-init m_initialImages and clear m_insertedImages. + // Return [ImagePath] -> IsRemote. + QHash clearObsoleteImages(); - protected: - ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) Q_DECL_OVERRIDE; +protected: + ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) Q_DECL_OVERRIDE; - private: - void fetchInitialImages(); +private: + void fetchInitialImages(); - // Images referenced in the file before opening this buffer. - QVector m_initialImages; + // Images referenced in the file before opening this buffer. + QVector m_initialImages; - // Images newly inserted during this buffer's lifetime. - QVector m_insertedImages; - }; -} // ns vnotex + // Images newly inserted during this buffer's lifetime. + QVector m_insertedImages; +}; +} // namespace vnotex #endif // MARKDOWNBUFFER_H diff --git a/src/core/buffer/markdownbufferfactory.cpp b/src/core/buffer/markdownbufferfactory.cpp index 1b084c29c4..f5bcb6ab13 100644 --- a/src/core/buffer/markdownbufferfactory.cpp +++ b/src/core/buffer/markdownbufferfactory.cpp @@ -5,12 +5,10 @@ using namespace vnotex; Buffer *MarkdownBufferFactory::createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) -{ - return new MarkdownBuffer(p_parameters, p_parent); + QObject *p_parent) { + return new MarkdownBuffer(p_parameters, p_parent); } -bool MarkdownBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const -{ - return dynamic_cast(p_buffer) != nullptr; +bool MarkdownBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const { + return dynamic_cast(p_buffer) != nullptr; } diff --git a/src/core/buffer/markdownbufferfactory.h b/src/core/buffer/markdownbufferfactory.h index 316efa88de..b30895ad2b 100644 --- a/src/core/buffer/markdownbufferfactory.h +++ b/src/core/buffer/markdownbufferfactory.h @@ -3,17 +3,14 @@ #include "ibufferfactory.h" -namespace vnotex -{ - // Buffer factory for Markdown file. - class MarkdownBufferFactory : public IBufferFactory - { - public: - Buffer *createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) Q_DECL_OVERRIDE; +namespace vnotex { +// Buffer factory for Markdown file. +class MarkdownBufferFactory : public IBufferFactory { +public: + Buffer *createBuffer(const BufferParameters &p_parameters, QObject *p_parent) Q_DECL_OVERRIDE; - bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; - }; -} // vnotex + bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // MARKDOWNBUFFERFACTORY_H diff --git a/src/core/buffer/mindmapbuffer.cpp b/src/core/buffer/mindmapbuffer.cpp index 06fa9f2486..daf91ace76 100644 --- a/src/core/buffer/mindmapbuffer.cpp +++ b/src/core/buffer/mindmapbuffer.cpp @@ -4,14 +4,12 @@ using namespace vnotex; -MindMapBuffer::MindMapBuffer(const BufferParameters &p_parameters, - QObject *p_parent) - : Buffer(p_parameters, p_parent) -{ -} - -ViewWindow *MindMapBuffer::createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) -{ - Q_UNUSED(p_paras); - return new MindMapViewWindow(p_parent); +MindMapBuffer::MindMapBuffer(const BufferParameters &p_parameters, QObject *p_parent) + : Buffer(p_parameters, p_parent) {} + +ViewWindow * +MindMapBuffer::createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) { + Q_UNUSED(p_paras); + return new MindMapViewWindow(p_parent); } diff --git a/src/core/buffer/mindmapbuffer.h b/src/core/buffer/mindmapbuffer.h index 41101d9b5b..5ce44b6c0f 100644 --- a/src/core/buffer/mindmapbuffer.h +++ b/src/core/buffer/mindmapbuffer.h @@ -3,19 +3,16 @@ #include "buffer.h" -namespace vnotex -{ - class MindMapBuffer : public Buffer - { - Q_OBJECT - public: - MindMapBuffer(const BufferParameters &p_parameters, - QObject *p_parent = nullptr); +namespace vnotex { +class MindMapBuffer : public Buffer { + Q_OBJECT +public: + MindMapBuffer(const BufferParameters &p_parameters, QObject *p_parent = nullptr); - protected: - ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, - QWidget *p_parent) Q_DECL_OVERRIDE; - }; -} +protected: + ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // MINDMAPBUFFER_H diff --git a/src/core/buffer/mindmapbufferfactory.cpp b/src/core/buffer/mindmapbufferfactory.cpp index f2f699bccc..31cc91b1d9 100644 --- a/src/core/buffer/mindmapbufferfactory.cpp +++ b/src/core/buffer/mindmapbufferfactory.cpp @@ -5,12 +5,10 @@ using namespace vnotex; Buffer *MindMapBufferFactory::createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) -{ - return new MindMapBuffer(p_parameters, p_parent); + QObject *p_parent) { + return new MindMapBuffer(p_parameters, p_parent); } -bool MindMapBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const -{ - return dynamic_cast(p_buffer) != nullptr; +bool MindMapBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const { + return dynamic_cast(p_buffer) != nullptr; } diff --git a/src/core/buffer/mindmapbufferfactory.h b/src/core/buffer/mindmapbufferfactory.h index 68522e6aae..ab256e4cda 100644 --- a/src/core/buffer/mindmapbufferfactory.h +++ b/src/core/buffer/mindmapbufferfactory.h @@ -3,17 +3,14 @@ #include "ibufferfactory.h" -namespace vnotex -{ - // Buffer factory for MindMap file. - class MindMapBufferFactory : public IBufferFactory - { - public: - Buffer *createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) Q_DECL_OVERRIDE; +namespace vnotex { +// Buffer factory for MindMap file. +class MindMapBufferFactory : public IBufferFactory { +public: + Buffer *createBuffer(const BufferParameters &p_parameters, QObject *p_parent) Q_DECL_OVERRIDE; - bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; - }; -} + bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // MINDMAPBUFFERFACTORY_H diff --git a/src/core/buffer/nodebufferprovider.cpp b/src/core/buffer/nodebufferprovider.cpp index 373a5f651a..99f61c423a 100644 --- a/src/core/buffer/nodebufferprovider.cpp +++ b/src/core/buffer/nodebufferprovider.cpp @@ -2,174 +2,123 @@ #include +#include +#include #include #include #include -#include -#include using namespace vnotex; NodeBufferProvider::NodeBufferProvider(const QSharedPointer &p_node, - const QSharedPointer &p_file, - QObject *p_parent) - : BufferProvider(p_parent), - m_node(p_node), - m_nodeFile(p_file) -{ -} + const QSharedPointer &p_file, QObject *p_parent) + : BufferProvider(p_parent), m_node(p_node), m_nodeFile(p_file) {} -Buffer::ProviderType NodeBufferProvider::getType() const -{ - return Buffer::ProviderType::Internal; -} +Buffer::ProviderType NodeBufferProvider::getType() const { return Buffer::ProviderType::Internal; } -bool NodeBufferProvider::match(const Node *p_node) const -{ - return m_node.data() == p_node; -} +bool NodeBufferProvider::match(const Node *p_node) const { return m_node.data() == p_node; } -bool NodeBufferProvider::match(const QString &p_filePath) const -{ - return PathUtils::areSamePaths(getPath(), p_filePath); +bool NodeBufferProvider::match(const QString &p_filePath) const { + return PathUtils::areSamePaths(getPath(), p_filePath); } -QString NodeBufferProvider::getName() const -{ - return m_node->getName(); -} +QString NodeBufferProvider::getName() const { return m_node->getName(); } -QString NodeBufferProvider::getPath() const -{ - return m_nodeFile->getFilePath(); -} +QString NodeBufferProvider::getPath() const { return m_nodeFile->getFilePath(); } -QString NodeBufferProvider::getContentPath() const -{ - return m_nodeFile->getContentPath(); -} +QString NodeBufferProvider::getContentPath() const { return m_nodeFile->getContentPath(); } -QString NodeBufferProvider::getResourcePath() const -{ - return m_nodeFile->getResourcePath(); -} +QString NodeBufferProvider::getResourcePath() const { return m_nodeFile->getResourcePath(); } -void NodeBufferProvider::write(const QString &p_content) -{ - m_nodeFile->write(p_content); - m_lastModified = getLastModifiedFromFile(); +void NodeBufferProvider::write(const QString &p_content) { + m_nodeFile->write(p_content); + m_lastModified = getLastModifiedFromFile(); } -QString NodeBufferProvider::read() const -{ - const_cast(this)->m_lastModified = getLastModifiedFromFile(); - return m_nodeFile->read(); +QString NodeBufferProvider::read() const { + const_cast(this)->m_lastModified = getLastModifiedFromFile(); + return m_nodeFile->read(); } -QString NodeBufferProvider::fetchImageFolderPath() -{ - auto file = m_nodeFile->getImageInterface(); - if (file) { - return file->fetchImageFolderPath(); - } else { - Q_ASSERT(false); - return getContentPath(); - } +QString NodeBufferProvider::fetchImageFolderPath() { + auto file = m_nodeFile->getImageInterface(); + if (file) { + return file->fetchImageFolderPath(); + } else { + Q_ASSERT(false); + return getContentPath(); + } } -bool NodeBufferProvider::isChildOf(const Node *p_node) const -{ - return Node::isAncestor(p_node, m_node.data()); +bool NodeBufferProvider::isChildOf(const Node *p_node) const { + return Node::isAncestor(p_node, m_node.data()); } -QString NodeBufferProvider::getAttachmentFolder() const -{ - return m_node->getAttachmentFolder(); -} +QString NodeBufferProvider::getAttachmentFolder() const { return m_node->getAttachmentFolder(); } -QString NodeBufferProvider::fetchAttachmentFolderPath() -{ - return m_node->fetchAttachmentFolderPath(); +QString NodeBufferProvider::fetchAttachmentFolderPath() { + return m_node->fetchAttachmentFolderPath(); } -QStringList NodeBufferProvider::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) -{ - return m_node->addAttachment(p_destFolderPath, p_files); +QStringList NodeBufferProvider::addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) { + return m_node->addAttachment(p_destFolderPath, p_files); } -QString NodeBufferProvider::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) -{ - return m_node->newAttachmentFile(p_destFolderPath, p_name); +QString NodeBufferProvider::newAttachmentFile(const QString &p_destFolderPath, + const QString &p_name) { + return m_node->newAttachmentFile(p_destFolderPath, p_name); } -QString NodeBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) -{ - return m_node->newAttachmentFolder(p_destFolderPath, p_name); +QString NodeBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) { + return m_node->newAttachmentFolder(p_destFolderPath, p_name); } -QString NodeBufferProvider::renameAttachment(const QString &p_path, const QString &p_name) -{ - return m_node->renameAttachment(p_path, p_name); +QString NodeBufferProvider::renameAttachment(const QString &p_path, const QString &p_name) { + return m_node->renameAttachment(p_path, p_name); } -void NodeBufferProvider::removeAttachment(const QStringList &p_paths) -{ - return m_node->removeAttachment(p_paths); +void NodeBufferProvider::removeAttachment(const QStringList &p_paths) { + return m_node->removeAttachment(p_paths); } -QString NodeBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - auto file = m_nodeFile->getImageInterface(); - if (file) { - return file->insertImage(p_srcImagePath, p_imageFileName); - } else { - return QString(); - } +QString NodeBufferProvider::insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) { + auto file = m_nodeFile->getImageInterface(); + if (file) { + return file->insertImage(p_srcImagePath, p_imageFileName); + } else { + return QString(); + } } -QString NodeBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - auto file = m_nodeFile->getImageInterface(); - if (file) { - return file->insertImage(p_image, p_imageFileName); - } else { - return QString(); - } +QString NodeBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) { + auto file = m_nodeFile->getImageInterface(); + if (file) { + return file->insertImage(p_image, p_imageFileName); + } else { + return QString(); + } } -void NodeBufferProvider::removeImage(const QString &p_imagePath) -{ - auto file = m_nodeFile->getImageInterface(); - if (file) { - try { - file->removeImage(p_imagePath); - } catch (Exception &e) { - qWarning() << "failed to remove image" << p_imagePath << e.what(); - } +void NodeBufferProvider::removeImage(const QString &p_imagePath) { + auto file = m_nodeFile->getImageInterface(); + if (file) { + try { + file->removeImage(p_imagePath); + } catch (Exception &e) { + qWarning() << "failed to remove image" << p_imagePath << e.what(); } + } } -bool NodeBufferProvider::isAttachmentSupported() const -{ - return true; -} +bool NodeBufferProvider::isAttachmentSupported() const { return true; } -bool NodeBufferProvider::isTagSupported() const -{ - return m_node->getNotebook()->tag() != nullptr; -} +bool NodeBufferProvider::isTagSupported() const { return m_node->getNotebook()->tag() != nullptr; } -Node *NodeBufferProvider::getNode() const -{ - return m_node.data(); -} +Node *NodeBufferProvider::getNode() const { return m_node.data(); } -bool NodeBufferProvider::isReadOnly() const -{ - return m_node->isReadOnly(); -} +bool NodeBufferProvider::isReadOnly() const { return m_node->isReadOnly(); } -QSharedPointer NodeBufferProvider::getFile() const -{ - return m_nodeFile; -} +QSharedPointer NodeBufferProvider::getFile() const { return m_nodeFile; } diff --git a/src/core/buffer/nodebufferprovider.h b/src/core/buffer/nodebufferprovider.h index cab88d2ef2..d9e0043be1 100644 --- a/src/core/buffer/nodebufferprovider.h +++ b/src/core/buffer/nodebufferprovider.h @@ -5,77 +5,77 @@ #include "bufferprovider.h" -namespace vnotex -{ - class File; - class IFileWithImage; +namespace vnotex { +class File; +class IFileWithImage; - // Buffer provider based on an internal node. - class NodeBufferProvider : public BufferProvider - { - Q_OBJECT - public: - NodeBufferProvider(const QSharedPointer &p_node, - const QSharedPointer &p_file, - QObject *p_parent = nullptr); +// Buffer provider based on an internal node. +class NodeBufferProvider : public BufferProvider { + Q_OBJECT +public: + NodeBufferProvider(const QSharedPointer &p_node, const QSharedPointer &p_file, + QObject *p_parent = nullptr); - Buffer::ProviderType getType() const Q_DECL_OVERRIDE; + Buffer::ProviderType getType() const Q_DECL_OVERRIDE; - bool match(const Node *p_node) const Q_DECL_OVERRIDE; + bool match(const Node *p_node) const Q_DECL_OVERRIDE; - bool match(const QString &p_filePath) const Q_DECL_OVERRIDE; + bool match(const QString &p_filePath) const Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getPath() const Q_DECL_OVERRIDE; + QString getPath() const Q_DECL_OVERRIDE; - QString getContentPath() const Q_DECL_OVERRIDE; + QString getContentPath() const Q_DECL_OVERRIDE; - QString getResourcePath() const Q_DECL_OVERRIDE; + QString getResourcePath() const Q_DECL_OVERRIDE; - void write(const QString &p_content) Q_DECL_OVERRIDE; + void write(const QString &p_content) Q_DECL_OVERRIDE; - QString read() const Q_DECL_OVERRIDE; + QString read() const Q_DECL_OVERRIDE; - QString fetchImageFolderPath() Q_DECL_OVERRIDE; + QString fetchImageFolderPath() Q_DECL_OVERRIDE; - bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE; + bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE; - Node *getNode() const Q_DECL_OVERRIDE; + Node *getNode() const Q_DECL_OVERRIDE; - QString getAttachmentFolder() const Q_DECL_OVERRIDE; + QString getAttachmentFolder() const Q_DECL_OVERRIDE; - QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE; + QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE; - QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE; + QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) Q_DECL_OVERRIDE; - QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; - QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) Q_DECL_OVERRIDE; - QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; + QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; - void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; + void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE; - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; - bool isAttachmentSupported() const Q_DECL_OVERRIDE; + bool isAttachmentSupported() const Q_DECL_OVERRIDE; - bool isTagSupported() const Q_DECL_OVERRIDE; + bool isTagSupported() const Q_DECL_OVERRIDE; - bool isReadOnly() const Q_DECL_OVERRIDE; + bool isReadOnly() const Q_DECL_OVERRIDE; - QSharedPointer getFile() const Q_DECL_OVERRIDE; + QSharedPointer getFile() const Q_DECL_OVERRIDE; - private: - QSharedPointer m_node; +private: + QSharedPointer m_node; - QSharedPointer m_nodeFile; - }; -} + QSharedPointer m_nodeFile; +}; +} // namespace vnotex #endif // NODEBUFFERPROVIDER_H diff --git a/src/core/buffer/pdfbuffer.cpp b/src/core/buffer/pdfbuffer.cpp index 1a6c353eef..e4cb173dfd 100644 --- a/src/core/buffer/pdfbuffer.cpp +++ b/src/core/buffer/pdfbuffer.cpp @@ -4,14 +4,11 @@ using namespace vnotex; -PdfBuffer::PdfBuffer(const BufferParameters &p_parameters, - QObject *p_parent) - : Buffer(p_parameters, p_parent) -{ -} +PdfBuffer::PdfBuffer(const BufferParameters &p_parameters, QObject *p_parent) + : Buffer(p_parameters, p_parent) {} -ViewWindow *PdfBuffer::createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) -{ - Q_UNUSED(p_paras); - return new PdfViewWindow(p_parent); +ViewWindow *PdfBuffer::createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) { + Q_UNUSED(p_paras); + return new PdfViewWindow(p_parent); } diff --git a/src/core/buffer/pdfbuffer.h b/src/core/buffer/pdfbuffer.h index d66e37b1eb..2933b2c74a 100644 --- a/src/core/buffer/pdfbuffer.h +++ b/src/core/buffer/pdfbuffer.h @@ -3,19 +3,16 @@ #include "buffer.h" -namespace vnotex -{ - class PdfBuffer : public Buffer - { - Q_OBJECT - public: - PdfBuffer(const BufferParameters &p_parameters, - QObject *p_parent = nullptr); +namespace vnotex { +class PdfBuffer : public Buffer { + Q_OBJECT +public: + PdfBuffer(const BufferParameters &p_parameters, QObject *p_parent = nullptr); - protected: - ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, - QWidget *p_parent) Q_DECL_OVERRIDE; - }; -} // ns vnotex +protected: + ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // PDFBUFFER_H diff --git a/src/core/buffer/pdfbufferfactory.cpp b/src/core/buffer/pdfbufferfactory.cpp index c2562770ae..1585209b6c 100644 --- a/src/core/buffer/pdfbufferfactory.cpp +++ b/src/core/buffer/pdfbufferfactory.cpp @@ -5,15 +5,12 @@ using namespace vnotex; -Buffer *PdfBufferFactory::createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) -{ - BufferParameters paras; - paras.m_provider = QSharedPointer::create(p_parameters.m_provider); - return new PdfBuffer(paras, p_parent); +Buffer *PdfBufferFactory::createBuffer(const BufferParameters &p_parameters, QObject *p_parent) { + BufferParameters paras; + paras.m_provider = QSharedPointer::create(p_parameters.m_provider); + return new PdfBuffer(paras, p_parent); } -bool PdfBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const -{ - return dynamic_cast(p_buffer) != nullptr; +bool PdfBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const { + return dynamic_cast(p_buffer) != nullptr; } diff --git a/src/core/buffer/pdfbufferfactory.h b/src/core/buffer/pdfbufferfactory.h index fd08142dc4..1d3f70571b 100644 --- a/src/core/buffer/pdfbufferfactory.h +++ b/src/core/buffer/pdfbufferfactory.h @@ -3,17 +3,14 @@ #include "ibufferfactory.h" -namespace vnotex -{ - // Buffer factory for Pdf file. - class PdfBufferFactory : public IBufferFactory - { - public: - Buffer *createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) Q_DECL_OVERRIDE; +namespace vnotex { +// Buffer factory for Pdf file. +class PdfBufferFactory : public IBufferFactory { +public: + Buffer *createBuffer(const BufferParameters &p_parameters, QObject *p_parent) Q_DECL_OVERRIDE; - bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; - }; -} // vnotex + bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // PDFBUFFERFACTORY_H diff --git a/src/core/buffer/textbuffer.cpp b/src/core/buffer/textbuffer.cpp index 8dce4b83f3..00bc1a3d57 100644 --- a/src/core/buffer/textbuffer.cpp +++ b/src/core/buffer/textbuffer.cpp @@ -4,14 +4,11 @@ using namespace vnotex; -TextBuffer::TextBuffer(const BufferParameters &p_parameters, - QObject *p_parent) - : Buffer(p_parameters, p_parent) -{ -} +TextBuffer::TextBuffer(const BufferParameters &p_parameters, QObject *p_parent) + : Buffer(p_parameters, p_parent) {} -ViewWindow *TextBuffer::createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) -{ - Q_UNUSED(p_paras); - return new TextViewWindow(p_parent); +ViewWindow *TextBuffer::createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) { + Q_UNUSED(p_paras); + return new TextViewWindow(p_parent); } diff --git a/src/core/buffer/textbuffer.h b/src/core/buffer/textbuffer.h index 2ea4911e37..3b011b6c8c 100644 --- a/src/core/buffer/textbuffer.h +++ b/src/core/buffer/textbuffer.h @@ -3,18 +3,16 @@ #include "buffer.h" -namespace vnotex -{ - class TextBuffer : public Buffer - { - Q_OBJECT - public: - TextBuffer(const BufferParameters &p_parameters, - QObject *p_parent = nullptr); +namespace vnotex { +class TextBuffer : public Buffer { + Q_OBJECT +public: + TextBuffer(const BufferParameters &p_parameters, QObject *p_parent = nullptr); - protected: - ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) Q_DECL_OVERRIDE; - }; -} +protected: + ViewWindow *createViewWindowInternal(const QSharedPointer &p_paras, + QWidget *p_parent) Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // TEXTBUFFER_H diff --git a/src/core/buffer/textbufferfactory.cpp b/src/core/buffer/textbufferfactory.cpp index cb5a1c23a3..494252d5ad 100644 --- a/src/core/buffer/textbufferfactory.cpp +++ b/src/core/buffer/textbufferfactory.cpp @@ -4,13 +4,10 @@ using namespace vnotex; -Buffer *TextBufferFactory::createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) -{ - return new TextBuffer(p_parameters, p_parent); +Buffer *TextBufferFactory::createBuffer(const BufferParameters &p_parameters, QObject *p_parent) { + return new TextBuffer(p_parameters, p_parent); } -bool TextBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const -{ - return dynamic_cast(p_buffer) != nullptr; +bool TextBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const { + return dynamic_cast(p_buffer) != nullptr; } diff --git a/src/core/buffer/textbufferfactory.h b/src/core/buffer/textbufferfactory.h index 5c53477f8f..b8175a11ea 100644 --- a/src/core/buffer/textbufferfactory.h +++ b/src/core/buffer/textbufferfactory.h @@ -3,17 +3,14 @@ #include "ibufferfactory.h" -namespace vnotex -{ - // Buffer factory for text file. - class TextBufferFactory : public IBufferFactory - { - public: - Buffer *createBuffer(const BufferParameters &p_parameters, - QObject *p_parent) Q_DECL_OVERRIDE; +namespace vnotex { +// Buffer factory for text file. +class TextBufferFactory : public IBufferFactory { +public: + Buffer *createBuffer(const BufferParameters &p_parameters, QObject *p_parent) Q_DECL_OVERRIDE; - bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; - }; -} + bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // TEXTBUFFERFACTORY_H diff --git a/src/core/buffer/urlbasedbufferprovider.h b/src/core/buffer/urlbasedbufferprovider.h index a1d8965d5b..84d404e4f0 100644 --- a/src/core/buffer/urlbasedbufferprovider.h +++ b/src/core/buffer/urlbasedbufferprovider.h @@ -5,128 +5,98 @@ #include -namespace vnotex -{ - // A wrapper provider to provide URL-based buffer (instead of content-based). - class UrlBasedBufferProvider : public BufferProvider - { - Q_OBJECT - public: - // Will own @p_provider. - UrlBasedBufferProvider(const QSharedPointer &p_provider, QObject *p_parent = nullptr) - : BufferProvider(p_parent), - m_provider(p_provider) - { - } - - Buffer::ProviderType getType() const Q_DECL_OVERRIDE { - return m_provider->getType(); - } - - bool match(const Node *p_node) const Q_DECL_OVERRIDE { - return m_provider->match(p_node); - } - - bool match(const QString &p_filePath) const Q_DECL_OVERRIDE { - return m_provider->match(p_filePath); - } - - QString getName() const Q_DECL_OVERRIDE { - return m_provider->getName(); - } - - QString getPath() const Q_DECL_OVERRIDE { - return m_provider->getPath(); - } - - QString getContentPath() const Q_DECL_OVERRIDE { - return m_provider->getContentPath(); - } - - QString getResourcePath() const Q_DECL_OVERRIDE { - return m_provider->getResourcePath(); - } - - void write(const QString &p_content) Q_DECL_OVERRIDE { - Q_UNUSED(p_content); - } - - QString read() const Q_DECL_OVERRIDE { - const_cast(this)->m_lastModified = getLastModifiedFromFile(); - return QString(); - } - - QString fetchImageFolderPath() Q_DECL_OVERRIDE { - return m_provider->fetchImageFolderPath(); - } - - bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE { - return m_provider->isChildOf(p_node); - } - - Node *getNode() const Q_DECL_OVERRIDE { - return m_provider->getNode(); - } - - QString getAttachmentFolder() const Q_DECL_OVERRIDE { - return m_provider->getAttachmentFolder(); - } - - QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE { - return m_provider->fetchAttachmentFolderPath(); - } - - QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE { - return m_provider->addAttachment(p_destFolderPath, p_files); - } - - QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE { - return m_provider->newAttachmentFile(p_destFolderPath, p_name); - } - - QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE { - return m_provider->newAttachmentFolder(p_destFolderPath, p_name); - } - - QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE { - return m_provider->renameAttachment(p_path, p_name); - } - - void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE { - m_provider->removeAttachment(p_paths); - } - - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE { - return m_provider->insertImage(p_srcImagePath, p_imageFileName); - } - - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE { - return m_provider->insertImage(p_image, p_imageFileName); - } - - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE { - m_provider->removeImage(p_imagePath); - } - - bool isAttachmentSupported() const Q_DECL_OVERRIDE { - return m_provider->isAttachmentSupported(); - } - - bool isTagSupported() const Q_DECL_OVERRIDE { - return m_provider->isTagSupported(); - } - - bool isReadOnly() const Q_DECL_OVERRIDE { - return true; - } - - QSharedPointer getFile() const Q_DECL_OVERRIDE { - return m_provider->getFile(); - } - - private: - QSharedPointer m_provider; - }; -} +namespace vnotex { +// A wrapper provider to provide URL-based buffer (instead of content-based). +class UrlBasedBufferProvider : public BufferProvider { + Q_OBJECT +public: + // Will own @p_provider. + UrlBasedBufferProvider(const QSharedPointer &p_provider, + QObject *p_parent = nullptr) + : BufferProvider(p_parent), m_provider(p_provider) {} + + Buffer::ProviderType getType() const Q_DECL_OVERRIDE { return m_provider->getType(); } + + bool match(const Node *p_node) const Q_DECL_OVERRIDE { return m_provider->match(p_node); } + + bool match(const QString &p_filePath) const Q_DECL_OVERRIDE { + return m_provider->match(p_filePath); + } + + QString getName() const Q_DECL_OVERRIDE { return m_provider->getName(); } + + QString getPath() const Q_DECL_OVERRIDE { return m_provider->getPath(); } + + QString getContentPath() const Q_DECL_OVERRIDE { return m_provider->getContentPath(); } + + QString getResourcePath() const Q_DECL_OVERRIDE { return m_provider->getResourcePath(); } + + void write(const QString &p_content) Q_DECL_OVERRIDE { Q_UNUSED(p_content); } + + QString read() const Q_DECL_OVERRIDE { + const_cast(this)->m_lastModified = getLastModifiedFromFile(); + return QString(); + } + + QString fetchImageFolderPath() Q_DECL_OVERRIDE { return m_provider->fetchImageFolderPath(); } + + bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE { return m_provider->isChildOf(p_node); } + + Node *getNode() const Q_DECL_OVERRIDE { return m_provider->getNode(); } + + QString getAttachmentFolder() const Q_DECL_OVERRIDE { return m_provider->getAttachmentFolder(); } + + QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE { + return m_provider->fetchAttachmentFolderPath(); + } + + QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) Q_DECL_OVERRIDE { + return m_provider->addAttachment(p_destFolderPath, p_files); + } + + QString newAttachmentFile(const QString &p_destFolderPath, + const QString &p_name) Q_DECL_OVERRIDE { + return m_provider->newAttachmentFile(p_destFolderPath, p_name); + } + + QString newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) Q_DECL_OVERRIDE { + return m_provider->newAttachmentFolder(p_destFolderPath, p_name); + } + + QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE { + return m_provider->renameAttachment(p_path, p_name); + } + + void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE { + m_provider->removeAttachment(p_paths); + } + + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE { + return m_provider->insertImage(p_srcImagePath, p_imageFileName); + } + + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE { + return m_provider->insertImage(p_image, p_imageFileName); + } + + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE { + m_provider->removeImage(p_imagePath); + } + + bool isAttachmentSupported() const Q_DECL_OVERRIDE { return m_provider->isAttachmentSupported(); } + + bool isTagSupported() const Q_DECL_OVERRIDE { return m_provider->isTagSupported(); } + + bool isReadOnly() const Q_DECL_OVERRIDE { return true; } + + QSharedPointer getFile() const Q_DECL_OVERRIDE { return m_provider->getFile(); } + +private: + QSharedPointer m_provider; +}; +} // namespace vnotex #endif // URLBASEDBUFFERPROVIDER_H diff --git a/src/core/buffermgr.cpp b/src/core/buffermgr.cpp index 529c551b91..a894f8fd2f 100644 --- a/src/core/buffermgr.cpp +++ b/src/core/buffermgr.cpp @@ -1,24 +1,24 @@ #include "buffermgr.h" -#include #include +#include -#include +#include "configmgr.h" +#include "externalfile.h" +#include "notebookmgr.h" +#include "sessionconfig.h" +#include "vnotex.h" +#include +#include #include #include -#include -#include #include -#include #include -#include -#include +#include +#include +#include #include -#include "notebookmgr.h" -#include "vnotex.h" -#include "externalfile.h" -#include "sessionconfig.h" -#include "configmgr.h" +#include #include "fileopenparameters.h" @@ -26,283 +26,258 @@ using namespace vnotex; QMap BufferMgr::s_suffixToFileType; -BufferMgr::BufferMgr(QObject *p_parent) - : QObject(p_parent) -{ -} +BufferMgr::BufferMgr(QObject *p_parent) : QObject(p_parent) {} -BufferMgr::~BufferMgr() -{ - Q_ASSERT(m_buffers.isEmpty()); -} +BufferMgr::~BufferMgr() { Q_ASSERT(m_buffers.isEmpty()); } -void BufferMgr::init() -{ - initBufferServer(); -} +void BufferMgr::init() { initBufferServer(); } -void BufferMgr::initBufferServer() -{ - m_bufferServer.reset(new NameBasedServer); +void BufferMgr::initBufferServer() { + m_bufferServer.reset(new NameBasedServer); - const auto &helper = FileTypeHelper::getInst(); + const auto &helper = FileTypeHelper::getInst(); - // Markdown. - auto markdownFactory = QSharedPointer::create(); - m_bufferServer->registerItem(helper.getFileType(FileType::Markdown).m_typeName, markdownFactory); + // Markdown. + auto markdownFactory = QSharedPointer::create(); + m_bufferServer->registerItem(helper.getFileType(FileType::Markdown).m_typeName, markdownFactory); - // Text. - auto textFactory = QSharedPointer::create(); - m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory); + // Text. + auto textFactory = QSharedPointer::create(); + m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory); - // Pdf. - auto pdfFactory = QSharedPointer::create(); - m_bufferServer->registerItem(helper.getFileType(FileType::Pdf).m_typeName, pdfFactory); + // Pdf. + auto pdfFactory = QSharedPointer::create(); + m_bufferServer->registerItem(helper.getFileType(FileType::Pdf).m_typeName, pdfFactory); - // MindMap. - auto mindMapFactory = QSharedPointer::create(); - m_bufferServer->registerItem(helper.getFileType(FileType::MindMap).m_typeName, mindMapFactory); + // MindMap. + auto mindMapFactory = QSharedPointer::create(); + m_bufferServer->registerItem(helper.getFileType(FileType::MindMap).m_typeName, mindMapFactory); } -void BufferMgr::open(Node *p_node, const QSharedPointer &p_paras) -{ - if (!p_node) { - return; - } - - if (p_node->isContainer()) { - return; - } - - if (!p_node->checkExists()) { - auto msg = QStringLiteral("Failed to open node that does not exist (%1)").arg(p_node->fetchAbsolutePath()); - qWarning() << msg; - VNoteX::getInst().showStatusMessageShort(msg); - return; +void BufferMgr::open(Node *p_node, const QSharedPointer &p_paras) { + if (!p_node) { + return; + } + + if (p_node->isContainer()) { + return; + } + + if (!p_node->checkExists()) { + auto msg = QStringLiteral("Failed to open node that does not exist (%1)") + .arg(p_node->fetchAbsolutePath()); + qWarning() << msg; + VNoteX::getInst().showStatusMessageShort(msg); + return; + } + + const auto nodePath = p_node->fetchAbsolutePath(); + + auto fileType = p_paras->m_fileType; + if (fileType.isEmpty()) { + // Check if we need to open it with external program by default according to the suffix. + fileType = findFileTypeByFile(nodePath); + if (openWithExternalProgram(nodePath, fileType)) { + return; } + } - const auto nodePath = p_node->fetchAbsolutePath(); - - auto fileType = p_paras->m_fileType; + auto buffer = findBuffer(p_node); + if (!buffer || !isSameTypeBuffer(buffer, fileType)) { + auto nodeFile = p_node->getContentFile(); + Q_ASSERT(nodeFile); if (fileType.isEmpty()) { - // Check if we need to open it with external program by default according to the suffix. - fileType = findFileTypeByFile(nodePath); - if (openWithExternalProgram(nodePath, fileType)) { - return; - } + fileType = nodeFile->getContentType().m_typeName; + } else if (fileType != nodeFile->getContentType().m_typeName) { + nodeFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type); } - auto buffer = findBuffer(p_node); - if (!buffer || !isSameTypeBuffer(buffer, fileType)) { - auto nodeFile = p_node->getContentFile(); - Q_ASSERT(nodeFile); - if (fileType.isEmpty()) { - fileType = nodeFile->getContentType().m_typeName; - } else if (fileType != nodeFile->getContentType().m_typeName) { - nodeFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type); - } - - auto factory = m_bufferServer->getItem(fileType); - if (!factory) { - // No factory to open this file type. - qInfo() << "file will be opened by default program" << nodePath; - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(nodePath)); - return; - } - - BufferParameters paras; - paras.m_provider.reset(new NodeBufferProvider(p_node->sharedFromThis(), nodeFile)); - buffer = factory->createBuffer(paras, this); - addBuffer(buffer); - } - - Q_ASSERT(buffer); - emit bufferRequested(buffer, p_paras); -} - -void BufferMgr::open(const QString &p_filePath, const QSharedPointer &p_paras) -{ - if (p_filePath.isEmpty()) { - return; + auto factory = m_bufferServer->getItem(fileType); + if (!factory) { + // No factory to open this file type. + qInfo() << "file will be opened by default program" << nodePath; + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(nodePath)); + return; } - // Check if it is requested to open with external program. - if (openWithExternalProgram(p_filePath, p_paras->m_fileType)) { - return; - } + BufferParameters paras; + paras.m_provider.reset(new NodeBufferProvider(p_node->sharedFromThis(), nodeFile)); + buffer = factory->createBuffer(paras, this); + addBuffer(buffer); + } - QFileInfo finfo(p_filePath); - if (!finfo.exists()) { - auto msg = QStringLiteral("Failed to open file that does not exist (%1)").arg(p_filePath); - qWarning() << msg; - VNoteX::getInst().showStatusMessageShort(msg); - WidgetUtils::openUrlByDesktop(QUrl::fromUserInput(p_filePath)); - return; - } + Q_ASSERT(buffer); + emit bufferRequested(buffer, p_paras); +} - // Check if it is an internal node or not. - auto node = VNoteX::getInst().getNotebookMgr().loadNodeByPath(p_filePath); - if (node) { - if (node->hasContent()) { - open(node.data(), p_paras); - return; - } else { - // Folder node. Currently just locate to it. - emit VNoteX::getInst().locateNodeRequested(node.data()); - return; - } +void BufferMgr::open(const QString &p_filePath, const QSharedPointer &p_paras) { + if (p_filePath.isEmpty()) { + return; + } + + // Check if it is requested to open with external program. + if (openWithExternalProgram(p_filePath, p_paras->m_fileType)) { + return; + } + + QFileInfo finfo(p_filePath); + if (!finfo.exists()) { + auto msg = QStringLiteral("Failed to open file that does not exist (%1)").arg(p_filePath); + qWarning() << msg; + VNoteX::getInst().showStatusMessageShort(msg); + WidgetUtils::openUrlByDesktop(QUrl::fromUserInput(p_filePath)); + return; + } + + // Check if it is an internal node or not. + auto node = VNoteX::getInst().getNotebookMgr().loadNodeByPath(p_filePath); + if (node) { + if (node->hasContent()) { + open(node.data(), p_paras); + return; + } else { + // Folder node. Currently just locate to it. + emit VNoteX::getInst().locateNodeRequested(node.data()); + return; } - - if (finfo.isDir()) { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); - return; + } + + if (finfo.isDir()) { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); + return; + } + + auto fileType = p_paras->m_fileType; + if (fileType.isEmpty()) { + // Check if we need to open it with external program by default according to the suffix. + fileType = findFileTypeByFile(p_filePath); + if (openWithExternalProgram(p_filePath, fileType)) { + return; } + } - auto fileType = p_paras->m_fileType; + auto buffer = findBuffer(p_filePath); + if (!buffer || !isSameTypeBuffer(buffer, fileType)) { + // Open it as external file. + auto externalFile = QSharedPointer::create(p_filePath); if (fileType.isEmpty()) { - // Check if we need to open it with external program by default according to the suffix. - fileType = findFileTypeByFile(p_filePath); - if (openWithExternalProgram(p_filePath, fileType)) { - return; - } + fileType = externalFile->getContentType().m_typeName; + } else if (fileType != externalFile->getContentType().m_typeName) { + externalFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type); } - auto buffer = findBuffer(p_filePath); - if (!buffer || !isSameTypeBuffer(buffer, fileType)) { - // Open it as external file. - auto externalFile = QSharedPointer::create(p_filePath); - if (fileType.isEmpty()) { - fileType = externalFile->getContentType().m_typeName; - } else if (fileType != externalFile->getContentType().m_typeName) { - externalFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type); - } - - auto factory = m_bufferServer->getItem(fileType); - if (!factory) { - // No factory to open this file type. - qInfo() << "file will be opened by default program" << p_filePath; - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); - return; - } - - BufferParameters paras; - paras.m_provider.reset(new FileBufferProvider(externalFile, - p_paras->m_nodeAttachedTo, - p_paras->m_readOnly)); - buffer = factory->createBuffer(paras, this); - addBuffer(buffer); + auto factory = m_bufferServer->getItem(fileType); + if (!factory) { + // No factory to open this file type. + qInfo() << "file will be opened by default program" << p_filePath; + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); + return; } - Q_ASSERT(buffer); - emit bufferRequested(buffer, p_paras); + BufferParameters paras; + paras.m_provider.reset( + new FileBufferProvider(externalFile, p_paras->m_nodeAttachedTo, p_paras->m_readOnly)); + buffer = factory->createBuffer(paras, this); + addBuffer(buffer); + } + + Q_ASSERT(buffer); + emit bufferRequested(buffer, p_paras); } -Buffer *BufferMgr::findBuffer(const Node *p_node) const -{ - auto it = std::find_if(m_buffers.constBegin(), - m_buffers.constEnd(), - [p_node](const Buffer *p_buffer) { - return p_buffer->match(p_node); - }); - if (it != m_buffers.constEnd()) { - return *it; - } +Buffer *BufferMgr::findBuffer(const Node *p_node) const { + auto it = std::find_if(m_buffers.constBegin(), m_buffers.constEnd(), + [p_node](const Buffer *p_buffer) { return p_buffer->match(p_node); }); + if (it != m_buffers.constEnd()) { + return *it; + } - return nullptr; + return nullptr; } -Buffer *BufferMgr::findBuffer(const QString &p_filePath) const -{ - auto it = std::find_if(m_buffers.constBegin(), - m_buffers.constEnd(), - [p_filePath](const Buffer *p_buffer) { - return p_buffer->match(p_filePath); - }); - if (it != m_buffers.constEnd()) { - return *it; - } +Buffer *BufferMgr::findBuffer(const QString &p_filePath) const { + auto it = + std::find_if(m_buffers.constBegin(), m_buffers.constEnd(), + [p_filePath](const Buffer *p_buffer) { return p_buffer->match(p_filePath); }); + if (it != m_buffers.constEnd()) { + return *it; + } - return nullptr; + return nullptr; } -void BufferMgr::addBuffer(Buffer *p_buffer) -{ - m_buffers.push_back(p_buffer); - connect(p_buffer, &Buffer::attachedViewWindowEmpty, - this, [this, p_buffer]() { - qDebug() << "delete buffer without attached view window" - << p_buffer->getName(); - m_buffers.removeAll(p_buffer); - p_buffer->close(); - p_buffer->deleteLater(); - }); +void BufferMgr::addBuffer(Buffer *p_buffer) { + m_buffers.push_back(p_buffer); + connect(p_buffer, &Buffer::attachedViewWindowEmpty, this, [this, p_buffer]() { + qDebug() << "delete buffer without attached view window" << p_buffer->getName(); + m_buffers.removeAll(p_buffer); + p_buffer->close(); + p_buffer->deleteLater(); + }); } -bool BufferMgr::openWithExternalProgram(const QString &p_filePath, const QString &p_name) const -{ - if (p_name.isEmpty()) { - return false; - } +bool BufferMgr::openWithExternalProgram(const QString &p_filePath, const QString &p_name) const { + if (p_name.isEmpty()) { + return false; + } - if (p_name == FileTypeHelper::s_systemDefaultProgram) { - // Open it by system default program. - qInfo() << "file will be opened by default program" << p_filePath; - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); - return true; - } + if (p_name == FileTypeHelper::s_systemDefaultProgram) { + // Open it by system default program. + qInfo() << "file will be opened by default program" << p_filePath; + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); + return true; + } - if (auto pro = ConfigMgr::getInst().getSessionConfig().findExternalProgram(p_name)) { - const auto command = pro->fetchCommand(p_filePath); - qDebug() << "external program" << command; - if (!command.isEmpty()) { - ProcessUtils::startDetached(command); - } - return true; + if (auto pro = ConfigMgr::getInst().getSessionConfig().findExternalProgram(p_name)) { + const auto command = pro->fetchCommand(p_filePath); + qDebug() << "external program" << command; + if (!command.isEmpty()) { + ProcessUtils::startDetached(command); } + return true; + } - return false; + return false; } -bool BufferMgr::isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const -{ - if (p_typeName.isEmpty()) { - return true; - } +bool BufferMgr::isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const { + if (p_typeName.isEmpty()) { + return true; + } - auto factory = m_bufferServer->getItem(p_typeName); - Q_ASSERT(factory); - if (factory) { - return factory->isBufferCreatedByFactory(p_buffer); - } + auto factory = m_bufferServer->getItem(p_typeName); + Q_ASSERT(factory); + if (factory) { + return factory->isBufferCreatedByFactory(p_buffer); + } - return true; + return true; } -void BufferMgr::updateSuffixToFileType(const QVector &p_fileTypeSuffixes) -{ - s_suffixToFileType.clear(); - - for (const auto &fts : p_fileTypeSuffixes) { - for (const auto &suf : fts.m_suffixes) { - auto it = s_suffixToFileType.find(suf); - if (it != s_suffixToFileType.end()) { - qWarning() << "suffix conflicts for file types" << fts.m_name << it.value(); - it.value() = fts.m_name; - } else { - s_suffixToFileType.insert(suf, fts.m_name); - } - } +void BufferMgr::updateSuffixToFileType( + const QVector &p_fileTypeSuffixes) { + s_suffixToFileType.clear(); + + for (const auto &fts : p_fileTypeSuffixes) { + for (const auto &suf : fts.m_suffixes) { + auto it = s_suffixToFileType.find(suf); + if (it != s_suffixToFileType.end()) { + qWarning() << "suffix conflicts for file types" << fts.m_name << it.value(); + it.value() = fts.m_name; + } else { + s_suffixToFileType.insert(suf, fts.m_name); + } } + } } -QString BufferMgr::findFileTypeByFile(const QString &p_filePath) -{ - QFileInfo fi(p_filePath); - auto suffix = fi.suffix().toLower(); - auto it = s_suffixToFileType.find(suffix); - if (it != s_suffixToFileType.end()) { - return it.value(); - } else { - return QString(); - } +QString BufferMgr::findFileTypeByFile(const QString &p_filePath) { + QFileInfo fi(p_filePath); + auto suffix = fi.suffix().toLower(); + auto it = s_suffixToFileType.find(suffix); + if (it != s_suffixToFileType.end()) { + return it.value(); + } else { + return QString(); + } } diff --git a/src/core/buffermgr.h b/src/core/buffermgr.h index b4eaf898e5..cd29d2314b 100644 --- a/src/core/buffermgr.h +++ b/src/core/buffermgr.h @@ -1,65 +1,63 @@ #ifndef BUFFERMGR_H #define BUFFERMGR_H +#include #include #include #include #include -#include -#include "namebasedserver.h" #include "coreconfig.h" +#include "namebasedserver.h" -namespace vnotex -{ - class IBufferFactory; - class Node; - class Buffer; - struct FileOpenParameters; +namespace vnotex { +class IBufferFactory; +class Node; +class Buffer; +struct FileOpenParameters; - class BufferMgr : public QObject - { - Q_OBJECT - public: - explicit BufferMgr(QObject *p_parent = nullptr); +class BufferMgr : public QObject { + Q_OBJECT +public: + explicit BufferMgr(QObject *p_parent = nullptr); - ~BufferMgr(); + ~BufferMgr(); - void init(); + void init(); - public slots: - void open(Node *p_node, const QSharedPointer &p_paras); +public slots: + void open(Node *p_node, const QSharedPointer &p_paras); - void open(const QString &p_filePath, const QSharedPointer &p_paras); + void open(const QString &p_filePath, const QSharedPointer &p_paras); - static void updateSuffixToFileType(const QVector &p_fileTypeSuffixes); + static void updateSuffixToFileType(const QVector &p_fileTypeSuffixes); - signals: - void bufferRequested(Buffer *p_buffer, const QSharedPointer &p_paras); +signals: + void bufferRequested(Buffer *p_buffer, const QSharedPointer &p_paras); - private: - void initBufferServer(); +private: + void initBufferServer(); - Buffer *findBuffer(const Node *p_node) const; + Buffer *findBuffer(const Node *p_node) const; - Buffer *findBuffer(const QString &p_filePath) const; + Buffer *findBuffer(const QString &p_filePath) const; - void addBuffer(Buffer *p_buffer); + void addBuffer(Buffer *p_buffer); - bool openWithExternalProgram(const QString &p_filePath, const QString &p_name) const; + bool openWithExternalProgram(const QString &p_filePath, const QString &p_name) const; - bool isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const; + bool isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const; - static QString findFileTypeByFile(const QString &p_filePath); + static QString findFileTypeByFile(const QString &p_filePath); - QSharedPointer> m_bufferServer; + QSharedPointer> m_bufferServer; - // Managed by QObject. - QVector m_buffers; + // Managed by QObject. + QVector m_buffers; - // Mapping from suffix to file type or external program name. - static QMap s_suffixToFileType; - }; -} // ns vnotex + // Mapping from suffix to file type or external program name. + static QMap s_suffixToFileType; +}; +} // namespace vnotex #endif // BUFFERMGR_H diff --git a/src/core/clipboarddata.cpp b/src/core/clipboarddata.cpp index df9b491301..9df1a47dc2 100644 --- a/src/core/clipboarddata.cpp +++ b/src/core/clipboarddata.cpp @@ -11,178 +11,149 @@ const QString NodeClipboardDataItem::c_notebookId = "notebook_id"; const QString NodeClipboardDataItem::c_nodePath = "node_path"; -NodeClipboardDataItem::NodeClipboardDataItem() -{ -} +NodeClipboardDataItem::NodeClipboardDataItem() {} NodeClipboardDataItem::NodeClipboardDataItem(ID p_notebookId, const QString &p_nodePath) - : m_notebookId(p_notebookId), - m_nodeRelativePath(p_nodePath) -{ -} + : m_notebookId(p_notebookId), m_nodeRelativePath(p_nodePath) {} -QJsonObject NodeClipboardDataItem::toJson() const -{ - QJsonObject jobj; - jobj[c_notebookId] = QString::number(m_notebookId); - jobj[c_nodePath] = m_nodeRelativePath; - return jobj; +QJsonObject NodeClipboardDataItem::toJson() const { + QJsonObject jobj; + jobj[c_notebookId] = QString::number(m_notebookId); + jobj[c_nodePath] = m_nodeRelativePath; + return jobj; } -void NodeClipboardDataItem::fromJson(const QJsonObject &p_jobj) -{ - Q_ASSERT(p_jobj.contains(c_notebookId) && p_jobj.contains(c_nodePath)); - auto idRet = stringToID(p_jobj[c_notebookId].toString()); - Q_ASSERT(idRet.first); - m_notebookId = idRet.second; - m_nodeRelativePath = p_jobj[c_nodePath].toString(); +void NodeClipboardDataItem::fromJson(const QJsonObject &p_jobj) { + Q_ASSERT(p_jobj.contains(c_notebookId) && p_jobj.contains(c_nodePath)); + auto idRet = stringToID(p_jobj[c_notebookId].toString()); + Q_ASSERT(idRet.first); + m_notebookId = idRet.second; + m_nodeRelativePath = p_jobj[c_nodePath].toString(); } - const QString ClipboardData::c_instanceId = "instance_id"; const QString ClipboardData::c_action = "action"; const QString ClipboardData::c_data = "data"; -ClipboardData::ClipboardData() -{ -} +ClipboardData::ClipboardData() {} ClipboardData::ClipboardData(ID p_instanceId, Action p_action) - : m_instanceId(p_instanceId), - m_action(p_action) -{ -} - -void ClipboardData::fromJson(const QJsonObject &p_jobj) -{ - clear(); - - if (!p_jobj.contains(c_instanceId) - || !p_jobj.contains(c_action) - || !p_jobj.contains(c_data)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); - return; - } - - auto idRet = stringToID(p_jobj[c_instanceId].toString()); - if (!idRet.first) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); - return; - } - m_instanceId = idRet.second; - - int act = p_jobj[c_action].toInt(Action::Invalid); - m_action = intToAction(act); - if (m_action == Action::Invalid) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); - return; - } - - const auto itemArr = p_jobj[c_data].toArray(); - for (int i = 0; i < itemArr.size(); ++i) { - auto dataItem = createClipboardDataItem(m_action); - dataItem->fromJson(itemArr[i].toObject()); - m_data.push_back(dataItem); - } -} - -QJsonObject ClipboardData::toJson() const -{ - QJsonObject jobj; - jobj[c_instanceId] = QString::number(m_instanceId); - jobj[c_action] = static_cast(m_action); - - QJsonArray data; - for (const auto& item : m_data) { - data.append(item->toJson()); - } - jobj[c_data] = data; + : m_instanceId(p_instanceId), m_action(p_action) {} + +void ClipboardData::fromJson(const QJsonObject &p_jobj) { + clear(); + + if (!p_jobj.contains(c_instanceId) || !p_jobj.contains(c_action) || !p_jobj.contains(c_data)) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); + return; + } + + auto idRet = stringToID(p_jobj[c_instanceId].toString()); + if (!idRet.first) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); + return; + } + m_instanceId = idRet.second; + + int act = p_jobj[c_action].toInt(Action::Invalid); + m_action = intToAction(act); + if (m_action == Action::Invalid) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(','))); + return; + } + + const auto itemArr = p_jobj[c_data].toArray(); + for (int i = 0; i < itemArr.size(); ++i) { + auto dataItem = createClipboardDataItem(m_action); + dataItem->fromJson(itemArr[i].toObject()); + m_data.push_back(dataItem); + } +} + +QJsonObject ClipboardData::toJson() const { + QJsonObject jobj; + jobj[c_instanceId] = QString::number(m_instanceId); + jobj[c_action] = static_cast(m_action); + + QJsonArray data; + for (const auto &item : m_data) { + data.append(item->toJson()); + } + jobj[c_data] = data; + + return jobj; +} + +ClipboardData::Action ClipboardData::intToAction(int p_act) const { + Action act = Action::Invalid; + if (p_act >= Action::CopyNode && p_act < Action::Invalid) { + act = static_cast(p_act); + } + + return act; +} + +void ClipboardData::clear() { + m_instanceId = 0; + m_action = Action::Invalid; + m_data.clear(); +} + +QSharedPointer ClipboardData::createClipboardDataItem(Action p_act) { + switch (p_act) { + case Action::CopyNode: + case Action::MoveNode: + return QSharedPointer::create(); + + case Action::Invalid: + Q_ASSERT(false); + return nullptr; + } - return jobj; + return nullptr; } -ClipboardData::Action ClipboardData::intToAction(int p_act) const -{ - Action act = Action::Invalid; - if (p_act >= Action::CopyNode && p_act < Action::Invalid) { - act = static_cast(p_act); - } - - return act; +void ClipboardData::addItem(const QSharedPointer &p_item) { + Q_ASSERT(p_item); + m_data.push_back(p_item); } -void ClipboardData::clear() -{ - m_instanceId = 0; - m_action = Action::Invalid; - m_data.clear(); +QString ClipboardData::toJsonText() const { + auto data = QJsonDocument(toJson()).toJson(); + return QString::fromUtf8(data); } -QSharedPointer ClipboardData::createClipboardDataItem(Action p_act) -{ - switch (p_act) { - case Action::CopyNode: - case Action::MoveNode: - return QSharedPointer::create(); - - case Action::Invalid: - Q_ASSERT(false); - return nullptr; - } - +QSharedPointer ClipboardData::fromJsonText(const QString &p_json) { + if (p_json.isEmpty()) { return nullptr; -} + } -void ClipboardData::addItem(const QSharedPointer &p_item) -{ - Q_ASSERT(p_item); - m_data.push_back(p_item); -} + auto data = QSharedPointer::create(); + auto jobj = QJsonDocument::fromJson(p_json.toUtf8()).object(); + if (jobj.isEmpty()) { + return nullptr; + } -QString ClipboardData::toJsonText() const -{ - auto data = QJsonDocument(toJson()).toJson(); - return QString::fromUtf8(data); -} + try { + data->fromJson(jobj); + } catch (Exception &p_e) { + Q_UNUSED(p_e); + return nullptr; + } -QSharedPointer ClipboardData::fromJsonText(const QString &p_json) -{ - if (p_json.isEmpty()) { - return nullptr; - } - - auto data = QSharedPointer::create(); - auto jobj = QJsonDocument::fromJson(p_json.toUtf8()).object(); - if (jobj.isEmpty()) { - return nullptr; - } - - try { - data->fromJson(jobj); - } catch (Exception &p_e) { - Q_UNUSED(p_e); - return nullptr; - } - - return data; + return data; } -const QVector> &ClipboardData::getData() const -{ - return m_data; -} +const QVector> &ClipboardData::getData() const { return m_data; } -ID ClipboardData::getInstanceId() const -{ - return m_instanceId; -} +ID ClipboardData::getInstanceId() const { return m_instanceId; } -ClipboardData::Action ClipboardData::getAction() const -{ - return m_action; -} +ClipboardData::Action ClipboardData::getAction() const { return m_action; } diff --git a/src/core/clipboarddata.h b/src/core/clipboarddata.h index 9964197377..00d43b4477 100644 --- a/src/core/clipboarddata.h +++ b/src/core/clipboarddata.h @@ -1,85 +1,79 @@ #ifndef CLIPBOARDDATA_H #define CLIPBOARDDATA_H -#include #include #include +#include #include "global.h" -namespace vnotex -{ - class ClipboardDataItem - { - public: - virtual ~ClipboardDataItem() - { - } +namespace vnotex { +class ClipboardDataItem { +public: + virtual ~ClipboardDataItem() {} - virtual QJsonObject toJson() const = 0; + virtual QJsonObject toJson() const = 0; - virtual void fromJson(const QJsonObject &p_jobj) = 0; - }; + virtual void fromJson(const QJsonObject &p_jobj) = 0; +}; - class NodeClipboardDataItem : public ClipboardDataItem - { - public: - NodeClipboardDataItem(); +class NodeClipboardDataItem : public ClipboardDataItem { +public: + NodeClipboardDataItem(); - NodeClipboardDataItem(ID p_notebookId, const QString &p_nodePath); + NodeClipboardDataItem(ID p_notebookId, const QString &p_nodePath); - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - void fromJson(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; + void fromJson(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; - ID m_notebookId; - QString m_nodeRelativePath; + ID m_notebookId; + QString m_nodeRelativePath; - private: - static const QString c_notebookId; - static const QString c_nodePath; - }; +private: + static const QString c_notebookId; + static const QString c_nodePath; +}; - class ClipboardData - { - public: - enum Action { CopyNode, MoveNode, Invalid }; +class ClipboardData { +public: + enum Action { CopyNode, MoveNode, Invalid }; - ClipboardData(); + ClipboardData(); - ClipboardData(ID p_instanceId, Action p_action); + ClipboardData(ID p_instanceId, Action p_action); - ID getInstanceId() const; + ID getInstanceId() const; - ClipboardData::Action getAction() const; + ClipboardData::Action getAction() const; - const QVector> &getData() const; + const QVector> &getData() const; - void addItem(const QSharedPointer &p_item); + void addItem(const QSharedPointer &p_item); - QString toJsonText() const; + QString toJsonText() const; - static QSharedPointer fromJsonText(const QString &p_json); + static QSharedPointer fromJsonText(const QString &p_json); - private: - void fromJson(const QJsonObject &p_jobj); +private: + void fromJson(const QJsonObject &p_jobj); - QJsonObject toJson() const; + QJsonObject toJson() const; - ClipboardData::Action intToAction(int p_act) const; + ClipboardData::Action intToAction(int p_act) const; - void clear(); + void clear(); - static QSharedPointer createClipboardDataItem(Action p_act); + static QSharedPointer createClipboardDataItem(Action p_act); - ID m_instanceId = 0; - Action m_action = Action::Invalid; - QVector> m_data; + ID m_instanceId = 0; + Action m_action = Action::Invalid; + QVector> m_data; - static const QString c_instanceId; - static const QString c_action; - static const QString c_data; - }; -} // ns vnotex + static const QString c_instanceId; + static const QString c_action; + static const QString c_data; +}; +} // namespace vnotex #endif // CLIPBOARDDATA_H diff --git a/src/core/configmgr.cpp b/src/core/configmgr.cpp index d68add0787..f10b33bfc3 100644 --- a/src/core/configmgr.cpp +++ b/src/core/configmgr.cpp @@ -1,25 +1,25 @@ #include "configmgr.h" -#include #include -#include #include -#include +#include +#include #include -#include -#include #include -#include +#include +#include #include +#include +#include #include -#include -#include #include "exception.h" +#include +#include #include -#include "mainconfig.h" #include "coreconfig.h" +#include "mainconfig.h" #include "sessionconfig.h" using namespace vnotex; @@ -40,575 +40,507 @@ const QString ConfigMgr::c_userFilesFolder = "user_files"; const QString ConfigMgr::c_appFilesFolder = "vnotex_files"; -const QJsonObject &ConfigMgr::Settings::getJson() const -{ - return m_jobj; -} +const QJsonObject &ConfigMgr::Settings::getJson() const { return m_jobj; } -QSharedPointer ConfigMgr::Settings::fromFile(const QString &p_jsonFilePath) -{ - if (!QFileInfo::exists(p_jsonFilePath)) { - qWarning() << "return empty Settings from non-exist config file" << p_jsonFilePath; - return QSharedPointer::create(); - } +QSharedPointer ConfigMgr::Settings::fromFile(const QString &p_jsonFilePath) { + if (!QFileInfo::exists(p_jsonFilePath)) { + qWarning() << "return empty Settings from non-exist config file" << p_jsonFilePath; + return QSharedPointer::create(); + } - auto bytes = FileUtils::readFile(p_jsonFilePath); - return QSharedPointer::create(QJsonDocument::fromJson(bytes).object()); + auto bytes = FileUtils::readFile(p_jsonFilePath); + return QSharedPointer::create(QJsonDocument::fromJson(bytes).object()); } -void ConfigMgr::Settings::writeToFile(const QString &p_jsonFilePath) const -{ - FileUtils::writeFile(p_jsonFilePath, QJsonDocument(this->m_jobj).toJson()); +void ConfigMgr::Settings::writeToFile(const QString &p_jsonFilePath) const { + FileUtils::writeFile(p_jsonFilePath, QJsonDocument(this->m_jobj).toJson()); } ConfigMgr::ConfigMgr(bool p_isUnitTest, QObject *p_parent) - : QObject(p_parent), - m_config(new MainConfig(this)), - m_sessionConfig(new SessionConfig(this)) -{ - if (p_isUnitTest) { - m_dirForUnitTest.reset(new QTemporaryDir()); - if (!m_dirForUnitTest->isValid()) { - qWarning() << "failed to init ConfigMgr for UnitTest"; - return; - } - - QDir dir(m_dirForUnitTest->path()); - dir.mkdir(c_appFilesFolder); - dir.mkdir(c_userFilesFolder); - - m_appConfigFolderPath = m_dirForUnitTest->filePath(c_appFilesFolder); - m_userConfigFolderPath = m_dirForUnitTest->filePath(c_userFilesFolder); - return; + : QObject(p_parent), m_config(new MainConfig(this)), m_sessionConfig(new SessionConfig(this)) { + if (p_isUnitTest) { + m_dirForUnitTest.reset(new QTemporaryDir()); + if (!m_dirForUnitTest->isValid()) { + qWarning() << "failed to init ConfigMgr for UnitTest"; + return; } - locateConfigFolder(); + QDir dir(m_dirForUnitTest->path()); + dir.mkdir(c_appFilesFolder); + dir.mkdir(c_userFilesFolder); - bool needUpdate = checkAppConfig(); - if (needUpdate) { - checkUserConfig(); - } + m_appConfigFolderPath = m_dirForUnitTest->filePath(c_appFilesFolder); + m_userConfigFolderPath = m_dirForUnitTest->filePath(c_userFilesFolder); + return; + } - m_config->init(); - m_sessionConfig->init(); -} + locateConfigFolder(); -ConfigMgr::~ConfigMgr() -{ -} + bool needUpdate = checkAppConfig(); + if (needUpdate) { + checkUserConfig(); + } -ConfigMgr &ConfigMgr::getInst(bool p_isUnitTest) -{ - static ConfigMgr inst(p_isUnitTest); - return inst; + m_config->init(); + m_sessionConfig->init(); } -void ConfigMgr::initForUnitTest() -{ - getInst(true); +ConfigMgr::~ConfigMgr() {} + +ConfigMgr &ConfigMgr::getInst(bool p_isUnitTest) { + static ConfigMgr inst(p_isUnitTest); + return inst; } -void ConfigMgr::locateConfigFolder() -{ - const auto appDirPath = getApplicationDirPath(); - qInfo() << "app folder" << appDirPath; - // Check app config. - { - QString folderPath(appDirPath + '/' + c_appFilesFolder); - if (QDir(folderPath).exists()) { - // Config folder in app/. - m_appConfigFolderPath = PathUtils::cleanPath(folderPath); - } else { - m_appConfigFolderPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); - } - } +void ConfigMgr::initForUnitTest() { getInst(true); } - // Check user config. - { - QString folderPath(appDirPath + '/' + c_userFilesFolder); - if (QDir(folderPath).exists()) { - // Config folder in app/. - m_userConfigFolderPath = PathUtils::cleanPath(folderPath); - } else { - m_userConfigFolderPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - - // Make sure it exists. - QDir dir(m_userConfigFolderPath); - dir.mkpath(m_userConfigFolderPath); - } +void ConfigMgr::locateConfigFolder() { + const auto appDirPath = getApplicationDirPath(); + qInfo() << "app folder" << appDirPath; + // Check app config. + { + QString folderPath(appDirPath + '/' + c_appFilesFolder); + if (QDir(folderPath).exists()) { + // Config folder in app/. + m_appConfigFolderPath = PathUtils::cleanPath(folderPath); + } else { + m_appConfigFolderPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); } + } + + // Check user config. + { + QString folderPath(appDirPath + '/' + c_userFilesFolder); + if (QDir(folderPath).exists()) { + // Config folder in app/. + m_userConfigFolderPath = PathUtils::cleanPath(folderPath); + } else { + m_userConfigFolderPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - Q_ASSERT(m_appConfigFolderPath != m_userConfigFolderPath); - qInfo() << "app config folder" << m_appConfigFolderPath; - qInfo() << "user config folder" << m_userConfigFolderPath; -} - -bool ConfigMgr::checkAppConfig() -{ - bool needUpdate = false; - QDir appConfigDir(m_appConfigFolderPath); - if (!appConfigDir.exists()) { - needUpdate = true; - appConfigDir.mkpath(m_appConfigFolderPath); + // Make sure it exists. + QDir dir(m_userConfigFolderPath); + dir.mkpath(m_userConfigFolderPath); + } + } + + Q_ASSERT(m_appConfigFolderPath != m_userConfigFolderPath); + qInfo() << "app config folder" << m_appConfigFolderPath; + qInfo() << "user config folder" << m_userConfigFolderPath; +} + +bool ConfigMgr::checkAppConfig() { + bool needUpdate = false; + QDir appConfigDir(m_appConfigFolderPath); + if (!appConfigDir.exists()) { + needUpdate = true; + appConfigDir.mkpath(m_appConfigFolderPath); + } else { + if (!appConfigDir.exists(c_configFileName)) { + needUpdate = true; } else { - if (!appConfigDir.exists(c_configFileName)) { - needUpdate = true; - } else { - // Check version of config file. - auto defaultSettings = getSettings(Source::Default); - auto appSettings = getSettings(Source::App); - auto defaultVersion = MainConfig::getVersion(defaultSettings->getJson()); - auto appVersion = MainConfig::getVersion(appSettings->getJson()); - if (defaultVersion != appVersion) { - qInfo() << "new version" << appVersion << defaultVersion; - needUpdate = true; - } - } - - if (needUpdate) { - FileUtils::removeDir(m_appConfigFolderPath); - // Wait for the OS delete the folder. - Utils::sleepWait(1000); - appConfigDir.mkpath(m_appConfigFolderPath); - } + // Check version of config file. + auto defaultSettings = getSettings(Source::Default); + auto appSettings = getSettings(Source::App); + auto defaultVersion = MainConfig::getVersion(defaultSettings->getJson()); + auto appVersion = MainConfig::getVersion(appSettings->getJson()); + if (defaultVersion != appVersion) { + qInfo() << "new version" << appVersion << defaultVersion; + needUpdate = true; + } + } + + if (needUpdate) { + FileUtils::removeDir(m_appConfigFolderPath); + // Wait for the OS delete the folder. + Utils::sleepWait(1000); + appConfigDir.mkpath(m_appConfigFolderPath); } + } - const auto mainConfigFilePath = appConfigDir.filePath(c_configFileName); + const auto mainConfigFilePath = appConfigDir.filePath(c_configFileName); #ifndef VX_DEBUG_WEB - if (!needUpdate) { - return false; - } + if (!needUpdate) { + return false; + } #endif - qInfo() << "update app config files in" << m_appConfigFolderPath; + qInfo() << "update app config files in" << m_appConfigFolderPath; - Q_ASSERT(appConfigDir.exists()); + Q_ASSERT(appConfigDir.exists()); - QPixmap pixmap(":/vnotex/data/core/logo/vnote.png"); - QScopedPointer splash(new QSplashScreen(pixmap)); - splash->show(); + QPixmap pixmap(":/vnotex/data/core/logo/vnote.png"); + QScopedPointer splash(new QSplashScreen(pixmap)); + splash->show(); - // Load extra data. - splash->showMessage("Loading extra resource data"); - const QString extraRcc("app:vnote_extra.rcc"); - bool ret = QResource::registerResource(extraRcc); - if (!ret) { - Exception::throwOne(Exception::Type::FailToReadFile, - QStringLiteral("failed to register resource file %1").arg(extraRcc)); - } - auto cleanup = qScopeGuard([extraRcc]() { - QResource::unregisterResource(extraRcc); - }); + // Load extra data. + splash->showMessage("Loading extra resource data"); + const QString extraRcc("app:vnote_extra.rcc"); + bool ret = QResource::registerResource(extraRcc); + if (!ret) { + Exception::throwOne(Exception::Type::FailToReadFile, + QStringLiteral("failed to register resource file %1").arg(extraRcc)); + } + auto cleanup = qScopeGuard([extraRcc]() { QResource::unregisterResource(extraRcc); }); - const QString extraDataRoot(QStringLiteral(":/vnotex/data/extra")); + const QString extraDataRoot(QStringLiteral(":/vnotex/data/extra")); #ifdef VX_DEBUG_WEB - if (!needUpdate) { - // Always update main config file and web folder. - qDebug() << "forced to update main config file and web folder for debugging"; - splash->showMessage("update main config file and web folder for debugging"); - - // Cancel the read-only permission of the main config file. - QFile::setPermissions(mainConfigFilePath, QFile::WriteUser); - FileUtils::removeFile(mainConfigFilePath); - FileUtils::removeDir(appConfigDir.filePath(QStringLiteral("web"))); - - // Wait for the OS delete the folder. - Utils::sleepWait(1000); - - FileUtils::copyFile(getConfigFilePath(Source::Default), mainConfigFilePath); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/web"), - appConfigDir.filePath(QStringLiteral("web"))); - return false; - } -#else - Q_ASSERT(needUpdate); -#endif + if (!needUpdate) { + // Always update main config file and web folder. + qDebug() << "forced to update main config file and web folder for debugging"; + splash->showMessage("update main config file and web folder for debugging"); - // Copy themes. - qApp->processEvents(); - splash->showMessage("Copying themes"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/themes"), - appConfigDir.filePath(QStringLiteral("themes"))); - - // Copy tasks. - qApp->processEvents(); - splash->showMessage("Copying tasks"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/tasks"), - appConfigDir.filePath(QStringLiteral("tasks"))); - - // Copy docs. - qApp->processEvents(); - splash->showMessage("Copying docs"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/docs"), - appConfigDir.filePath(QStringLiteral("docs"))); - - // Copy syntax-highlighting. - qApp->processEvents(); - splash->showMessage("Copying syntax-highlighting"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/syntax-highlighting"), - appConfigDir.filePath(QStringLiteral("syntax-highlighting"))); - - // Copy web. - qApp->processEvents(); - splash->showMessage("Copying web"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/web"), - appConfigDir.filePath(QStringLiteral("web"))); - - // Copy dicts. - qApp->processEvents(); - splash->showMessage("Copying dicts"); - FileUtils::copyDir(extraDataRoot + QStringLiteral("/dicts"), - appConfigDir.filePath(QStringLiteral("dicts"))); + // Cancel the read-only permission of the main config file. + QFile::setPermissions(mainConfigFilePath, QFile::WriteUser); + FileUtils::removeFile(mainConfigFilePath); + FileUtils::removeDir(appConfigDir.filePath(QStringLiteral("web"))); - // Main config file. - FileUtils::copyFile(getConfigFilePath(Source::Default), appConfigDir.filePath(c_configFileName)); + // Wait for the OS delete the folder. + Utils::sleepWait(1000); - return needUpdate; -} + FileUtils::copyFile(getConfigFilePath(Source::Default), mainConfigFilePath); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/web"), + appConfigDir.filePath(QStringLiteral("web"))); + return false; + } +#else + Q_ASSERT(needUpdate); +#endif -void ConfigMgr::checkUserConfig() -{ - // Mainly check if the user config and session config is read-only. - const auto userFile = getConfigFilePath(Source::User); - if (QFileInfo::exists(userFile)) { - if (!(QFile::permissions(userFile) & QFile::WriteUser)) { - qDebug() << "make user config file writable" << userFile; - QFile::setPermissions(userFile, QFile::WriteUser); - } + // Copy themes. + qApp->processEvents(); + splash->showMessage("Copying themes"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/themes"), + appConfigDir.filePath(QStringLiteral("themes"))); + + // Copy tasks. + qApp->processEvents(); + splash->showMessage("Copying tasks"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/tasks"), + appConfigDir.filePath(QStringLiteral("tasks"))); + + // Copy docs. + qApp->processEvents(); + splash->showMessage("Copying docs"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/docs"), + appConfigDir.filePath(QStringLiteral("docs"))); + + // Copy syntax-highlighting. + qApp->processEvents(); + splash->showMessage("Copying syntax-highlighting"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/syntax-highlighting"), + appConfigDir.filePath(QStringLiteral("syntax-highlighting"))); + + // Copy web. + qApp->processEvents(); + splash->showMessage("Copying web"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/web"), + appConfigDir.filePath(QStringLiteral("web"))); + + // Copy dicts. + qApp->processEvents(); + splash->showMessage("Copying dicts"); + FileUtils::copyDir(extraDataRoot + QStringLiteral("/dicts"), + appConfigDir.filePath(QStringLiteral("dicts"))); + + // Main config file. + FileUtils::copyFile(getConfigFilePath(Source::Default), appConfigDir.filePath(c_configFileName)); + + return needUpdate; +} + +void ConfigMgr::checkUserConfig() { + // Mainly check if the user config and session config is read-only. + const auto userFile = getConfigFilePath(Source::User); + if (QFileInfo::exists(userFile)) { + if (!(QFile::permissions(userFile) & QFile::WriteUser)) { + qDebug() << "make user config file writable" << userFile; + QFile::setPermissions(userFile, QFile::WriteUser); } + } - const auto sessionFile = getConfigFilePath(Source::Session); - if (QFileInfo::exists(sessionFile)) { - if (!(QFile::permissions(sessionFile) & QFile::WriteUser)) { - qDebug() << "make session config file writable" << sessionFile; - QFile::setPermissions(sessionFile, QFile::WriteUser); - } + const auto sessionFile = getConfigFilePath(Source::Session); + if (QFileInfo::exists(sessionFile)) { + if (!(QFile::permissions(sessionFile) & QFile::WriteUser)) { + qDebug() << "make session config file writable" << sessionFile; + QFile::setPermissions(sessionFile, QFile::WriteUser); } + } } -QString ConfigMgr::getConfigFilePath(Source p_src) const -{ - QString configPath; - switch (p_src) { - case Source::Default: - configPath = getDefaultConfigFilePath(); - break; +QString ConfigMgr::getConfigFilePath(Source p_src) const { + QString configPath; + switch (p_src) { + case Source::Default: + configPath = getDefaultConfigFilePath(); + break; - case Source::App: - configPath = m_appConfigFolderPath + QLatin1Char('/') + c_configFileName; - break; + case Source::App: + configPath = m_appConfigFolderPath + QLatin1Char('/') + c_configFileName; + break; - case Source::User: - { - configPath = m_userConfigFolderPath + QLatin1Char('/') + c_configFileName; - break; - } + case Source::User: { + configPath = m_userConfigFolderPath + QLatin1Char('/') + c_configFileName; + break; + } - case Source::Session: - { - configPath = m_userConfigFolderPath + QLatin1Char('/') + c_sessionFileName; - break; - } + case Source::Session: { + configPath = m_userConfigFolderPath + QLatin1Char('/') + c_sessionFileName; + break; + } - default: - Q_ASSERT(false); - } + default: + Q_ASSERT(false); + } - return configPath; + return configPath; } -QString ConfigMgr::getDefaultConfigFilePath() -{ - return QStringLiteral(":/vnotex/data/core/") + c_configFileName; +QString ConfigMgr::getDefaultConfigFilePath() { + return QStringLiteral(":/vnotex/data/core/") + c_configFileName; } -QSharedPointer ConfigMgr::getSettings(Source p_src) const -{ - return ConfigMgr::Settings::fromFile(getConfigFilePath(p_src)); +QSharedPointer ConfigMgr::getSettings(Source p_src) const { + return ConfigMgr::Settings::fromFile(getConfigFilePath(p_src)); } -void ConfigMgr::writeUserSettings(const QJsonObject &p_jobj) -{ - Settings settings(p_jobj); - settings.writeToFile(getConfigFilePath(Source::User)); +void ConfigMgr::writeUserSettings(const QJsonObject &p_jobj) { + Settings settings(p_jobj); + settings.writeToFile(getConfigFilePath(Source::User)); } -void ConfigMgr::writeSessionSettings(const QJsonObject &p_jobj) -{ - Settings settings(p_jobj); - settings.writeToFile(getConfigFilePath(Source::Session)); +void ConfigMgr::writeSessionSettings(const QJsonObject &p_jobj) { + Settings settings(p_jobj); + settings.writeToFile(getConfigFilePath(Source::Session)); } -MainConfig &ConfigMgr::getConfig() -{ - return *m_config; -} +MainConfig &ConfigMgr::getConfig() { return *m_config; } -SessionConfig &ConfigMgr::getSessionConfig() -{ - return *m_sessionConfig; -} +SessionConfig &ConfigMgr::getSessionConfig() { return *m_sessionConfig; } -CoreConfig &ConfigMgr::getCoreConfig() -{ - return m_config->getCoreConfig(); -} +CoreConfig &ConfigMgr::getCoreConfig() { return m_config->getCoreConfig(); } -EditorConfig &ConfigMgr::getEditorConfig() -{ - return m_config->getEditorConfig(); -} +EditorConfig &ConfigMgr::getEditorConfig() { return m_config->getEditorConfig(); } -WidgetConfig &ConfigMgr::getWidgetConfig() -{ - return m_config->getWidgetConfig(); -} +WidgetConfig &ConfigMgr::getWidgetConfig() { return m_config->getWidgetConfig(); } -QString ConfigMgr::getAppFolder() const -{ - return m_appConfigFolderPath; -} +QString ConfigMgr::getAppFolder() const { return m_appConfigFolderPath; } -QString ConfigMgr::getUserFolder() const -{ - return m_userConfigFolderPath; -} +QString ConfigMgr::getUserFolder() const { return m_userConfigFolderPath; } -QString ConfigMgr::getAppThemeFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("themes")); +QString ConfigMgr::getAppThemeFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("themes")); } -QString ConfigMgr::getUserThemeFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("themes")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserThemeFolder() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("themes")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getAppTaskFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("tasks")); +QString ConfigMgr::getAppTaskFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("tasks")); } -QString ConfigMgr::getUserTaskFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("tasks")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserTaskFolder() const { + auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("tasks")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getAppWebStylesFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("web-styles")); +QString ConfigMgr::getAppWebStylesFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("web-styles")); } -QString ConfigMgr::getUserWebStylesFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("web-styles")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserWebStylesFolder() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("web-styles")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getAppDocsFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("docs")); +QString ConfigMgr::getAppDocsFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("docs")); } -QString ConfigMgr::getUserDocsFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("docs")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserDocsFolder() const { + auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("docs")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getAppSyntaxHighlightingFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, - QStringLiteral("syntax-highlighting")); +QString ConfigMgr::getAppSyntaxHighlightingFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, + QStringLiteral("syntax-highlighting")); } -QString ConfigMgr::getUserSyntaxHighlightingFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, - QStringLiteral("syntax-highlighting")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserSyntaxHighlightingFolder() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("syntax-highlighting")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getAppDictsFolder() const -{ - return PathUtils::concatenateFilePath(m_appConfigFolderPath, - QStringLiteral("dicts")); +QString ConfigMgr::getAppDictsFolder() const { + return PathUtils::concatenateFilePath(m_appConfigFolderPath, QStringLiteral("dicts")); } -QString ConfigMgr::getUserDictsFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, - QStringLiteral("dicts")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserDictsFolder() const { + auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("dicts")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getUserTemplateFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("templates")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserTemplateFolder() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("templates")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getUserSnippetFolder() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("snippets")); - QDir().mkpath(folderPath); - return folderPath; +QString ConfigMgr::getUserSnippetFolder() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("snippets")); + QDir().mkpath(folderPath); + return folderPath; } -QString ConfigMgr::getUserMarkdownUserStyleFile() const -{ - auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("web/css")); - auto filePath = PathUtils::concatenateFilePath(folderPath, QStringLiteral("user.css")); - if (!QFileInfo::exists(filePath)) { - QDir().mkpath(folderPath); - FileUtils::writeFile(filePath, QByteArray()); - } - return filePath; +QString ConfigMgr::getUserMarkdownUserStyleFile() const { + auto folderPath = + PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("web/css")); + auto filePath = PathUtils::concatenateFilePath(folderPath, QStringLiteral("user.css")); + if (!QFileInfo::exists(filePath)) { + QDir().mkpath(folderPath); + FileUtils::writeFile(filePath, QByteArray()); + } + return filePath; } -QString ConfigMgr::getUserOrAppFile(const QString &p_filePath) const -{ - QFileInfo fi(p_filePath); - if (fi.isAbsolute()) { - return p_filePath; - } +QString ConfigMgr::getUserOrAppFile(const QString &p_filePath) const { + QFileInfo fi(p_filePath); + if (fi.isAbsolute()) { + return p_filePath; + } - // Check user folder first. - QDir userConfigDir(m_userConfigFolderPath); - if (userConfigDir.exists(p_filePath)) { - return userConfigDir.absoluteFilePath(p_filePath); - } + // Check user folder first. + QDir userConfigDir(m_userConfigFolderPath); + if (userConfigDir.exists(p_filePath)) { + return userConfigDir.absoluteFilePath(p_filePath); + } - // App folder. - QDir appConfigDir(m_appConfigFolderPath); - return appConfigDir.absoluteFilePath(p_filePath); + // App folder. + QDir appConfigDir(m_appConfigFolderPath); + return appConfigDir.absoluteFilePath(p_filePath); } -QString ConfigMgr::locateSessionConfigFilePathAtBootstrap() -{ - // QApplication is not init yet, so org and app name are empty here. - auto folderPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - folderPath = PathUtils::concatenateFilePath(folderPath, c_orgName + "/" + c_appName); - QDir dir(folderPath); - if (dir.exists(c_sessionFileName)) { - qInfo() << "locateSessionConfigFilePathAtBootstrap" << folderPath; - return dir.filePath(c_sessionFileName); - } +QString ConfigMgr::locateSessionConfigFilePathAtBootstrap() { + // QApplication is not init yet, so org and app name are empty here. + auto folderPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); + folderPath = PathUtils::concatenateFilePath(folderPath, c_orgName + "/" + c_appName); + QDir dir(folderPath); + if (dir.exists(c_sessionFileName)) { + qInfo() << "locateSessionConfigFilePathAtBootstrap" << folderPath; + return dir.filePath(c_sessionFileName); + } - return QString(); + return QString(); } -QString ConfigMgr::getLogFile() const -{ - return PathUtils::concatenateFilePath(ConfigMgr::getInst().getUserFolder(), "vnotex.log"); +QString ConfigMgr::getLogFile() const { + return PathUtils::concatenateFilePath(ConfigMgr::getInst().getUserFolder(), "vnotex.log"); } -QString ConfigMgr::getApplicationFilePath() -{ +QString ConfigMgr::getApplicationFilePath() { #if defined(Q_OS_LINUX) - // We could get the APPIMAGE env variable from the AppRun script. - auto appImageVar = QString::fromLocal8Bit(qgetenv("APPIMAGE")); - qInfo() << "APPIMAGE" << appImageVar; - if (!appImageVar.isEmpty()) { - return appImageVar; - } + // We could get the APPIMAGE env variable from the AppRun script. + auto appImageVar = QString::fromLocal8Bit(qgetenv("APPIMAGE")); + qInfo() << "APPIMAGE" << appImageVar; + if (!appImageVar.isEmpty()) { + return appImageVar; + } #elif defined(Q_OS_MACOS) - auto exePath = QCoreApplication::applicationFilePath(); - const QString exeName = c_appName.toLower() + ".app"; - int idx = exePath.indexOf(exeName + QStringLiteral("/Contents/MacOS/")); - if (idx != -1) { - return exePath.left(idx + exeName.size()); - } + auto exePath = QCoreApplication::applicationFilePath(); + const QString exeName = c_appName.toLower() + ".app"; + int idx = exePath.indexOf(exeName + QStringLiteral("/Contents/MacOS/")); + if (idx != -1) { + return exePath.left(idx + exeName.size()); + } #endif - return QCoreApplication::applicationFilePath(); + return QCoreApplication::applicationFilePath(); } -QString ConfigMgr::getApplicationDirPath() -{ - return PathUtils::parentDirPath(getApplicationFilePath()); +QString ConfigMgr::getApplicationDirPath() { + return PathUtils::parentDirPath(getApplicationFilePath()); } -QString ConfigMgr::getDocumentOrHomePath() -{ - static QString docHomePath; - if (docHomePath.isEmpty()) { - QStringList folders = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (folders.isEmpty()) { - docHomePath = QDir::homePath(); - } else { - docHomePath = folders[0]; - } +QString ConfigMgr::getDocumentOrHomePath() { + static QString docHomePath; + if (docHomePath.isEmpty()) { + QStringList folders = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (folders.isEmpty()) { + docHomePath = QDir::homePath(); + } else { + docHomePath = folders[0]; } + } - return docHomePath; + return docHomePath; } -QString ConfigMgr::getApplicationVersion() -{ - static QString appVersion; +QString ConfigMgr::getApplicationVersion() { + static QString appVersion; - if (appVersion.isEmpty()) { - auto defaultSettings = ConfigMgr::Settings::fromFile(getDefaultConfigFilePath()); - const auto &defaultObj = defaultSettings->getJson(); + if (appVersion.isEmpty()) { + auto defaultSettings = ConfigMgr::Settings::fromFile(getDefaultConfigFilePath()); + const auto &defaultObj = defaultSettings->getJson(); - auto metaDataObj = defaultObj.value(QStringLiteral("metadata")).toObject(); - appVersion = metaDataObj.value(QStringLiteral("version")).toString(); - } + auto metaDataObj = defaultObj.value(QStringLiteral("metadata")).toObject(); + appVersion = metaDataObj.value(QStringLiteral("version")).toString(); + } - return appVersion; + return appVersion; } -void ConfigMgr::initAppPrefixPath() -{ - // Support QFile("app:abc.txt"). - QStringList potential_dirs; - auto app_dir_path = QCoreApplication::applicationDirPath(); - qInfo() << "app prefix path: " << app_dir_path; - potential_dirs << app_dir_path; +void ConfigMgr::initAppPrefixPath() { + // Support QFile("app:abc.txt"). + QStringList potential_dirs; + auto app_dir_path = QCoreApplication::applicationDirPath(); + qInfo() << "app prefix path: " << app_dir_path; + potential_dirs << app_dir_path; #if defined(Q_OS_LINUX) - QDir localBinDir(app_dir_path); - if (localBinDir.exists("../local/bin/vnote")) { - auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../local/share")); - qInfo() << "app prefix path: " << app_dir_path2; - potential_dirs << app_dir_path2; - } - if (localBinDir.exists("../share")) { - auto app_dir_path3 = localBinDir.cleanPath(localBinDir.filePath("../share")); - qInfo() << "app prefix path: " << app_dir_path3; - potential_dirs << app_dir_path3; - } + QDir localBinDir(app_dir_path); + if (localBinDir.exists("../local/bin/vnote")) { + auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../local/share")); + qInfo() << "app prefix path: " << app_dir_path2; + potential_dirs << app_dir_path2; + } + if (localBinDir.exists("../share")) { + auto app_dir_path3 = localBinDir.cleanPath(localBinDir.filePath("../share")); + qInfo() << "app prefix path: " << app_dir_path3; + potential_dirs << app_dir_path3; + } #elif defined(Q_OS_MACOS) - QDir localBinDir(app_dir_path); - if (localBinDir.exists("../Resources")) { - auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../Resources")); - qInfo() << "app prefix path: " << app_dir_path2; - potential_dirs << app_dir_path2; - } + QDir localBinDir(app_dir_path); + if (localBinDir.exists("../Resources")) { + auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../Resources")); + qInfo() << "app prefix path: " << app_dir_path2; + potential_dirs << app_dir_path2; + } #endif - QDir::setSearchPaths("app", potential_dirs); + QDir::setSearchPaths("app", potential_dirs); } -QJsonValue ConfigMgr::parseAndReadConfig(const QString &p_exp) const -{ - if (p_exp.startsWith(QStringLiteral("main."))) { - return Utils::parseAndReadJson(m_config->toJson(), p_exp.mid(5)); - } else if (p_exp.startsWith(QStringLiteral("session."))) { - return Utils::parseAndReadJson(m_sessionConfig->toJson(), p_exp.mid(8)); - } else { - return QJsonValue(); - } +QJsonValue ConfigMgr::parseAndReadConfig(const QString &p_exp) const { + if (p_exp.startsWith(QStringLiteral("main."))) { + return Utils::parseAndReadJson(m_config->toJson(), p_exp.mid(5)); + } else if (p_exp.startsWith(QStringLiteral("session."))) { + return Utils::parseAndReadJson(m_sessionConfig->toJson(), p_exp.mid(8)); + } else { + return QJsonValue(); + } } diff --git a/src/core/configmgr.h b/src/core/configmgr.h index 0642baebc8..4d9438a7e3 100644 --- a/src/core/configmgr.h +++ b/src/core/configmgr.h @@ -1,183 +1,172 @@ #ifndef CONFIGMGR_H #define CONFIGMGR_H -#include -#include #include +#include #include +#include #include "noncopyable.h" class QTemporaryDir; -namespace vnotex -{ - class MainConfig; - class SessionConfig; - class CoreConfig; - class EditorConfig; - class WidgetConfig; +namespace vnotex { +class MainConfig; +class SessionConfig; +class CoreConfig; +class EditorConfig; +class WidgetConfig; - class ConfigMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - enum class Source - { - Default, - App, - User, - Session - }; +class ConfigMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + enum class Source { Default, App, User, Session }; - class Settings - { - public: - Settings() = default; + class Settings { + public: + Settings() = default; - Settings(const QJsonObject &p_jobj) - : m_jobj(p_jobj) - { - } + Settings(const QJsonObject &p_jobj) : m_jobj(p_jobj) {} - const QJsonObject &getJson() const; + const QJsonObject &getJson() const; - void writeToFile(const QString &p_jsonFilePath) const; + void writeToFile(const QString &p_jsonFilePath) const; - static QSharedPointer fromFile(const QString &p_jsonFilePath); + static QSharedPointer fromFile(const QString &p_jsonFilePath); - private: - QJsonObject m_jobj; - }; + private: + QJsonObject m_jobj; + }; - ~ConfigMgr(); + ~ConfigMgr(); - static ConfigMgr &getInst(bool p_isUnitTest = false); + static ConfigMgr &getInst(bool p_isUnitTest = false); - MainConfig &getConfig(); + MainConfig &getConfig(); - SessionConfig &getSessionConfig(); + SessionConfig &getSessionConfig(); - CoreConfig &getCoreConfig(); + CoreConfig &getCoreConfig(); - EditorConfig &getEditorConfig(); + EditorConfig &getEditorConfig(); - WidgetConfig &getWidgetConfig(); + WidgetConfig &getWidgetConfig(); - QString getAppFolder() const; + QString getAppFolder() const; - QString getUserFolder() const; + QString getUserFolder() const; - QString getLogFile() const; + QString getLogFile() const; - QString getAppThemeFolder() const; + QString getAppThemeFolder() const; - QString getUserThemeFolder() const; + QString getUserThemeFolder() const; - QString getAppTaskFolder() const; + QString getAppTaskFolder() const; - QString getUserTaskFolder() const; + QString getUserTaskFolder() const; - QString getAppWebStylesFolder() const; + QString getAppWebStylesFolder() const; - QString getUserWebStylesFolder() const; + QString getUserWebStylesFolder() const; - QString getAppDocsFolder() const; + QString getAppDocsFolder() const; - QString getUserDocsFolder() const; + QString getUserDocsFolder() const; - QString getAppSyntaxHighlightingFolder() const; + QString getAppSyntaxHighlightingFolder() const; - QString getUserSyntaxHighlightingFolder() const; + QString getUserSyntaxHighlightingFolder() const; - QString getAppDictsFolder() const; - QString getUserDictsFolder() const; + QString getAppDictsFolder() const; + QString getUserDictsFolder() const; - QString getUserTemplateFolder() const; + QString getUserTemplateFolder() const; - QString getUserSnippetFolder() const; + QString getUserSnippetFolder() const; - // web/css/user.css. - QString getUserMarkdownUserStyleFile() const; + // web/css/user.css. + QString getUserMarkdownUserStyleFile() const; - // If @p_filePath is absolute, just return it. - // Otherwise, first try to find it in user folder, then in app folder. - QString getUserOrAppFile(const QString &p_filePath) const; + // If @p_filePath is absolute, just return it. + // Otherwise, first try to find it in user folder, then in app folder. + QString getUserOrAppFile(const QString &p_filePath) const; - QString getConfigFilePath(Source p_src) const; + QString getConfigFilePath(Source p_src) const; - // Parse exp like "[main|session].core.shortcuts.FullScreen" and return the config value. - QJsonValue parseAndReadConfig(const QString &p_exp) const; + // Parse exp like "[main|session].core.shortcuts.FullScreen" and return the config value. + QJsonValue parseAndReadConfig(const QString &p_exp) const; - // Called at boostrap without QApplication instance. - static QString locateSessionConfigFilePathAtBootstrap(); + // Called at boostrap without QApplication instance. + static QString locateSessionConfigFilePathAtBootstrap(); - static QString getApplicationFilePath(); + static QString getApplicationFilePath(); - static QString getApplicationDirPath(); + static QString getApplicationDirPath(); - static QString getDocumentOrHomePath(); + static QString getDocumentOrHomePath(); - static QString getApplicationVersion(); + static QString getApplicationVersion(); - static void initAppPrefixPath(); + static void initAppPrefixPath(); - static void initForUnitTest(); + static void initForUnitTest(); - static const QString c_orgName; + static const QString c_orgName; - static const QString c_appName; + static const QString c_appName; - public: - // Used by IConfig. - QSharedPointer getSettings(Source p_src) const; +public: + // Used by IConfig. + QSharedPointer getSettings(Source p_src) const; - void writeUserSettings(const QJsonObject &p_jobj); + void writeUserSettings(const QJsonObject &p_jobj); - void writeSessionSettings(const QJsonObject &p_jobj); + void writeSessionSettings(const QJsonObject &p_jobj); - signals: - void editorConfigChanged(); +signals: + void editorConfigChanged(); - private: - ConfigMgr(bool p_isUnitTest, QObject *p_parent = nullptr); +private: + ConfigMgr(bool p_isUnitTest, QObject *p_parent = nullptr); - // Locate the folder path where the config file exists. - void locateConfigFolder(); + // Locate the folder path where the config file exists. + void locateConfigFolder(); - // Check if app config exists and is updated. - // Update it if in need. - // Return true if there is update. - bool checkAppConfig(); + // Check if app config exists and is updated. + // Update it if in need. + // Return true if there is update. + bool checkAppConfig(); - void checkUserConfig(); + void checkUserConfig(); - static QString getDefaultConfigFilePath(); + static QString getDefaultConfigFilePath(); - QScopedPointer m_config;; + QScopedPointer m_config; + ; - // Session config. - QScopedPointer m_sessionConfig; + // Session config. + QScopedPointer m_sessionConfig; - // Absolute path of the app config folder. - QString m_appConfigFolderPath; + // Absolute path of the app config folder. + QString m_appConfigFolderPath; - // Absolute path of the user config folder. - QString m_userConfigFolderPath; + // Absolute path of the user config folder. + QString m_userConfigFolderPath; - // In UnitTest, we use a temp dir to hold the user files and app files. - QScopedPointer m_dirForUnitTest; + // In UnitTest, we use a temp dir to hold the user files and app files. + QScopedPointer m_dirForUnitTest; - // Name of the core config file. - static const QString c_configFileName; + // Name of the core config file. + static const QString c_configFileName; - // Name of the session config file. - static const QString c_sessionFileName; + // Name of the session config file. + static const QString c_sessionFileName; - static const QString c_userFilesFolder; + static const QString c_userFilesFolder; - static const QString c_appFilesFolder; - }; -} // ns vnotex + static const QString c_appFilesFolder; +}; +} // namespace vnotex #endif // CONFIGMGR_H diff --git a/src/core/coreconfig.cpp b/src/core/coreconfig.cpp index 132f6c296b..6191bab5b7 100644 --- a/src/core/coreconfig.cpp +++ b/src/core/coreconfig.cpp @@ -1,10 +1,10 @@ #include "coreconfig.h" -#include #include +#include -#include #include +#include using namespace vnotex; @@ -14,386 +14,315 @@ using namespace vnotex; #define READSTRLIST(key) readStringList(appObj, userObj, (key)) CoreConfig::FileTypeSuffix::FileTypeSuffix(const QString &p_name, const QStringList &p_suffixes) - : m_name(p_name), - m_suffixes(p_suffixes) -{ -} + : m_name(p_name), m_suffixes(p_suffixes) {} -bool CoreConfig::FileTypeSuffix::operator==(const FileTypeSuffix &p_other) const -{ - return m_name == p_other.m_name && m_suffixes == p_other.m_suffixes; +bool CoreConfig::FileTypeSuffix::operator==(const FileTypeSuffix &p_other) const { + return m_name == p_other.m_name && m_suffixes == p_other.m_suffixes; } QStringList CoreConfig::s_availableLocales; -CoreConfig::CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig) -{ - m_sessionName = QStringLiteral("core"); +CoreConfig::CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) : IConfig(p_mgr, p_topConfig) { + m_sessionName = QStringLiteral("core"); } -const QString &CoreConfig::getTheme() const -{ - return m_theme; -} +const QString &CoreConfig::getTheme() const { return m_theme; } -void CoreConfig::setTheme(const QString &p_name) -{ - updateConfig(m_theme, p_name, this); -} +void CoreConfig::setTheme(const QString &p_name) { updateConfig(m_theme, p_name, this); } -void CoreConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void CoreConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - m_theme = READSTR(QStringLiteral("theme")); + m_theme = READSTR(QStringLiteral("theme")); - m_locale = READSTR(QStringLiteral("locale")); - if (!m_locale.isEmpty() && !getAvailableLocales().contains(m_locale)) { - m_locale = QStringLiteral("en_US"); - } + m_locale = READSTR(QStringLiteral("locale")); + if (!m_locale.isEmpty() && !getAvailableLocales().contains(m_locale)) { + m_locale = QStringLiteral("en_US"); + } - loadShortcuts(appObj, userObj); + loadShortcuts(appObj, userObj); - m_shortcutLeaderKey = READSTR(QStringLiteral("shortcut_leader_key")); + m_shortcutLeaderKey = READSTR(QStringLiteral("shortcut_leader_key")); - m_toolBarIconSize = READINT(QStringLiteral("toolbar_icon_size")); - if (m_toolBarIconSize <= 0) { - m_toolBarIconSize = 18; - } + m_toolBarIconSize = READINT(QStringLiteral("toolbar_icon_size")); + if (m_toolBarIconSize <= 0) { + m_toolBarIconSize = 18; + } - m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size")); - if (m_docksTabBarIconSize <= 0) { - m_docksTabBarIconSize = 18; - } + m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size")); + if (m_docksTabBarIconSize <= 0) { + m_docksTabBarIconSize = 18; + } - loadNoteManagement(appObj, userObj); + loadNoteManagement(appObj, userObj); - m_recoverLastSessionOnStartEnabled = READBOOL(QStringLiteral("recover_last_session_on_start")); + m_recoverLastSessionOnStartEnabled = READBOOL(QStringLiteral("recover_last_session_on_start")); - m_checkForUpdatesOnStartEnabled = READBOOL(QStringLiteral("check_for_updates_on_start")); + m_checkForUpdatesOnStartEnabled = READBOOL(QStringLiteral("check_for_updates_on_start")); - m_historyMaxCount = READINT(QStringLiteral("history_max_count")); - if (m_historyMaxCount < 0) { - m_historyMaxCount = 100; - } + m_historyMaxCount = READINT(QStringLiteral("history_max_count")); + if (m_historyMaxCount < 0) { + m_historyMaxCount = 100; + } - m_perNotebookHistoryEnabled = READBOOL(QStringLiteral("per_notebook_history")); + m_perNotebookHistoryEnabled = READBOOL(QStringLiteral("per_notebook_history")); - { - auto lineEnding = READSTR(QStringLiteral("line_ending")); - m_lineEnding = stringToLineEndingPolicy(lineEnding); - } + { + auto lineEnding = READSTR(QStringLiteral("line_ending")); + m_lineEnding = stringToLineEndingPolicy(lineEnding); + } - { - auto mode = READSTR(QStringLiteral("default_open_mode")); - m_defaultOpenMode = stringToViewWindowMode(mode); - } + { + auto mode = READSTR(QStringLiteral("default_open_mode")); + m_defaultOpenMode = stringToViewWindowMode(mode); + } - loadFileTypeSuffixes(appObj, userObj); + loadFileTypeSuffixes(appObj, userObj); - loadUnitedEntry(appObj, userObj); + loadUnitedEntry(appObj, userObj); } -QJsonObject CoreConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("theme")] = m_theme; - obj[QStringLiteral("locale")] = m_locale; - obj[QStringLiteral("shortcuts")] = saveShortcuts(); - obj[QStringLiteral("shortcut_leader_key")] = m_shortcutLeaderKey; - 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("check_for_updates_on_start")] = m_checkForUpdatesOnStartEnabled; - obj[QStringLiteral("history_max_count")] = m_historyMaxCount; - obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled; - obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding); - obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes(); - obj[QStringLiteral("united_entry")] = saveUnitedEntry(); - obj[QStringLiteral("default_open_mode")] = viewWindowModeToString(m_defaultOpenMode); - return obj; +QJsonObject CoreConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("theme")] = m_theme; + obj[QStringLiteral("locale")] = m_locale; + obj[QStringLiteral("shortcuts")] = saveShortcuts(); + obj[QStringLiteral("shortcut_leader_key")] = m_shortcutLeaderKey; + 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("check_for_updates_on_start")] = m_checkForUpdatesOnStartEnabled; + obj[QStringLiteral("history_max_count")] = m_historyMaxCount; + obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled; + obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding); + obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes(); + obj[QStringLiteral("united_entry")] = saveUnitedEntry(); + obj[QStringLiteral("default_open_mode")] = viewWindowModeToString(m_defaultOpenMode); + return obj; } -const QString &CoreConfig::getLocale() const -{ - return m_locale; -} +const QString &CoreConfig::getLocale() const { return m_locale; } -void CoreConfig::setLocale(const QString &p_locale) -{ - updateConfig(m_locale, p_locale, this); -} +void CoreConfig::setLocale(const QString &p_locale) { updateConfig(m_locale, p_locale, this); } -QString CoreConfig::getLocaleToUse() const -{ - return QLocale().name(); -} +QString CoreConfig::getLocaleToUse() const { return QLocale().name(); } -const QStringList &CoreConfig::getAvailableLocales() -{ - if (s_availableLocales.isEmpty()) { - s_availableLocales << QStringLiteral("en_US"); - s_availableLocales << QStringLiteral("zh_CN"); - s_availableLocales << QStringLiteral("ja_JP"); - } +const QStringList &CoreConfig::getAvailableLocales() { + if (s_availableLocales.isEmpty()) { + s_availableLocales << QStringLiteral("en_US"); + s_availableLocales << QStringLiteral("zh_CN"); + s_availableLocales << QStringLiteral("ja_JP"); + } - return s_availableLocales; + return s_availableLocales; } -void CoreConfig::loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(QStringLiteral("shortcuts")).toObject(); - const auto userObj = p_user.value(QStringLiteral("shortcuts")).toObject(); - - static const auto indexOfShortcutEnum = CoreConfig::staticMetaObject.indexOfEnumerator("Shortcut"); - Q_ASSERT(indexOfShortcutEnum >= 0); - const auto metaEnum = CoreConfig::staticMetaObject.enumerator(indexOfShortcutEnum); - // Skip the Max flag. - for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { - m_shortcuts[i] = READSTR(metaEnum.key(i)); - } +void CoreConfig::loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(QStringLiteral("shortcuts")).toObject(); + const auto userObj = p_user.value(QStringLiteral("shortcuts")).toObject(); + + static const auto indexOfShortcutEnum = + CoreConfig::staticMetaObject.indexOfEnumerator("Shortcut"); + Q_ASSERT(indexOfShortcutEnum >= 0); + const auto metaEnum = CoreConfig::staticMetaObject.enumerator(indexOfShortcutEnum); + // Skip the Max flag. + for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { + m_shortcuts[i] = READSTR(metaEnum.key(i)); + } } -void CoreConfig::loadNoteManagement(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto topAppObj = p_app.value(QStringLiteral("note_management")).toObject(); - const auto topUserObj = p_user.value(QStringLiteral("note_management")).toObject(); +void CoreConfig::loadNoteManagement(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto topAppObj = p_app.value(QStringLiteral("note_management")).toObject(); + const auto topUserObj = p_user.value(QStringLiteral("note_management")).toObject(); - // External node. - { - const auto appObj = topAppObj.value(QStringLiteral("external_node")).toObject(); - const auto userObj = topUserObj.value(QStringLiteral("external_node")).toObject(); + // External node. + { + const auto appObj = topAppObj.value(QStringLiteral("external_node")).toObject(); + const auto userObj = topUserObj.value(QStringLiteral("external_node")).toObject(); - m_externalNodeExcludePatterns = READSTRLIST(QStringLiteral("exclude_patterns")); - } + m_externalNodeExcludePatterns = READSTRLIST(QStringLiteral("exclude_patterns")); + } } -QJsonObject CoreConfig::saveShortcuts() const -{ - QJsonObject obj; - static const auto indexOfShortcutEnum = CoreConfig::staticMetaObject.indexOfEnumerator("Shortcut"); - Q_ASSERT(indexOfShortcutEnum >= 0); - const auto metaEnum = CoreConfig::staticMetaObject.enumerator(indexOfShortcutEnum); - // Skip the Max flag. - for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { - obj[metaEnum.key(i)] = m_shortcuts[i]; - } - return obj; +QJsonObject CoreConfig::saveShortcuts() const { + QJsonObject obj; + static const auto indexOfShortcutEnum = + CoreConfig::staticMetaObject.indexOfEnumerator("Shortcut"); + Q_ASSERT(indexOfShortcutEnum >= 0); + const auto metaEnum = CoreConfig::staticMetaObject.enumerator(indexOfShortcutEnum); + // Skip the Max flag. + for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { + obj[metaEnum.key(i)] = m_shortcuts[i]; + } + return obj; } -const QString &CoreConfig::getShortcut(Shortcut p_shortcut) const -{ - Q_ASSERT(p_shortcut < Shortcut::MaxShortcut); - return m_shortcuts[p_shortcut]; +const QString &CoreConfig::getShortcut(Shortcut p_shortcut) const { + Q_ASSERT(p_shortcut < Shortcut::MaxShortcut); + return m_shortcuts[p_shortcut]; } -int CoreConfig::getToolBarIconSize() const -{ - return m_toolBarIconSize; -} +int CoreConfig::getToolBarIconSize() const { return m_toolBarIconSize; } -void CoreConfig::setToolBarIconSize(int p_size) -{ - Q_ASSERT(p_size > 0); - updateConfig(m_toolBarIconSize, p_size, this); +void CoreConfig::setToolBarIconSize(int p_size) { + Q_ASSERT(p_size > 0); + updateConfig(m_toolBarIconSize, p_size, this); } -int CoreConfig::getDocksTabBarIconSize() const -{ - return m_docksTabBarIconSize; -} +int CoreConfig::getDocksTabBarIconSize() const { return m_docksTabBarIconSize; } -void CoreConfig::setDocksTabBarIconSize(int p_size) -{ - Q_ASSERT(p_size > 0); - updateConfig(m_docksTabBarIconSize, p_size, this); +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; +const QStringList &CoreConfig::getExternalNodeExcludePatterns() const { + return m_externalNodeExcludePatterns; } -bool CoreConfig::isRecoverLastSessionOnStartEnabled() const -{ - return m_recoverLastSessionOnStartEnabled; +bool CoreConfig::isRecoverLastSessionOnStartEnabled() const { + return m_recoverLastSessionOnStartEnabled; } -void CoreConfig::setRecoverLastSessionOnStartEnabled(bool p_enabled) -{ - updateConfig(m_recoverLastSessionOnStartEnabled, p_enabled, this); +void CoreConfig::setRecoverLastSessionOnStartEnabled(bool p_enabled) { + updateConfig(m_recoverLastSessionOnStartEnabled, p_enabled, this); } -bool CoreConfig::isCheckForUpdatesOnStartEnabled() const -{ - return m_checkForUpdatesOnStartEnabled; -} +bool CoreConfig::isCheckForUpdatesOnStartEnabled() const { return m_checkForUpdatesOnStartEnabled; } -void CoreConfig::setCheckForUpdatesOnStartEnabled(bool p_enabled) -{ - updateConfig(m_checkForUpdatesOnStartEnabled, p_enabled, this); +void CoreConfig::setCheckForUpdatesOnStartEnabled(bool p_enabled) { + updateConfig(m_checkForUpdatesOnStartEnabled, p_enabled, this); } -int CoreConfig::getHistoryMaxCount() const -{ - return m_historyMaxCount; -} +int CoreConfig::getHistoryMaxCount() const { return m_historyMaxCount; } -bool CoreConfig::isPerNotebookHistoryEnabled() const -{ - return m_perNotebookHistoryEnabled; -} +bool CoreConfig::isPerNotebookHistoryEnabled() const { return m_perNotebookHistoryEnabled; } -void CoreConfig::setPerNotebookHistoryEnabled(bool p_enabled) -{ - updateConfig(m_perNotebookHistoryEnabled, p_enabled, this); +void CoreConfig::setPerNotebookHistoryEnabled(bool p_enabled) { + updateConfig(m_perNotebookHistoryEnabled, p_enabled, this); } -const QString &CoreConfig::getShortcutLeaderKey() const -{ - return m_shortcutLeaderKey; -} +const QString &CoreConfig::getShortcutLeaderKey() const { return m_shortcutLeaderKey; } -LineEndingPolicy CoreConfig::getLineEndingPolicy() const -{ - return m_lineEnding; -} +LineEndingPolicy CoreConfig::getLineEndingPolicy() const { return m_lineEnding; } -void CoreConfig::setLineEndingPolicy(LineEndingPolicy p_ending) -{ - updateConfig(m_lineEnding, p_ending, this); +void CoreConfig::setLineEndingPolicy(LineEndingPolicy p_ending) { + updateConfig(m_lineEnding, p_ending, this); } -void CoreConfig::loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user) -{ - m_fileTypeSuffixes.clear(); - - QJsonArray arr; - if (p_user.contains(QStringLiteral("file_type_suffixes"))) { - arr = p_user[QStringLiteral("file_type_suffixes")].toArray(); - } else { - arr = p_app[QStringLiteral("file_type_suffixes")].toArray(); - } +void CoreConfig::loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user) { + m_fileTypeSuffixes.clear(); - m_fileTypeSuffixes.reserve(arr.size()); + QJsonArray arr; + if (p_user.contains(QStringLiteral("file_type_suffixes"))) { + arr = p_user[QStringLiteral("file_type_suffixes")].toArray(); + } else { + arr = p_app[QStringLiteral("file_type_suffixes")].toArray(); + } - bool hasSystemDefined = false; + m_fileTypeSuffixes.reserve(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - const auto obj = arr[i].toObject(); - const auto name = obj[QStringLiteral("name")].toString(); - if (name.isEmpty()) { - continue; - } + bool hasSystemDefined = false; - if (!hasSystemDefined && name == FileTypeHelper::s_systemDefaultProgram) { - hasSystemDefined = true; - } - - const auto suffixes = readStringList(obj, QStringLiteral("suffixes")); - m_fileTypeSuffixes.push_back(FileTypeSuffix(name, Utils::toLower(suffixes))); + for (int i = 0; i < arr.size(); ++i) { + const auto obj = arr[i].toObject(); + const auto name = obj[QStringLiteral("name")].toString(); + if (name.isEmpty()) { + continue; } - if (!hasSystemDefined) { - m_fileTypeSuffixes.push_back(FileTypeSuffix(FileTypeHelper::s_systemDefaultProgram, QStringList())); + if (!hasSystemDefined && name == FileTypeHelper::s_systemDefaultProgram) { + hasSystemDefined = true; } + + const auto suffixes = readStringList(obj, QStringLiteral("suffixes")); + m_fileTypeSuffixes.push_back(FileTypeSuffix(name, Utils::toLower(suffixes))); + } + + if (!hasSystemDefined) { + m_fileTypeSuffixes.push_back( + FileTypeSuffix(FileTypeHelper::s_systemDefaultProgram, QStringList())); + } } -QJsonArray CoreConfig::saveFileTypeSuffixes() const -{ - QJsonArray arr; - for (const auto &fts : m_fileTypeSuffixes) { - QJsonObject obj; - obj[QStringLiteral("name")] = fts.m_name; - writeStringList(obj, QStringLiteral("suffixes"), fts.m_suffixes); - arr.push_back(obj); - } - return arr; +QJsonArray CoreConfig::saveFileTypeSuffixes() const { + QJsonArray arr; + for (const auto &fts : m_fileTypeSuffixes) { + QJsonObject obj; + obj[QStringLiteral("name")] = fts.m_name; + writeStringList(obj, QStringLiteral("suffixes"), fts.m_suffixes); + arr.push_back(obj); + } + return arr; } -void CoreConfig::loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user) -{ - QJsonObject unitedObj; - if (p_user.contains(QStringLiteral("united_entry"))) { - unitedObj = p_user[QStringLiteral("united_entry")].toObject(); - } else { - unitedObj = p_app[QStringLiteral("united_entry")].toObject(); - } +void CoreConfig::loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user) { + QJsonObject unitedObj; + if (p_user.contains(QStringLiteral("united_entry"))) { + unitedObj = p_user[QStringLiteral("united_entry")].toObject(); + } else { + unitedObj = p_app[QStringLiteral("united_entry")].toObject(); + } - m_unitedEntryAlias = unitedObj[QStringLiteral("alias")].toArray(); + m_unitedEntryAlias = unitedObj[QStringLiteral("alias")].toArray(); } -QJsonObject CoreConfig::saveUnitedEntry() const -{ - QJsonObject unitedObj; - unitedObj[QStringLiteral("alias")] = m_unitedEntryAlias; - return unitedObj; +QJsonObject CoreConfig::saveUnitedEntry() const { + QJsonObject unitedObj; + unitedObj[QStringLiteral("alias")] = m_unitedEntryAlias; + return unitedObj; } -const QVector &CoreConfig::getFileTypeSuffixes() const -{ - return m_fileTypeSuffixes; +const QVector &CoreConfig::getFileTypeSuffixes() const { + return m_fileTypeSuffixes; } -void CoreConfig::setFileTypeSuffixes(const QVector &p_fileTypeSuffixes) -{ - updateConfig(m_fileTypeSuffixes, p_fileTypeSuffixes, this); +void CoreConfig::setFileTypeSuffixes( + const QVector &p_fileTypeSuffixes) { + updateConfig(m_fileTypeSuffixes, p_fileTypeSuffixes, this); } -const QStringList *CoreConfig::findFileTypeSuffix(const QString &p_name) const -{ - if (p_name.isEmpty()) { - return nullptr; - } +const QStringList *CoreConfig::findFileTypeSuffix(const QString &p_name) const { + if (p_name.isEmpty()) { + return nullptr; + } - for (const auto &fts : m_fileTypeSuffixes) { - if (fts.m_name == p_name) { - return &fts.m_suffixes; - } + for (const auto &fts : m_fileTypeSuffixes) { + if (fts.m_name == p_name) { + return &fts.m_suffixes; } + } - return nullptr; + return nullptr; } -const QJsonArray &CoreConfig::getUnitedEntryAlias() const -{ - return m_unitedEntryAlias; -} +const QJsonArray &CoreConfig::getUnitedEntryAlias() const { return m_unitedEntryAlias; } -void CoreConfig::setUnitedEntryAlias(const QJsonArray &p_alias) -{ - updateConfig(m_unitedEntryAlias, p_alias, this); +void CoreConfig::setUnitedEntryAlias(const QJsonArray &p_alias) { + updateConfig(m_unitedEntryAlias, p_alias, this); } -ViewWindowMode CoreConfig::getDefaultOpenMode() const -{ - return m_defaultOpenMode; -} +ViewWindowMode CoreConfig::getDefaultOpenMode() const { return m_defaultOpenMode; } -void CoreConfig::setDefaultOpenMode(ViewWindowMode p_mode) -{ - updateConfig(m_defaultOpenMode, p_mode, this); +void CoreConfig::setDefaultOpenMode(ViewWindowMode p_mode) { + updateConfig(m_defaultOpenMode, p_mode, this); } -ViewWindowMode CoreConfig::stringToViewWindowMode(const QString &p_mode) -{ - if (p_mode == "edit") { - return ViewWindowMode::Edit; - } +ViewWindowMode CoreConfig::stringToViewWindowMode(const QString &p_mode) { + if (p_mode == "edit") { + return ViewWindowMode::Edit; + } - return ViewWindowMode::Read; + return ViewWindowMode::Read; } -QString CoreConfig::viewWindowModeToString(ViewWindowMode p_mode) -{ - switch (p_mode) { - case ViewWindowMode::Edit: - return "edit"; +QString CoreConfig::viewWindowModeToString(ViewWindowMode p_mode) { + switch (p_mode) { + case ViewWindowMode::Edit: + return "edit"; - default: - return "read"; - } + default: + return "read"; + } } diff --git a/src/core/coreconfig.h b/src/core/coreconfig.h index 2a297c3f5c..d8483d1428 100644 --- a/src/core/coreconfig.h +++ b/src/core/coreconfig.h @@ -3,214 +3,210 @@ #include "iconfig.h" -#include #include #include +#include #include "global.h" -namespace vnotex -{ - class CoreConfig : public IConfig - { - Q_GADGET - public: - enum Shortcut - { - FullScreen, - StayOnTop, - ExpandContentArea, - Settings, - NewNote, - NewQuickNote, - NewFolder, - CloseTab, - CloseAllTabs, - CloseOtherTabs, - CloseTabsToTheLeft, - CloseTabsToTheRight, - NavigationDock, - OutlineDock, - SearchDock, - SnippetDock, - LocationListDock, - HistoryDock, - WindowsDock, - TagDock, - Search, - NavigationMode, - LocateNode, - VerticalSplit, - HorizontalSplit, - MaximizeSplit, - DistributeSplits, - RemoveSplitAndWorkspace, - NewWorkspace, - Export, - Quit, - FlashPage, - QuickAccess, - ActivateTab1, - ActivateTab2, - ActivateTab3, - ActivateTab4, - ActivateTab5, - ActivateTab6, - ActivateTab7, - ActivateTab8, - ActivateTab9, - AlternateTab, - ActivateNextTab, - ActivatePreviousTab, - FocusContentArea, - OpenWithDefaultProgram, - OneSplitLeft, - OneSplitDown, - OneSplitUp, - OneSplitRight, - MoveOneSplitLeft, - MoveOneSplitDown, - MoveOneSplitUp, - MoveOneSplitRight, - OpenLastClosedFile, - UnitedEntry, - Copy, - Paste, - Cut, - Properties, - Global_WakeUp, - MaxShortcut - }; - Q_ENUM(Shortcut) - - struct FileTypeSuffix - { - FileTypeSuffix() = default; - - FileTypeSuffix(const QString &p_name, const QStringList &p_suffixes); - - bool operator==(const FileTypeSuffix &p_other) const; - - QString m_name; - - QStringList m_suffixes; - }; - - CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); +namespace vnotex { +class CoreConfig : public IConfig { + Q_GADGET +public: + enum Shortcut { + FullScreen, + StayOnTop, + ExpandContentArea, + Settings, + NewNote, + NewQuickNote, + NewFolder, + CloseTab, + CloseAllTabs, + CloseOtherTabs, + CloseTabsToTheLeft, + CloseTabsToTheRight, + NavigationDock, + OutlineDock, + SearchDock, + SnippetDock, + LocationListDock, + HistoryDock, + WindowsDock, + TagDock, + Search, + NavigationMode, + LocateNode, + VerticalSplit, + HorizontalSplit, + MaximizeSplit, + DistributeSplits, + RemoveSplitAndWorkspace, + NewWorkspace, + Export, + Quit, + FlashPage, + QuickAccess, + ActivateTab1, + ActivateTab2, + ActivateTab3, + ActivateTab4, + ActivateTab5, + ActivateTab6, + ActivateTab7, + ActivateTab8, + ActivateTab9, + AlternateTab, + ActivateNextTab, + ActivatePreviousTab, + FocusContentArea, + OpenWithDefaultProgram, + OneSplitLeft, + OneSplitDown, + OneSplitUp, + OneSplitRight, + MoveOneSplitLeft, + MoveOneSplitDown, + MoveOneSplitUp, + MoveOneSplitRight, + OpenLastClosedFile, + UnitedEntry, + Copy, + Paste, + Cut, + Properties, + Global_WakeUp, + MaxShortcut + }; + Q_ENUM(Shortcut) + + struct FileTypeSuffix { + FileTypeSuffix() = default; + + FileTypeSuffix(const QString &p_name, const QStringList &p_suffixes); + + bool operator==(const FileTypeSuffix &p_other) const; + + QString m_name; + + QStringList m_suffixes; + }; + + CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); + + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - const QString &getTheme() const; - void setTheme(const QString &p_name); + const QString &getTheme() const; + void setTheme(const QString &p_name); - const QString &getLocale() const; - void setLocale(const QString &p_locale); + const QString &getLocale() const; + void setLocale(const QString &p_locale); - // Should be called after locale is properly set. - QString getLocaleToUse() const; + // Should be called after locale is properly set. + QString getLocaleToUse() const; - const QString &getShortcut(Shortcut p_shortcut) const; + const QString &getShortcut(Shortcut p_shortcut) const; - int getToolBarIconSize() const; - void setToolBarIconSize(int p_size); + int getToolBarIconSize() const; + void setToolBarIconSize(int p_size); - int getDocksTabBarIconSize() const; - void setDocksTabBarIconSize(int p_size); + int getDocksTabBarIconSize() const; + void setDocksTabBarIconSize(int p_size); - const QStringList &getExternalNodeExcludePatterns() const; + const QStringList &getExternalNodeExcludePatterns() const; - static const QStringList &getAvailableLocales(); + static const QStringList &getAvailableLocales(); - bool isRecoverLastSessionOnStartEnabled() const; - void setRecoverLastSessionOnStartEnabled(bool p_enabled); + bool isRecoverLastSessionOnStartEnabled() const; + void setRecoverLastSessionOnStartEnabled(bool p_enabled); - bool isCheckForUpdatesOnStartEnabled() const; - void setCheckForUpdatesOnStartEnabled(bool p_enabled); + bool isCheckForUpdatesOnStartEnabled() const; + void setCheckForUpdatesOnStartEnabled(bool p_enabled); - int getHistoryMaxCount() const; + int getHistoryMaxCount() const; - bool isPerNotebookHistoryEnabled() const; - void setPerNotebookHistoryEnabled(bool p_enabled); + bool isPerNotebookHistoryEnabled() const; + void setPerNotebookHistoryEnabled(bool p_enabled); - const QString &getShortcutLeaderKey() const; + const QString &getShortcutLeaderKey() const; - LineEndingPolicy getLineEndingPolicy() const; - void setLineEndingPolicy(LineEndingPolicy p_ending); + LineEndingPolicy getLineEndingPolicy() const; + void setLineEndingPolicy(LineEndingPolicy p_ending); - const QVector &getFileTypeSuffixes() const; - void setFileTypeSuffixes(const QVector &p_fileTypeSuffixes); + const QVector &getFileTypeSuffixes() const; + void setFileTypeSuffixes(const QVector &p_fileTypeSuffixes); - const QStringList *findFileTypeSuffix(const QString &p_name) const; + const QStringList *findFileTypeSuffix(const QString &p_name) const; - const QJsonArray &getUnitedEntryAlias() const; - void setUnitedEntryAlias(const QJsonArray &p_alias); + const QJsonArray &getUnitedEntryAlias() const; + void setUnitedEntryAlias(const QJsonArray &p_alias); - ViewWindowMode getDefaultOpenMode() const; - void setDefaultOpenMode(ViewWindowMode p_mode); + ViewWindowMode getDefaultOpenMode() const; + void setDefaultOpenMode(ViewWindowMode p_mode); - private: - friend class MainConfig; +private: + friend class MainConfig; - void loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user); + void loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user); - void loadNoteManagement(const QJsonObject &p_app, const QJsonObject &p_user); + void loadNoteManagement(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveShortcuts() const; + QJsonObject saveShortcuts() const; - void loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user); + void loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonArray saveFileTypeSuffixes() const; + QJsonArray saveFileTypeSuffixes() const; - void loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user); + void loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveUnitedEntry() const; + QJsonObject saveUnitedEntry() const; - static ViewWindowMode stringToViewWindowMode(const QString &p_mode); - static QString viewWindowModeToString(ViewWindowMode p_mode); + static ViewWindowMode stringToViewWindowMode(const QString &p_mode); + static QString viewWindowModeToString(ViewWindowMode p_mode); - // Theme name. - QString m_theme; + // Theme name. + QString m_theme; - // User-specified locale, such as zh_CN, en_US. - // Empty if not specified. - QString m_locale; + // User-specified locale, such as zh_CN, en_US. + // Empty if not specified. + QString m_locale; - QString m_shortcuts[Shortcut::MaxShortcut]; + QString m_shortcuts[Shortcut::MaxShortcut]; - // Leader key of shortcuts defined in m_shortctus. - QString m_shortcutLeaderKey; + // Leader key of shortcuts defined in m_shortctus. + QString m_shortcutLeaderKey; - // Icon size of MainWindow tool bar. - int m_toolBarIconSize = 18; + // Icon size of MainWindow tool bar. + int m_toolBarIconSize = 18; - // Icon size of MainWindow QDockWidgets tab bar. - int m_docksTabBarIconSize = 20; + // Icon size of MainWindow QDockWidgets tab bar. + int m_docksTabBarIconSize = 20; - QStringList m_externalNodeExcludePatterns; + QStringList m_externalNodeExcludePatterns; - // Whether recover last session on start. - bool m_recoverLastSessionOnStartEnabled = true; + // Whether recover last session on start. + bool m_recoverLastSessionOnStartEnabled = true; - bool m_checkForUpdatesOnStartEnabled = true; + bool m_checkForUpdatesOnStartEnabled = true; - // Max count of the history items for each notebook and session config. - int m_historyMaxCount = 100; + // Max count of the history items for each notebook and session config. + int m_historyMaxCount = 100; - // Whether store history in each notebook. - bool m_perNotebookHistoryEnabled = false; + // Whether store history in each notebook. + bool m_perNotebookHistoryEnabled = false; - LineEndingPolicy m_lineEnding = LineEndingPolicy::LF; + LineEndingPolicy m_lineEnding = LineEndingPolicy::LF; - QVector m_fileTypeSuffixes; + QVector m_fileTypeSuffixes; - QJsonArray m_unitedEntryAlias; + QJsonArray m_unitedEntryAlias; - ViewWindowMode m_defaultOpenMode = ViewWindowMode::Read; + ViewWindowMode m_defaultOpenMode = ViewWindowMode::Read; - static QStringList s_availableLocales; - }; -} // ns vnotex + static QStringList s_availableLocales; +}; +} // namespace vnotex #endif // CORECONFIG_H diff --git a/src/core/editorconfig.cpp b/src/core/editorconfig.cpp index a0a4439a21..121d75ba4d 100644 --- a/src/core/editorconfig.cpp +++ b/src/core/editorconfig.cpp @@ -1,12 +1,12 @@ #include "editorconfig.h" -#include #include +#include -#include "texteditorconfig.h" #include "markdowneditorconfig.h" -#include "pdfviewerconfig.h" #include "mindmapeditorconfig.h" +#include "pdfviewerconfig.h" +#include "texteditorconfig.h" #include @@ -16,350 +16,279 @@ using namespace vnotex; #define READSTR(key) readString(appObj, userObj, (key)) #define READBOOL(key) readBool(appObj, userObj, (key)) -bool EditorConfig::ImageHostItem::operator==(const ImageHostItem &p_other) const -{ - return m_type == p_other.m_type - && m_name == p_other.m_name - && m_config == p_other.m_config; +bool EditorConfig::ImageHostItem::operator==(const ImageHostItem &p_other) const { + return m_type == p_other.m_type && m_name == p_other.m_name && m_config == p_other.m_config; } -void EditorConfig::ImageHostItem::fromJson(const QJsonObject &p_jobj) -{ - m_type = p_jobj[QStringLiteral("type")].toInt(); - m_name = p_jobj[QStringLiteral("name")].toString(); - m_config = p_jobj[QStringLiteral("config")].toObject(); +void EditorConfig::ImageHostItem::fromJson(const QJsonObject &p_jobj) { + m_type = p_jobj[QStringLiteral("type")].toInt(); + m_name = p_jobj[QStringLiteral("name")].toString(); + m_config = p_jobj[QStringLiteral("config")].toObject(); } -QJsonObject EditorConfig::ImageHostItem::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("type")] = m_type; - obj[QStringLiteral("name")] = m_name; - obj[QStringLiteral("config")] = m_config; - return obj; +QJsonObject EditorConfig::ImageHostItem::toJson() const { + QJsonObject obj; + obj[QStringLiteral("type")] = m_type; + obj[QStringLiteral("name")] = m_name; + obj[QStringLiteral("config")] = m_config; + return obj; } - EditorConfig::EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig), - m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)), + : IConfig(p_mgr, p_topConfig), m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)), m_markdownEditorConfig(new MarkdownEditorConfig(p_mgr, p_topConfig, m_textEditorConfig)), m_pdfViewerConfig(new PdfViewerConfig(p_mgr, p_topConfig)), - m_mindMapEditorConfig(new MindMapEditorConfig(p_mgr, p_topConfig)) -{ - m_sessionName = QStringLiteral("editor"); + m_mindMapEditorConfig(new MindMapEditorConfig(p_mgr, p_topConfig)) { + m_sessionName = QStringLiteral("editor"); } -EditorConfig::~EditorConfig() -{ -} +EditorConfig::~EditorConfig() {} -void EditorConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void EditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - loadCore(appObj, userObj); + loadCore(appObj, userObj); - loadImageHost(appObj, userObj); + loadImageHost(appObj, userObj); - m_viConfig = QSharedPointer::create(); - m_viConfig->fromJson(read(appObj, userObj, QStringLiteral("vi")).toObject()); + m_viConfig = QSharedPointer::create(); + m_viConfig->fromJson(read(appObj, userObj, QStringLiteral("vi")).toObject()); - m_textEditorConfig->init(appObj, userObj); - m_markdownEditorConfig->init(appObj, userObj); - m_pdfViewerConfig->init(appObj, userObj); - m_mindMapEditorConfig->init(appObj, userObj); + m_textEditorConfig->init(appObj, userObj); + m_markdownEditorConfig->init(appObj, userObj); + m_pdfViewerConfig->init(appObj, userObj); + m_mindMapEditorConfig->init(appObj, userObj); } -void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(QStringLiteral("core")).toObject(); - const auto userObj = p_user.value(QStringLiteral("core")).toObject(); +void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(QStringLiteral("core")).toObject(); + const auto userObj = p_user.value(QStringLiteral("core")).toObject(); - { - m_toolBarIconSize = READINT(QStringLiteral("toolbar_icon_size")); - if (m_toolBarIconSize <= 0) { - m_toolBarIconSize = 14; - } + { + m_toolBarIconSize = READINT(QStringLiteral("toolbar_icon_size")); + if (m_toolBarIconSize <= 0) { + m_toolBarIconSize = 14; } + } - { - auto autoSavePolicy = READSTR(QStringLiteral("auto_save_policy")); - m_autoSavePolicy = stringToAutoSavePolicy(autoSavePolicy); - } + { + auto autoSavePolicy = READSTR(QStringLiteral("auto_save_policy")); + m_autoSavePolicy = stringToAutoSavePolicy(autoSavePolicy); + } - m_backupFileDirectory = READSTR(QStringLiteral("backup_file_directory")); + m_backupFileDirectory = READSTR(QStringLiteral("backup_file_directory")); - m_backupFileExtension = READSTR(QStringLiteral("backup_file_extension")); + m_backupFileExtension = READSTR(QStringLiteral("backup_file_extension")); - loadShortcuts(appObj, userObj); + loadShortcuts(appObj, userObj); - m_spellCheckAutoDetectLanguageEnabled = READBOOL(QStringLiteral("spell_check_auto_detect_language")); - m_spellCheckDefaultDictionary = READSTR(QStringLiteral("spell_check_default_dictionary")); - if (m_spellCheckDefaultDictionary.isEmpty()) { - m_spellCheckDefaultDictionary = QStringLiteral("en_US"); - } + m_spellCheckAutoDetectLanguageEnabled = + READBOOL(QStringLiteral("spell_check_auto_detect_language")); + m_spellCheckDefaultDictionary = READSTR(QStringLiteral("spell_check_default_dictionary")); + if (m_spellCheckDefaultDictionary.isEmpty()) { + m_spellCheckDefaultDictionary = QStringLiteral("en_US"); + } - { - auto lineEnding = READSTR(QStringLiteral("line_ending")); - m_lineEnding = stringToLineEndingPolicy(lineEnding); - } + { + auto lineEnding = READSTR(QStringLiteral("line_ending")); + m_lineEnding = stringToLineEndingPolicy(lineEnding); + } } -QJsonObject EditorConfig::saveCore() const -{ - QJsonObject obj; - obj[QStringLiteral("toolbar_icon_size")] = m_toolBarIconSize; - obj[QStringLiteral("auto_save_policy")] = autoSavePolicyToString(m_autoSavePolicy); - obj[QStringLiteral("backup_file_directory")] = m_backupFileDirectory; - obj[QStringLiteral("backup_file_extension")] = m_backupFileExtension; - obj[QStringLiteral("shortcuts")] = saveShortcuts(); - obj[QStringLiteral("spell_check_auto_detect_language")] = m_spellCheckAutoDetectLanguageEnabled; - obj[QStringLiteral("spell_check_default_dictionary")] = m_spellCheckDefaultDictionary; - obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding); - return obj; +QJsonObject EditorConfig::saveCore() const { + QJsonObject obj; + obj[QStringLiteral("toolbar_icon_size")] = m_toolBarIconSize; + obj[QStringLiteral("auto_save_policy")] = autoSavePolicyToString(m_autoSavePolicy); + obj[QStringLiteral("backup_file_directory")] = m_backupFileDirectory; + obj[QStringLiteral("backup_file_extension")] = m_backupFileExtension; + obj[QStringLiteral("shortcuts")] = saveShortcuts(); + obj[QStringLiteral("spell_check_auto_detect_language")] = m_spellCheckAutoDetectLanguageEnabled; + obj[QStringLiteral("spell_check_default_dictionary")] = m_spellCheckDefaultDictionary; + obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding); + return obj; } -void EditorConfig::loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(QStringLiteral("shortcuts")).toObject(); - const auto userObj = p_user.value(QStringLiteral("shortcuts")).toObject(); - - static const auto indexOfShortcutEnum = EditorConfig::staticMetaObject.indexOfEnumerator("Shortcut"); - Q_ASSERT(indexOfShortcutEnum >= 0); - const auto metaEnum = EditorConfig::staticMetaObject.enumerator(indexOfShortcutEnum); - // Skip the Max flag. - for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { - m_shortcuts[i] = READSTR(metaEnum.key(i)); - } -} +void EditorConfig::loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(QStringLiteral("shortcuts")).toObject(); + const auto userObj = p_user.value(QStringLiteral("shortcuts")).toObject(); -QJsonObject EditorConfig::saveShortcuts() const -{ - QJsonObject obj; - static const auto indexOfShortcutEnum = EditorConfig::staticMetaObject.indexOfEnumerator("Shortcut"); - Q_ASSERT(indexOfShortcutEnum >= 0); - const auto metaEnum = EditorConfig::staticMetaObject.enumerator(indexOfShortcutEnum); - // Skip the Max flag. - for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { - obj[metaEnum.key(i)] = m_shortcuts[i]; - } - return obj; + static const auto indexOfShortcutEnum = + EditorConfig::staticMetaObject.indexOfEnumerator("Shortcut"); + Q_ASSERT(indexOfShortcutEnum >= 0); + const auto metaEnum = EditorConfig::staticMetaObject.enumerator(indexOfShortcutEnum); + // Skip the Max flag. + for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { + m_shortcuts[i] = READSTR(metaEnum.key(i)); + } } -QJsonObject EditorConfig::toJson() const -{ - QJsonObject obj; - obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson(); - obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson(); - obj[m_pdfViewerConfig->getSessionName()] = m_pdfViewerConfig->toJson(); - obj[m_mindMapEditorConfig->getSessionName()] = m_mindMapEditorConfig->toJson(); - obj[QStringLiteral("core")] = saveCore(); - obj[QStringLiteral("image_host")] = saveImageHost(); - - // In UT, it may be nullptr. - if (m_viConfig) { - obj[QStringLiteral("vi")] = m_viConfig->toJson(); - } - return obj; +QJsonObject EditorConfig::saveShortcuts() const { + QJsonObject obj; + static const auto indexOfShortcutEnum = + EditorConfig::staticMetaObject.indexOfEnumerator("Shortcut"); + Q_ASSERT(indexOfShortcutEnum >= 0); + const auto metaEnum = EditorConfig::staticMetaObject.enumerator(indexOfShortcutEnum); + // Skip the Max flag. + for (int i = 0; i < metaEnum.keyCount() - 1; ++i) { + obj[metaEnum.key(i)] = m_shortcuts[i]; + } + return obj; } -TextEditorConfig &EditorConfig::getTextEditorConfig() -{ - return *m_textEditorConfig; -} +QJsonObject EditorConfig::toJson() const { + QJsonObject obj; + obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson(); + obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson(); + obj[m_pdfViewerConfig->getSessionName()] = m_pdfViewerConfig->toJson(); + obj[m_mindMapEditorConfig->getSessionName()] = m_mindMapEditorConfig->toJson(); + obj[QStringLiteral("core")] = saveCore(); + obj[QStringLiteral("image_host")] = saveImageHost(); -const TextEditorConfig &EditorConfig::getTextEditorConfig() const -{ - return *m_textEditorConfig; + // In UT, it may be nullptr. + if (m_viConfig) { + obj[QStringLiteral("vi")] = m_viConfig->toJson(); + } + return obj; } -MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() -{ - return *m_markdownEditorConfig; -} +TextEditorConfig &EditorConfig::getTextEditorConfig() { return *m_textEditorConfig; } -const MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() const -{ - return *m_markdownEditorConfig; -} +const TextEditorConfig &EditorConfig::getTextEditorConfig() const { return *m_textEditorConfig; } -PdfViewerConfig &EditorConfig::getPdfViewerConfig() -{ - return *m_pdfViewerConfig; -} +MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() { return *m_markdownEditorConfig; } -const PdfViewerConfig &EditorConfig::getPdfViewerConfig() const -{ - return *m_pdfViewerConfig; +const MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() const { + return *m_markdownEditorConfig; } -MindMapEditorConfig &EditorConfig::getMindMapEditorConfig() -{ - return *m_mindMapEditorConfig; -} +PdfViewerConfig &EditorConfig::getPdfViewerConfig() { return *m_pdfViewerConfig; } -const MindMapEditorConfig &EditorConfig::getMindMapEditorConfig() const -{ - return *m_mindMapEditorConfig; -} +const PdfViewerConfig &EditorConfig::getPdfViewerConfig() const { return *m_pdfViewerConfig; } + +MindMapEditorConfig &EditorConfig::getMindMapEditorConfig() { return *m_mindMapEditorConfig; } -int EditorConfig::getToolBarIconSize() const -{ - return m_toolBarIconSize; +const MindMapEditorConfig &EditorConfig::getMindMapEditorConfig() const { + return *m_mindMapEditorConfig; } -void EditorConfig::setToolBarIconSize(int p_size) -{ - Q_ASSERT(p_size > 0); - updateConfig(m_toolBarIconSize, p_size, this); +int EditorConfig::getToolBarIconSize() const { return m_toolBarIconSize; } + +void EditorConfig::setToolBarIconSize(int p_size) { + Q_ASSERT(p_size > 0); + updateConfig(m_toolBarIconSize, p_size, this); } -const QString &EditorConfig::getShortcut(Shortcut p_shortcut) const -{ - Q_ASSERT(p_shortcut < Shortcut::MaxShortcut); - return m_shortcuts[p_shortcut]; +const QString &EditorConfig::getShortcut(Shortcut p_shortcut) const { + Q_ASSERT(p_shortcut < Shortcut::MaxShortcut); + return m_shortcuts[p_shortcut]; } -QString EditorConfig::autoSavePolicyToString(AutoSavePolicy p_policy) const -{ - switch (p_policy) { - case AutoSavePolicy::None: - return QStringLiteral("none"); +QString EditorConfig::autoSavePolicyToString(AutoSavePolicy p_policy) const { + switch (p_policy) { + case AutoSavePolicy::None: + return QStringLiteral("none"); - case AutoSavePolicy::AutoSave: - return QStringLiteral("autosave"); + case AutoSavePolicy::AutoSave: + return QStringLiteral("autosave"); - default: - return QStringLiteral("backupfile"); - } + default: + return QStringLiteral("backupfile"); + } } -EditorConfig::AutoSavePolicy EditorConfig::stringToAutoSavePolicy(const QString &p_str) const -{ - auto policy = p_str.toLower(); - if (policy == QStringLiteral("none")) { - return AutoSavePolicy::None; - } else if (policy == QStringLiteral("autosave")) { - return AutoSavePolicy::AutoSave; - } else { - return AutoSavePolicy::BackupFile; - } +EditorConfig::AutoSavePolicy EditorConfig::stringToAutoSavePolicy(const QString &p_str) const { + auto policy = p_str.toLower(); + if (policy == QStringLiteral("none")) { + return AutoSavePolicy::None; + } else if (policy == QStringLiteral("autosave")) { + return AutoSavePolicy::AutoSave; + } else { + return AutoSavePolicy::BackupFile; + } } -EditorConfig::AutoSavePolicy EditorConfig::getAutoSavePolicy() const -{ - return m_autoSavePolicy; -} +EditorConfig::AutoSavePolicy EditorConfig::getAutoSavePolicy() const { return m_autoSavePolicy; } -void EditorConfig::setAutoSavePolicy(EditorConfig::AutoSavePolicy p_policy) -{ - updateConfig(m_autoSavePolicy, p_policy, this); +void EditorConfig::setAutoSavePolicy(EditorConfig::AutoSavePolicy p_policy) { + updateConfig(m_autoSavePolicy, p_policy, this); } -LineEndingPolicy EditorConfig::getLineEndingPolicy() const -{ - return m_lineEnding; -} +LineEndingPolicy EditorConfig::getLineEndingPolicy() const { return m_lineEnding; } -void EditorConfig::setLineEndingPolicy(LineEndingPolicy p_ending) -{ - updateConfig(m_lineEnding, p_ending, this); +void EditorConfig::setLineEndingPolicy(LineEndingPolicy p_ending) { + updateConfig(m_lineEnding, p_ending, this); } -const QString &EditorConfig::getBackupFileDirectory() const -{ - return m_backupFileDirectory; -} +const QString &EditorConfig::getBackupFileDirectory() const { return m_backupFileDirectory; } -const QString &EditorConfig::getBackupFileExtension() const -{ - return m_backupFileExtension; -} +const QString &EditorConfig::getBackupFileExtension() const { return m_backupFileExtension; } -bool EditorConfig::isSpellCheckAutoDetectLanguageEnabled() const -{ - return m_spellCheckAutoDetectLanguageEnabled; +bool EditorConfig::isSpellCheckAutoDetectLanguageEnabled() const { + return m_spellCheckAutoDetectLanguageEnabled; } -const QString &EditorConfig::getSpellCheckDefaultDictionary() const -{ - return m_spellCheckDefaultDictionary; +const QString &EditorConfig::getSpellCheckDefaultDictionary() const { + return m_spellCheckDefaultDictionary; } -void EditorConfig::setSpellCheckDefaultDictionary(const QString &p_dict) -{ - updateConfig(m_spellCheckDefaultDictionary, p_dict, this); +void EditorConfig::setSpellCheckDefaultDictionary(const QString &p_dict) { + updateConfig(m_spellCheckDefaultDictionary, p_dict, this); } -void EditorConfig::loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(QStringLiteral("image_host")).toObject(); - const auto userObj = p_user.value(QStringLiteral("image_host")).toObject(); - - { - auto arr = read(appObj, userObj, QStringLiteral("hosts")).toArray(); - m_imageHosts.resize(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - m_imageHosts[i].fromJson(arr[i].toObject()); - } +void EditorConfig::loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(QStringLiteral("image_host")).toObject(); + const auto userObj = p_user.value(QStringLiteral("image_host")).toObject(); + + { + auto arr = read(appObj, userObj, QStringLiteral("hosts")).toArray(); + m_imageHosts.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_imageHosts[i].fromJson(arr[i].toObject()); } + } - m_defaultImageHost = READSTR(QStringLiteral("default_image_host")); - m_clearObsoleteImageAtImageHost = READBOOL(QStringLiteral("clear_obsolete_image")); + m_defaultImageHost = READSTR(QStringLiteral("default_image_host")); + m_clearObsoleteImageAtImageHost = READBOOL(QStringLiteral("clear_obsolete_image")); } -QJsonObject EditorConfig::saveImageHost() const -{ - QJsonObject obj; +QJsonObject EditorConfig::saveImageHost() const { + QJsonObject obj; - { - QJsonArray arr; - for (const auto &item : m_imageHosts) { - arr.append(item.toJson()); - } - obj[QStringLiteral("hosts")] = arr; + { + QJsonArray arr; + for (const auto &item : m_imageHosts) { + arr.append(item.toJson()); } + obj[QStringLiteral("hosts")] = arr; + } - obj[QStringLiteral("default_image_host")] = m_defaultImageHost; - obj[QStringLiteral("clear_obsolete_image")] = m_clearObsoleteImageAtImageHost; + obj[QStringLiteral("default_image_host")] = m_defaultImageHost; + obj[QStringLiteral("clear_obsolete_image")] = m_clearObsoleteImageAtImageHost; - return obj; + return obj; } -const QVector &EditorConfig::getImageHosts() const -{ - return m_imageHosts; +const QVector &EditorConfig::getImageHosts() const { + return m_imageHosts; } -void EditorConfig::setImageHosts(const QVector &p_hosts) -{ - updateConfig(m_imageHosts, p_hosts, this); +void EditorConfig::setImageHosts(const QVector &p_hosts) { + updateConfig(m_imageHosts, p_hosts, this); } -const QString &EditorConfig::getDefaultImageHost() const -{ - return m_defaultImageHost; -} +const QString &EditorConfig::getDefaultImageHost() const { return m_defaultImageHost; } -void EditorConfig::setDefaultImageHost(const QString &p_host) -{ - updateConfig(m_defaultImageHost, p_host, this); +void EditorConfig::setDefaultImageHost(const QString &p_host) { + updateConfig(m_defaultImageHost, p_host, this); } -bool EditorConfig::isClearObsoleteImageAtImageHostEnabled() const -{ - return m_clearObsoleteImageAtImageHost; +bool EditorConfig::isClearObsoleteImageAtImageHostEnabled() const { + return m_clearObsoleteImageAtImageHost; } -void EditorConfig::setClearObsoleteImageAtImageHostEnabled(bool p_enabled) -{ - updateConfig(m_clearObsoleteImageAtImageHost, p_enabled, this); +void EditorConfig::setClearObsoleteImageAtImageHostEnabled(bool p_enabled) { + updateConfig(m_clearObsoleteImageAtImageHost, p_enabled, this); } -const QSharedPointer &EditorConfig::getViConfig() const -{ - return m_viConfig; -} +const QSharedPointer &EditorConfig::getViConfig() const { return m_viConfig; } diff --git a/src/core/editorconfig.h b/src/core/editorconfig.h index 31f29ede10..fbdda32438 100644 --- a/src/core/editorconfig.h +++ b/src/core/editorconfig.h @@ -3,205 +3,195 @@ #include "iconfig.h" +#include #include #include -#include #include #include "global.h" -namespace vte -{ - class ViConfig; +namespace vte { +class ViConfig; } -namespace vnotex -{ - class TextEditorConfig; - class MarkdownEditorConfig; - class PdfViewerConfig; - class MindMapEditorConfig; - - class EditorConfig : public IConfig - { - Q_GADGET - public: - enum Shortcut - { - Save, - EditRead, - Discard, - TypeHeading1, - TypeHeading2, - TypeHeading3, - TypeHeading4, - TypeHeading5, - TypeHeading6, - TypeHeadingNone, - TypeBold, - TypeItalic, - TypeStrikethrough, - TypeUnorderedList, - TypeOrderedList, - TypeTodoList, - TypeCheckedTodoList, - TypeCode, - TypeCodeBlock, - TypeMath, - TypeMathBlock, - TypeQuote, - TypeLink, - TypeImage, - TypeTable, - TypeMark, - Outline, - AltPaste, - FindAndReplace, - FindNext, - FindPrevious, - ApplySnippet, - Tag, - Debug, - Print, - ClearHighlights, - WordCount, - Attachment, - AlternateViewMode, - ParseToMarkdownAndPaste, - MaxShortcut - }; - Q_ENUM(Shortcut) +namespace vnotex { +class TextEditorConfig; +class MarkdownEditorConfig; +class PdfViewerConfig; +class MindMapEditorConfig; + +class EditorConfig : public IConfig { + Q_GADGET +public: + enum Shortcut { + Save, + EditRead, + Discard, + TypeHeading1, + TypeHeading2, + TypeHeading3, + TypeHeading4, + TypeHeading5, + TypeHeading6, + TypeHeadingNone, + TypeBold, + TypeItalic, + TypeStrikethrough, + TypeUnorderedList, + TypeOrderedList, + TypeTodoList, + TypeCheckedTodoList, + TypeCode, + TypeCodeBlock, + TypeMath, + TypeMathBlock, + TypeQuote, + TypeLink, + TypeImage, + TypeTable, + TypeMark, + Outline, + AltPaste, + FindAndReplace, + FindNext, + FindPrevious, + ApplySnippet, + Tag, + Debug, + Print, + ClearHighlights, + WordCount, + Attachment, + AlternateViewMode, + ParseToMarkdownAndPaste, + MaxShortcut + }; + Q_ENUM(Shortcut) - enum AutoSavePolicy - { - None, - AutoSave, - BackupFile - }; - Q_ENUM(AutoSavePolicy) + enum AutoSavePolicy { None, AutoSave, BackupFile }; + Q_ENUM(AutoSavePolicy) - struct ImageHostItem - { - ImageHostItem() = default; + struct ImageHostItem { + ImageHostItem() = default; - bool operator==(const ImageHostItem &p_other) const; + bool operator==(const ImageHostItem &p_other) const; - void fromJson(const QJsonObject &p_jobj); + void fromJson(const QJsonObject &p_jobj); - QJsonObject toJson() const; + QJsonObject toJson() const; - int m_type = 0; + int m_type = 0; - QString m_name; + QString m_name; - QJsonObject m_config; - }; + QJsonObject m_config; + }; - EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); + EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); - ~EditorConfig(); + ~EditorConfig(); - TextEditorConfig &getTextEditorConfig(); - const TextEditorConfig &getTextEditorConfig() const; + TextEditorConfig &getTextEditorConfig(); + const TextEditorConfig &getTextEditorConfig() const; - MarkdownEditorConfig &getMarkdownEditorConfig(); - const MarkdownEditorConfig &getMarkdownEditorConfig() const; + MarkdownEditorConfig &getMarkdownEditorConfig(); + const MarkdownEditorConfig &getMarkdownEditorConfig() const; - PdfViewerConfig &getPdfViewerConfig(); - const PdfViewerConfig &getPdfViewerConfig() const; + PdfViewerConfig &getPdfViewerConfig(); + const PdfViewerConfig &getPdfViewerConfig() const; - MindMapEditorConfig &getMindMapEditorConfig(); - const MindMapEditorConfig &getMindMapEditorConfig() const; + MindMapEditorConfig &getMindMapEditorConfig(); + const MindMapEditorConfig &getMindMapEditorConfig() const; - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - int getToolBarIconSize() const; - void setToolBarIconSize(int p_size); + int getToolBarIconSize() const; + void setToolBarIconSize(int p_size); - EditorConfig::AutoSavePolicy getAutoSavePolicy() const; - void setAutoSavePolicy(EditorConfig::AutoSavePolicy p_policy); + EditorConfig::AutoSavePolicy getAutoSavePolicy() const; + void setAutoSavePolicy(EditorConfig::AutoSavePolicy p_policy); - const QString &getBackupFileDirectory() const; + const QString &getBackupFileDirectory() const; - const QString &getBackupFileExtension() const; + const QString &getBackupFileExtension() const; - const QString &getShortcut(Shortcut p_shortcut) const; + const QString &getShortcut(Shortcut p_shortcut) const; - bool isSpellCheckAutoDetectLanguageEnabled() const; + bool isSpellCheckAutoDetectLanguageEnabled() const; - const QString &getSpellCheckDefaultDictionary() const; - void setSpellCheckDefaultDictionary(const QString &p_dict); + const QString &getSpellCheckDefaultDictionary() const; + void setSpellCheckDefaultDictionary(const QString &p_dict); - const QVector &getImageHosts() const; - void setImageHosts(const QVector &p_hosts); + const QVector &getImageHosts() const; + void setImageHosts(const QVector &p_hosts); - const QString &getDefaultImageHost() const; - void setDefaultImageHost(const QString &p_host); + const QString &getDefaultImageHost() const; + void setDefaultImageHost(const QString &p_host); - bool isClearObsoleteImageAtImageHostEnabled() const; - void setClearObsoleteImageAtImageHostEnabled(bool p_enabled); + bool isClearObsoleteImageAtImageHostEnabled() const; + void setClearObsoleteImageAtImageHostEnabled(bool p_enabled); - const QSharedPointer &getViConfig() const; + const QSharedPointer &getViConfig() const; - LineEndingPolicy getLineEndingPolicy() const; - void setLineEndingPolicy(LineEndingPolicy p_ending); + LineEndingPolicy getLineEndingPolicy() const; + void setLineEndingPolicy(LineEndingPolicy p_ending); - private: - friend class MainConfig; +private: + friend class MainConfig; - void loadCore(const QJsonObject &p_app, const QJsonObject &p_user); + void loadCore(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveCore() const; + QJsonObject saveCore() const; - void loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user); + void loadShortcuts(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveShortcuts() const; + QJsonObject saveShortcuts() const; - QString autoSavePolicyToString(AutoSavePolicy p_policy) const; - AutoSavePolicy stringToAutoSavePolicy(const QString &p_str) const; + QString autoSavePolicyToString(AutoSavePolicy p_policy) const; + AutoSavePolicy stringToAutoSavePolicy(const QString &p_str) const; - void loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user); + void loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveImageHost() const; + QJsonObject saveImageHost() const; - // Icon size of editor tool bar. - int m_toolBarIconSize = 16; + // Icon size of editor tool bar. + int m_toolBarIconSize = 16; - QString m_shortcuts[Shortcut::MaxShortcut]; + QString m_shortcuts[Shortcut::MaxShortcut]; - AutoSavePolicy m_autoSavePolicy = AutoSavePolicy::AutoSave; + AutoSavePolicy m_autoSavePolicy = AutoSavePolicy::AutoSave; - // Where to put backup file, relative to the content file itself. - QString m_backupFileDirectory; + // Where to put backup file, relative to the content file itself. + QString m_backupFileDirectory; - // Backup file extension. - QString m_backupFileExtension; + // Backup file extension. + QString m_backupFileExtension; - // Will be shared with MarkdownEditorConfig. - QSharedPointer m_textEditorConfig; + // Will be shared with MarkdownEditorConfig. + QSharedPointer m_textEditorConfig; - QScopedPointer m_markdownEditorConfig; + QScopedPointer m_markdownEditorConfig; - QScopedPointer m_pdfViewerConfig; + QScopedPointer m_pdfViewerConfig; - QScopedPointer m_mindMapEditorConfig; + QScopedPointer m_mindMapEditorConfig; - bool m_spellCheckAutoDetectLanguageEnabled = false; + bool m_spellCheckAutoDetectLanguageEnabled = false; - QString m_spellCheckDefaultDictionary; + QString m_spellCheckDefaultDictionary; - QVector m_imageHosts; + QVector m_imageHosts; - QString m_defaultImageHost; + QString m_defaultImageHost; - bool m_clearObsoleteImageAtImageHost = false; + bool m_clearObsoleteImageAtImageHost = false; - QSharedPointer m_viConfig; + QSharedPointer m_viConfig; - LineEndingPolicy m_lineEnding = LineEndingPolicy::LF; - }; -} + LineEndingPolicy m_lineEnding = LineEndingPolicy::LF; +}; +} // namespace vnotex #endif // EDITORCONFIG_H diff --git a/src/core/events.h b/src/core/events.h index 27fb9aabdc..957faf64a7 100644 --- a/src/core/events.h +++ b/src/core/events.h @@ -3,24 +3,21 @@ #include -namespace vnotex -{ - class Event - { - public: - void reset() - { - m_handled = false; - m_response.clear(); - } +namespace vnotex { +class Event { +public: + void reset() { + m_handled = false; + m_response.clear(); + } - // Whether this event is handled. - // If it is handled, later handler should just ignore this event. - bool m_handled = false; + // Whether this event is handled. + // If it is handled, later handler should just ignore this event. + bool m_handled = false; - // Handler could use this field to return state to the event sender. - QVariant m_response = true; - }; -} + // Handler could use this field to return state to the event sender. + QVariant m_response = true; +}; +} // namespace vnotex #endif // EVENTS_H diff --git a/src/core/exception.h b/src/core/exception.h index f267789db7..a3f63ca0cb 100644 --- a/src/core/exception.h +++ b/src/core/exception.h @@ -1,97 +1,89 @@ #ifndef EXCEPTION_H #define EXCEPTION_H -#include -#include #include +#include +#include -namespace vnotex -{ - class Exception : virtual public std::runtime_error - { - public: - enum class Type - { - InvalidPath, - FailToCreateDir, - FailToWriteFile, - FailToReadFile, - FailToRenameFile, - FailToCopyFile, - FailToCopyDir, - FailToRemoveFile, - FailToRemoveDir, - FileMissingOnDisk, - EssentialFileMissing, - FileExistsOnCreate, - DirExistsOnCreate, - InvalidArgument - }; - - Exception(Type p_type, const QString &p_what) - : std::runtime_error(p_what.toStdString()), - m_type(p_type) - { - } - - Type m_type; - - [[noreturn]] static void throwOne(Exception::Type p_type, const QString &p_what) - { - qCritical() << typeToString(p_type) << p_what; - throw Exception(p_type, p_what); - } - - private: - static QString typeToString(Exception::Type p_type) - { - switch (p_type) { - case Type::InvalidPath: - return QStringLiteral("InvalidPath"); - - case Type::FailToCreateDir: - return QStringLiteral("FailToCreateDir"); - - case Type::FailToWriteFile: - return QStringLiteral("FailToWriteFile"); - - case Type::FailToReadFile: - return QStringLiteral("FailToReadFile"); - - case Type::FailToRenameFile: - return QStringLiteral("FailToRenameFile"); - - case Type::FailToCopyFile: - return QStringLiteral("FailToCopyFile"); - - case Type::FailToCopyDir: - return QStringLiteral("FailToCopyDir"); - - case Type::FailToRemoveFile: - return QStringLiteral("FailToRemoveFile"); - - case Type::FailToRemoveDir: - return QStringLiteral("FailToRemoveDir"); - - case Type::FileMissingOnDisk: - return QStringLiteral("FileMissingOnDisk"); - - case Type::EssentialFileMissing: - return QStringLiteral("EssentialFileMissing"); - - case Type::FileExistsOnCreate: - return QStringLiteral("FileExistsOnCreate"); - - case Type::DirExistsOnCreate: - return QStringLiteral("DirExistsOnCreate"); - - case Type::InvalidArgument: - return QStringLiteral("InvalidArgument"); - } - - return QString::number(static_cast(p_type)); - } - }; -} // ns vnotex +namespace vnotex { +class Exception : virtual public std::runtime_error { +public: + enum class Type { + InvalidPath, + FailToCreateDir, + FailToWriteFile, + FailToReadFile, + FailToRenameFile, + FailToCopyFile, + FailToCopyDir, + FailToRemoveFile, + FailToRemoveDir, + FileMissingOnDisk, + EssentialFileMissing, + FileExistsOnCreate, + DirExistsOnCreate, + InvalidArgument + }; + + Exception(Type p_type, const QString &p_what) + : std::runtime_error(p_what.toStdString()), m_type(p_type) {} + + Type m_type; + + [[noreturn]] static void throwOne(Exception::Type p_type, const QString &p_what) { + qCritical() << typeToString(p_type) << p_what; + throw Exception(p_type, p_what); + } + +private: + static QString typeToString(Exception::Type p_type) { + switch (p_type) { + case Type::InvalidPath: + return QStringLiteral("InvalidPath"); + + case Type::FailToCreateDir: + return QStringLiteral("FailToCreateDir"); + + case Type::FailToWriteFile: + return QStringLiteral("FailToWriteFile"); + + case Type::FailToReadFile: + return QStringLiteral("FailToReadFile"); + + case Type::FailToRenameFile: + return QStringLiteral("FailToRenameFile"); + + case Type::FailToCopyFile: + return QStringLiteral("FailToCopyFile"); + + case Type::FailToCopyDir: + return QStringLiteral("FailToCopyDir"); + + case Type::FailToRemoveFile: + return QStringLiteral("FailToRemoveFile"); + + case Type::FailToRemoveDir: + return QStringLiteral("FailToRemoveDir"); + + case Type::FileMissingOnDisk: + return QStringLiteral("FileMissingOnDisk"); + + case Type::EssentialFileMissing: + return QStringLiteral("EssentialFileMissing"); + + case Type::FileExistsOnCreate: + return QStringLiteral("FileExistsOnCreate"); + + case Type::DirExistsOnCreate: + return QStringLiteral("DirExistsOnCreate"); + + case Type::InvalidArgument: + return QStringLiteral("InvalidArgument"); + } + + return QString::number(static_cast(p_type)); + } +}; +} // namespace vnotex #endif // EXCEPTION_H diff --git a/src/core/externalfile.cpp b/src/core/externalfile.cpp index 7d78493f7b..bb9d7939a0 100644 --- a/src/core/externalfile.cpp +++ b/src/core/externalfile.cpp @@ -5,76 +5,48 @@ using namespace vnotex; -ExternalFile::ExternalFile(const QString &p_filePath) - : c_filePath(p_filePath) -{ - setContentType(FileTypeHelper::getInst().getFileType(c_filePath).m_type); +ExternalFile::ExternalFile(const QString &p_filePath) : c_filePath(p_filePath) { + setContentType(FileTypeHelper::getInst().getFileType(c_filePath).m_type); } -QString ExternalFile::read() const -{ - return FileUtils::readTextFile(getContentPath()); -} +QString ExternalFile::read() const { return FileUtils::readTextFile(getContentPath()); } -void ExternalFile::write(const QString &p_content) -{ - FileUtils::writeFile(getContentPath(), p_content); +void ExternalFile::write(const QString &p_content) { + FileUtils::writeFile(getContentPath(), p_content); } -QString ExternalFile::getName() const -{ - return PathUtils::fileName(c_filePath); -} +QString ExternalFile::getName() const { return PathUtils::fileName(c_filePath); } -QString ExternalFile::getFilePath() const -{ - return c_filePath; -} +QString ExternalFile::getFilePath() const { return c_filePath; } -QString ExternalFile::getContentPath() const -{ - return c_filePath; -} +QString ExternalFile::getContentPath() const { return c_filePath; } -QString ExternalFile::getResourcePath() const -{ - return PathUtils::parentDirPath(getContentPath()); -} +QString ExternalFile::getResourcePath() const { return PathUtils::parentDirPath(getContentPath()); } -IFileWithImage *ExternalFile::getImageInterface() -{ - return this; -} +IFileWithImage *ExternalFile::getImageInterface() { return this; } -Node *ExternalFile::getNode() const -{ - return nullptr; -} +Node *ExternalFile::getNode() const { return nullptr; } -QString ExternalFile::fetchImageFolderPath() -{ - auto pa = PathUtils::concatenateFilePath(getResourcePath(), QStringLiteral("vx_images")); - QDir().mkpath(pa); - return pa; +QString ExternalFile::fetchImageFolderPath() { + auto pa = PathUtils::concatenateFilePath(getResourcePath(), QStringLiteral("vx_images")); + QDir().mkpath(pa); + return pa; } -QString ExternalFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - const auto imageFolderPath = fetchImageFolderPath(); - auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); - FileUtils::copyFile(p_srcImagePath, destFilePath); - return destFilePath; +QString ExternalFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) { + const auto imageFolderPath = fetchImageFolderPath(); + auto destFilePath = FileUtils::renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); + FileUtils::copyFile(p_srcImagePath, destFilePath); + return destFilePath; } -QString ExternalFile::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - const auto imageFolderPath = fetchImageFolderPath(); - auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); - p_image.save(destFilePath); - return destFilePath; +QString ExternalFile::insertImage(const QImage &p_image, const QString &p_imageFileName) { + const auto imageFolderPath = fetchImageFolderPath(); + auto destFilePath = FileUtils::renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); + p_image.save(destFilePath); + return destFilePath; } -void ExternalFile::removeImage(const QString &p_imagePath) -{ - FileUtils::removeFile(p_imagePath); -} +void ExternalFile::removeImage(const QString &p_imagePath) { FileUtils::removeFile(p_imagePath); } diff --git a/src/core/externalfile.h b/src/core/externalfile.h index ddafc95543..56e9c08751 100644 --- a/src/core/externalfile.h +++ b/src/core/externalfile.h @@ -3,46 +3,45 @@ #include "file.h" -namespace vnotex -{ - class ExternalFile : public File, public IFileWithImage - { - public: - explicit ExternalFile(const QString &p_filePath); +namespace vnotex { +class ExternalFile : public File, public IFileWithImage { +public: + explicit ExternalFile(const QString &p_filePath); - QString read() const Q_DECL_OVERRIDE; + QString read() const Q_DECL_OVERRIDE; - void write(const QString &p_content) Q_DECL_OVERRIDE; + void write(const QString &p_content) Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getFilePath() const Q_DECL_OVERRIDE; + QString getFilePath() const Q_DECL_OVERRIDE; - QString getContentPath() const Q_DECL_OVERRIDE; + QString getContentPath() const Q_DECL_OVERRIDE; - // Path to resolve resources. - QString getResourcePath() const Q_DECL_OVERRIDE; + // Path to resolve resources. + QString getResourcePath() const Q_DECL_OVERRIDE; - IFileWithImage *getImageInterface() Q_DECL_OVERRIDE; + IFileWithImage *getImageInterface() Q_DECL_OVERRIDE; - // Get the corresponding node if available. - Node *getNode() const Q_DECL_OVERRIDE; + // Get the corresponding node if available. + Node *getNode() const Q_DECL_OVERRIDE; - // IFileWithImage interfaces. - public: - QString fetchImageFolderPath() Q_DECL_OVERRIDE; + // IFileWithImage interfaces. +public: + QString fetchImageFolderPath() Q_DECL_OVERRIDE; - // Insert image from @p_srcImagePath. - // Return inserted image file path. - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE; + // Insert image from @p_srcImagePath. + // Return inserted image file path. + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE; - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; - private: - QString c_filePath; - }; -} +private: + QString c_filePath; +}; +} // namespace vnotex #endif // EXTERNALFILE_H diff --git a/src/core/file.cpp b/src/core/file.cpp index 2a23fe3b26..ef6f0fbdb0 100644 --- a/src/core/file.cpp +++ b/src/core/file.cpp @@ -2,12 +2,8 @@ using namespace vnotex; -const FileType &File::getContentType() const -{ - return FileTypeHelper::getInst().getFileType(m_contentType); +const FileType &File::getContentType() const { + return FileTypeHelper::getInst().getFileType(m_contentType); } -void File::setContentType(int p_type) -{ - m_contentType = p_type; -} +void File::setContentType(int p_type) { m_contentType = p_type; } diff --git a/src/core/file.h b/src/core/file.h index f804e55685..60c6912ab3 100644 --- a/src/core/file.h +++ b/src/core/file.h @@ -7,63 +7,61 @@ class QImage; -namespace vnotex -{ - class Node; +namespace vnotex { +class Node; - class IFileWithImage - { - public: - IFileWithImage() = default; +class IFileWithImage { +public: + IFileWithImage() = default; - virtual ~IFileWithImage() = default; + virtual ~IFileWithImage() = default; - virtual QString fetchImageFolderPath() = 0; + virtual QString fetchImageFolderPath() = 0; - // Insert image from @p_srcImagePath. - // Return inserted image file path. - virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0; + // Insert image from @p_srcImagePath. + // Return inserted image file path. + virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0; - virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0; + virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0; - virtual void removeImage(const QString &p_imagePath) = 0; - }; + virtual void removeImage(const QString &p_imagePath) = 0; +}; - // Abstract file interface. - class File - { - public: - File() = default; +// Abstract file interface. +class File { +public: + File() = default; - virtual ~File() = default; + virtual ~File() = default; - virtual QString read() const = 0; + virtual QString read() const = 0; - virtual void write(const QString &p_content) = 0; + virtual void write(const QString &p_content) = 0; - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getFilePath() const = 0; + virtual QString getFilePath() const = 0; - // The main content file of File. - // In bundle case, getFilePath() may point to a folder, getContentPath() points to the real content file. - virtual QString getContentPath() const = 0; + // The main content file of File. + // In bundle case, getFilePath() may point to a folder, getContentPath() points to the real + // content file. + virtual QString getContentPath() const = 0; - // Path to resolve resources. - virtual QString getResourcePath() const = 0; + // Path to resolve resources. + virtual QString getResourcePath() const = 0; - virtual IFileWithImage *getImageInterface() = 0; + virtual IFileWithImage *getImageInterface() = 0; - // Get the corresponding node if available. - virtual Node *getNode() const = 0; + // Get the corresponding node if available. + virtual Node *getNode() const = 0; - const FileType &getContentType() const; + const FileType &getContentType() const; - void setContentType(int p_type); + void setContentType(int p_type); - private: - int m_contentType = FileType::Others; - }; -} +private: + int m_contentType = FileType::Others; +}; +} // namespace vnotex #endif // FILE_H diff --git a/src/core/filelocator.h b/src/core/filelocator.h index ca8824edc2..0bd0b0e97c 100644 --- a/src/core/filelocator.h +++ b/src/core/filelocator.h @@ -3,46 +3,33 @@ #include -namespace vnotex -{ - class Node; - - // A unique locator for both internal Node and external file. - class FileLocator - { - public: - FileLocator(Node *p_node) - : m_node(p_node) - { - } - - FileLocator(const QString &p_filePath) - : m_filePath(p_filePath) - { - } - - bool isNode() const - { - return m_node; - } - - Node *node() const - { - Q_ASSERT(isNode()); - return m_node; - } - - const QString &filePath() const - { - Q_ASSERT(!isNode()); - return m_filePath; - } - - private: - Node *m_node = nullptr; - - QString m_filePath; - }; -} +namespace vnotex { +class Node; + +// A unique locator for both internal Node and external file. +class FileLocator { +public: + FileLocator(Node *p_node) : m_node(p_node) {} + + FileLocator(const QString &p_filePath) : m_filePath(p_filePath) {} + + bool isNode() const { return m_node; } + + Node *node() const { + Q_ASSERT(isNode()); + return m_node; + } + + const QString &filePath() const { + Q_ASSERT(!isNode()); + return m_filePath; + } + +private: + Node *m_node = nullptr; + + QString m_filePath; +}; +} // namespace vnotex #endif // FILELOCATOR_H diff --git a/src/core/fileopenparameters.h b/src/core/fileopenparameters.h index ad473aca8d..598b525053 100644 --- a/src/core/fileopenparameters.h +++ b/src/core/fileopenparameters.h @@ -7,54 +7,48 @@ #include "global.h" -namespace vnotex -{ - class Node; - class SearchToken; +namespace vnotex { +class Node; +class SearchToken; - struct FileOpenParameters - { - enum Hook - { - PostSave, - MaxHook - }; +struct FileOpenParameters { + enum Hook { PostSave, MaxHook }; - ViewWindowMode m_mode = ViewWindowMode::Read; + ViewWindowMode m_mode = ViewWindowMode::Read; - // Force to enter m_mode. - bool m_forceMode = false; + // Force to enter m_mode. + bool m_forceMode = false; - // Whether focus to the opened window. - bool m_focus = true; + // Whether focus to the opened window. + bool m_focus = true; - // Whether it is a new file. - bool m_newFile = false; + // Whether it is a new file. + bool m_newFile = false; - // If this file is an attachment of a node, this field indicates it. - Node *m_nodeAttachedTo = nullptr; + // If this file is an attachment of a node, this field indicates it. + Node *m_nodeAttachedTo = nullptr; - // Open as read-only. - bool m_readOnly = false; + // Open as read-only. + bool m_readOnly = false; - // If m_lineNumber > -1, it indicates the line to scroll to after opening the file. - // 0-based. - int m_lineNumber = -1; + // If m_lineNumber > -1, it indicates the line to scroll to after opening the file. + // 0-based. + int m_lineNumber = -1; - // Whether always open a new window for file. - bool m_alwaysNewWindow = false; + // Whether always open a new window for file. + bool m_alwaysNewWindow = false; - // If not empty, use this token to do a search text highlight. - QSharedPointer m_searchToken; + // If not empty, use this token to do a search text highlight. + QSharedPointer m_searchToken; - // Whether should save this file into session. - bool m_sessionEnabled = true; + // Whether should save this file into session. + bool m_sessionEnabled = true; - // Whether specify the built-in file type to open as or the external program to open with. - QString m_fileType; + // Whether specify the built-in file type to open as or the external program to open with. + QString m_fileType; - std::function m_hooks[Hook::MaxHook]; - }; -} + std::function m_hooks[Hook::MaxHook]; +}; +} // namespace vnotex #endif // FILEOPENPARAMETERS_H diff --git a/src/core/global.h b/src/core/global.h index 35a7b3e035..6e7199c43c 100644 --- a/src/core/global.h +++ b/src/core/global.h @@ -1,204 +1,155 @@ #ifndef VNOTEX_GLOBAL_H #define VNOTEX_GLOBAL_H -#include -#include #include #include +#include +#include -namespace vnotex -{ - typedef quint64 ID; +namespace vnotex { +typedef quint64 ID; - inline QPair stringToID(const QString &p_str) - { - bool ok; - ID id = p_str.toULongLong(&ok); - return qMakePair(ok, id); - } +inline QPair stringToID(const QString &p_str) { + bool ok; + ID id = p_str.toULongLong(&ok); + return qMakePair(ok, id); +} - inline QString IDToString(ID p_id) - { - return QString::number(p_id); - } +inline QString IDToString(ID p_id) { return QString::number(p_id); } - typedef quint64 TimeStamp; +typedef quint64 TimeStamp; - struct Info - { - Info(const QString &p_name, const QString &p_displayName, const QString &p_description) - : m_name(p_name), m_displayName(p_displayName), m_description(p_description) - { - } +struct Info { + Info(const QString &p_name, const QString &p_displayName, const QString &p_description) + : m_name(p_name), m_displayName(p_displayName), m_description(p_description) {} - // Name for identification. - QString m_name; + // Name for identification. + QString m_name; - // User-visible name. - QString m_displayName; + // User-visible name. + QString m_displayName; - QString m_description; - }; + QString m_description; +}; - enum { CONTENTS_MARGIN = 2 }; +enum { CONTENTS_MARGIN = 2 }; - inline QString QJsonObjectToString(const QJsonObject &p_obj) - { - QString str = "{"; +inline QString QJsonObjectToString(const QJsonObject &p_obj) { + QString str = "{"; - auto keys = p_obj.keys(); - for (auto &key : keys) { - str += "\"" + key + "\": \"" + p_obj.value(key).toString() + "\";"; - } + auto keys = p_obj.keys(); + for (auto &key : keys) { + str += "\"" + key + "\": \"" + p_obj.value(key).toString() + "\";"; + } - str += "}"; - return str; - } + str += "}"; + return str; +} - inline QDebug operator<<(QDebug p_debug, const QJsonObject &p_obj) - { - QDebugStateSaver saver(p_debug); - p_debug << QJsonObjectToString(p_obj); - return p_debug; - } +inline QDebug operator<<(QDebug p_debug, const QJsonObject &p_obj) { + QDebugStateSaver saver(p_debug); + p_debug << QJsonObjectToString(p_obj); + return p_debug; +} - enum FindOption - { - FindNone = 0, - FindBackward = 0x1U, - CaseSensitive = 0x2U, - WholeWordOnly = 0x4U, - RegularExpression = 0x8U, - IncrementalSearch = 0x10U, - // Used in full-text search. - FuzzySearch = 0x20U - }; - Q_DECLARE_FLAGS(FindOptions, FindOption); - - enum OverrideState - { - NoOverride = 0, - ForceEnable = 1, - ForceDisable = 2 - }; - - enum class Alignment - { - None, - Left, - Center, - Right - }; - - enum class ViewWindowMode - { - Read, - Edit, - Invalid - }; - - enum { InvalidViewSplitId = 0 }; - - enum class Direction - { - Left, - Down, - Up, - Right - }; - - struct Segment - { - Segment() = default; - - Segment(int p_offset, int p_length) - : m_offset(p_offset), - m_length(p_length) - { - } - - bool operator<(const Segment &p_other) const - { - if (m_offset < p_other.m_offset) { - return true;; - } else { - return m_length < p_other.m_length; - } - } - - int m_offset = 0; - - int m_length = -1; - }; - - enum class LineEndingPolicy - { - Platform, - File, - LF, - CRLF, - CR - }; - - inline QString lineEndingPolicyToString(LineEndingPolicy p_ending) - { - switch (p_ending) { - case LineEndingPolicy::Platform: - return QStringLiteral("platform"); - - case LineEndingPolicy::File: - return QStringLiteral("file"); - - case LineEndingPolicy::LF: - return QStringLiteral("lf"); - - case LineEndingPolicy::CRLF: - return QStringLiteral("crlf"); - - case LineEndingPolicy::CR: - return QStringLiteral("cr"); - } - - return QStringLiteral("platform"); - } +enum FindOption { + FindNone = 0, + FindBackward = 0x1U, + CaseSensitive = 0x2U, + WholeWordOnly = 0x4U, + RegularExpression = 0x8U, + IncrementalSearch = 0x10U, + // Used in full-text search. + FuzzySearch = 0x20U +}; +Q_DECLARE_FLAGS(FindOptions, FindOption); - inline LineEndingPolicy stringToLineEndingPolicy(const QString &p_str) - { - auto ending = p_str.toLower(); - if (ending == QStringLiteral("file")) { - return LineEndingPolicy::File; - } else if (ending == QStringLiteral("lf")) { - return LineEndingPolicy::LF; - } else if (ending == QStringLiteral("crlf")) { - return LineEndingPolicy::CRLF; - } else if (ending == QStringLiteral("cr")) { - return LineEndingPolicy::CR; - } else { - return LineEndingPolicy::Platform; - } - } +enum OverrideState { NoOverride = 0, ForceEnable = 1, ForceDisable = 2 }; + +enum class Alignment { None, Left, Center, Right }; + +enum class ViewWindowMode { Read, Edit, Invalid }; + +enum { InvalidViewSplitId = 0 }; - enum Role - { - // Qt::UserRole = 0x0100 - UserRole2 = 0x0101, - HighlightsRole = 0x0102, - // Used for comparison. - ComparisonRole = 0x0103 - }; - - enum ViewOrder - { - OrderedByConfiguration = 0, - OrderedByName, - OrderedByNameReversed, - OrderedByCreatedTime, - OrderedByCreatedTimeReversed, - OrderedByModifiedTime, - OrderedByModifiedTimeReversed, - ViewOrderMax - }; -} // ns vnotex +enum class Direction { Left, Down, Up, Right }; + +struct Segment { + Segment() = default; + + Segment(int p_offset, int p_length) : m_offset(p_offset), m_length(p_length) {} + + bool operator<(const Segment &p_other) const { + if (m_offset < p_other.m_offset) { + return true; + ; + } else { + return m_length < p_other.m_length; + } + } + + int m_offset = 0; + + int m_length = -1; +}; + +enum class LineEndingPolicy { Platform, File, LF, CRLF, CR }; + +inline QString lineEndingPolicyToString(LineEndingPolicy p_ending) { + switch (p_ending) { + case LineEndingPolicy::Platform: + return QStringLiteral("platform"); + + case LineEndingPolicy::File: + return QStringLiteral("file"); + + case LineEndingPolicy::LF: + return QStringLiteral("lf"); + + case LineEndingPolicy::CRLF: + return QStringLiteral("crlf"); + + case LineEndingPolicy::CR: + return QStringLiteral("cr"); + } + + return QStringLiteral("platform"); +} + +inline LineEndingPolicy stringToLineEndingPolicy(const QString &p_str) { + auto ending = p_str.toLower(); + if (ending == QStringLiteral("file")) { + return LineEndingPolicy::File; + } else if (ending == QStringLiteral("lf")) { + return LineEndingPolicy::LF; + } else if (ending == QStringLiteral("crlf")) { + return LineEndingPolicy::CRLF; + } else if (ending == QStringLiteral("cr")) { + return LineEndingPolicy::CR; + } else { + return LineEndingPolicy::Platform; + } +} + +enum Role { + // Qt::UserRole = 0x0100 + UserRole2 = 0x0101, + HighlightsRole = 0x0102, + // Used for comparison. + ComparisonRole = 0x0103 +}; + +enum ViewOrder { + OrderedByConfiguration = 0, + OrderedByName, + OrderedByNameReversed, + OrderedByCreatedTime, + OrderedByCreatedTimeReversed, + OrderedByModifiedTime, + OrderedByModifiedTimeReversed, + ViewOrderMax +}; +} // namespace vnotex Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions); diff --git a/src/core/historyitem.cpp b/src/core/historyitem.cpp index 4ac68cd217..44762ac58d 100644 --- a/src/core/historyitem.cpp +++ b/src/core/historyitem.cpp @@ -4,25 +4,21 @@ using namespace vnotex; -HistoryItem::HistoryItem(const QString &p_path, int p_lineNumber, const QDateTime &p_lastAccessedTimeUtc) - : m_path(p_path), - m_lineNumber(p_lineNumber), - m_lastAccessedTimeUtc(p_lastAccessedTimeUtc) -{ -} +HistoryItem::HistoryItem(const QString &p_path, int p_lineNumber, + const QDateTime &p_lastAccessedTimeUtc) + : m_path(p_path), m_lineNumber(p_lineNumber), m_lastAccessedTimeUtc(p_lastAccessedTimeUtc) {} -QJsonObject HistoryItem::toJson() const -{ - QJsonObject jobj; - jobj[QStringLiteral("path")] = m_path; - jobj[QStringLiteral("line_number")] = m_lineNumber; - jobj[QStringLiteral("last_accessed_time")] = Utils::dateTimeStringUniform(m_lastAccessedTimeUtc); - return jobj; +QJsonObject HistoryItem::toJson() const { + QJsonObject jobj; + jobj[QStringLiteral("path")] = m_path; + jobj[QStringLiteral("line_number")] = m_lineNumber; + jobj[QStringLiteral("last_accessed_time")] = Utils::dateTimeStringUniform(m_lastAccessedTimeUtc); + return jobj; } -void HistoryItem::fromJson(const QJsonObject &p_jobj) -{ - m_path = p_jobj[QStringLiteral("path")].toString(); - m_lineNumber = p_jobj[QStringLiteral("line_number")].toInt(); - m_lastAccessedTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[QStringLiteral("last_accessed_time")].toString()); +void HistoryItem::fromJson(const QJsonObject &p_jobj) { + m_path = p_jobj[QStringLiteral("path")].toString(); + m_lineNumber = p_jobj[QStringLiteral("line_number")].toInt(); + m_lastAccessedTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[QStringLiteral("last_accessed_time")].toString()); } diff --git a/src/core/historyitem.h b/src/core/historyitem.h index 5044c73d1b..2bf6541a61 100644 --- a/src/core/historyitem.h +++ b/src/core/historyitem.h @@ -1,32 +1,28 @@ #ifndef HISTORYITEM_H #define HISTORYITEM_H -#include -#include #include +#include +#include -namespace vnotex -{ - struct HistoryItem - { - HistoryItem() = default; +namespace vnotex { +struct HistoryItem { + HistoryItem() = default; - HistoryItem(const QString &p_path, - int p_lineNumber, - const QDateTime &p_lastAccessedTimeUtc); + HistoryItem(const QString &p_path, int p_lineNumber, const QDateTime &p_lastAccessedTimeUtc); - QJsonObject toJson() const; + QJsonObject toJson() const; - void fromJson(const QJsonObject &p_jobj); + void fromJson(const QJsonObject &p_jobj); - // Relative path if it is a node within a notebook. - QString m_path; + // Relative path if it is a node within a notebook. + QString m_path; - // 0-based. - int m_lineNumber = -1; + // 0-based. + int m_lineNumber = -1; - QDateTime m_lastAccessedTimeUtc; - }; -} + QDateTime m_lastAccessedTimeUtc; +}; +} // namespace vnotex #endif // HISTORYITEM_H diff --git a/src/core/historymgr.cpp b/src/core/historymgr.cpp index 8e1761549f..f7b8f4a7bc 100644 --- a/src/core/historymgr.cpp +++ b/src/core/historymgr.cpp @@ -3,223 +3,208 @@ #include #include "configmgr.h" -#include "sessionconfig.h" #include "coreconfig.h" -#include "vnotex.h" +#include "exception.h" #include "notebookmgr.h" -#include +#include "sessionconfig.h" +#include "vnotex.h" #include +#include #include -#include "exception.h" using namespace vnotex; -bool HistoryItemFull::operator<(const HistoryItemFull &p_other) const -{ - if (m_item.m_lastAccessedTimeUtc < p_other.m_item.m_lastAccessedTimeUtc) { - return true; - } else if (m_item.m_lastAccessedTimeUtc > p_other.m_item.m_lastAccessedTimeUtc) { - return false; - } else { - return m_item.m_path < p_other.m_item.m_path; - } +bool HistoryItemFull::operator<(const HistoryItemFull &p_other) const { + if (m_item.m_lastAccessedTimeUtc < p_other.m_item.m_lastAccessedTimeUtc) { + return true; + } else if (m_item.m_lastAccessedTimeUtc > p_other.m_item.m_lastAccessedTimeUtc) { + return false; + } else { + return m_item.m_path < p_other.m_item.m_path; + } } - HistoryMgr::HistoryMgr() - : m_perNotebookHistoryEnabled(ConfigMgr::getInst().getCoreConfig().isPerNotebookHistoryEnabled()) -{ - connect(&VNoteX::getInst().getNotebookMgr(), &NotebookMgr::notebooksUpdated, - this, &HistoryMgr::loadHistory); + : m_perNotebookHistoryEnabled( + ConfigMgr::getInst().getCoreConfig().isPerNotebookHistoryEnabled()) { + connect(&VNoteX::getInst().getNotebookMgr(), &NotebookMgr::notebooksUpdated, this, + &HistoryMgr::loadHistory); - loadHistory(); + loadHistory(); } -static bool historyPtrCmp(const QSharedPointer &p_a, const QSharedPointer &p_b) -{ - return *p_a < *p_b; +static bool historyPtrCmp(const QSharedPointer &p_a, + const QSharedPointer &p_b) { + return *p_a < *p_b; } -void HistoryMgr::loadHistory() -{ - m_history.clear(); - - // Load from session. - { - const auto &history = ConfigMgr::getInst().getSessionConfig().getHistory(); - for (const auto &item : history) { - auto fullItem = QSharedPointer::create(); - fullItem->m_item = item; - m_history.push_back(fullItem); - } +void HistoryMgr::loadHistory() { + m_history.clear(); + + // Load from session. + { + const auto &history = ConfigMgr::getInst().getSessionConfig().getHistory(); + for (const auto &item : history) { + auto fullItem = QSharedPointer::create(); + fullItem->m_item = item; + m_history.push_back(fullItem); } + } + + // Load from notebooks. + if (m_perNotebookHistoryEnabled) { + const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks(); + for (const auto &nb : notebooks) { + auto historyI = nb->history(); + if (!historyI) { + continue; + } + const auto &history = historyI->getHistory(); + const auto &backend = nb->getBackend(); + for (const auto &item : history) { + auto fullItem = QSharedPointer::create(); + fullItem->m_item = item; - // Load from notebooks. - if (m_perNotebookHistoryEnabled) { - const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks(); - for (const auto &nb : notebooks) { - auto historyI = nb->history(); - if (!historyI) { - continue; - } - const auto &history = historyI->getHistory(); - const auto &backend = nb->getBackend(); - for (const auto &item : history) { - auto fullItem = QSharedPointer::create(); - fullItem->m_item = item; - - // We saved the absolute path by mistake in previous version. - try { - fullItem->m_item.m_path = backend->getFullPath(item.m_path); - } catch (Exception &p_e) { - qWarning() << "skipped loading history item" << item.m_path << "from notebook" << nb->getName() << p_e.what(); - continue; - } - - fullItem->m_notebookName = nb->getName(); - m_history.push_back(fullItem); - } + // We saved the absolute path by mistake in previous version. + try { + fullItem->m_item.m_path = backend->getFullPath(item.m_path); + } catch (Exception &p_e) { + qWarning() << "skipped loading history item" << item.m_path << "from notebook" + << nb->getName() << p_e.what(); + continue; } + + fullItem->m_notebookName = nb->getName(); + m_history.push_back(fullItem); + } } + } - std::sort(m_history.begin(), m_history.end(), historyPtrCmp); + std::sort(m_history.begin(), m_history.end(), historyPtrCmp); - qDebug() << "loaded" << m_history.size() << "history items"; + qDebug() << "loaded" << m_history.size() << "history items"; - emit historyUpdated(); + emit historyUpdated(); } -const QVector> &HistoryMgr::getHistory() const -{ - return m_history; -} +const QVector> &HistoryMgr::getHistory() const { return m_history; } -void HistoryMgr::removeFromHistory(const QString &p_itemPath) -{ - for (int i = m_history.size() - 1; i >= 0; --i) { - if (m_history[i]->m_item.m_path == p_itemPath) { - m_history.remove(i); - break; - } +void HistoryMgr::removeFromHistory(const QString &p_itemPath) { + for (int i = m_history.size() - 1; i >= 0; --i) { + if (m_history[i]->m_item.m_path == p_itemPath) { + m_history.remove(i); + break; } + } } -void HistoryMgr::add(const QString &p_path, - int p_lineNumber, - ViewWindowMode p_mode, - bool p_readOnly, - Notebook *p_notebook) -{ - const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount(); - if (p_path.isEmpty() || maxHistoryCount == 0) { - return; - } - - HistoryItem item(p_path, p_lineNumber, QDateTime::currentDateTimeUtc()); - - if (p_notebook && m_perNotebookHistoryEnabled && p_notebook->history()) { - p_notebook->history()->addHistory(item); - } else { - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - sessionConfig.addHistory(item); +void HistoryMgr::add(const QString &p_path, int p_lineNumber, ViewWindowMode p_mode, + bool p_readOnly, Notebook *p_notebook) { + const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount(); + if (p_path.isEmpty() || maxHistoryCount == 0) { + return; + } + + HistoryItem item(p_path, p_lineNumber, QDateTime::currentDateTimeUtc()); + + if (p_notebook && m_perNotebookHistoryEnabled && p_notebook->history()) { + p_notebook->history()->addHistory(item); + } else { + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + sessionConfig.addHistory(item); + } + + // Maintain the combined queue. + { + removeFromHistory(item.m_path); + + auto fullItem = QSharedPointer::create(); + fullItem->m_item = item; + if (p_notebook) { + fullItem->m_notebookName = p_notebook->getName(); } - - // Maintain the combined queue. - { - removeFromHistory(item.m_path); - - auto fullItem = QSharedPointer::create(); - fullItem->m_item = item; - if (p_notebook) { - fullItem->m_notebookName = p_notebook->getName(); - } - m_history.append(fullItem); + m_history.append(fullItem); + } + + // Update m_lastClosedFiles. + { + for (int i = m_lastClosedFiles.size() - 1; i >= 0; --i) { + if (m_lastClosedFiles[i].m_path == p_path) { + m_lastClosedFiles.remove(i); + break; + } } - // Update m_lastClosedFiles. - { - for (int i = m_lastClosedFiles.size() - 1; i >= 0; --i) { - if (m_lastClosedFiles[i].m_path == p_path) { - m_lastClosedFiles.remove(i); - break; - } - } - - m_lastClosedFiles.append(LastClosedFile()); - auto &file = m_lastClosedFiles.back(); - file.m_path = p_path; - file.m_lineNumber = p_lineNumber; - file.m_mode = p_mode; - file.m_readOnly = p_readOnly; + m_lastClosedFiles.append(LastClosedFile()); + auto &file = m_lastClosedFiles.back(); + file.m_path = p_path; + file.m_lineNumber = p_lineNumber; + file.m_mode = p_mode; + file.m_readOnly = p_readOnly; - if (m_lastClosedFiles.size() > maxHistoryCount) { - m_lastClosedFiles.remove(0, m_lastClosedFiles.size() - maxHistoryCount); - } + if (m_lastClosedFiles.size() > maxHistoryCount) { + m_lastClosedFiles.remove(0, m_lastClosedFiles.size() - maxHistoryCount); } + } - emit historyUpdated(); + emit historyUpdated(); } -void HistoryMgr::remove(const QVector &p_paths, Notebook *p_notebook) -{ - for(const QString &p_itemPath : p_paths) { - if (p_notebook && m_perNotebookHistoryEnabled && p_notebook->history()) { - p_notebook->history()->removeHistory(p_itemPath); - } else { - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - sessionConfig.removeHistory(p_itemPath); - } - - removeFromHistory(p_itemPath); +void HistoryMgr::remove(const QVector &p_paths, Notebook *p_notebook) { + for (const QString &p_itemPath : p_paths) { + if (p_notebook && m_perNotebookHistoryEnabled && p_notebook->history()) { + p_notebook->history()->removeHistory(p_itemPath); + } else { + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + sessionConfig.removeHistory(p_itemPath); } - emit historyUpdated(); + removeFromHistory(p_itemPath); + } + + emit historyUpdated(); } -void HistoryMgr::removeHistoryItem(QVector &p_history, const QString &p_itemPath) -{ - for (int i = p_history.size() - 1; i >= 0; --i) { - if (p_history[i].m_path == p_itemPath) { - p_history.remove(i); - break; - } +void HistoryMgr::removeHistoryItem(QVector &p_history, const QString &p_itemPath) { + for (int i = p_history.size() - 1; i >= 0; --i) { + if (p_history[i].m_path == p_itemPath) { + p_history.remove(i); + break; } + } } -void HistoryMgr::insertHistoryItem(QVector &p_history, const HistoryItem &p_item) -{ - removeHistoryItem(p_history, p_item.m_path); - p_history.append(p_item); +void HistoryMgr::insertHistoryItem(QVector &p_history, const HistoryItem &p_item) { + removeHistoryItem(p_history, p_item.m_path); + p_history.append(p_item); - const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount(); - if (p_history.size() > maxHistoryCount) { - p_history.remove(0, p_history.size() - maxHistoryCount); - } + const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount(); + if (p_history.size() > maxHistoryCount) { + p_history.remove(0, p_history.size() - maxHistoryCount); + } } -void HistoryMgr::clear() -{ - ConfigMgr::getInst().getSessionConfig().clearHistory(); +void HistoryMgr::clear() { + ConfigMgr::getInst().getSessionConfig().clearHistory(); - if (m_perNotebookHistoryEnabled) { - const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks(); - for (const auto &nb : notebooks) { - if (auto historyI = nb->history()) { - historyI->clearHistory(); - } - } + if (m_perNotebookHistoryEnabled) { + const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks(); + for (const auto &nb : notebooks) { + if (auto historyI = nb->history()) { + historyI->clearHistory(); + } } + } - loadHistory(); + loadHistory(); } -HistoryMgr::LastClosedFile HistoryMgr::popLastClosedFile() -{ - if (m_lastClosedFiles.isEmpty()) { - return LastClosedFile(); - } +HistoryMgr::LastClosedFile HistoryMgr::popLastClosedFile() { + if (m_lastClosedFiles.isEmpty()) { + return LastClosedFile(); + } - auto file = m_lastClosedFiles.back(); - m_lastClosedFiles.pop_back(); - return file; + auto file = m_lastClosedFiles.back(); + m_lastClosedFiles.pop_back(); + return file; } diff --git a/src/core/historymgr.h b/src/core/historymgr.h index d2c1da1f05..9113829bdd 100644 --- a/src/core/historymgr.h +++ b/src/core/historymgr.h @@ -2,86 +2,78 @@ #define HISTORYMGR_H #include -#include #include +#include -#include "noncopyable.h" -#include "historyitem.h" #include "global.h" +#include "historyitem.h" +#include "noncopyable.h" -namespace vnotex -{ - class Notebook; +namespace vnotex { +class Notebook; - struct HistoryItemFull - { - bool operator<(const HistoryItemFull &p_other) const; +struct HistoryItemFull { + bool operator<(const HistoryItemFull &p_other) const; - HistoryItem m_item; + HistoryItem m_item; - QString m_notebookName; - }; + QString m_notebookName; +}; - // Combine the history from all notebooks and from SessionConfig. - // SessionConfig will store history about external files. - // Also provide stack of files accessed during current session, which could be re-opened - // via Ctrl+Shit+T. - class HistoryMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - struct LastClosedFile - { - QString m_path; +// Combine the history from all notebooks and from SessionConfig. +// SessionConfig will store history about external files. +// Also provide stack of files accessed during current session, which could be re-opened +// via Ctrl+Shit+T. +class HistoryMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + struct LastClosedFile { + QString m_path; - int m_lineNumber = 0; + int m_lineNumber = 0; - ViewWindowMode m_mode = ViewWindowMode::Read; + ViewWindowMode m_mode = ViewWindowMode::Read; - bool m_readOnly = false; - }; + bool m_readOnly = false; + }; - static HistoryMgr &getInst() - { - static HistoryMgr inst; - return inst; - } + static HistoryMgr &getInst() { + static HistoryMgr inst; + return inst; + } - const QVector> &getHistory() const; + const QVector> &getHistory() const; - void add(const QString &p_path, - int p_lineNumber, - ViewWindowMode p_mode, - bool p_readOnly, - Notebook *p_notebook); + void add(const QString &p_path, int p_lineNumber, ViewWindowMode p_mode, bool p_readOnly, + Notebook *p_notebook); - void remove(const QVector &p_paths, Notebook *p_notebook); + void remove(const QVector &p_paths, Notebook *p_notebook); - void clear(); + void clear(); - LastClosedFile popLastClosedFile(); + LastClosedFile popLastClosedFile(); - static void removeHistoryItem(QVector &p_history, const QString &p_itemPath); + static void removeHistoryItem(QVector &p_history, const QString &p_itemPath); - static void insertHistoryItem(QVector &p_history, const HistoryItem &p_item); + static void insertHistoryItem(QVector &p_history, const HistoryItem &p_item); - signals: - void historyUpdated(); +signals: + void historyUpdated(); - private: - HistoryMgr(); +private: + HistoryMgr(); - void loadHistory(); + void loadHistory(); - // Sorted by last accessed time ascendingly. - QVector> m_history; + // Sorted by last accessed time ascendingly. + QVector> m_history; - void removeFromHistory(const QString &p_itemPath); + void removeFromHistory(const QString &p_itemPath); - QVector m_lastClosedFiles; + QVector m_lastClosedFiles; - const bool m_perNotebookHistoryEnabled = false; - }; -} + const bool m_perNotebookHistoryEnabled = false; +}; +} // namespace vnotex #endif // HISTORYMGR_H diff --git a/src/core/htmltemplatehelper.cpp b/src/core/htmltemplatehelper.cpp index dba7468479..081cbcdd78 100644 --- a/src/core/htmltemplatehelper.cpp +++ b/src/core/htmltemplatehelper.cpp @@ -2,17 +2,17 @@ #include +#include +#include #include -#include #include -#include -#include -#include -#include -#include +#include #include #include -#include +#include +#include +#include +#include using namespace vnotex; @@ -22,382 +22,367 @@ HtmlTemplateHelper::Template HtmlTemplateHelper::s_pdfViewerTemplate; HtmlTemplateHelper::Template HtmlTemplateHelper::s_mindMapEditorTemplate; -QString MarkdownWebGlobalOptions::toJavascriptObject() const -{ - return QStringLiteral("window.vxOptions = {\n") - + QStringLiteral("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml)) - + QStringLiteral("plantUmlWebService: '%1',\n").arg(m_plantUmlWebService) - + QStringLiteral("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz)) - + QStringLiteral("mathJaxScript: '%1',\n").arg(m_mathJaxScript) - + QStringLiteral("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled)) - + QStringLiteral("imageAlignCenterEnabled: %1,\n").arg(Utils::boolToString(m_imageAlignCenterEnabled)) - + QStringLiteral("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss)) - + QStringLiteral("htmlTagEnabled: %1,\n").arg(Utils::boolToString(m_htmlTagEnabled)) - + QStringLiteral("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled)) - + QStringLiteral("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled)) - + QStringLiteral("indentFirstLineEnabled: %1,\n").arg(Utils::boolToString(m_indentFirstLineEnabled)) - + QStringLiteral("codeBlockLineNumberEnabled: %1,\n").arg(Utils::boolToString(m_codeBlockLineNumberEnabled)) - + QStringLiteral("sectionNumberEnabled: %1,\n").arg(Utils::boolToString(m_sectionNumberEnabled)) - + QStringLiteral("transparentBackgroundEnabled: %1,\n").arg(Utils::boolToString(m_transparentBackgroundEnabled)) - + QStringLiteral("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable)) - + QStringLiteral("bodyWidth: %1,\n").arg(m_bodyWidth) - + QStringLiteral("bodyHeight: %1,\n").arg(m_bodyHeight) - + QStringLiteral("transformSvgToPngEnabled: %1,\n").arg(Utils::boolToString(m_transformSvgToPngEnabled)) - + QStringLiteral("mathJaxScale: %1,\n").arg(m_mathJaxScale) - + QStringLiteral("removeCodeToolBarEnabled: %1,\n").arg(Utils::boolToString(m_removeCodeToolBarEnabled)) - + QStringLiteral("sectionNumberBaseLevel: %1\n").arg(m_sectionNumberBaseLevel) - + QStringLiteral("}"); +QString MarkdownWebGlobalOptions::toJavascriptObject() const { + return QStringLiteral("window.vxOptions = {\n") + + QStringLiteral("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml)) + + QStringLiteral("plantUmlWebService: '%1',\n").arg(m_plantUmlWebService) + + QStringLiteral("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz)) + + QStringLiteral("mathJaxScript: '%1',\n").arg(m_mathJaxScript) + + QStringLiteral("constrainImageWidthEnabled: %1,\n") + .arg(Utils::boolToString(m_constrainImageWidthEnabled)) + + QStringLiteral("imageAlignCenterEnabled: %1,\n") + .arg(Utils::boolToString(m_imageAlignCenterEnabled)) + + QStringLiteral("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss)) + + QStringLiteral("htmlTagEnabled: %1,\n").arg(Utils::boolToString(m_htmlTagEnabled)) + + QStringLiteral("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled)) + + QStringLiteral("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled)) + + QStringLiteral("indentFirstLineEnabled: %1,\n") + .arg(Utils::boolToString(m_indentFirstLineEnabled)) + + QStringLiteral("codeBlockLineNumberEnabled: %1,\n") + .arg(Utils::boolToString(m_codeBlockLineNumberEnabled)) + + QStringLiteral("sectionNumberEnabled: %1,\n") + .arg(Utils::boolToString(m_sectionNumberEnabled)) + + QStringLiteral("transparentBackgroundEnabled: %1,\n") + .arg(Utils::boolToString(m_transparentBackgroundEnabled)) + + QStringLiteral("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable)) + + QStringLiteral("bodyWidth: %1,\n").arg(m_bodyWidth) + + QStringLiteral("bodyHeight: %1,\n").arg(m_bodyHeight) + + QStringLiteral("transformSvgToPngEnabled: %1,\n") + .arg(Utils::boolToString(m_transformSvgToPngEnabled)) + + QStringLiteral("mathJaxScale: %1,\n").arg(m_mathJaxScale) + + QStringLiteral("removeCodeToolBarEnabled: %1,\n") + .arg(Utils::boolToString(m_removeCodeToolBarEnabled)) + + QStringLiteral("sectionNumberBaseLevel: %1\n").arg(m_sectionNumberBaseLevel) + + QStringLiteral("}"); } // Read "global_styles" from resource and fill the holder with the content. -static void fillGlobalStyles(QString &p_template, const WebResource &p_resource, const QString &p_additionalStyles) -{ - QString styles; - for (const auto &ele : p_resource.m_resources) { - if (ele.isGlobal()) { - if (ele.m_enabled) { - for (const auto &style : ele.m_styles) { - // Read the style file content. - auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); - try { - styles += FileUtils::readTextFile(styleFile); - } catch (Exception &p_e) { - qWarning() << "failed to read global styles" << ele.m_name << styleFile << p_e.what(); - } - } - } - break; +static void fillGlobalStyles(QString &p_template, const WebResource &p_resource, + const QString &p_additionalStyles) { + QString styles; + for (const auto &ele : p_resource.m_resources) { + if (ele.isGlobal()) { + if (ele.m_enabled) { + for (const auto &style : ele.m_styles) { + // Read the style file content. + auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); + try { + styles += FileUtils::readTextFile(styleFile); + } catch (Exception &p_e) { + qWarning() << "failed to read global styles" << ele.m_name << styleFile << p_e.what(); + } } + } + break; } + } - styles += p_additionalStyles; + styles += p_additionalStyles; - if (!styles.isEmpty()) { - p_template.replace("/* VX_GLOBAL_STYLES_PLACEHOLDER */", styles); - } + if (!styles.isEmpty()) { + p_template.replace("/* VX_GLOBAL_STYLES_PLACEHOLDER */", styles); + } } -static QString fillStyleTag(const QString &p_styleFile) -{ - if (p_styleFile.isEmpty()) { - return ""; - } - auto url = PathUtils::pathToUrl(p_styleFile); - return QStringLiteral("\n").arg(url.toString()); +static QString fillStyleTag(const QString &p_styleFile) { + if (p_styleFile.isEmpty()) { + return ""; + } + auto url = PathUtils::pathToUrl(p_styleFile); + return QStringLiteral("\n") + .arg(url.toString()); } -static QString fillScriptTag(const QString &p_scriptFile) -{ - if (p_scriptFile.isEmpty()) { - return ""; - } - auto url = PathUtils::pathToUrl(p_scriptFile); - return QStringLiteral("\n").arg(url.toString()); +static QString fillScriptTag(const QString &p_scriptFile) { + if (p_scriptFile.isEmpty()) { + return ""; + } + auto url = PathUtils::pathToUrl(p_scriptFile); + return QStringLiteral("\n") + .arg(url.toString()); } -static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetFile, const QString &p_highlightStyleSheetFile) -{ - QString styles; - styles += fillStyleTag(p_webStyleSheetFile); - styles += fillStyleTag(p_highlightStyleSheetFile); +static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetFile, + const QString &p_highlightStyleSheetFile) { + QString styles; + styles += fillStyleTag(p_webStyleSheetFile); + styles += fillStyleTag(p_highlightStyleSheetFile); - if (!styles.isEmpty()) { - p_template.replace(QStringLiteral(""), - styles); - } + if (!styles.isEmpty()) { + p_template.replace(QStringLiteral(""), styles); + } } -static void fillGlobalOptions(QString &p_template, const MarkdownWebGlobalOptions &p_opts) -{ - p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"), - p_opts.toJavascriptObject()); +static void fillGlobalOptions(QString &p_template, const MarkdownWebGlobalOptions &p_opts) { + p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"), + p_opts.toJavascriptObject()); } // Read all other resources in @p_resource and fill the holder with proper resource path. -static void fillResources(QString &p_template, const WebResource &p_resource) -{ - QString styles; - QString scripts; - - for (const auto &ele : p_resource.m_resources) { - if (ele.m_enabled && !ele.isGlobal()) { - // Styles. - for (const auto &style : ele.m_styles) { - auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); - styles += fillStyleTag(styleFile); - } - - // Scripts. - for (const auto &script : ele.m_scripts) { - auto scriptFile = ConfigMgr::getInst().getUserOrAppFile(script); - scripts += fillScriptTag(scriptFile); - } - } +static void fillResources(QString &p_template, const WebResource &p_resource) { + QString styles; + QString scripts; + + for (const auto &ele : p_resource.m_resources) { + if (ele.m_enabled && !ele.isGlobal()) { + // Styles. + for (const auto &style : ele.m_styles) { + auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); + styles += fillStyleTag(styleFile); + } + + // Scripts. + for (const auto &script : ele.m_scripts) { + auto scriptFile = ConfigMgr::getInst().getUserOrAppFile(script); + scripts += fillScriptTag(scriptFile); + } } + } - if (!styles.isEmpty()) { - p_template.replace(QStringLiteral(""), - styles); - } + if (!styles.isEmpty()) { + p_template.replace(QStringLiteral(""), styles); + } - if (!scripts.isEmpty()) { - p_template.replace(QStringLiteral(""), - scripts); - } + if (!scripts.isEmpty()) { + p_template.replace(QStringLiteral(""), scripts); + } } -static void fillResourcesByContent(QString &p_template, const WebResource &p_resource) -{ - QString styles; - QString scripts; - - for (const auto &ele : p_resource.m_resources) { - if (ele.m_enabled && !ele.isGlobal()) { - try { - // Styles. - for (const auto &style : ele.m_styles) { - auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); - styles += FileUtils::readTextFile(styleFile); - } - - // Scripts. - for (const auto &script : ele.m_scripts) { - auto scriptFile = ConfigMgr::getInst().getUserOrAppFile(script); - scripts += FileUtils::readTextFile(scriptFile); - } - } catch (Exception &p_e) { - qWarning() << "failed to read resource" << ele.m_name << p_e.what(); - } +static void fillResourcesByContent(QString &p_template, const WebResource &p_resource) { + QString styles; + QString scripts; + + for (const auto &ele : p_resource.m_resources) { + if (ele.m_enabled && !ele.isGlobal()) { + try { + // Styles. + for (const auto &style : ele.m_styles) { + auto styleFile = ConfigMgr::getInst().getUserOrAppFile(style); + styles += FileUtils::readTextFile(styleFile); } - } - if (!styles.isEmpty()) { - p_template.replace(QStringLiteral("/* VX_STYLES_PLACEHOLDER */"), styles); + // Scripts. + for (const auto &script : ele.m_scripts) { + auto scriptFile = ConfigMgr::getInst().getUserOrAppFile(script); + scripts += FileUtils::readTextFile(scriptFile); + } + } catch (Exception &p_e) { + qWarning() << "failed to read resource" << ele.m_name << p_e.what(); + } } + } - if (!scripts.isEmpty()) { - p_template.replace(QStringLiteral("/* VX_SCRIPTS_PLACEHOLDER */"), scripts); - } + if (!styles.isEmpty()) { + p_template.replace(QStringLiteral("/* VX_STYLES_PLACEHOLDER */"), styles); + } + + if (!scripts.isEmpty()) { + p_template.replace(QStringLiteral("/* VX_SCRIPTS_PLACEHOLDER */"), scripts); + } } -const QString &HtmlTemplateHelper::getMarkdownViewerTemplate() -{ - return s_markdownViewerTemplate.m_template; +const QString &HtmlTemplateHelper::getMarkdownViewerTemplate() { + return s_markdownViewerTemplate.m_template; } -void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force) -{ - if (!p_force && p_config.revision() == s_markdownViewerTemplate.m_revision) { - return; - } +void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, + bool p_force) { + if (!p_force && p_config.revision() == s_markdownViewerTemplate.m_revision) { + return; + } - s_markdownViewerTemplate.m_revision = p_config.revision(); + s_markdownViewerTemplate.m_revision = p_config.revision(); - MarkdownParas paras; - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet); - paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet); + MarkdownParas paras; + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet); + paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet); - s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras); + s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras); } QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, - const MarkdownParas &p_paras) -{ - const auto &viewerResource = p_config.getViewerResource(); - const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template); - QString htmlTemplate; - try { - htmlTemplate = FileUtils::readTextFile(templateFile); - } catch (Exception &p_e) { - qWarning() << "failed to read HTML template" << templateFile << p_e.what(); - return errorPage(); - } - - fillGlobalStyles(htmlTemplate, viewerResource, ""); - - fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile); - - { - MarkdownWebGlobalOptions opts; - opts.m_webPlantUml = p_config.getWebPlantUml(); - opts.m_plantUmlWebService = p_config.getPlantUmlWebService(); - opts.m_webGraphviz = p_config.getWebGraphviz(); - opts.m_mathJaxScript = p_config.getMathJaxScript(); - opts.m_sectionNumberEnabled = p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read; - opts.m_sectionNumberBaseLevel = p_config.getSectionNumberBaseLevel(); - opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled(); - opts.m_imageAlignCenterEnabled = p_config.getImageAlignCenterEnabled(); - opts.m_protectFromXss = p_config.getProtectFromXss(); - opts.m_htmlTagEnabled = p_config.getHtmlTagEnabled(); - opts.m_autoBreakEnabled = p_config.getAutoBreakEnabled(); - opts.m_linkifyEnabled = p_config.getLinkifyEnabled(); - opts.m_indentFirstLineEnabled = p_config.getIndentFirstLineEnabled(); - opts.m_codeBlockLineNumberEnabled = p_config.getCodeBlockLineNumberEnabled(); - opts.m_transparentBackgroundEnabled = p_paras.m_transparentBackgroundEnabled; - opts.m_scrollable = p_paras.m_scrollable; - opts.m_bodyWidth = p_paras.m_bodyWidth; - opts.m_bodyHeight = p_paras.m_bodyHeight; - opts.m_transformSvgToPngEnabled = p_paras.m_transformSvgToPngEnabled; - opts.m_mathJaxScale = p_paras.m_mathJaxScale; - opts.m_removeCodeToolBarEnabled = p_paras.m_removeCodeToolBarEnabled; - fillGlobalOptions(htmlTemplate, opts); - } - - fillResources(htmlTemplate, viewerResource); - - return htmlTemplate; + const MarkdownParas &p_paras) { + const auto &viewerResource = p_config.getViewerResource(); + const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template); + QString htmlTemplate; + try { + htmlTemplate = FileUtils::readTextFile(templateFile); + } catch (Exception &p_e) { + qWarning() << "failed to read HTML template" << templateFile << p_e.what(); + return errorPage(); + } + + fillGlobalStyles(htmlTemplate, viewerResource, ""); + + fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile); + + { + MarkdownWebGlobalOptions opts; + opts.m_webPlantUml = p_config.getWebPlantUml(); + opts.m_plantUmlWebService = p_config.getPlantUmlWebService(); + opts.m_webGraphviz = p_config.getWebGraphviz(); + opts.m_mathJaxScript = p_config.getMathJaxScript(); + opts.m_sectionNumberEnabled = + p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read; + opts.m_sectionNumberBaseLevel = p_config.getSectionNumberBaseLevel(); + opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled(); + opts.m_imageAlignCenterEnabled = p_config.getImageAlignCenterEnabled(); + opts.m_protectFromXss = p_config.getProtectFromXss(); + opts.m_htmlTagEnabled = p_config.getHtmlTagEnabled(); + opts.m_autoBreakEnabled = p_config.getAutoBreakEnabled(); + opts.m_linkifyEnabled = p_config.getLinkifyEnabled(); + opts.m_indentFirstLineEnabled = p_config.getIndentFirstLineEnabled(); + opts.m_codeBlockLineNumberEnabled = p_config.getCodeBlockLineNumberEnabled(); + opts.m_transparentBackgroundEnabled = p_paras.m_transparentBackgroundEnabled; + opts.m_scrollable = p_paras.m_scrollable; + opts.m_bodyWidth = p_paras.m_bodyWidth; + opts.m_bodyHeight = p_paras.m_bodyHeight; + opts.m_transformSvgToPngEnabled = p_paras.m_transformSvgToPngEnabled; + opts.m_mathJaxScale = p_paras.m_mathJaxScale; + opts.m_removeCodeToolBarEnabled = p_paras.m_removeCodeToolBarEnabled; + fillGlobalOptions(htmlTemplate, opts); + } + + fillResources(htmlTemplate, viewerResource); + + return htmlTemplate; } QString HtmlTemplateHelper::generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config, - bool p_addOutlinePanel) -{ - auto exportResource = p_config.getExportResource(); - const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template); - QString htmlTemplate; - try { - htmlTemplate = FileUtils::readTextFile(templateFile); - } catch (Exception &p_e) { - qWarning() << "failed to read Markdown export HTML template" << templateFile << p_e.what(); - return errorPage(); - } + bool p_addOutlinePanel) { + auto exportResource = p_config.getExportResource(); + const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template); + QString htmlTemplate; + try { + htmlTemplate = FileUtils::readTextFile(templateFile); + } catch (Exception &p_e) { + qWarning() << "failed to read Markdown export HTML template" << templateFile << p_e.what(); + return errorPage(); + } - fillGlobalStyles(htmlTemplate, exportResource, ""); + fillGlobalStyles(htmlTemplate, exportResource, ""); - fillOutlinePanel(htmlTemplate, exportResource, p_addOutlinePanel); + fillOutlinePanel(htmlTemplate, exportResource, p_addOutlinePanel); - fillResourcesByContent(htmlTemplate, exportResource); + fillResourcesByContent(htmlTemplate, exportResource); - return htmlTemplate; + return htmlTemplate; } -void HtmlTemplateHelper::fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel) -{ - for (auto &ele : p_exportResource.m_resources) { - if (ele.m_name == QStringLiteral("outline")) { - ele.m_enabled = p_addOutlinePanel; - break; - } - } - - // Remove static content to make the page clean. - if (!p_addOutlinePanel) { - int startIdx = p_template.indexOf(""); - QString endMark(""); - int endIdx = p_template.lastIndexOf(endMark); - Q_ASSERT(startIdx > -1 && endIdx > startIdx); - p_template.remove(startIdx, endIdx + endMark.size() - startIdx); - - startIdx = p_template.indexOf(""); - endMark = ""; - endIdx = p_template.lastIndexOf(endMark); - Q_ASSERT(startIdx > -1 && endIdx > startIdx); - p_template.remove(startIdx, endIdx + endMark.size() - startIdx); +void HtmlTemplateHelper::fillOutlinePanel(QString &p_template, WebResource &p_exportResource, + bool p_addOutlinePanel) { + for (auto &ele : p_exportResource.m_resources) { + if (ele.m_name == QStringLiteral("outline")) { + ele.m_enabled = p_addOutlinePanel; + break; } + } + + // Remove static content to make the page clean. + if (!p_addOutlinePanel) { + int startIdx = p_template.indexOf(""); + QString endMark(""); + int endIdx = p_template.lastIndexOf(endMark); + Q_ASSERT(startIdx > -1 && endIdx > startIdx); + p_template.remove(startIdx, endIdx + endMark.size() - startIdx); + + startIdx = p_template.indexOf(""); + endMark = ""; + endIdx = p_template.lastIndexOf(endMark); + Q_ASSERT(startIdx > -1 && endIdx > startIdx); + p_template.remove(startIdx, endIdx + endMark.size() - startIdx); + } } -void HtmlTemplateHelper::fillTitle(QString &p_template, const QString &p_title) -{ - if (!p_title.isEmpty()) { - p_template.replace("", - QStringLiteral("%1").arg(HtmlUtils::escapeHtml(p_title))); - } +void HtmlTemplateHelper::fillTitle(QString &p_template, const QString &p_title) { + if (!p_title.isEmpty()) { + p_template.replace("", + QStringLiteral("%1").arg(HtmlUtils::escapeHtml(p_title))); + } } -void HtmlTemplateHelper::fillStyleContent(QString &p_template, const QString &p_styles) -{ - p_template.replace("/* VX_STYLES_CONTENT_PLACEHOLDER */", p_styles); +void HtmlTemplateHelper::fillStyleContent(QString &p_template, const QString &p_styles) { + p_template.replace("/* VX_STYLES_CONTENT_PLACEHOLDER */", p_styles); } -void HtmlTemplateHelper::fillHeadContent(QString &p_template, const QString &p_head) -{ - p_template.replace("", p_head); +void HtmlTemplateHelper::fillHeadContent(QString &p_template, const QString &p_head) { + p_template.replace("", p_head); } -void HtmlTemplateHelper::fillContent(QString &p_template, const QString &p_content) -{ - p_template.replace("", p_content); +void HtmlTemplateHelper::fillContent(QString &p_template, const QString &p_content) { + p_template.replace("", p_content); } -void HtmlTemplateHelper::fillBodyClassList(QString &p_template, const QString &p_classList) -{ - p_template.replace("", p_classList); +void HtmlTemplateHelper::fillBodyClassList(QString &p_template, const QString &p_classList) { + p_template.replace("", p_classList); } -QString HtmlTemplateHelper::errorPage() -{ - return VNoteX::tr("Failed to load HTML template. Check the logs for details. " - "Try deleting the user configuration file and the default configuration file."); +QString HtmlTemplateHelper::errorPage() { + return VNoteX::tr("Failed to load HTML template. Check the logs for details. " + "Try deleting the user configuration file and the default configuration file."); } -const QString &HtmlTemplateHelper::getPdfViewerTemplate() -{ - return s_pdfViewerTemplate.m_template; -} +const QString &HtmlTemplateHelper::getPdfViewerTemplate() { return s_pdfViewerTemplate.m_template; } -const QString &HtmlTemplateHelper::getPdfViewerTemplatePath() -{ - return s_pdfViewerTemplate.m_templatePath; +const QString &HtmlTemplateHelper::getPdfViewerTemplatePath() { + return s_pdfViewerTemplate.m_templatePath; } -void HtmlTemplateHelper::updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force) -{ - if (!p_force && p_config.revision() == s_pdfViewerTemplate.m_revision) { - return; - } +void HtmlTemplateHelper::updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force) { + if (!p_force && p_config.revision() == s_pdfViewerTemplate.m_revision) { + return; + } - s_pdfViewerTemplate.m_revision = p_config.revision(); - generatePdfViewerTemplate(p_config, s_pdfViewerTemplate); + s_pdfViewerTemplate.m_revision = p_config.revision(); + generatePdfViewerTemplate(p_config, s_pdfViewerTemplate); } -void HtmlTemplateHelper::generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template) -{ - const auto &viewerResource = p_config.getViewerResource(); - p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template); - try { - p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath); - } catch (Exception &p_e) { - qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what(); - p_template.m_template = errorPage(); - return; - } - - fillResources(p_template.m_template, viewerResource); +void HtmlTemplateHelper::generatePdfViewerTemplate(const PdfViewerConfig &p_config, + Template &p_template) { + const auto &viewerResource = p_config.getViewerResource(); + p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template); + try { + p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath); + } catch (Exception &p_e) { + qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what(); + p_template.m_template = errorPage(); + return; + } + + fillResources(p_template.m_template, viewerResource); } -const QString &HtmlTemplateHelper::getMindMapEditorTemplate() -{ - return s_mindMapEditorTemplate.m_template; +const QString &HtmlTemplateHelper::getMindMapEditorTemplate() { + return s_mindMapEditorTemplate.m_template; } -void HtmlTemplateHelper::updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, bool p_force) -{ - if (!p_force && p_config.revision() == s_mindMapEditorTemplate.m_revision) { - return; - } +void HtmlTemplateHelper::updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, + bool p_force) { + if (!p_force && p_config.revision() == s_mindMapEditorTemplate.m_revision) { + return; + } - s_mindMapEditorTemplate.m_revision = p_config.revision(); + s_mindMapEditorTemplate.m_revision = p_config.revision(); - generateMindMapEditorTemplate(p_config, - QString() /* Use empty theme style for now */, - s_mindMapEditorTemplate); + generateMindMapEditorTemplate(p_config, QString() /* Use empty theme style for now */, + s_mindMapEditorTemplate); } void HtmlTemplateHelper::generateMindMapEditorTemplate(const MindMapEditorConfig &p_config, const QString &p_webStyleSheetFile, - Template& p_template) -{ - const auto &editorResource = p_config.getEditorResource(); - p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(editorResource.m_template); - try { - p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath); - } catch (Exception &p_e) { - qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what(); - p_template.m_template = errorPage(); - return; - } - - fillThemeStyles(p_template.m_template, p_webStyleSheetFile, QString()); - - fillResources(p_template.m_template, editorResource); + Template &p_template) { + const auto &editorResource = p_config.getEditorResource(); + p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(editorResource.m_template); + try { + p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath); + } catch (Exception &p_e) { + qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what(); + p_template.m_template = errorPage(); + return; + } + + fillThemeStyles(p_template.m_template, p_webStyleSheetFile, QString()); + + fillResources(p_template.m_template, editorResource); } diff --git a/src/core/htmltemplatehelper.h b/src/core/htmltemplatehelper.h index 2bc1b121a3..307a07a8b7 100644 --- a/src/core/htmltemplatehelper.h +++ b/src/core/htmltemplatehelper.h @@ -3,149 +3,148 @@ #include -namespace vnotex -{ - class MarkdownEditorConfig; - class PdfViewerConfig; - class MindMapEditorConfig; - struct WebResource; +namespace vnotex { +class MarkdownEditorConfig; +class PdfViewerConfig; +class MindMapEditorConfig; +struct WebResource; - // Global options to be passed to Web side at the very beginning for Markdown. - struct MarkdownWebGlobalOptions - { - bool m_webPlantUml = true; +// Global options to be passed to Web side at the very beginning for Markdown. +struct MarkdownWebGlobalOptions { + bool m_webPlantUml = true; - QString m_plantUmlWebService; + QString m_plantUmlWebService; - bool m_webGraphviz = true; + bool m_webGraphviz = true; - QString m_mathJaxScript; + QString m_mathJaxScript; - bool m_sectionNumberEnabled = true; + bool m_sectionNumberEnabled = true; - int m_sectionNumberBaseLevel = 2; + int m_sectionNumberBaseLevel = 2; - bool m_constrainImageWidthEnabled = true; + bool m_constrainImageWidthEnabled = true; - bool m_imageAlignCenterEnabled = true; + bool m_imageAlignCenterEnabled = true; - bool m_protectFromXss = false; + bool m_protectFromXss = false; - bool m_htmlTagEnabled = true; + bool m_htmlTagEnabled = true; - bool m_autoBreakEnabled = false; + bool m_autoBreakEnabled = false; - bool m_linkifyEnabled = true; + bool m_linkifyEnabled = true; - bool m_indentFirstLineEnabled = false; + bool m_indentFirstLineEnabled = false; - bool m_codeBlockLineNumberEnabled = true; + bool m_codeBlockLineNumberEnabled = true; - // Force to use transparent background. - bool m_transparentBackgroundEnabled = false; + // Force to use transparent background. + bool m_transparentBackgroundEnabled = false; - // Whether the content elements are scrollable. Like PDF, it is false. - bool m_scrollable = true; + // Whether the content elements are scrollable. Like PDF, it is false. + bool m_scrollable = true; - int m_bodyWidth = -1; + int m_bodyWidth = -1; - int m_bodyHeight = -1; + int m_bodyHeight = -1; - // Whether transform inlie SVG to PNG. - // For wkhtmltopdf converter, it could not render some inline SVG correctly. - // This is just a hint not mandatory. For now, PlantUML and Graphviz needs this. - bool m_transformSvgToPngEnabled = false; + // Whether transform inlie SVG to PNG. + // For wkhtmltopdf converter, it could not render some inline SVG correctly. + // This is just a hint not mandatory. For now, PlantUML and Graphviz needs this. + bool m_transformSvgToPngEnabled = false; - // wkhtmltopdf will make the MathJax formula too small. - qreal m_mathJaxScale = -1; + // wkhtmltopdf will make the MathJax formula too small. + qreal m_mathJaxScale = -1; - // Whether remove the tool bar of code blocks added by Prism.js. - bool m_removeCodeToolBarEnabled = false; + // Whether remove the tool bar of code blocks added by Prism.js. + bool m_removeCodeToolBarEnabled = false; - QString toJavascriptObject() const; - }; + QString toJavascriptObject() const; +}; - // Help to generate and update HTML templates. - class HtmlTemplateHelper - { - public: - struct MarkdownParas - { - QString m_webStyleSheetFile; +// Help to generate and update HTML templates. +class HtmlTemplateHelper { +public: + struct MarkdownParas { + QString m_webStyleSheetFile; - QString m_highlightStyleSheetFile; + QString m_highlightStyleSheetFile; - bool m_transparentBackgroundEnabled = false; + bool m_transparentBackgroundEnabled = false; - bool m_scrollable = true; + bool m_scrollable = true; - int m_bodyWidth = -1; + int m_bodyWidth = -1; - int m_bodyHeight = -1; + int m_bodyHeight = -1; - bool m_transformSvgToPngEnabled = false; + bool m_transformSvgToPngEnabled = false; - qreal m_mathJaxScale = -1; + qreal m_mathJaxScale = -1; - bool m_removeCodeToolBarEnabled = false; - }; + bool m_removeCodeToolBarEnabled = false; + }; - HtmlTemplateHelper() = delete; + HtmlTemplateHelper() = delete; - // For MarkdownViewer. - static const QString &getMarkdownViewerTemplate(); - static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force = false); + // For MarkdownViewer. + static const QString &getMarkdownViewerTemplate(); + static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, + bool p_force = false); - static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const MarkdownParas &p_paras); + static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, + const MarkdownParas &p_paras); - static QString generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config, - bool p_addOutlinePanel); + static QString generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config, + bool p_addOutlinePanel); - // For common HTML content manipulation. - static void fillTitle(QString &p_template, const QString &p_title); + // For common HTML content manipulation. + static void fillTitle(QString &p_template, const QString &p_title); - static void fillStyleContent(QString &p_template, const QString &p_styles); + static void fillStyleContent(QString &p_template, const QString &p_styles); - static void fillHeadContent(QString &p_template, const QString &p_head); + static void fillHeadContent(QString &p_template, const QString &p_head); - static void fillContent(QString &p_template, const QString &p_content); + static void fillContent(QString &p_template, const QString &p_content); - static void fillBodyClassList(QString &p_template, const QString &p_classList); + static void fillBodyClassList(QString &p_template, const QString &p_classList); - static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel); + static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, + bool p_addOutlinePanel); - // For PdfViewer. - static const QString &getPdfViewerTemplate(); - static void updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force = false); + // For PdfViewer. + static const QString &getPdfViewerTemplate(); + static void updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force = false); - static const QString &getPdfViewerTemplatePath(); + static const QString &getPdfViewerTemplatePath(); - // For MindMapEditor. - static const QString &getMindMapEditorTemplate(); - static void updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, bool p_force = false); + // For MindMapEditor. + static const QString &getMindMapEditorTemplate(); + static void updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, + bool p_force = false); - private: - struct Template - { - int m_revision = -1; - QString m_template; - QString m_templatePath; - }; +private: + struct Template { + int m_revision = -1; + QString m_template; + QString m_templatePath; + }; - static QString errorPage(); + static QString errorPage(); - static void generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template); + static void generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template &p_template); - static void generateMindMapEditorTemplate(const MindMapEditorConfig &p_config, - const QString &p_webStyleSheetFile, - Template& p_template); + static void generateMindMapEditorTemplate(const MindMapEditorConfig &p_config, + const QString &p_webStyleSheetFile, + Template &p_template); - static Template s_markdownViewerTemplate; + static Template s_markdownViewerTemplate; - static Template s_pdfViewerTemplate; + static Template s_pdfViewerTemplate; - static Template s_mindMapEditorTemplate; - }; -} + static Template s_mindMapEditorTemplate; +}; +} // namespace vnotex #endif // HTMLTEMPLATEHELPER_H diff --git a/src/core/iconfig.h b/src/core/iconfig.h index d7dad076e4..0508fa839c 100644 --- a/src/core/iconfig.h +++ b/src/core/iconfig.h @@ -1,249 +1,189 @@ #ifndef ICONFIG_H #define ICONFIG_H -#include -#include -#include #include #include #include +#include +#include +#include -namespace vnotex -{ - class ConfigMgr; - - // Interface for Config. - class IConfig - { - public: - IConfig(ConfigMgr *p_mgr, IConfig *p_topConfig = nullptr) - : m_topConfig(p_topConfig), - m_mgr(p_mgr) - { - } - - virtual ~IConfig() - { - } - - // Called to init top level config. - virtual void init() - { - Q_ASSERT(false); - } - - // Init from QJsonObject. - virtual void init(const QJsonObject &p_default, const QJsonObject &p_user) - { - Q_UNUSED(p_default); - Q_UNUSED(p_user); - Q_ASSERT(false); - } - - virtual void writeToSettings() const - { - Q_ASSERT(m_topConfig); - m_topConfig->writeToSettings(); - } - - virtual QJsonObject toJson() const = 0; - - const QString &getSessionName() const - { - return m_sessionName; - } - - virtual int revision() const - { - return m_revision; - } - - void update() - { - ++m_revision; - writeToSettings(); - } - - protected: - ConfigMgr *getMgr() const - { - return m_mgr; - } - - // First read user config, then the default config. - static QJsonValue read(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - auto it = p_user.find(p_key); - if (it != p_user.end()) { - return it.value(); - } else { - return p_default.value(p_key); - } - } - - static QString readString(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - return read(p_default, p_user, p_key).toString(); - } - - static QStringList readStringList(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - auto arr = read(p_default, p_user, p_key).toArray(); - QStringList res; - res.reserve(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - res.push_back(arr[i].toString()); - } - return res; - } - - static QStringList readStringList(const QJsonObject &p_obj, - const QString &p_key) - { - auto arr = p_obj.value(p_key).toArray(); - QStringList res; - res.reserve(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - res.push_back(arr[i].toString()); - } - return res; - } - - static void writeStringList(QJsonObject &p_obj, - const QString &p_key, - const QStringList &p_list) - { - QJsonArray arr; - for (const auto &ele : p_list) { - arr.push_back(ele); - } - - p_obj[p_key] = arr; - } - - static QString readString(const QJsonObject &p_obj, - const QString &p_key) - { - return p_obj.value(p_key).toString(); - } - - static QByteArray readByteArray(const QJsonObject &p_obj, - const QString &p_key) - { - return QByteArray::fromBase64(readString(p_obj, p_key).toLatin1()); - } - - static void writeByteArray(QJsonObject &p_obj, - const QString &p_key, - const QByteArray &p_bytes) - { - p_obj.insert(p_key, QLatin1String(p_bytes.toBase64())); - } - - static QBitArray readBitArray(const QJsonObject &p_obj, - const QString &p_key) - { - auto bytes = readByteArray(p_obj, p_key); - if (bytes.isEmpty()) { - return QBitArray(); - } - - QDataStream ds(bytes); - ds.setVersion(QDataStream::Qt_5_12); - - QBitArray bits; - ds >> bits; - return bits; - } - - static void writeBitArray(QJsonObject &p_obj, - const QString &p_key, - const QBitArray &p_bits) - { - QByteArray bytes; - QDataStream ds(&bytes, QIODevice::WriteOnly); - ds.setVersion(QDataStream::Qt_5_12); - ds << p_bits; - - writeByteArray(p_obj, p_key, bytes); - } - - static bool readBool(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - return read(p_default, p_user, p_key).toBool(); - } - - static bool readBool(const QJsonObject &p_obj, - const QString &p_key) - { - return p_obj.value(p_key).toBool(); - } - - static int readInt(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - return read(p_default, p_user, p_key).toInt(); - } - - static qreal readReal(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - return read(p_default, p_user, p_key).toDouble(); - } - - static bool isUndefinedKey(const QJsonObject &p_default, - const QJsonObject &p_user, - const QString &p_key) - { - return !p_default.contains(p_key) && !p_user.contains(p_key); - } - - static bool isUndefinedKey(const QJsonObject &p_obj, - const QString &p_key) - { - return !p_obj.contains(p_key); - } - - template - static void updateConfig(T &p_cur, const T &p_new, IConfig *p_config) - { - if (p_cur == p_new) { - return; - } - - ++p_config->m_revision; - p_cur = p_new; - p_config->writeToSettings(); - } - - template - static void updateConfigWithoutCheck(T &p_cur, const T &p_new, IConfig *p_config) - { - ++p_config->m_revision; - p_cur = p_new; - p_config->writeToSettings(); - } - - IConfig *m_topConfig = nullptr; - - QString m_sessionName; - - // Used to indicate whether there is change after last read. - int m_revision = 0; - - private: - ConfigMgr *m_mgr = nullptr; - }; -} // ns vnotex +namespace vnotex { +class ConfigMgr; + +// Interface for Config. +class IConfig { +public: + IConfig(ConfigMgr *p_mgr, IConfig *p_topConfig = nullptr) + : m_topConfig(p_topConfig), m_mgr(p_mgr) {} + + virtual ~IConfig() {} + + // Called to init top level config. + virtual void init() { Q_ASSERT(false); } + + // Init from QJsonObject. + virtual void init(const QJsonObject &p_default, const QJsonObject &p_user) { + Q_UNUSED(p_default); + Q_UNUSED(p_user); + Q_ASSERT(false); + } + + virtual void writeToSettings() const { + Q_ASSERT(m_topConfig); + m_topConfig->writeToSettings(); + } + + virtual QJsonObject toJson() const = 0; + + const QString &getSessionName() const { return m_sessionName; } + + virtual int revision() const { return m_revision; } + + void update() { + ++m_revision; + writeToSettings(); + } + +protected: + ConfigMgr *getMgr() const { return m_mgr; } + + // First read user config, then the default config. + static QJsonValue read(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + auto it = p_user.find(p_key); + if (it != p_user.end()) { + return it.value(); + } else { + return p_default.value(p_key); + } + } + + static QString readString(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + return read(p_default, p_user, p_key).toString(); + } + + static QStringList readStringList(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + auto arr = read(p_default, p_user, p_key).toArray(); + QStringList res; + res.reserve(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + res.push_back(arr[i].toString()); + } + return res; + } + + static QStringList readStringList(const QJsonObject &p_obj, const QString &p_key) { + auto arr = p_obj.value(p_key).toArray(); + QStringList res; + res.reserve(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + res.push_back(arr[i].toString()); + } + return res; + } + + static void writeStringList(QJsonObject &p_obj, const QString &p_key, const QStringList &p_list) { + QJsonArray arr; + for (const auto &ele : p_list) { + arr.push_back(ele); + } + + p_obj[p_key] = arr; + } + + static QString readString(const QJsonObject &p_obj, const QString &p_key) { + return p_obj.value(p_key).toString(); + } + + static QByteArray readByteArray(const QJsonObject &p_obj, const QString &p_key) { + return QByteArray::fromBase64(readString(p_obj, p_key).toLatin1()); + } + + static void writeByteArray(QJsonObject &p_obj, const QString &p_key, const QByteArray &p_bytes) { + p_obj.insert(p_key, QLatin1String(p_bytes.toBase64())); + } + + static QBitArray readBitArray(const QJsonObject &p_obj, const QString &p_key) { + auto bytes = readByteArray(p_obj, p_key); + if (bytes.isEmpty()) { + return QBitArray(); + } + + QDataStream ds(bytes); + ds.setVersion(QDataStream::Qt_5_12); + + QBitArray bits; + ds >> bits; + return bits; + } + + static void writeBitArray(QJsonObject &p_obj, const QString &p_key, const QBitArray &p_bits) { + QByteArray bytes; + QDataStream ds(&bytes, QIODevice::WriteOnly); + ds.setVersion(QDataStream::Qt_5_12); + ds << p_bits; + + writeByteArray(p_obj, p_key, bytes); + } + + static bool readBool(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + return read(p_default, p_user, p_key).toBool(); + } + + static bool readBool(const QJsonObject &p_obj, const QString &p_key) { + return p_obj.value(p_key).toBool(); + } + + static int readInt(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + return read(p_default, p_user, p_key).toInt(); + } + + static qreal readReal(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + return read(p_default, p_user, p_key).toDouble(); + } + + static bool isUndefinedKey(const QJsonObject &p_default, const QJsonObject &p_user, + const QString &p_key) { + return !p_default.contains(p_key) && !p_user.contains(p_key); + } + + static bool isUndefinedKey(const QJsonObject &p_obj, const QString &p_key) { + return !p_obj.contains(p_key); + } + + template static void updateConfig(T &p_cur, const T &p_new, IConfig *p_config) { + if (p_cur == p_new) { + return; + } + + ++p_config->m_revision; + p_cur = p_new; + p_config->writeToSettings(); + } + + template + static void updateConfigWithoutCheck(T &p_cur, const T &p_new, IConfig *p_config) { + ++p_config->m_revision; + p_cur = p_new; + p_config->writeToSettings(); + } + + IConfig *m_topConfig = nullptr; + + QString m_sessionName; + + // Used to indicate whether there is change after last read. + int m_revision = 0; + +private: + ConfigMgr *m_mgr = nullptr; +}; +} // namespace vnotex #endif // ICONFIG_H diff --git a/src/core/location.h b/src/core/location.h index 31b40e7959..98a0517f54 100644 --- a/src/core/location.h +++ b/src/core/location.h @@ -5,75 +5,58 @@ #include "global.h" -namespace vnotex -{ - struct Location - { - friend QDebug operator<<(QDebug p_dbg, const Location &p_loc) - { - QDebugStateSaver saver(p_dbg); - p_dbg.nospace() << p_loc.m_path << ":" << p_loc.m_lineNumber; - return p_dbg; - } - - // TODO: support encoding like buffer/notebook. - QString m_path; - - QString m_displayPath; - - // 0-based. - int m_lineNumber = -1; - }; - - enum class LocationType - { - Buffer, - File, - Folder, - Notebook - }; - - struct ComplexLocation - { - struct Line - { - Line() = default; - - Line(int p_lineNumber, const QString &p_text, const QList &p_segments) - : m_lineNumber(p_lineNumber), - m_text(p_text), - m_segments(p_segments) - { - } - - // 0-based. - int m_lineNumber = -1; - - QString m_text; - - QList m_segments; - }; - - void addLine(int p_lineNumber, const QString &p_text, const QList &p_segments) - { - m_lines.push_back(Line(p_lineNumber, p_text, p_segments)); - } - - friend QDebug operator<<(QDebug p_dbg, const ComplexLocation &p_loc) - { - QDebugStateSaver saver(p_dbg); - p_dbg.nospace() << static_cast(p_loc.m_type) << p_loc.m_path << p_loc.m_displayPath; - return p_dbg; - } - - LocationType m_type = LocationType::File; - - QString m_path; - - QString m_displayPath; - - QVector m_lines; - }; -} +namespace vnotex { +struct Location { + friend QDebug operator<<(QDebug p_dbg, const Location &p_loc) { + QDebugStateSaver saver(p_dbg); + p_dbg.nospace() << p_loc.m_path << ":" << p_loc.m_lineNumber; + return p_dbg; + } + + // TODO: support encoding like buffer/notebook. + QString m_path; + + QString m_displayPath; + + // 0-based. + int m_lineNumber = -1; +}; + +enum class LocationType { Buffer, File, Folder, Notebook }; + +struct ComplexLocation { + struct Line { + Line() = default; + + Line(int p_lineNumber, const QString &p_text, const QList &p_segments) + : m_lineNumber(p_lineNumber), m_text(p_text), m_segments(p_segments) {} + + // 0-based. + int m_lineNumber = -1; + + QString m_text; + + QList m_segments; + }; + + void addLine(int p_lineNumber, const QString &p_text, const QList &p_segments) { + m_lines.push_back(Line(p_lineNumber, p_text, p_segments)); + } + + friend QDebug operator<<(QDebug p_dbg, const ComplexLocation &p_loc) { + QDebugStateSaver saver(p_dbg); + p_dbg.nospace() << static_cast(p_loc.m_type) << p_loc.m_path << p_loc.m_displayPath; + return p_dbg; + } + + LocationType m_type = LocationType::File; + + QString m_path; + + QString m_displayPath; + + QVector m_lines; +}; +} // namespace vnotex #endif // LOCATION_H diff --git a/src/core/logger.cpp b/src/core/logger.cpp index 1fc7305002..12d6cc873b 100644 --- a/src/core/logger.cpp +++ b/src/core/logger.cpp @@ -1,8 +1,8 @@ #include "logger.h" +#include "configmgr.h" #include #include -#include "configmgr.h" using namespace vnotex; @@ -12,115 +12,112 @@ bool Logger::s_verbose = false; bool Logger::s_logToStderr = false; -void Logger::init(bool p_verbose, bool p_logToStderr) -{ - s_verbose = p_verbose; - s_logToStderr = p_logToStderr; +void Logger::init(bool p_verbose, bool p_logToStderr) { + s_verbose = p_verbose; + s_logToStderr = p_logToStderr; #if defined(QT_NO_DEBUG) - if (!s_logToStderr) { - s_file.setFileName(ConfigMgr::getInst().getLogFile()); - if (s_file.size() >= 5 * 1024 * 1024) { - s_file.open(QIODevice::WriteOnly | QIODevice::Text); - } else { - s_file.open(QIODevice::Append | QIODevice::Text); - } + if (!s_logToStderr) { + s_file.setFileName(ConfigMgr::getInst().getLogFile()); + if (s_file.size() >= 5 * 1024 * 1024) { + s_file.open(QIODevice::WriteOnly | QIODevice::Text); + } else { + s_file.open(QIODevice::Append | QIODevice::Text); } + } #else - // Always log to stderr in debug. - s_logToStderr = true; + // Always log to stderr in debug. + s_logToStderr = true; #endif - qInstallMessageHandler(Logger::log); + qInstallMessageHandler(Logger::log); } -static QString getFileName(const char *p_file) -{ - QString file(p_file); - int idx = file.lastIndexOf(QChar('/')); - if (idx == -1) { - idx = file.lastIndexOf(QChar('\\')); - } - - if (idx == -1) { - return file; - } else { - return file.mid(idx + 1); - } +static QString getFileName(const char *p_file) { + QString file(p_file); + int idx = file.lastIndexOf(QChar('/')); + if (idx == -1) { + idx = file.lastIndexOf(QChar('\\')); + } + + if (idx == -1) { + return file; + } else { + return file.mid(idx + 1); + } } -void Logger::log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg) -{ +void Logger::log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg) { #if defined(QT_NO_DEBUG) - if (!s_verbose && p_type == QtDebugMsg) { - return; - } + if (!s_verbose && p_type == QtDebugMsg) { + return; + } #endif - QByteArray localMsg = p_msg.toUtf8(); - QString header; + QByteArray localMsg = p_msg.toUtf8(); + QString header; - switch (p_type) { - case QtDebugMsg: - header = QStringLiteral("Debug:"); - break; + switch (p_type) { + case QtDebugMsg: + header = QStringLiteral("Debug:"); + break; - case QtInfoMsg: - header = QStringLiteral("Info:"); - break; + case QtInfoMsg: + header = QStringLiteral("Info:"); + break; - case QtWarningMsg: - header = QStringLiteral("Warning:"); - break; + case QtWarningMsg: + header = QStringLiteral("Warning:"); + break; - case QtCriticalMsg: - header = QStringLiteral("Critical:"); - break; + case QtCriticalMsg: + header = QStringLiteral("Critical:"); + break; - case QtFatalMsg: - header = QStringLiteral("Fatal:"); - break; - } + case QtFatalMsg: + header = QStringLiteral("Fatal:"); + break; + } - QString fileName = getFileName(p_context.file); + QString fileName = getFileName(p_context.file); - if (!s_logToStderr) { - QTextStream stream(&s_file); - stream << header << (QStringLiteral("(%1:%2) ").arg(fileName).arg(p_context.line)) - << localMsg << "\n"; + if (!s_logToStderr) { + QTextStream stream(&s_file); + stream << header << (QStringLiteral("(%1:%2) ").arg(fileName).arg(p_context.line)) << localMsg + << "\n"; - if (p_type == QtFatalMsg) { - s_file.close(); - abort(); - } - } else { - std::string fileStr = fileName.toStdString(); - const char *file = fileStr.c_str(); - - switch (p_type) { - case QtDebugMsg: - fprintf(stderr, "%s(%s:%u) %s\n", - header.toStdString().c_str(), file, p_context.line, localMsg.constData()); - break; - case QtInfoMsg: - fprintf(stderr, "%s(%s:%u) %s\n", - header.toStdString().c_str(), file, p_context.line, localMsg.constData()); - break; - case QtWarningMsg: - fprintf(stderr, "%s(%s:%u) %s\n", - header.toStdString().c_str(), file, p_context.line, localMsg.constData()); - break; - case QtCriticalMsg: - fprintf(stderr, "%s(%s:%u) %s\n", - header.toStdString().c_str(), file, p_context.line, localMsg.constData()); - break; - case QtFatalMsg: - fprintf(stderr, "%s(%s:%u) %s\n", - header.toStdString().c_str(), file, p_context.line, localMsg.constData()); - abort(); - break; - } - - fflush(stderr); + if (p_type == QtFatalMsg) { + s_file.close(); + abort(); + } + } else { + std::string fileStr = fileName.toStdString(); + const char *file = fileStr.c_str(); + + switch (p_type) { + case QtDebugMsg: + fprintf(stderr, "%s(%s:%u) %s\n", header.toStdString().c_str(), file, p_context.line, + localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stderr, "%s(%s:%u) %s\n", header.toStdString().c_str(), file, p_context.line, + localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "%s(%s:%u) %s\n", header.toStdString().c_str(), file, p_context.line, + localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "%s(%s:%u) %s\n", header.toStdString().c_str(), file, p_context.line, + localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "%s(%s:%u) %s\n", header.toStdString().c_str(), file, p_context.line, + localMsg.constData()); + abort(); + break; } + + fflush(stderr); + } } diff --git a/src/core/logger.h b/src/core/logger.h index e19b421381..6a5f12d7fb 100644 --- a/src/core/logger.h +++ b/src/core/logger.h @@ -1,29 +1,27 @@ #ifndef LOGGER_H #define LOGGER_H -#include #include +#include class QFile; -namespace vnotex -{ - class Logger - { - public: - Logger() = delete; +namespace vnotex { +class Logger { +public: + Logger() = delete; - static void init(bool p_verbose, bool p_logToStderr); + static void init(bool p_verbose, bool p_logToStderr); - private: - static void log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg); +private: + static void log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg); - static QFile s_file; + static QFile s_file; - static bool s_verbose; + static bool s_verbose; - static bool s_logToStderr; - }; -} + static bool s_logToStderr; +}; +} // namespace vnotex #endif // LOGGER_H diff --git a/src/core/mainconfig.cpp b/src/core/mainconfig.cpp index a9e7254c90..c455a74ad8 100644 --- a/src/core/mainconfig.cpp +++ b/src/core/mainconfig.cpp @@ -1,122 +1,92 @@ #include "mainconfig.h" -#include #include +#include #include "configmgr.h" #include "coreconfig.h" #include "editorconfig.h" -#include "widgetconfig.h" -#include "texteditorconfig.h" #include "markdowneditorconfig.h" +#include "texteditorconfig.h" +#include "widgetconfig.h" using namespace vnotex; bool MainConfig::s_versionChanged = false; MainConfig::MainConfig(ConfigMgr *p_mgr) - : IConfig(p_mgr, nullptr), - m_coreConfig(new CoreConfig(p_mgr, this)), - m_editorConfig(new EditorConfig(p_mgr, this)), - m_widgetConfig(new WidgetConfig(p_mgr, this)) -{ + : IConfig(p_mgr, nullptr), m_coreConfig(new CoreConfig(p_mgr, this)), + m_editorConfig(new EditorConfig(p_mgr, this)), m_widgetConfig(new WidgetConfig(p_mgr, this)) { } -MainConfig::~MainConfig() -{ - -} +MainConfig::~MainConfig() {} -void MainConfig::init() -{ - auto mgr = getMgr(); - auto appSettings = mgr->getSettings(ConfigMgr::Source::App); - auto userSettings = mgr->getSettings(ConfigMgr::Source::User); - const auto &appJobj = appSettings->getJson(); - const auto &userJobj = userSettings->getJson(); +void MainConfig::init() { + auto mgr = getMgr(); + auto appSettings = mgr->getSettings(ConfigMgr::Source::App); + auto userSettings = mgr->getSettings(ConfigMgr::Source::User); + const auto &appJobj = appSettings->getJson(); + const auto &userJobj = userSettings->getJson(); - loadMetadata(appJobj, userJobj); + loadMetadata(appJobj, userJobj); - m_coreConfig->init(appJobj, userJobj); + m_coreConfig->init(appJobj, userJobj); - m_editorConfig->init(appJobj, userJobj); + m_editorConfig->init(appJobj, userJobj); - m_widgetConfig->init(appJobj, userJobj); + m_widgetConfig->init(appJobj, userJobj); - if (isVersionChanged()) { - doVersionSpecificOverride(); + if (isVersionChanged()) { + doVersionSpecificOverride(); - // Update user config. - writeToSettings(); - } + // Update user config. + writeToSettings(); + } } -void MainConfig::loadMetadata(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(QStringLiteral("metadata")).toObject(); - const auto userObj = p_user.value(QStringLiteral("metadata")).toObject(); +void MainConfig::loadMetadata(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(QStringLiteral("metadata")).toObject(); + const auto userObj = p_user.value(QStringLiteral("metadata")).toObject(); - m_version = appObj.value(QStringLiteral("version")).toString(); - m_userVersion = userObj.value(QStringLiteral("version")).toString(); - s_versionChanged = m_version != m_userVersion; - qDebug() << "version" << m_version << "user version" << m_userVersion; + m_version = appObj.value(QStringLiteral("version")).toString(); + m_userVersion = userObj.value(QStringLiteral("version")).toString(); + s_versionChanged = m_version != m_userVersion; + qDebug() << "version" << m_version << "user version" << m_userVersion; } -QJsonObject MainConfig::saveMetaData() const -{ - QJsonObject metaObj; - metaObj[QStringLiteral("version")] = m_version; +QJsonObject MainConfig::saveMetaData() const { + QJsonObject metaObj; + metaObj[QStringLiteral("version")] = m_version; - return metaObj; + return metaObj; } -bool MainConfig::isVersionChanged() -{ - return s_versionChanged; -} +bool MainConfig::isVersionChanged() { return s_versionChanged; } -CoreConfig &MainConfig::getCoreConfig() -{ - return *m_coreConfig; -} +CoreConfig &MainConfig::getCoreConfig() { return *m_coreConfig; } -EditorConfig &MainConfig::getEditorConfig() -{ - return *m_editorConfig; -} +EditorConfig &MainConfig::getEditorConfig() { return *m_editorConfig; } -WidgetConfig &MainConfig::getWidgetConfig() -{ - return *m_widgetConfig; -} +WidgetConfig &MainConfig::getWidgetConfig() { return *m_widgetConfig; } -void MainConfig::writeToSettings() const -{ - getMgr()->writeUserSettings(toJson()); -} +void MainConfig::writeToSettings() const { getMgr()->writeUserSettings(toJson()); } -QJsonObject MainConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("metadata")] = saveMetaData(); - obj[m_coreConfig->getSessionName()] = m_coreConfig->toJson(); - obj[m_editorConfig->getSessionName()] = m_editorConfig->toJson(); - obj[m_widgetConfig->getSessionName()] = m_widgetConfig->toJson(); - return obj; +QJsonObject MainConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("metadata")] = saveMetaData(); + obj[m_coreConfig->getSessionName()] = m_coreConfig->toJson(); + obj[m_editorConfig->getSessionName()] = m_editorConfig->toJson(); + obj[m_widgetConfig->getSessionName()] = m_widgetConfig->toJson(); + return obj; } -const QString &MainConfig::getVersion() const -{ - return m_version; -} +const QString &MainConfig::getVersion() const { return m_version; } -QString MainConfig::getVersion(const QJsonObject &p_jobj) -{ - const auto metadataObj = p_jobj.value(QStringLiteral("metadata")).toObject(); - return metadataObj.value(QStringLiteral("version")).toString(); +QString MainConfig::getVersion(const QJsonObject &p_jobj) { + const auto metadataObj = p_jobj.value(QStringLiteral("metadata")).toObject(); + return metadataObj.value(QStringLiteral("version")).toString(); } -void MainConfig::doVersionSpecificOverride() -{ - // In a new version, we may want to change one value by force. +void MainConfig::doVersionSpecificOverride() { + // In a new version, we may want to change one value by force. } diff --git a/src/core/mainconfig.h b/src/core/mainconfig.h index 9b9ccf4836..ed6ad37fc5 100644 --- a/src/core/mainconfig.h +++ b/src/core/mainconfig.h @@ -3,63 +3,61 @@ #include "iconfig.h" -#include #include +#include class QJsonObject; -namespace vnotex -{ - class CoreConfig; - class EditorConfig; - class WidgetConfig; +namespace vnotex { +class CoreConfig; +class EditorConfig; +class WidgetConfig; - class MainConfig : public IConfig - { - public: - explicit MainConfig(ConfigMgr *p_mgr); +class MainConfig : public IConfig { +public: + explicit MainConfig(ConfigMgr *p_mgr); - ~MainConfig(); + ~MainConfig(); - void init() Q_DECL_OVERRIDE; + void init() Q_DECL_OVERRIDE; - const QString &getVersion() const; + const QString &getVersion() const; - CoreConfig &getCoreConfig(); + CoreConfig &getCoreConfig(); - EditorConfig &getEditorConfig(); + EditorConfig &getEditorConfig(); - WidgetConfig &getWidgetConfig(); + WidgetConfig &getWidgetConfig(); - void writeToSettings() const Q_DECL_OVERRIDE; + void writeToSettings() const Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - static QString getVersion(const QJsonObject &p_jobj); + static QString getVersion(const QJsonObject &p_jobj); - static bool isVersionChanged(); + static bool isVersionChanged(); - private: - void loadMetadata(const QJsonObject &p_app, const QJsonObject &p_user); +private: + void loadMetadata(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveMetaData() const; + QJsonObject saveMetaData() const; - void doVersionSpecificOverride(); + void doVersionSpecificOverride(); - // Version of VNoteX. - QString m_version; + // Version of VNoteX. + QString m_version; - // Version of user's configuration. - QString m_userVersion; + // Version of user's configuration. + QString m_userVersion; - QScopedPointer m_coreConfig; + QScopedPointer m_coreConfig; - QScopedPointer m_editorConfig; + QScopedPointer m_editorConfig; - QScopedPointer m_widgetConfig; + QScopedPointer m_widgetConfig; - static bool s_versionChanged; - }; -} // ns vnotex + static bool s_versionChanged; +}; +} // namespace vnotex #endif // MAINCONFIG_H diff --git a/src/core/markdowneditorconfig.cpp b/src/core/markdowneditorconfig.cpp index 7b6cef9c8b..1b65021d5c 100644 --- a/src/core/markdowneditorconfig.cpp +++ b/src/core/markdowneditorconfig.cpp @@ -2,8 +2,8 @@ #include -#include "texteditorconfig.h" #include "mainconfig.h" +#include "texteditorconfig.h" using namespace vnotex; @@ -12,595 +12,473 @@ using namespace vnotex; #define READREAL(key) readReal(appObj, userObj, (key)) #define READINT(key) readInt(appObj, userObj, (key)) -MarkdownEditorConfig::MarkdownEditorConfig(ConfigMgr *p_mgr, - IConfig *p_topConfig, - const QSharedPointer &p_textEditorConfig) - : IConfig(p_mgr, p_topConfig), - m_textEditorConfig(p_textEditorConfig) -{ - m_sessionName = QStringLiteral("markdown_editor"); +MarkdownEditorConfig::MarkdownEditorConfig( + ConfigMgr *p_mgr, IConfig *p_topConfig, + const QSharedPointer &p_textEditorConfig) + : IConfig(p_mgr, p_topConfig), m_textEditorConfig(p_textEditorConfig) { + m_sessionName = QStringLiteral("markdown_editor"); } -void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - loadViewerResource(appObj, userObj); - loadExportResource(appObj, userObj); + loadViewerResource(appObj, userObj); + loadExportResource(appObj, userObj); - m_webPlantUml = READBOOL(QStringLiteral("web_plantuml")); + m_webPlantUml = READBOOL(QStringLiteral("web_plantuml")); - m_plantUmlJar = READSTR(QStringLiteral("plantuml_jar")); + m_plantUmlJar = READSTR(QStringLiteral("plantuml_jar")); - m_plantUmlCommand = READSTR(QStringLiteral("plantuml_command")); + m_plantUmlCommand = READSTR(QStringLiteral("plantuml_command")); - m_plantUmlWebService = READSTR(QStringLiteral("plantuml_web_service")); + m_plantUmlWebService = READSTR(QStringLiteral("plantuml_web_service")); - m_webGraphviz = READBOOL(QStringLiteral("web_graphviz")); + m_webGraphviz = READBOOL(QStringLiteral("web_graphviz")); - m_graphvizExe = READSTR(QStringLiteral("graphviz_exe")); + m_graphvizExe = READSTR(QStringLiteral("graphviz_exe")); - m_mathJaxScript = READSTR(QStringLiteral("mathjax_script")); + m_mathJaxScript = READSTR(QStringLiteral("mathjax_script")); - m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link")); - m_confirmBeforeClearObsoleteImages = READBOOL(QStringLiteral("confirm_before_clear_obsolete_images")); - m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title")); + m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link")); + m_confirmBeforeClearObsoleteImages = + READBOOL(QStringLiteral("confirm_before_clear_obsolete_images")); + m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title")); - m_sectionNumberMode = stringToSectionNumberMode(READSTR(QStringLiteral("section_number"))); - m_sectionNumberBaseLevel = READINT(QStringLiteral("section_number_base_level")); - m_sectionNumberStyle = stringToSectionNumberStyle(READSTR(QStringLiteral("section_number_style"))); + m_sectionNumberMode = stringToSectionNumberMode(READSTR(QStringLiteral("section_number"))); + m_sectionNumberBaseLevel = READINT(QStringLiteral("section_number_base_level")); + m_sectionNumberStyle = + stringToSectionNumberStyle(READSTR(QStringLiteral("section_number_style"))); - m_constrainImageWidthEnabled = READBOOL(QStringLiteral("constrain_image_width")); - m_imageAlignCenterEnabled = READBOOL(QStringLiteral("image_align_center")); - m_constrainInplacePreviewWidthEnabled = READBOOL(QStringLiteral("constrain_inplace_preview_width")); - m_zoomFactorInReadMode = READREAL(QStringLiteral("zoom_factor_in_read_mode")); - m_fetchImagesInParseAndPaste = READBOOL(QStringLiteral("fetch_images_in_parse_and_paste")); + m_constrainImageWidthEnabled = READBOOL(QStringLiteral("constrain_image_width")); + m_imageAlignCenterEnabled = READBOOL(QStringLiteral("image_align_center")); + m_constrainInplacePreviewWidthEnabled = + READBOOL(QStringLiteral("constrain_inplace_preview_width")); + m_zoomFactorInReadMode = READREAL(QStringLiteral("zoom_factor_in_read_mode")); + m_fetchImagesInParseAndPaste = READBOOL(QStringLiteral("fetch_images_in_parse_and_paste")); - m_protectFromXss = READBOOL(QStringLiteral("protect_from_xss")); - m_htmlTagEnabled = READBOOL(QStringLiteral("html_tag")); - m_autoBreakEnabled = READBOOL(QStringLiteral("auto_break")); - m_linkifyEnabled = READBOOL(QStringLiteral("linkify")); - m_indentFirstLineEnabled = READBOOL(QStringLiteral("indent_first_line")); - m_codeBlockLineNumberEnabled = READBOOL(QStringLiteral("code_block_line_number")); + m_protectFromXss = READBOOL(QStringLiteral("protect_from_xss")); + m_htmlTagEnabled = READBOOL(QStringLiteral("html_tag")); + m_autoBreakEnabled = READBOOL(QStringLiteral("auto_break")); + m_linkifyEnabled = READBOOL(QStringLiteral("linkify")); + m_indentFirstLineEnabled = READBOOL(QStringLiteral("indent_first_line")); + m_codeBlockLineNumberEnabled = READBOOL(QStringLiteral("code_block_line_number")); - m_smartTableEnabled = READBOOL(QStringLiteral("smart_table")); - m_smartTableInterval = READINT(QStringLiteral("smart_table_interval")); + m_smartTableEnabled = READBOOL(QStringLiteral("smart_table")); + m_smartTableInterval = READINT(QStringLiteral("smart_table_interval")); - m_spellCheckEnabled = READBOOL(QStringLiteral("spell_check")); + m_spellCheckEnabled = READBOOL(QStringLiteral("spell_check")); - m_editorOverriddenFontFamily = READSTR(QStringLiteral("editor_overridden_font_family")); + m_editorOverriddenFontFamily = READSTR(QStringLiteral("editor_overridden_font_family")); - { - m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; - auto srcs = READSTR(QStringLiteral("inplace_preview_sources")).split(QLatin1Char(';')); - for (const auto &src : srcs) { - m_inplacePreviewSources |= stringToInplacePreviewSource(src); - } + { + m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; + auto srcs = READSTR(QStringLiteral("inplace_preview_sources")).split(QLatin1Char(';')); + for (const auto &src : srcs) { + m_inplacePreviewSources |= stringToInplacePreviewSource(src); } - - m_editViewMode = stringToEditViewMode(READSTR(QStringLiteral("edit_view_mode"))); - - m_richPasteByDefaultEnabled = READBOOL(QStringLiteral("rich_paste_by_default")); -} - -QJsonObject MarkdownEditorConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("viewer_resource")] = saveViewerResource(); - obj[QStringLiteral("export_resource")] = saveExportResource(); - obj[QStringLiteral("web_plantuml")] = m_webPlantUml; - obj[QStringLiteral("plantuml_jar")] = m_plantUmlJar; - obj[QStringLiteral("plantuml_command")] = m_plantUmlCommand; - obj[QStringLiteral("plantuml_web_service")] = m_plantUmlWebService; - obj[QStringLiteral("web_graphviz")] = m_webGraphviz; - obj[QStringLiteral("graphviz_exe")] = m_graphvizExe; - obj[QStringLiteral("mathjax_script")] = m_mathJaxScript; - obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink; - obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages; - obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle; - - obj[QStringLiteral("section_number")] = sectionNumberModeToString(m_sectionNumberMode); - obj[QStringLiteral("section_number_base_level")] = m_sectionNumberBaseLevel; - obj[QStringLiteral("section_number_style")] = sectionNumberStyleToString(m_sectionNumberStyle); - - obj[QStringLiteral("constrain_image_width")] = m_constrainImageWidthEnabled; - obj[QStringLiteral("image_align_center")] = m_imageAlignCenterEnabled; - obj[QStringLiteral("constrain_inplace_preview_width")] = m_constrainInplacePreviewWidthEnabled; - obj[QStringLiteral("zoom_factor_in_read_mode")] = m_zoomFactorInReadMode; - obj[QStringLiteral("fetch_images_in_parse_and_paste")] = m_fetchImagesInParseAndPaste; - obj[QStringLiteral("protect_from_xss")] = m_protectFromXss; - obj[QStringLiteral("html_tag")] = m_htmlTagEnabled; - obj[QStringLiteral("auto_break")] = m_autoBreakEnabled; - obj[QStringLiteral("linkify")] = m_linkifyEnabled; - obj[QStringLiteral("indent_first_line")] = m_indentFirstLineEnabled; - obj[QStringLiteral("code_block_line_number")] = m_codeBlockLineNumberEnabled; - obj[QStringLiteral("smart_table")] = m_smartTableEnabled; - obj[QStringLiteral("smart_table_interval")] = m_smartTableInterval; - obj[QStringLiteral("spell_check")] = m_spellCheckEnabled; - obj[QStringLiteral("editor_overridden_font_family")] = m_editorOverriddenFontFamily; - - { - QStringList srcs; - if (m_inplacePreviewSources & InplacePreviewSource::ImageLink) { - srcs << inplacePreviewSourceToString(InplacePreviewSource::ImageLink); - } - if (m_inplacePreviewSources & InplacePreviewSource::CodeBlock) { - srcs << inplacePreviewSourceToString(InplacePreviewSource::CodeBlock); - } - if (m_inplacePreviewSources & InplacePreviewSource::Math) { - srcs << inplacePreviewSourceToString(InplacePreviewSource::Math); - } - obj[QStringLiteral("inplace_preview_sources")] = srcs.join(QLatin1Char(';')); + } + + m_editViewMode = stringToEditViewMode(READSTR(QStringLiteral("edit_view_mode"))); + + m_richPasteByDefaultEnabled = READBOOL(QStringLiteral("rich_paste_by_default")); +} + +QJsonObject MarkdownEditorConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("viewer_resource")] = saveViewerResource(); + obj[QStringLiteral("export_resource")] = saveExportResource(); + obj[QStringLiteral("web_plantuml")] = m_webPlantUml; + obj[QStringLiteral("plantuml_jar")] = m_plantUmlJar; + obj[QStringLiteral("plantuml_command")] = m_plantUmlCommand; + obj[QStringLiteral("plantuml_web_service")] = m_plantUmlWebService; + obj[QStringLiteral("web_graphviz")] = m_webGraphviz; + obj[QStringLiteral("graphviz_exe")] = m_graphvizExe; + obj[QStringLiteral("mathjax_script")] = m_mathJaxScript; + obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink; + obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages; + obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle; + + obj[QStringLiteral("section_number")] = sectionNumberModeToString(m_sectionNumberMode); + obj[QStringLiteral("section_number_base_level")] = m_sectionNumberBaseLevel; + obj[QStringLiteral("section_number_style")] = sectionNumberStyleToString(m_sectionNumberStyle); + + obj[QStringLiteral("constrain_image_width")] = m_constrainImageWidthEnabled; + obj[QStringLiteral("image_align_center")] = m_imageAlignCenterEnabled; + obj[QStringLiteral("constrain_inplace_preview_width")] = m_constrainInplacePreviewWidthEnabled; + obj[QStringLiteral("zoom_factor_in_read_mode")] = m_zoomFactorInReadMode; + obj[QStringLiteral("fetch_images_in_parse_and_paste")] = m_fetchImagesInParseAndPaste; + obj[QStringLiteral("protect_from_xss")] = m_protectFromXss; + obj[QStringLiteral("html_tag")] = m_htmlTagEnabled; + obj[QStringLiteral("auto_break")] = m_autoBreakEnabled; + obj[QStringLiteral("linkify")] = m_linkifyEnabled; + obj[QStringLiteral("indent_first_line")] = m_indentFirstLineEnabled; + obj[QStringLiteral("code_block_line_number")] = m_codeBlockLineNumberEnabled; + obj[QStringLiteral("smart_table")] = m_smartTableEnabled; + obj[QStringLiteral("smart_table_interval")] = m_smartTableInterval; + obj[QStringLiteral("spell_check")] = m_spellCheckEnabled; + obj[QStringLiteral("editor_overridden_font_family")] = m_editorOverriddenFontFamily; + + { + QStringList srcs; + if (m_inplacePreviewSources & InplacePreviewSource::ImageLink) { + srcs << inplacePreviewSourceToString(InplacePreviewSource::ImageLink); + } + if (m_inplacePreviewSources & InplacePreviewSource::CodeBlock) { + srcs << inplacePreviewSourceToString(InplacePreviewSource::CodeBlock); + } + if (m_inplacePreviewSources & InplacePreviewSource::Math) { + srcs << inplacePreviewSourceToString(InplacePreviewSource::Math); } + obj[QStringLiteral("inplace_preview_sources")] = srcs.join(QLatin1Char(';')); + } - obj[QStringLiteral("edit_view_mode")] = editViewModeToString(m_editViewMode); + obj[QStringLiteral("edit_view_mode")] = editViewModeToString(m_editViewMode); - obj[QStringLiteral("rich_paste_by_default")] = m_richPasteByDefaultEnabled; + obj[QStringLiteral("rich_paste_by_default")] = m_richPasteByDefaultEnabled; - return obj; + return obj; } -TextEditorConfig &MarkdownEditorConfig::getTextEditorConfig() -{ - return *m_textEditorConfig; -} +TextEditorConfig &MarkdownEditorConfig::getTextEditorConfig() { return *m_textEditorConfig; } -const TextEditorConfig &MarkdownEditorConfig::getTextEditorConfig() const -{ - return *m_textEditorConfig; +const TextEditorConfig &MarkdownEditorConfig::getTextEditorConfig() const { + return *m_textEditorConfig; } -int MarkdownEditorConfig::revision() const -{ - return m_revision + m_textEditorConfig->revision(); -} +int MarkdownEditorConfig::revision() const { return m_revision + m_textEditorConfig->revision(); } -void MarkdownEditorConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const QString name(QStringLiteral("viewer_resource")); +void MarkdownEditorConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user) { + const QString name(QStringLiteral("viewer_resource")); - if (MainConfig::isVersionChanged()) { - bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); - if (needOverride) { - qInfo() << "override \"viewer_resource\" in user configuration due to version change"; - m_viewerResource.init(p_app[name].toObject()); - return; - } + if (MainConfig::isVersionChanged()) { + bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); + if (needOverride) { + qInfo() << "override \"viewer_resource\" in user configuration due to version change"; + m_viewerResource.init(p_app[name].toObject()); + return; } + } - if (p_user.contains(name)) { - m_viewerResource.init(p_user[name].toObject()); - } else { - m_viewerResource.init(p_app[name].toObject()); - } + if (p_user.contains(name)) { + m_viewerResource.init(p_user[name].toObject()); + } else { + m_viewerResource.init(p_app[name].toObject()); + } } -QJsonObject MarkdownEditorConfig::saveViewerResource() const -{ - return m_viewerResource.toJson(); -} +QJsonObject MarkdownEditorConfig::saveViewerResource() const { return m_viewerResource.toJson(); } -void MarkdownEditorConfig::loadExportResource(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const QString name(QStringLiteral("export_resource")); +void MarkdownEditorConfig::loadExportResource(const QJsonObject &p_app, const QJsonObject &p_user) { + const QString name(QStringLiteral("export_resource")); - if (MainConfig::isVersionChanged()) { - bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); - if (needOverride) { - qInfo() << "override \"viewer_resource\" in user configuration due to version change"; - m_exportResource.init(p_app[name].toObject()); - return; - } + if (MainConfig::isVersionChanged()) { + bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); + if (needOverride) { + qInfo() << "override \"viewer_resource\" in user configuration due to version change"; + m_exportResource.init(p_app[name].toObject()); + return; } + } - if (p_user.contains(name)) { - m_exportResource.init(p_user[name].toObject()); - } else { - m_exportResource.init(p_app[name].toObject()); - } + if (p_user.contains(name)) { + m_exportResource.init(p_user[name].toObject()); + } else { + m_exportResource.init(p_app[name].toObject()); + } } -QJsonObject MarkdownEditorConfig::saveExportResource() const -{ - return m_exportResource.toJson(); -} +QJsonObject MarkdownEditorConfig::saveExportResource() const { return m_exportResource.toJson(); } -const WebResource &MarkdownEditorConfig::getViewerResource() const -{ - return m_viewerResource; -} +const WebResource &MarkdownEditorConfig::getViewerResource() const { return m_viewerResource; } -const WebResource &MarkdownEditorConfig::getExportResource() const -{ - return m_exportResource; -} +const WebResource &MarkdownEditorConfig::getExportResource() const { return m_exportResource; } -bool MarkdownEditorConfig::getWebPlantUml() const -{ - return m_webPlantUml; -} +bool MarkdownEditorConfig::getWebPlantUml() const { return m_webPlantUml; } -void MarkdownEditorConfig::setWebPlantUml(bool p_enabled) -{ - updateConfig(m_webPlantUml, p_enabled, this); +void MarkdownEditorConfig::setWebPlantUml(bool p_enabled) { + updateConfig(m_webPlantUml, p_enabled, this); } -const QString &MarkdownEditorConfig::getPlantUmlJar() const -{ - return m_plantUmlJar; -} +const QString &MarkdownEditorConfig::getPlantUmlJar() const { return m_plantUmlJar; } -void MarkdownEditorConfig::setPlantUmlJar(const QString &p_jar) -{ - updateConfig(m_plantUmlJar, p_jar, this); +void MarkdownEditorConfig::setPlantUmlJar(const QString &p_jar) { + updateConfig(m_plantUmlJar, p_jar, this); } -const QString &MarkdownEditorConfig::getPlantUmlCommand() const -{ - return m_plantUmlCommand; -} +const QString &MarkdownEditorConfig::getPlantUmlCommand() const { return m_plantUmlCommand; } -const QString &MarkdownEditorConfig::getPlantUmlWebService() const -{ - return m_plantUmlWebService; -} +const QString &MarkdownEditorConfig::getPlantUmlWebService() const { return m_plantUmlWebService; } -void MarkdownEditorConfig::setPlantUmlWebService(const QString &p_service) -{ - updateConfig(m_plantUmlWebService, p_service, this); +void MarkdownEditorConfig::setPlantUmlWebService(const QString &p_service) { + updateConfig(m_plantUmlWebService, p_service, this); } -bool MarkdownEditorConfig::getWebGraphviz() const -{ - return m_webGraphviz; -} +bool MarkdownEditorConfig::getWebGraphviz() const { return m_webGraphviz; } -void MarkdownEditorConfig::setWebGraphviz(bool p_enabled) -{ - updateConfig(m_webGraphviz, p_enabled, this); +void MarkdownEditorConfig::setWebGraphviz(bool p_enabled) { + updateConfig(m_webGraphviz, p_enabled, this); } -const QString &MarkdownEditorConfig::getGraphvizExe() const -{ - return m_graphvizExe; -} +const QString &MarkdownEditorConfig::getGraphvizExe() const { return m_graphvizExe; } -void MarkdownEditorConfig::setGraphvizExe(const QString &p_exe) -{ - updateConfig(m_graphvizExe, p_exe, this); +void MarkdownEditorConfig::setGraphvizExe(const QString &p_exe) { + updateConfig(m_graphvizExe, p_exe, this); } -const QString &MarkdownEditorConfig::getMathJaxScript() const -{ - return m_mathJaxScript; -} +const QString &MarkdownEditorConfig::getMathJaxScript() const { return m_mathJaxScript; } -void MarkdownEditorConfig::setMathJaxScript(const QString &p_script) -{ - updateConfig(m_mathJaxScript, p_script, this); +void MarkdownEditorConfig::setMathJaxScript(const QString &p_script) { + updateConfig(m_mathJaxScript, p_script, this); } -bool MarkdownEditorConfig::getPrependDotInRelativeLink() const -{ - return m_prependDotInRelativeLink; +bool MarkdownEditorConfig::getPrependDotInRelativeLink() const { + return m_prependDotInRelativeLink; } -bool MarkdownEditorConfig::getConfirmBeforeClearObsoleteImages() const -{ - return m_confirmBeforeClearObsoleteImages; +bool MarkdownEditorConfig::getConfirmBeforeClearObsoleteImages() const { + return m_confirmBeforeClearObsoleteImages; } -void MarkdownEditorConfig::setConfirmBeforeClearObsoleteImages(bool p_confirm) -{ - updateConfig(m_confirmBeforeClearObsoleteImages, p_confirm, this); +void MarkdownEditorConfig::setConfirmBeforeClearObsoleteImages(bool p_confirm) { + updateConfig(m_confirmBeforeClearObsoleteImages, p_confirm, this); } -bool MarkdownEditorConfig::getInsertFileNameAsTitle() const -{ - return m_insertFileNameAsTitle; -} +bool MarkdownEditorConfig::getInsertFileNameAsTitle() const { return m_insertFileNameAsTitle; } -void MarkdownEditorConfig::setInsertFileNameAsTitle(bool p_enabled) -{ - updateConfig(m_insertFileNameAsTitle, p_enabled, this); +void MarkdownEditorConfig::setInsertFileNameAsTitle(bool p_enabled) { + updateConfig(m_insertFileNameAsTitle, p_enabled, this); } -bool MarkdownEditorConfig::getConstrainImageWidthEnabled() const -{ - return m_constrainImageWidthEnabled; +bool MarkdownEditorConfig::getConstrainImageWidthEnabled() const { + return m_constrainImageWidthEnabled; } -void MarkdownEditorConfig::setConstrainImageWidthEnabled(bool p_enabled) -{ - updateConfig(m_constrainImageWidthEnabled, p_enabled, this); +void MarkdownEditorConfig::setConstrainImageWidthEnabled(bool p_enabled) { + updateConfig(m_constrainImageWidthEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getImageAlignCenterEnabled() const -{ - return m_imageAlignCenterEnabled; -} +bool MarkdownEditorConfig::getImageAlignCenterEnabled() const { return m_imageAlignCenterEnabled; } -void MarkdownEditorConfig::setImageAlignCenterEnabled(bool p_enabled) -{ - updateConfig(m_imageAlignCenterEnabled, p_enabled, this); +void MarkdownEditorConfig::setImageAlignCenterEnabled(bool p_enabled) { + updateConfig(m_imageAlignCenterEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getConstrainInplacePreviewWidthEnabled() const -{ - return m_constrainInplacePreviewWidthEnabled; +bool MarkdownEditorConfig::getConstrainInplacePreviewWidthEnabled() const { + return m_constrainInplacePreviewWidthEnabled; } -void MarkdownEditorConfig::setConstrainInplacePreviewWidthEnabled(bool p_enabled) -{ - updateConfig(m_constrainInplacePreviewWidthEnabled, p_enabled, this); +void MarkdownEditorConfig::setConstrainInplacePreviewWidthEnabled(bool p_enabled) { + updateConfig(m_constrainInplacePreviewWidthEnabled, p_enabled, this); } -qreal MarkdownEditorConfig::getZoomFactorInReadMode() const -{ - return m_zoomFactorInReadMode; -} +qreal MarkdownEditorConfig::getZoomFactorInReadMode() const { return m_zoomFactorInReadMode; } -void MarkdownEditorConfig::setZoomFactorInReadMode(qreal p_factor) -{ - updateConfig(m_zoomFactorInReadMode, p_factor, this); +void MarkdownEditorConfig::setZoomFactorInReadMode(qreal p_factor) { + updateConfig(m_zoomFactorInReadMode, p_factor, this); } -bool MarkdownEditorConfig::getFetchImagesInParseAndPaste() const -{ - return m_fetchImagesInParseAndPaste; +bool MarkdownEditorConfig::getFetchImagesInParseAndPaste() const { + return m_fetchImagesInParseAndPaste; } -void MarkdownEditorConfig::setFetchImagesInParseAndPaste(bool p_enabled) -{ - updateConfig(m_fetchImagesInParseAndPaste, p_enabled, this); +void MarkdownEditorConfig::setFetchImagesInParseAndPaste(bool p_enabled) { + updateConfig(m_fetchImagesInParseAndPaste, p_enabled, this); } -bool MarkdownEditorConfig::getProtectFromXss() const -{ - return m_protectFromXss; -} +bool MarkdownEditorConfig::getProtectFromXss() const { return m_protectFromXss; } -bool MarkdownEditorConfig::getHtmlTagEnabled() const -{ - return m_htmlTagEnabled; -} +bool MarkdownEditorConfig::getHtmlTagEnabled() const { return m_htmlTagEnabled; } -void MarkdownEditorConfig::setHtmlTagEnabled(bool p_enabled) -{ - updateConfig(m_htmlTagEnabled, p_enabled, this); +void MarkdownEditorConfig::setHtmlTagEnabled(bool p_enabled) { + updateConfig(m_htmlTagEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getAutoBreakEnabled() const -{ - return m_autoBreakEnabled; -} +bool MarkdownEditorConfig::getAutoBreakEnabled() const { return m_autoBreakEnabled; } -void MarkdownEditorConfig::setAutoBreakEnabled(bool p_enabled) -{ - updateConfig(m_autoBreakEnabled, p_enabled, this); +void MarkdownEditorConfig::setAutoBreakEnabled(bool p_enabled) { + updateConfig(m_autoBreakEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getLinkifyEnabled() const -{ - return m_linkifyEnabled; -} +bool MarkdownEditorConfig::getLinkifyEnabled() const { return m_linkifyEnabled; } -void MarkdownEditorConfig::setLinkifyEnabled(bool p_enabled) -{ - updateConfig(m_linkifyEnabled, p_enabled, this); +void MarkdownEditorConfig::setLinkifyEnabled(bool p_enabled) { + updateConfig(m_linkifyEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getIndentFirstLineEnabled() const -{ - return m_indentFirstLineEnabled; -} +bool MarkdownEditorConfig::getIndentFirstLineEnabled() const { return m_indentFirstLineEnabled; } -void MarkdownEditorConfig::setIndentFirstLineEnabled(bool p_enabled) -{ - updateConfig(m_indentFirstLineEnabled, p_enabled, this); +void MarkdownEditorConfig::setIndentFirstLineEnabled(bool p_enabled) { + updateConfig(m_indentFirstLineEnabled, p_enabled, this); } -bool MarkdownEditorConfig::getCodeBlockLineNumberEnabled() const -{ - return m_codeBlockLineNumberEnabled; +bool MarkdownEditorConfig::getCodeBlockLineNumberEnabled() const { + return m_codeBlockLineNumberEnabled; } -void MarkdownEditorConfig::setCodeBlockLineNumberEnabled(bool p_enabled) -{ - updateConfig(m_codeBlockLineNumberEnabled, p_enabled, this); +void MarkdownEditorConfig::setCodeBlockLineNumberEnabled(bool p_enabled) { + updateConfig(m_codeBlockLineNumberEnabled, p_enabled, this); } -QString MarkdownEditorConfig::sectionNumberModeToString(SectionNumberMode p_mode) const -{ - switch (p_mode) { - case SectionNumberMode::None: - return QStringLiteral("none"); +QString MarkdownEditorConfig::sectionNumberModeToString(SectionNumberMode p_mode) const { + switch (p_mode) { + case SectionNumberMode::None: + return QStringLiteral("none"); - case SectionNumberMode::Edit: - return QStringLiteral("edit"); + case SectionNumberMode::Edit: + return QStringLiteral("edit"); - default: - return QStringLiteral("read"); - } + default: + return QStringLiteral("read"); + } } -MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::stringToSectionNumberMode(const QString &p_str) const -{ - auto mode = p_str.toLower(); - if (mode == QStringLiteral("none")) { - return SectionNumberMode::None; - } else if (mode == QStringLiteral("edit")) { - return SectionNumberMode::Edit; - } else { - return SectionNumberMode::Read; - } +MarkdownEditorConfig::SectionNumberMode +MarkdownEditorConfig::stringToSectionNumberMode(const QString &p_str) const { + auto mode = p_str.toLower(); + if (mode == QStringLiteral("none")) { + return SectionNumberMode::None; + } else if (mode == QStringLiteral("edit")) { + return SectionNumberMode::Edit; + } else { + return SectionNumberMode::Read; + } } -QString MarkdownEditorConfig::sectionNumberStyleToString(SectionNumberStyle p_style) const -{ - switch (p_style) { - case SectionNumberStyle::DigDotDig: - return QStringLiteral("digdotdig"); +QString MarkdownEditorConfig::sectionNumberStyleToString(SectionNumberStyle p_style) const { + switch (p_style) { + case SectionNumberStyle::DigDotDig: + return QStringLiteral("digdotdig"); - default: - return QStringLiteral("digdotdigdot"); - } + default: + return QStringLiteral("digdotdigdot"); + } } -MarkdownEditorConfig::SectionNumberStyle MarkdownEditorConfig::stringToSectionNumberStyle(const QString &p_str) const -{ - auto style = p_str.toLower(); - if (style == QStringLiteral("digdotdig")) { - return SectionNumberStyle::DigDotDig; - } else { - return SectionNumberStyle::DigDotDigDot; - } +MarkdownEditorConfig::SectionNumberStyle +MarkdownEditorConfig::stringToSectionNumberStyle(const QString &p_str) const { + auto style = p_str.toLower(); + if (style == QStringLiteral("digdotdig")) { + return SectionNumberStyle::DigDotDig; + } else { + return SectionNumberStyle::DigDotDigDot; + } } -QString MarkdownEditorConfig::inplacePreviewSourceToString(InplacePreviewSource p_src) const -{ - switch (p_src) { - case InplacePreviewSource::ImageLink: - return QStringLiteral("imagelink"); +QString MarkdownEditorConfig::inplacePreviewSourceToString(InplacePreviewSource p_src) const { + switch (p_src) { + case InplacePreviewSource::ImageLink: + return QStringLiteral("imagelink"); - case InplacePreviewSource::CodeBlock: - return QStringLiteral("codeblock"); + case InplacePreviewSource::CodeBlock: + return QStringLiteral("codeblock"); - case InplacePreviewSource::Math: - return QStringLiteral("math"); + case InplacePreviewSource::Math: + return QStringLiteral("math"); - default: - return ""; - } + default: + return ""; + } } -MarkdownEditorConfig::InplacePreviewSource MarkdownEditorConfig::stringToInplacePreviewSource(const QString &p_str) const -{ - auto src = p_str.toLower(); - if (src == QStringLiteral("imagelink")) { - return InplacePreviewSource::ImageLink; - } else if (src == QStringLiteral("codeblock")) { - return InplacePreviewSource::CodeBlock; - } else if (src == QStringLiteral("math")) { - return InplacePreviewSource::Math; - } else { - return InplacePreviewSource::NoInplacePreview; - } +MarkdownEditorConfig::InplacePreviewSource +MarkdownEditorConfig::stringToInplacePreviewSource(const QString &p_str) const { + auto src = p_str.toLower(); + if (src == QStringLiteral("imagelink")) { + return InplacePreviewSource::ImageLink; + } else if (src == QStringLiteral("codeblock")) { + return InplacePreviewSource::CodeBlock; + } else if (src == QStringLiteral("math")) { + return InplacePreviewSource::Math; + } else { + return InplacePreviewSource::NoInplacePreview; + } } -MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::getSectionNumberMode() const -{ - return m_sectionNumberMode; +MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::getSectionNumberMode() const { + return m_sectionNumberMode; } -void MarkdownEditorConfig::setSectionNumberMode(SectionNumberMode p_mode) -{ - updateConfig(m_sectionNumberMode, p_mode, this); +void MarkdownEditorConfig::setSectionNumberMode(SectionNumberMode p_mode) { + updateConfig(m_sectionNumberMode, p_mode, this); } -int MarkdownEditorConfig::getSectionNumberBaseLevel() const -{ - return m_sectionNumberBaseLevel; -} +int MarkdownEditorConfig::getSectionNumberBaseLevel() const { return m_sectionNumberBaseLevel; } -void MarkdownEditorConfig::setSectionNumberBaseLevel(int p_level) -{ - updateConfig(m_sectionNumberBaseLevel, p_level, this); +void MarkdownEditorConfig::setSectionNumberBaseLevel(int p_level) { + updateConfig(m_sectionNumberBaseLevel, p_level, this); } -MarkdownEditorConfig::SectionNumberStyle MarkdownEditorConfig::getSectionNumberStyle() const -{ - return m_sectionNumberStyle; +MarkdownEditorConfig::SectionNumberStyle MarkdownEditorConfig::getSectionNumberStyle() const { + return m_sectionNumberStyle; } -void MarkdownEditorConfig::setSectionNumberStyle(SectionNumberStyle p_style) -{ - updateConfig(m_sectionNumberStyle, p_style, this); +void MarkdownEditorConfig::setSectionNumberStyle(SectionNumberStyle p_style) { + updateConfig(m_sectionNumberStyle, p_style, this); } -bool MarkdownEditorConfig::getSmartTableEnabled() const -{ - return m_smartTableEnabled; -} +bool MarkdownEditorConfig::getSmartTableEnabled() const { return m_smartTableEnabled; } -void MarkdownEditorConfig::setSmartTableEnabled(bool p_enabled) -{ - updateConfig(m_smartTableEnabled, p_enabled, this); +void MarkdownEditorConfig::setSmartTableEnabled(bool p_enabled) { + updateConfig(m_smartTableEnabled, p_enabled, this); } -int MarkdownEditorConfig::getSmartTableInterval() const -{ - return m_smartTableInterval; -} +int MarkdownEditorConfig::getSmartTableInterval() const { return m_smartTableInterval; } -bool MarkdownEditorConfig::isSpellCheckEnabled() const -{ - return m_spellCheckEnabled; -} +bool MarkdownEditorConfig::isSpellCheckEnabled() const { return m_spellCheckEnabled; } -void MarkdownEditorConfig::setSpellCheckEnabled(bool p_enabled) -{ - updateConfig(m_spellCheckEnabled, p_enabled, this); +void MarkdownEditorConfig::setSpellCheckEnabled(bool p_enabled) { + updateConfig(m_spellCheckEnabled, p_enabled, this); } -const QString &MarkdownEditorConfig::getEditorOverriddenFontFamily() const -{ - return m_editorOverriddenFontFamily; +const QString &MarkdownEditorConfig::getEditorOverriddenFontFamily() const { + return m_editorOverriddenFontFamily; } -void MarkdownEditorConfig::setEditorOverriddenFontFamily(const QString &p_family) -{ - updateConfig(m_editorOverriddenFontFamily, p_family, this); +void MarkdownEditorConfig::setEditorOverriddenFontFamily(const QString &p_family) { + updateConfig(m_editorOverriddenFontFamily, p_family, this); } -MarkdownEditorConfig::InplacePreviewSources MarkdownEditorConfig::getInplacePreviewSources() const -{ - return m_inplacePreviewSources; +MarkdownEditorConfig::InplacePreviewSources MarkdownEditorConfig::getInplacePreviewSources() const { + return m_inplacePreviewSources; } -void MarkdownEditorConfig::setInplacePreviewSources(InplacePreviewSources p_src) -{ - updateConfig(m_inplacePreviewSources, p_src, this); +void MarkdownEditorConfig::setInplacePreviewSources(InplacePreviewSources p_src) { + updateConfig(m_inplacePreviewSources, p_src, this); } -QString MarkdownEditorConfig::editViewModeToString(EditViewMode p_mode) const -{ - switch (p_mode) { - case EditViewMode::EditPreview: - return QStringLiteral("editpreview"); +QString MarkdownEditorConfig::editViewModeToString(EditViewMode p_mode) const { + switch (p_mode) { + case EditViewMode::EditPreview: + return QStringLiteral("editpreview"); - default: - return QStringLiteral("editonly"); - } + default: + return QStringLiteral("editonly"); + } } -MarkdownEditorConfig::EditViewMode MarkdownEditorConfig::stringToEditViewMode(const QString &p_str) const -{ - auto mode = p_str.toLower(); - if (mode == QStringLiteral("editpreview")) { - return EditViewMode::EditPreview; - } else { - return EditViewMode::EditOnly; - } +MarkdownEditorConfig::EditViewMode +MarkdownEditorConfig::stringToEditViewMode(const QString &p_str) const { + auto mode = p_str.toLower(); + if (mode == QStringLiteral("editpreview")) { + return EditViewMode::EditPreview; + } else { + return EditViewMode::EditOnly; + } } -MarkdownEditorConfig::EditViewMode MarkdownEditorConfig::getEditViewMode() const -{ - return m_editViewMode; +MarkdownEditorConfig::EditViewMode MarkdownEditorConfig::getEditViewMode() const { + return m_editViewMode; } -void MarkdownEditorConfig::setEditViewMode(EditViewMode p_mode) -{ - updateConfig(m_editViewMode, p_mode, this); +void MarkdownEditorConfig::setEditViewMode(EditViewMode p_mode) { + updateConfig(m_editViewMode, p_mode, this); } -bool MarkdownEditorConfig::getRichPasteByDefaultEnabled() const -{ - return m_richPasteByDefaultEnabled; +bool MarkdownEditorConfig::getRichPasteByDefaultEnabled() const { + return m_richPasteByDefaultEnabled; } -void MarkdownEditorConfig::setRichPasteByDefaultEnabled(bool p_enabled) -{ - updateConfig(m_richPasteByDefaultEnabled, p_enabled, this); +void MarkdownEditorConfig::setRichPasteByDefaultEnabled(bool p_enabled) { + updateConfig(m_richPasteByDefaultEnabled, p_enabled, this); } diff --git a/src/core/markdowneditorconfig.h b/src/core/markdowneditorconfig.h index 9a92464d4e..30276885e2 100644 --- a/src/core/markdowneditorconfig.h +++ b/src/core/markdowneditorconfig.h @@ -8,265 +8,246 @@ #include #include -namespace vnotex -{ - class TextEditorConfig; +namespace vnotex { +class TextEditorConfig; - class MarkdownEditorConfig : public IConfig - { - public: - enum SectionNumberMode - { - None, - Read, - Edit - }; +class MarkdownEditorConfig : public IConfig { +public: + enum SectionNumberMode { None, Read, Edit }; - enum SectionNumberStyle - { - // 1.1. - DigDotDigDot, - // 1.1 - DigDotDig - }; + enum SectionNumberStyle { + // 1.1. + DigDotDigDot, + // 1.1 + DigDotDig + }; - enum InplacePreviewSource - { - NoInplacePreview = 0, - ImageLink = 0x1, - CodeBlock = 0x2, - Math = 0x4 - }; - Q_DECLARE_FLAGS(InplacePreviewSources, InplacePreviewSource); + enum InplacePreviewSource { NoInplacePreview = 0, ImageLink = 0x1, CodeBlock = 0x2, Math = 0x4 }; + Q_DECLARE_FLAGS(InplacePreviewSources, InplacePreviewSource); - enum EditViewMode - { - EditOnly, - EditPreview - }; + enum EditViewMode { EditOnly, EditPreview }; - MarkdownEditorConfig(ConfigMgr *p_mgr, - IConfig *p_topConfig, - const QSharedPointer &p_textEditorConfig); + MarkdownEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig, + const QSharedPointer &p_textEditorConfig); - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - int revision() const Q_DECL_OVERRIDE; + int revision() const Q_DECL_OVERRIDE; - TextEditorConfig &getTextEditorConfig(); - const TextEditorConfig &getTextEditorConfig() const; + TextEditorConfig &getTextEditorConfig(); + const TextEditorConfig &getTextEditorConfig() const; - const WebResource &getViewerResource() const; + const WebResource &getViewerResource() const; - const WebResource &getExportResource() const; + const WebResource &getExportResource() const; - bool getWebPlantUml() const; - void setWebPlantUml(bool p_enabled); + bool getWebPlantUml() const; + void setWebPlantUml(bool p_enabled); - const QString &getPlantUmlJar() const; - void setPlantUmlJar(const QString &p_jar); + const QString &getPlantUmlJar() const; + void setPlantUmlJar(const QString &p_jar); - const QString &getPlantUmlCommand() const; + const QString &getPlantUmlCommand() const; - const QString &getPlantUmlWebService() const; - void setPlantUmlWebService(const QString &p_service); + const QString &getPlantUmlWebService() const; + void setPlantUmlWebService(const QString &p_service); - bool getWebGraphviz() const; - void setWebGraphviz(bool p_enabled); + bool getWebGraphviz() const; + void setWebGraphviz(bool p_enabled); - const QString &getGraphvizExe() const; - void setGraphvizExe(const QString &p_exe); + const QString &getGraphvizExe() const; + void setGraphvizExe(const QString &p_exe); - const QString &getMathJaxScript() const; - void setMathJaxScript(const QString &p_script); + const QString &getMathJaxScript() const; + void setMathJaxScript(const QString &p_script); - bool getPrependDotInRelativeLink() const; + bool getPrependDotInRelativeLink() const; - bool getConfirmBeforeClearObsoleteImages() const; - void setConfirmBeforeClearObsoleteImages(bool p_confirm); + bool getConfirmBeforeClearObsoleteImages() const; + void setConfirmBeforeClearObsoleteImages(bool p_confirm); - bool getInsertFileNameAsTitle() const; - void setInsertFileNameAsTitle(bool p_enabled); + bool getInsertFileNameAsTitle() const; + void setInsertFileNameAsTitle(bool p_enabled); - SectionNumberMode getSectionNumberMode() const; - void setSectionNumberMode(SectionNumberMode p_mode); + SectionNumberMode getSectionNumberMode() const; + void setSectionNumberMode(SectionNumberMode p_mode); - int getSectionNumberBaseLevel() const; - void setSectionNumberBaseLevel(int p_level); + int getSectionNumberBaseLevel() const; + void setSectionNumberBaseLevel(int p_level); - SectionNumberStyle getSectionNumberStyle() const; - void setSectionNumberStyle(SectionNumberStyle p_style); + SectionNumberStyle getSectionNumberStyle() const; + void setSectionNumberStyle(SectionNumberStyle p_style); - bool getConstrainImageWidthEnabled() const; - void setConstrainImageWidthEnabled(bool p_enabled); + bool getConstrainImageWidthEnabled() const; + void setConstrainImageWidthEnabled(bool p_enabled); - bool getImageAlignCenterEnabled() const; - void setImageAlignCenterEnabled(bool p_enabled); + bool getImageAlignCenterEnabled() const; + void setImageAlignCenterEnabled(bool p_enabled); - bool getConstrainInplacePreviewWidthEnabled() const; - void setConstrainInplacePreviewWidthEnabled(bool p_enabled); + bool getConstrainInplacePreviewWidthEnabled() const; + void setConstrainInplacePreviewWidthEnabled(bool p_enabled); - qreal getZoomFactorInReadMode() const; - void setZoomFactorInReadMode(qreal p_factor); + qreal getZoomFactorInReadMode() const; + void setZoomFactorInReadMode(qreal p_factor); - bool getFetchImagesInParseAndPaste() const; - void setFetchImagesInParseAndPaste(bool p_enabled); + bool getFetchImagesInParseAndPaste() const; + void setFetchImagesInParseAndPaste(bool p_enabled); - bool getProtectFromXss() const; + bool getProtectFromXss() const; - bool getHtmlTagEnabled() const; - void setHtmlTagEnabled(bool p_enabled); + bool getHtmlTagEnabled() const; + void setHtmlTagEnabled(bool p_enabled); - bool getAutoBreakEnabled() const; - void setAutoBreakEnabled(bool p_enabled); + bool getAutoBreakEnabled() const; + void setAutoBreakEnabled(bool p_enabled); - bool getLinkifyEnabled() const; - void setLinkifyEnabled(bool p_enabled); + bool getLinkifyEnabled() const; + void setLinkifyEnabled(bool p_enabled); - bool getIndentFirstLineEnabled() const; - void setIndentFirstLineEnabled(bool p_enabled); + bool getIndentFirstLineEnabled() const; + void setIndentFirstLineEnabled(bool p_enabled); - bool getCodeBlockLineNumberEnabled() const; - void setCodeBlockLineNumberEnabled(bool p_enabled); + bool getCodeBlockLineNumberEnabled() const; + void setCodeBlockLineNumberEnabled(bool p_enabled); - bool getSmartTableEnabled() const; - void setSmartTableEnabled(bool p_enabled); + bool getSmartTableEnabled() const; + void setSmartTableEnabled(bool p_enabled); - int getSmartTableInterval() const; + int getSmartTableInterval() const; - bool isSpellCheckEnabled() const; - void setSpellCheckEnabled(bool p_enabled); + bool isSpellCheckEnabled() const; + void setSpellCheckEnabled(bool p_enabled); - const QString &getEditorOverriddenFontFamily() const; - void setEditorOverriddenFontFamily(const QString &p_family); + const QString &getEditorOverriddenFontFamily() const; + void setEditorOverriddenFontFamily(const QString &p_family); - InplacePreviewSources getInplacePreviewSources() const; - void setInplacePreviewSources(InplacePreviewSources p_src); + InplacePreviewSources getInplacePreviewSources() const; + void setInplacePreviewSources(InplacePreviewSources p_src); - EditViewMode getEditViewMode() const; - void setEditViewMode(EditViewMode p_mode); + EditViewMode getEditViewMode() const; + void setEditViewMode(EditViewMode p_mode); - bool getRichPasteByDefaultEnabled() const; - void setRichPasteByDefaultEnabled(bool p_enabled); + bool getRichPasteByDefaultEnabled() const; + void setRichPasteByDefaultEnabled(bool p_enabled); - private: - friend class MainConfig; +private: + friend class MainConfig; - QString sectionNumberModeToString(SectionNumberMode p_mode) const; - SectionNumberMode stringToSectionNumberMode(const QString &p_str) const; + QString sectionNumberModeToString(SectionNumberMode p_mode) const; + SectionNumberMode stringToSectionNumberMode(const QString &p_str) const; - QString sectionNumberStyleToString(SectionNumberStyle p_style) const; - SectionNumberStyle stringToSectionNumberStyle(const QString &p_str) const; + QString sectionNumberStyleToString(SectionNumberStyle p_style) const; + SectionNumberStyle stringToSectionNumberStyle(const QString &p_str) const; - void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveViewerResource() const; + void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user); + QJsonObject saveViewerResource() const; - void loadExportResource(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveExportResource() const; + void loadExportResource(const QJsonObject &p_app, const QJsonObject &p_user); + QJsonObject saveExportResource() const; - QString inplacePreviewSourceToString(InplacePreviewSource p_src) const; - InplacePreviewSource stringToInplacePreviewSource(const QString &p_str) const; + QString inplacePreviewSourceToString(InplacePreviewSource p_src) const; + InplacePreviewSource stringToInplacePreviewSource(const QString &p_str) const; - QString editViewModeToString(EditViewMode p_mode) const; - EditViewMode stringToEditViewMode(const QString &p_str) const; + QString editViewModeToString(EditViewMode p_mode) const; + EditViewMode stringToEditViewMode(const QString &p_str) const; - QSharedPointer m_textEditorConfig; + QSharedPointer m_textEditorConfig; - WebResource m_viewerResource; + WebResource m_viewerResource; - WebResource m_exportResource; + WebResource m_exportResource; - // Whether use javascript or external program to render PlantUML. - bool m_webPlantUml = true; + // Whether use javascript or external program to render PlantUML. + bool m_webPlantUml = true; - // File path of the JAR to render PlantUmL. - QString m_plantUmlJar; + // File path of the JAR to render PlantUmL. + QString m_plantUmlJar; - // Command to render PlantUml. If set, will ignore m_plantUmlJar. - // %1: the format to render in. - QString m_plantUmlCommand; + // Command to render PlantUml. If set, will ignore m_plantUmlJar. + // %1: the format to render in. + QString m_plantUmlCommand; - // PlantUml Web service to override that in plantuml.js file. - QString m_plantUmlWebService; + // PlantUml Web service to override that in plantuml.js file. + QString m_plantUmlWebService; - bool m_webGraphviz = true; + bool m_webGraphviz = true; - // Graphviz executable file. - QString m_graphvizExe; + // Graphviz executable file. + QString m_graphvizExe; - // MathJax script to override that in mathjax.js file. - QString m_mathJaxScript; + // MathJax script to override that in mathjax.js file. + QString m_mathJaxScript; - // Whether prepend a dot in front of the relative link, like images. - bool m_prependDotInRelativeLink = false; + // Whether prepend a dot in front of the relative link, like images. + bool m_prependDotInRelativeLink = false; - // Whether ask for user confirmation before clearing obsolete images. - bool m_confirmBeforeClearObsoleteImages = true; + // Whether ask for user confirmation before clearing obsolete images. + bool m_confirmBeforeClearObsoleteImages = true; - // Whether insert the name of the new file as title. - bool m_insertFileNameAsTitle = true; + // Whether insert the name of the new file as title. + bool m_insertFileNameAsTitle = true; - // Whether enable section numbering. - SectionNumberMode m_sectionNumberMode = SectionNumberMode::Read; + // Whether enable section numbering. + SectionNumberMode m_sectionNumberMode = SectionNumberMode::Read; - // 1 based. - int m_sectionNumberBaseLevel = 2; + // 1 based. + int m_sectionNumberBaseLevel = 2; - // Section number style. - SectionNumberStyle m_sectionNumberStyle = SectionNumberStyle::DigDotDigDot; + // Section number style. + SectionNumberStyle m_sectionNumberStyle = SectionNumberStyle::DigDotDigDot; - // Whether enable image width constraint. - bool m_constrainImageWidthEnabled = true; + // Whether enable image width constraint. + bool m_constrainImageWidthEnabled = true; - bool m_imageAlignCenterEnabled = false; + bool m_imageAlignCenterEnabled = false; - // Whether enable in-place preview width constraint. - bool m_constrainInplacePreviewWidthEnabled = false; + // Whether enable in-place preview width constraint. + bool m_constrainInplacePreviewWidthEnabled = false; - qreal m_zoomFactorInReadMode = 1.0; + qreal m_zoomFactorInReadMode = 1.0; - // Whether fetch images to local in Parse To Markdown And Paste. - bool m_fetchImagesInParseAndPaste = true; + // Whether fetch images to local in Parse To Markdown And Paste. + bool m_fetchImagesInParseAndPaste = true; - // Whether protect from Cross-Site Scripting. - bool m_protectFromXss = true; + // Whether protect from Cross-Site Scripting. + bool m_protectFromXss = true; - // Whether allow HTML tag in Markdown source. - bool m_htmlTagEnabled = true; + // Whether allow HTML tag in Markdown source. + bool m_htmlTagEnabled = true; - // Whether auto break a line with `\n`. - bool m_autoBreakEnabled = false; + // Whether auto break a line with `\n`. + bool m_autoBreakEnabled = false; - // Whether convert URL-like text to links. - bool m_linkifyEnabled = true; + // Whether convert URL-like text to links. + bool m_linkifyEnabled = true; - // Whether indent the first line of a paragraph. - bool m_indentFirstLineEnabled = false; + // Whether indent the first line of a paragraph. + bool m_indentFirstLineEnabled = false; - // Whether enable code block line number in read mode. - bool m_codeBlockLineNumberEnabled = true; + // Whether enable code block line number in read mode. + bool m_codeBlockLineNumberEnabled = true; - bool m_smartTableEnabled = true; + bool m_smartTableEnabled = true; - // Interval time to do smart table format. - int m_smartTableInterval = 2000; + // Interval time to do smart table format. + int m_smartTableInterval = 2000; - // Override the config in TextEditorConfig. - bool m_spellCheckEnabled = true; + // Override the config in TextEditorConfig. + bool m_spellCheckEnabled = true; - // Font family to override the editor's theme. - QString m_editorOverriddenFontFamily; + // Font family to override the editor's theme. + QString m_editorOverriddenFontFamily; - InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; + InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; - // View mode in edit mode. - EditViewMode m_editViewMode = EditViewMode::EditOnly; + // View mode in edit mode. + EditViewMode m_editViewMode = EditViewMode::EditOnly; - bool m_richPasteByDefaultEnabled = true; - }; -} + bool m_richPasteByDefaultEnabled = true; +}; +} // namespace vnotex Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::MarkdownEditorConfig::InplacePreviewSources) diff --git a/src/core/mindmapeditorconfig.cpp b/src/core/mindmapeditorconfig.cpp index e463a63746..ef964f45e2 100644 --- a/src/core/mindmapeditorconfig.cpp +++ b/src/core/mindmapeditorconfig.cpp @@ -9,53 +9,42 @@ using namespace vnotex; MindMapEditorConfig::MindMapEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig) -{ - m_sessionName = QStringLiteral("mindmap_editor"); + : IConfig(p_mgr, p_topConfig) { + m_sessionName = QStringLiteral("mindmap_editor"); } -void MindMapEditorConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void MindMapEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - loadEditorResource(appObj, userObj); + loadEditorResource(appObj, userObj); } -QJsonObject MindMapEditorConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("editor_resource")] = saveEditorResource(); - return obj; +QJsonObject MindMapEditorConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("editor_resource")] = saveEditorResource(); + return obj; } -void MindMapEditorConfig::loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const QString name(QStringLiteral("editor_resource")); - - if (MainConfig::isVersionChanged()) { - bool needOverride = p_app[QStringLiteral("override_editor_resource")].toBool(); - if (needOverride) { - qInfo() << "override \"editor_resource\" in user configuration due to version change"; - m_editorResource.init(p_app[name].toObject()); - return; - } - } +void MindMapEditorConfig::loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user) { + const QString name(QStringLiteral("editor_resource")); - if (p_user.contains(name)) { - m_editorResource.init(p_user[name].toObject()); - } else { - m_editorResource.init(p_app[name].toObject()); + if (MainConfig::isVersionChanged()) { + bool needOverride = p_app[QStringLiteral("override_editor_resource")].toBool(); + if (needOverride) { + qInfo() << "override \"editor_resource\" in user configuration due to version change"; + m_editorResource.init(p_app[name].toObject()); + return; } -} + } -QJsonObject MindMapEditorConfig::saveEditorResource() const -{ - return m_editorResource.toJson(); + if (p_user.contains(name)) { + m_editorResource.init(p_user[name].toObject()); + } else { + m_editorResource.init(p_app[name].toObject()); + } } -const WebResource &MindMapEditorConfig::getEditorResource() const -{ - return m_editorResource; -} +QJsonObject MindMapEditorConfig::saveEditorResource() const { return m_editorResource.toJson(); } + +const WebResource &MindMapEditorConfig::getEditorResource() const { return m_editorResource; } diff --git a/src/core/mindmapeditorconfig.h b/src/core/mindmapeditorconfig.h index 0c04ea1b17..f3a18cb7db 100644 --- a/src/core/mindmapeditorconfig.h +++ b/src/core/mindmapeditorconfig.h @@ -5,27 +5,25 @@ #include "webresource.h" -namespace vnotex -{ - class MindMapEditorConfig : public IConfig - { - public: - MindMapEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); +namespace vnotex { +class MindMapEditorConfig : public IConfig { +public: + MindMapEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - const WebResource &getEditorResource() const; + const WebResource &getEditorResource() const; - private: - friend class MainConfig; +private: + friend class MainConfig; - void loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveEditorResource() const; + void loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user); + QJsonObject saveEditorResource() const; - WebResource m_editorResource; - }; -} + WebResource m_editorResource; +}; +} // namespace vnotex #endif // MINDMAPEDITORCONFIG_H diff --git a/src/core/namebasedserver.h b/src/core/namebasedserver.h index 9587e89793..a09001ba93 100644 --- a/src/core/namebasedserver.h +++ b/src/core/namebasedserver.h @@ -1,50 +1,41 @@ #ifndef NAMEBASEDSERVER_H #define NAMEBASEDSERVER_H -#include -#include #include +#include #include +#include -namespace vnotex -{ - template - class NameBasedServer - { - public: - // Register an item. - bool registerItem(const QString &p_name, const QSharedPointer &p_item) - { - if (m_data.contains(p_name)) { - qWarning() << "item to register already exists with name" << p_name; - return false; - } - - m_data.insert(p_name, p_item); - return true; - } - - // Get an item. - QSharedPointer getItem(const QString &p_name) - { - auto it = m_data.find(p_name); - if (it != m_data.end()) { - return it.value(); - } - - return nullptr; - } - - QList> getAllItems() const - { - return m_data.values(); - } - - private: - // Name to item mapping. - QHash> m_data; - }; -} // ns vnotex - +namespace vnotex { +template class NameBasedServer { +public: + // Register an item. + bool registerItem(const QString &p_name, const QSharedPointer &p_item) { + if (m_data.contains(p_name)) { + qWarning() << "item to register already exists with name" << p_name; + return false; + } + + m_data.insert(p_name, p_item); + return true; + } + + // Get an item. + QSharedPointer getItem(const QString &p_name) { + auto it = m_data.find(p_name); + if (it != m_data.end()) { + return it.value(); + } + + return nullptr; + } + + QList> getAllItems() const { return m_data.values(); } + +private: + // Name to item mapping. + QHash> m_data; +}; +} // namespace vnotex #endif // NAMEBASEDSERVER_H diff --git a/src/core/noncopyable.h b/src/core/noncopyable.h index 92cbfdf1bb..4ca9dc21cd 100644 --- a/src/core/noncopyable.h +++ b/src/core/noncopyable.h @@ -1,18 +1,16 @@ #ifndef NONCOPYABLE_H #define NONCOPYABLE_H -namespace vnotex -{ - class Noncopyable - { - protected: - Noncopyable() = default; +namespace vnotex { +class Noncopyable { +protected: + Noncopyable() = default; - virtual ~Noncopyable() = default; + virtual ~Noncopyable() = default; - Noncopyable(const Noncopyable&) = delete; - Noncopyable &operator=(const Noncopyable&) = delete; - }; -} + Noncopyable(const Noncopyable &) = delete; + Noncopyable &operator=(const Noncopyable &) = delete; +}; +} // namespace vnotex #endif // NONCOPYABLE_H diff --git a/src/core/notebook/bundlenotebook.cpp b/src/core/notebook/bundlenotebook.cpp index 0b0b436e63..fd99778122 100644 --- a/src/core/notebook/bundlenotebook.cpp +++ b/src/core/notebook/bundlenotebook.cpp @@ -1,14 +1,14 @@ #include "bundlenotebook.h" -#include #include +#include +#include +#include +#include #include #include #include -#include -#include -#include #include "notebookdatabaseaccess.h" #include "notebooktagmgr.h" @@ -18,251 +18,205 @@ using namespace vnotex; BundleNotebook::BundleNotebook(const NotebookParameters &p_paras, const QSharedPointer &p_notebookConfig, QObject *p_parent) - : Notebook(p_paras, p_parent), - m_configVersion(p_notebookConfig->m_version), - m_history(p_notebookConfig->m_history), - m_tagGraph(p_notebookConfig->m_tagGraph), - m_extraConfigs(p_notebookConfig->m_extraConfigs) -{ - setupDatabase(); + : Notebook(p_paras, p_parent), m_configVersion(p_notebookConfig->m_version), + m_history(p_notebookConfig->m_history), m_tagGraph(p_notebookConfig->m_tagGraph), + m_extraConfigs(p_notebookConfig->m_extraConfigs) { + setupDatabase(); } -BundleNotebook::~BundleNotebook() -{ - m_dbAccess->close(); -} +BundleNotebook::~BundleNotebook() { m_dbAccess->close(); } -BundleNotebookConfigMgr *BundleNotebook::getBundleNotebookConfigMgr() const -{ - return static_cast(getConfigMgr().data()); +BundleNotebookConfigMgr *BundleNotebook::getBundleNotebookConfigMgr() const { + return static_cast(getConfigMgr().data()); } -void BundleNotebook::setupDatabase() -{ - auto dbPath = getBackend()->getFullPath(BundleNotebookConfigMgr::getDatabasePath()); - m_dbAccess = new NotebookDatabaseAccess(this, dbPath, this); +void BundleNotebook::setupDatabase() { + auto dbPath = getBackend()->getFullPath(BundleNotebookConfigMgr::getDatabasePath()); + m_dbAccess = new NotebookDatabaseAccess(this, dbPath, this); } -void BundleNotebook::initializeInternal() -{ - initDatabase(); +void BundleNotebook::initializeInternal() { + initDatabase(); - if (m_configVersion != getConfigMgr()->getCodeVersion()) { - updateNotebookConfig(); - } + if (m_configVersion != getConfigMgr()->getCodeVersion()) { + updateNotebookConfig(); + } } -void BundleNotebook::initDatabase() -{ - m_dbAccess->initialize(m_configVersion); +void BundleNotebook::initDatabase() { + m_dbAccess->initialize(m_configVersion); - if (m_dbAccess->isFresh()) { - // For previous version notebook without DB, just ignore the node Id from config. - int cnt = 0; - fillNodeTableFromConfig(getRootNode().data(), m_configVersion < 2, cnt); - qDebug() << "fillNodeTableFromConfig nodes count" << cnt; + if (m_dbAccess->isFresh()) { + // For previous version notebook without DB, just ignore the node Id from config. + int cnt = 0; + fillNodeTableFromConfig(getRootNode().data(), m_configVersion < 2, cnt); + qDebug() << "fillNodeTableFromConfig nodes count" << cnt; - fillTagTableFromTagGraph(); + fillTagTableFromTagGraph(); - cnt = 0; - fillTagTableFromConfig(getRootNode().data(), cnt); - } + cnt = 0; + fillTagTableFromConfig(getRootNode().data(), cnt); + } - if (m_tagMgr) { - m_tagMgr->update(); - } + if (m_tagMgr) { + m_tagMgr->update(); + } } -void BundleNotebook::updateNotebookConfig() -{ - getBundleNotebookConfigMgr()->writeNotebookConfig(); -} +void BundleNotebook::updateNotebookConfig() { getBundleNotebookConfigMgr()->writeNotebookConfig(); } -void BundleNotebook::removeNotebookConfig() -{ - getBundleNotebookConfigMgr()->removeNotebookConfig(); +void BundleNotebook::removeNotebookConfig() { + getBundleNotebookConfigMgr()->removeNotebookConfig(); } -void BundleNotebook::remove() -{ - // Remove all nodes. - removeNode(getRootNode()); +void BundleNotebook::remove() { + // Remove all nodes. + removeNode(getRootNode()); - // Remove notebook config. - removeNotebookConfig(); + // Remove notebook config. + removeNotebookConfig(); - // Remove notebook root folder if it is empty. - if (!FileUtils::removeDirIfEmpty(getRootFolderAbsolutePath())) { - qInfo() << QStringLiteral("root folder of notebook (%1) is not empty and needs manual clean up") - .arg(getRootFolderAbsolutePath()); - } + // Remove notebook root folder if it is empty. + if (!FileUtils::removeDirIfEmpty(getRootFolderAbsolutePath())) { + qInfo() << QStringLiteral("root folder of notebook (%1) is not empty and needs manual clean up") + .arg(getRootFolderAbsolutePath()); + } } -HistoryI *BundleNotebook::history() -{ - return this; -} +HistoryI *BundleNotebook::history() { return this; } -const QVector &BundleNotebook::getHistory() const -{ - return m_history; -} +const QVector &BundleNotebook::getHistory() const { return m_history; } -void BundleNotebook::removeHistory(const QString &p_itemPath) -{ - HistoryMgr::removeHistoryItem(m_history, p_itemPath); +void BundleNotebook::removeHistory(const QString &p_itemPath) { + HistoryMgr::removeHistoryItem(m_history, p_itemPath); - updateNotebookConfig(); + updateNotebookConfig(); } -void BundleNotebook::addHistory(const HistoryItem &p_item) -{ - HistoryItem item(p_item); - item.m_path = getBackend()->getRelativePath(item.m_path); - HistoryMgr::insertHistoryItem(m_history, item); +void BundleNotebook::addHistory(const HistoryItem &p_item) { + HistoryItem item(p_item); + item.m_path = getBackend()->getRelativePath(item.m_path); + HistoryMgr::insertHistoryItem(m_history, item); - updateNotebookConfig(); + updateNotebookConfig(); } -void BundleNotebook::clearHistory() -{ - m_history.clear(); +void BundleNotebook::clearHistory() { + m_history.clear(); - updateNotebookConfig(); + updateNotebookConfig(); } -const QJsonObject &BundleNotebook::getExtraConfigs() const -{ - return m_extraConfigs; -} +const QJsonObject &BundleNotebook::getExtraConfigs() const { return m_extraConfigs; } -void BundleNotebook::setExtraConfig(const QString &p_key, const QJsonObject &p_obj) -{ - m_extraConfigs[p_key] = p_obj; +void BundleNotebook::setExtraConfig(const QString &p_key, const QJsonObject &p_obj) { + m_extraConfigs[p_key] = p_obj; - updateNotebookConfig(); + updateNotebookConfig(); } -void BundleNotebook::fillNodeTableFromConfig(Node *p_node, bool p_ignoreId, int &p_totalCnt) -{ - bool ret = m_dbAccess->addNode(p_node, p_ignoreId); - if (!ret) { - qWarning() << "failed to add node to DB" << p_node->getName() << p_ignoreId; - return; - } +void BundleNotebook::fillNodeTableFromConfig(Node *p_node, bool p_ignoreId, int &p_totalCnt) { + bool ret = m_dbAccess->addNode(p_node, p_ignoreId); + if (!ret) { + qWarning() << "failed to add node to DB" << p_node->getName() << p_ignoreId; + return; + } - if (++p_totalCnt % 10) { - QCoreApplication::processEvents(); + if (++p_totalCnt % 10) { + QCoreApplication::processEvents(); + } + + const auto &children = p_node->getChildrenRef(); + for (const auto &child : children) { + fillNodeTableFromConfig(child.data(), p_ignoreId, p_totalCnt); + } +} + +NotebookDatabaseAccess *BundleNotebook::getDatabaseAccess() const { return m_dbAccess; } + +bool BundleNotebook::rebuildDatabase() { + Q_ASSERT(m_dbAccess); + m_dbAccess->close(); + + auto backend = getBackend(); + const auto dbPath = BundleNotebookConfigMgr::getDatabasePath(); + if (backend->exists(dbPath)) { + try { + backend->removeFile(dbPath); + } catch (Exception &p_e) { + qWarning() << "failed to delete database file" << dbPath << p_e.what(); + if (!m_dbAccess->open()) { + qWarning() << "failed to open notebook database (restart is needed)"; + } + return false; } + } - const auto &children = p_node->getChildrenRef(); - for (const auto &child : children) { - fillNodeTableFromConfig(child.data(), p_ignoreId, p_totalCnt); - } -} + m_dbAccess->deleteLater(); -NotebookDatabaseAccess *BundleNotebook::getDatabaseAccess() const -{ - return m_dbAccess; -} + setupDatabase(); + initDatabase(); -bool BundleNotebook::rebuildDatabase() -{ - Q_ASSERT(m_dbAccess); - m_dbAccess->close(); - - auto backend = getBackend(); - const auto dbPath = BundleNotebookConfigMgr::getDatabasePath(); - if (backend->exists(dbPath)) { - try { - backend->removeFile(dbPath); - } catch (Exception &p_e) { - qWarning() << "failed to delete database file" << dbPath << p_e.what(); - if (!m_dbAccess->open()) { - qWarning() << "failed to open notebook database (restart is needed)"; - } - return false; - } - } + emit tagsUpdated(); - m_dbAccess->deleteLater(); + return true; +} - setupDatabase(); - initDatabase(); +const QString &BundleNotebook::getTagGraph() const { return m_tagGraph; } - emit tagsUpdated(); +void BundleNotebook::updateTagGraph(const QString &p_tagGraph) { + if (m_tagGraph == p_tagGraph) { + return; + } - return true; + m_tagGraph = p_tagGraph; + updateNotebookConfig(); } -const QString &BundleNotebook::getTagGraph() const -{ - return m_tagGraph; -} - -void BundleNotebook::updateTagGraph(const QString &p_tagGraph) -{ - if (m_tagGraph == p_tagGraph) { - return; +void BundleNotebook::fillTagTableFromTagGraph() { + auto tagGraph = NotebookTagMgr::stringToTagGraph(m_tagGraph); + for (const auto &tagPair : tagGraph) { + if (!m_dbAccess->addTag(tagPair.m_parent)) { + qWarning() << "failed to add tag to DB" << tagPair.m_parent; + continue; } - m_tagGraph = p_tagGraph; - updateNotebookConfig(); -} - -void BundleNotebook::fillTagTableFromTagGraph() -{ - auto tagGraph = NotebookTagMgr::stringToTagGraph(m_tagGraph); - for (const auto &tagPair : tagGraph) { - if (!m_dbAccess->addTag(tagPair.m_parent)) { - qWarning() << "failed to add tag to DB" << tagPair.m_parent; - continue; - } - - if (!m_dbAccess->addTag(tagPair.m_child, tagPair.m_parent)) { - qWarning() << "failed to add tag to DB" << tagPair.m_child; - continue; - } + if (!m_dbAccess->addTag(tagPair.m_child, tagPair.m_parent)) { + qWarning() << "failed to add tag to DB" << tagPair.m_child; + continue; } + } - QCoreApplication::processEvents(); + QCoreApplication::processEvents(); } -void BundleNotebook::fillTagTableFromConfig(Node *p_node, int &p_totalCnt) -{ - // @p_node must already exists in node table. - bool ret = m_dbAccess->updateNodeTags(p_node); - if (!ret) { - qWarning() << "failed to add tags of node to DB" << p_node->getName() << p_node->getTags(); - return; - } +void BundleNotebook::fillTagTableFromConfig(Node *p_node, int &p_totalCnt) { + // @p_node must already exists in node table. + bool ret = m_dbAccess->updateNodeTags(p_node); + if (!ret) { + qWarning() << "failed to add tags of node to DB" << p_node->getName() << p_node->getTags(); + return; + } - if (++p_totalCnt % 10) { - QCoreApplication::processEvents(); - } + if (++p_totalCnt % 10) { + QCoreApplication::processEvents(); + } - const auto &children = p_node->getChildrenRef(); - for (const auto &child : children) { - fillTagTableFromConfig(child.data(), p_totalCnt); - } + const auto &children = p_node->getChildrenRef(); + for (const auto &child : children) { + fillTagTableFromConfig(child.data(), p_totalCnt); + } } -NotebookTagMgr *BundleNotebook::getTagMgr() const -{ - if (!m_tagMgr) { - auto th = const_cast(this); - th->m_tagMgr = new NotebookTagMgr(th); - } +NotebookTagMgr *BundleNotebook::getTagMgr() const { + if (!m_tagMgr) { + auto th = const_cast(this); + th->m_tagMgr = new NotebookTagMgr(th); + } - return m_tagMgr; + return m_tagMgr; } -TagI *BundleNotebook::tag() -{ - return getTagMgr(); -} +TagI *BundleNotebook::tag() { return getTagMgr(); } -int BundleNotebook::getConfigVersion() const -{ - return m_configVersion; -} +int BundleNotebook::getConfigVersion() const { return m_configVersion; } diff --git a/src/core/notebook/bundlenotebook.h b/src/core/notebook/bundlenotebook.h index 6083945d91..bc0a7c3e8d 100644 --- a/src/core/notebook/bundlenotebook.h +++ b/src/core/notebook/bundlenotebook.h @@ -1,92 +1,89 @@ #ifndef BUNDLENOTEBOOK_H #define BUNDLENOTEBOOK_H -#include "notebook.h" #include "global.h" #include "historyi.h" +#include "notebook.h" -namespace vnotex -{ - class BundleNotebookConfigMgr; - class NotebookConfig; - class NotebookDatabaseAccess; - class NotebookTagMgr; +namespace vnotex { +class BundleNotebookConfigMgr; +class NotebookConfig; +class NotebookDatabaseAccess; +class NotebookTagMgr; - class BundleNotebook : public Notebook, - public HistoryI - { - Q_OBJECT - public: - BundleNotebook(const NotebookParameters &p_paras, - const QSharedPointer &p_notebookConfig, - QObject *p_parent = nullptr); +class BundleNotebook : public Notebook, public HistoryI { + Q_OBJECT +public: + BundleNotebook(const NotebookParameters &p_paras, + const QSharedPointer &p_notebookConfig, + QObject *p_parent = nullptr); - ~BundleNotebook(); + ~BundleNotebook(); - void updateNotebookConfig() Q_DECL_OVERRIDE; + void updateNotebookConfig() Q_DECL_OVERRIDE; - void removeNotebookConfig() Q_DECL_OVERRIDE; + void removeNotebookConfig() Q_DECL_OVERRIDE; - void remove() Q_DECL_OVERRIDE; + void remove() Q_DECL_OVERRIDE; - const QString &getTagGraph() const; - void updateTagGraph(const QString &p_tagGraph); + const QString &getTagGraph() const; + void updateTagGraph(const QString &p_tagGraph); - const QJsonObject &getExtraConfigs() const Q_DECL_OVERRIDE; - void setExtraConfig(const QString &p_key, const QJsonObject &p_obj) Q_DECL_OVERRIDE; + const QJsonObject &getExtraConfigs() const Q_DECL_OVERRIDE; + void setExtraConfig(const QString &p_key, const QJsonObject &p_obj) Q_DECL_OVERRIDE; - bool rebuildDatabase() Q_DECL_OVERRIDE; + bool rebuildDatabase() Q_DECL_OVERRIDE; - NotebookDatabaseAccess *getDatabaseAccess() const; + NotebookDatabaseAccess *getDatabaseAccess() const; - TagI *tag() Q_DECL_OVERRIDE; + TagI *tag() Q_DECL_OVERRIDE; - int getConfigVersion() const; + int getConfigVersion() const; - // HistoryI. - public: - HistoryI *history() Q_DECL_OVERRIDE; + // HistoryI. +public: + HistoryI *history() Q_DECL_OVERRIDE; - const QVector &getHistory() const Q_DECL_OVERRIDE; + const QVector &getHistory() const Q_DECL_OVERRIDE; - void removeHistory(const QString &p_itemPath) Q_DECL_OVERRIDE; + void removeHistory(const QString &p_itemPath) Q_DECL_OVERRIDE; - void addHistory(const HistoryItem &p_item) Q_DECL_OVERRIDE; + void addHistory(const HistoryItem &p_item) Q_DECL_OVERRIDE; - void clearHistory() Q_DECL_OVERRIDE; + void clearHistory() Q_DECL_OVERRIDE; - protected: - void initializeInternal() Q_DECL_OVERRIDE; +protected: + void initializeInternal() Q_DECL_OVERRIDE; - private: - BundleNotebookConfigMgr *getBundleNotebookConfigMgr() const; +private: + BundleNotebookConfigMgr *getBundleNotebookConfigMgr() const; - void setupDatabase(); + void setupDatabase(); - void fillNodeTableFromConfig(Node *p_node, bool p_ignoreId, int &p_totalCnt); + void fillNodeTableFromConfig(Node *p_node, bool p_ignoreId, int &p_totalCnt); - void initDatabase(); + void initDatabase(); - void fillTagTableFromTagGraph(); + void fillTagTableFromTagGraph(); - void fillTagTableFromConfig(Node *p_node, int &p_totalCnt); + void fillTagTableFromConfig(Node *p_node, int &p_totalCnt); - NotebookTagMgr *getTagMgr() const; + NotebookTagMgr *getTagMgr() const; - const int m_configVersion; + const int m_configVersion; - QVector m_history; + QVector m_history; - QString m_tagGraph; + QString m_tagGraph; - QJsonObject m_extraConfigs; + QJsonObject m_extraConfigs; - // Managed by QObject. - NotebookDatabaseAccess *m_dbAccess = nullptr; + // Managed by QObject. + NotebookDatabaseAccess *m_dbAccess = nullptr; - // Managed by QObject. - NotebookTagMgr *m_tagMgr = nullptr; - }; -} // ns vnotex + // Managed by QObject. + NotebookTagMgr *m_tagMgr = nullptr; +}; +} // namespace vnotex #endif // BUNDLENOTEBOOK_H diff --git a/src/core/notebook/bundlenotebookfactory.cpp b/src/core/notebook/bundlenotebookfactory.cpp index a7ab7d8207..86e95d5a8b 100644 --- a/src/core/notebook/bundlenotebookfactory.cpp +++ b/src/core/notebook/bundlenotebookfactory.cpp @@ -1,105 +1,84 @@ #include "bundlenotebookfactory.h" -#include #include +#include -#include #include "../exception.h" -#include "notebookconfigmgr/bundlenotebookconfigmgr.h" -#include "notebookparameters.h" #include "bundlenotebook.h" -#include "notebookmgr.h" +#include "notebookconfigmgr/bundlenotebookconfigmgr.h" #include "notebookconfigmgr/notebookconfig.h" +#include "notebookmgr.h" +#include "notebookparameters.h" +#include using namespace vnotex; -BundleNotebookFactory::BundleNotebookFactory() -{ -} +BundleNotebookFactory::BundleNotebookFactory() {} -QString BundleNotebookFactory::getName() const -{ - return QStringLiteral("bundle.vnotex"); -} +QString BundleNotebookFactory::getName() const { return QStringLiteral("bundle.vnotex"); } -QString BundleNotebookFactory::getDisplayName() const -{ - return QObject::tr("Bundle Notebook"); -} +QString BundleNotebookFactory::getDisplayName() const { return QObject::tr("Bundle Notebook"); } -QString BundleNotebookFactory::getDescription() const -{ - return QObject::tr("A notebook with configuration files to track its content"); +QString BundleNotebookFactory::getDescription() const { + return QObject::tr("A notebook with configuration files to track its content"); } // Check if root folder is valid for a new notebook. -static void checkRootFolderForNewNotebook(const NotebookParameters &p_paras) -{ - if (p_paras.m_rootFolderPath.isEmpty()) { - QString msg("no local root folder is specified"); - qCritical() << msg; - throw Exception(Exception::Type::InvalidPath, msg); - } else if (p_paras.m_ensureEmptyRootFolder && !PathUtils::isEmptyDir(p_paras.m_rootFolderPath)) { - QString msg = QStringLiteral("local root folder must be empty: %1 (%2)") - .arg(p_paras.m_rootFolderPath, PathUtils::absolutePath(p_paras.m_rootFolderPath)); - qCritical() << msg; - throw Exception(Exception::Type::InvalidPath, msg); - } +static void checkRootFolderForNewNotebook(const NotebookParameters &p_paras) { + if (p_paras.m_rootFolderPath.isEmpty()) { + QString msg("no local root folder is specified"); + qCritical() << msg; + throw Exception(Exception::Type::InvalidPath, msg); + } else if (p_paras.m_ensureEmptyRootFolder && !PathUtils::isEmptyDir(p_paras.m_rootFolderPath)) { + QString msg = + QStringLiteral("local root folder must be empty: %1 (%2)") + .arg(p_paras.m_rootFolderPath, PathUtils::absolutePath(p_paras.m_rootFolderPath)); + qCritical() << msg; + throw Exception(Exception::Type::InvalidPath, msg); + } } -QSharedPointer BundleNotebookFactory::newNotebook(const NotebookParameters &p_paras) -{ - checkParameters(p_paras); +QSharedPointer BundleNotebookFactory::newNotebook(const NotebookParameters &p_paras) { + checkParameters(p_paras); - checkRootFolderForNewNotebook(p_paras); + checkRootFolderForNewNotebook(p_paras); - p_paras.m_notebookConfigMgr->createEmptySkeleton(p_paras); + p_paras.m_notebookConfigMgr->createEmptySkeleton(p_paras); - auto nbConfig = BundleNotebookConfigMgr::readNotebookConfig(p_paras.m_notebookBackend); - auto notebook = QSharedPointer::create(p_paras, nbConfig); - return notebook; + auto nbConfig = BundleNotebookConfigMgr::readNotebookConfig(p_paras.m_notebookBackend); + auto notebook = QSharedPointer::create(p_paras, nbConfig); + return notebook; } -QSharedPointer BundleNotebookFactory::createNotebook(const NotebookMgr &p_mgr, - const QString &p_rootFolderPath, - const QSharedPointer &p_backend) -{ - // Read basic info about this notebook. - auto nbConfig = BundleNotebookConfigMgr::readNotebookConfig(p_backend); - auto paras = NotebookParameters::createNotebookParameters(p_mgr, - p_backend, - getName(), - nbConfig->m_name, - nbConfig->m_description, - p_rootFolderPath, - QIcon(), - nbConfig->m_imageFolder, - nbConfig->m_attachmentFolder, - nbConfig->m_createdTimeUtc, - nbConfig->m_versionController, - nbConfig->m_notebookConfigMgr); - checkParameters(*paras); - auto notebook = QSharedPointer::create(*paras, nbConfig); - return notebook; +QSharedPointer +BundleNotebookFactory::createNotebook(const NotebookMgr &p_mgr, const QString &p_rootFolderPath, + const QSharedPointer &p_backend) { + // Read basic info about this notebook. + auto nbConfig = BundleNotebookConfigMgr::readNotebookConfig(p_backend); + auto paras = NotebookParameters::createNotebookParameters( + p_mgr, p_backend, getName(), nbConfig->m_name, nbConfig->m_description, p_rootFolderPath, + QIcon(), nbConfig->m_imageFolder, nbConfig->m_attachmentFolder, nbConfig->m_createdTimeUtc, + nbConfig->m_versionController, nbConfig->m_notebookConfigMgr); + checkParameters(*paras); + auto notebook = QSharedPointer::create(*paras, nbConfig); + return notebook; } -void BundleNotebookFactory::checkParameters(const NotebookParameters &p_paras) const -{ - auto configMgr = dynamic_cast(p_paras.m_notebookConfigMgr.data()); - if (!configMgr) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("Invalid notebook configuration manager")); - } +void BundleNotebookFactory::checkParameters(const NotebookParameters &p_paras) const { + auto configMgr = dynamic_cast(p_paras.m_notebookConfigMgr.data()); + if (!configMgr) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("Invalid notebook configuration manager")); + } } -bool BundleNotebookFactory::checkRootFolder(const QSharedPointer &p_backend) -{ - try { - BundleNotebookConfigMgr::readNotebookConfig(p_backend); - } catch (Exception &p_e) { - Q_UNUSED(p_e); - return false; - } +bool BundleNotebookFactory::checkRootFolder(const QSharedPointer &p_backend) { + try { + BundleNotebookConfigMgr::readNotebookConfig(p_backend); + } catch (Exception &p_e) { + Q_UNUSED(p_e); + return false; + } - return true; + return true; } diff --git a/src/core/notebook/bundlenotebookfactory.h b/src/core/notebook/bundlenotebookfactory.h index 455c60311c..02e9ce845d 100644 --- a/src/core/notebook/bundlenotebookfactory.h +++ b/src/core/notebook/bundlenotebookfactory.h @@ -3,36 +3,33 @@ #include "inotebookfactory.h" +namespace vnotex { +class BundleNotebookFactory : public INotebookFactory { +public: + BundleNotebookFactory(); -namespace vnotex -{ - class BundleNotebookFactory : public INotebookFactory - { - public: - BundleNotebookFactory(); + // Get the name of this factory. + QString getName() const Q_DECL_OVERRIDE; - // Get the name of this factory. - QString getName() const Q_DECL_OVERRIDE; + // Get the display name of this factory. + QString getDisplayName() const Q_DECL_OVERRIDE; - // Get the display name of this factory. - QString getDisplayName() const Q_DECL_OVERRIDE; + // Get the description of this factory. + QString getDescription() const Q_DECL_OVERRIDE; - // Get the description of this factory. - QString getDescription() const Q_DECL_OVERRIDE; + // New a notebook with given information and return an instance of that notebook. + QSharedPointer newNotebook(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; - // New a notebook with given information and return an instance of that notebook. - QSharedPointer newNotebook(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; + // Create a Notebook instance from existing root folder. + QSharedPointer + createNotebook(const NotebookMgr &p_mgr, const QString &p_rootFolderPath, + const QSharedPointer &p_backend) Q_DECL_OVERRIDE; - // Create a Notebook instance from existing root folder. - QSharedPointer createNotebook(const NotebookMgr &p_mgr, - const QString &p_rootFolderPath, - const QSharedPointer &p_backend) Q_DECL_OVERRIDE; + bool checkRootFolder(const QSharedPointer &p_backend) Q_DECL_OVERRIDE; - bool checkRootFolder(const QSharedPointer &p_backend) Q_DECL_OVERRIDE; - - private: - void checkParameters(const NotebookParameters &p_paras) const; - }; -} // ns vnotex +private: + void checkParameters(const NotebookParameters &p_paras) const; +}; +} // namespace vnotex #endif // BUNDLENOTEBOOKFACTORY_H diff --git a/src/core/notebook/externalnode.cpp b/src/core/notebook/externalnode.cpp index 7d6d631b7b..5f1c7f8dc5 100644 --- a/src/core/notebook/externalnode.cpp +++ b/src/core/notebook/externalnode.cpp @@ -6,29 +6,16 @@ using namespace vnotex; ExternalNode::ExternalNode(Node *p_parent, const QString &p_name, Type p_type) - : m_parentNode(p_parent), - m_name(p_name), - m_type(p_type) -{ - Q_ASSERT(m_parentNode); + : m_parentNode(p_parent), m_name(p_name), m_type(p_type) { + Q_ASSERT(m_parentNode); } -Node *ExternalNode::getNode() const -{ - return m_parentNode; -} +Node *ExternalNode::getNode() const { return m_parentNode; } -const QString &ExternalNode::getName() const -{ - return m_name; -} +const QString &ExternalNode::getName() const { return m_name; } -bool ExternalNode::isFolder() const -{ - return m_type == Type::Folder; -} +bool ExternalNode::isFolder() const { return m_type == Type::Folder; } -QString ExternalNode::fetchAbsolutePath() const -{ - return PathUtils::concatenateFilePath(m_parentNode->fetchAbsolutePath(), m_name); +QString ExternalNode::fetchAbsolutePath() const { + return PathUtils::concatenateFilePath(m_parentNode->fetchAbsolutePath(), m_name); } diff --git a/src/core/notebook/externalnode.h b/src/core/notebook/externalnode.h index 5084abdbe3..6b3e5f5495 100644 --- a/src/core/notebook/externalnode.h +++ b/src/core/notebook/externalnode.h @@ -3,40 +3,34 @@ #include -namespace vnotex -{ - class Node; +namespace vnotex { +class Node; - // External node not managed by VNote. - class ExternalNode - { - public: - enum class Type - { - File, - Folder - }; +// External node not managed by VNote. +class ExternalNode { +public: + enum class Type { File, Folder }; - ExternalNode(Node *p_parent, const QString &p_name, Type p_type); + ExternalNode(Node *p_parent, const QString &p_name, Type p_type); - // Get parent node. - Node *getNode() const; + // Get parent node. + Node *getNode() const; - const QString &getName() const; + const QString &getName() const; - bool isFolder() const; + bool isFolder() const; - QString fetchAbsolutePath() const; + QString fetchAbsolutePath() const; - private: - // Parent node. - // We support only one level further the external folder. - Node *m_parentNode = nullptr; +private: + // Parent node. + // We support only one level further the external folder. + Node *m_parentNode = nullptr; - QString m_name; + QString m_name; - Type m_type = Type::File; - }; -} + Type m_type = Type::File; +}; +} // namespace vnotex #endif // EXTERNALNODE_H diff --git a/src/core/notebook/historyi.h b/src/core/notebook/historyi.h index f01fc95fe2..c5b582dca6 100644 --- a/src/core/notebook/historyi.h +++ b/src/core/notebook/historyi.h @@ -5,21 +5,19 @@ #include -namespace vnotex -{ - // History interface for notebook. - class HistoryI - { - public: - virtual ~HistoryI() = default; +namespace vnotex { +// History interface for notebook. +class HistoryI { +public: + virtual ~HistoryI() = default; - virtual const QVector &getHistory() const = 0; + virtual const QVector &getHistory() const = 0; - virtual void addHistory(const HistoryItem &p_item) = 0; + virtual void addHistory(const HistoryItem &p_item) = 0; - virtual void removeHistory(const QString &p_itemPath) = 0; + virtual void removeHistory(const QString &p_itemPath) = 0; - virtual void clearHistory() = 0; - }; -} + virtual void clearHistory() = 0; +}; +} // namespace vnotex #endif // HISTORYI_H diff --git a/src/core/notebook/inotebookfactory.h b/src/core/notebook/inotebookfactory.h index 9247ff44e8..f21afd0270 100644 --- a/src/core/notebook/inotebookfactory.h +++ b/src/core/notebook/inotebookfactory.h @@ -1,46 +1,42 @@ #ifndef INOTEBOOKFACTORY_H #define INOTEBOOKFACTORY_H -#include #include +#include + +namespace vnotex { +class Notebook; +class NotebookParameters; +class INotebookBackend; +class NotebookMgr; + +// Abstract factory to create notebook. +class INotebookFactory { +public: + virtual ~INotebookFactory() {} + + // Get the name of this factory. + virtual QString getName() const = 0; + + // Get the display name of this factory. + virtual QString getDisplayName() const = 0; + + // Get the description of this factory. + virtual QString getDescription() const = 0; + + // New a notebook with given information and return an instance of that notebook. + // The root folder should be empty. + virtual QSharedPointer newNotebook(const NotebookParameters &p_paras) = 0; + + // Create a Notebook instance from existing root folder. + virtual QSharedPointer + createNotebook(const NotebookMgr &p_mgr, const QString &p_rootFolderPath, + const QSharedPointer &p_backend) = 0; -namespace vnotex -{ - class Notebook; - class NotebookParameters; - class INotebookBackend; - class NotebookMgr; - - // Abstract factory to create notebook. - class INotebookFactory - { - public: - virtual ~INotebookFactory() - { - } - - // Get the name of this factory. - virtual QString getName() const = 0; - - // Get the display name of this factory. - virtual QString getDisplayName() const = 0; - - // Get the description of this factory. - virtual QString getDescription() const = 0; - - // New a notebook with given information and return an instance of that notebook. - // The root folder should be empty. - virtual QSharedPointer newNotebook(const NotebookParameters &p_paras) = 0; - - // Create a Notebook instance from existing root folder. - virtual QSharedPointer createNotebook(const NotebookMgr &p_mgr, - const QString &p_rootFolderPath, - const QSharedPointer &p_backend) = 0; - - // Check if @p_rootFolderPath is a valid root folder to use by this factory - // to create a notebook. - virtual bool checkRootFolder(const QSharedPointer &p_backend) = 0; - }; -} // ns vnotex + // Check if @p_rootFolderPath is a valid root folder to use by this factory + // to create a notebook. + virtual bool checkRootFolder(const QSharedPointer &p_backend) = 0; +}; +} // namespace vnotex #endif // INOTEBOOKFACTORY_H diff --git a/src/core/notebook/node.cpp b/src/core/notebook/node.cpp index a9eb8c273c..10a81647b6 100644 --- a/src/core/notebook/node.cpp +++ b/src/core/notebook/node.cpp @@ -2,566 +2,407 @@ #include -#include -#include -#include -#include -#include "notebook.h" #include "nodeparameters.h" +#include "notebook.h" #include +#include +#include +#include +#include using namespace vnotex; -Node::Node(Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras, - Notebook *p_notebook, - Node *p_parent) - : m_notebook(p_notebook), - m_loaded(true), - m_flags(p_flags), - m_id(p_paras.m_id), - m_signature(p_paras.m_signature), - m_name(p_name), - m_createdTimeUtc(p_paras.m_createdTimeUtc), - m_modifiedTimeUtc(p_paras.m_modifiedTimeUtc), - m_tags(p_paras.m_tags), - m_attachmentFolder(p_paras.m_attachmentFolder), - m_visual(p_paras.m_visual), - m_parent(p_parent) -{ - Q_ASSERT(m_notebook); - - checkSignature(); -} +Node::Node(Flags p_flags, const QString &p_name, const NodeParameters &p_paras, + Notebook *p_notebook, Node *p_parent) + : m_notebook(p_notebook), m_loaded(true), m_flags(p_flags), m_id(p_paras.m_id), + m_signature(p_paras.m_signature), m_name(p_name), m_createdTimeUtc(p_paras.m_createdTimeUtc), + m_modifiedTimeUtc(p_paras.m_modifiedTimeUtc), m_tags(p_paras.m_tags), + m_attachmentFolder(p_paras.m_attachmentFolder), m_visual(p_paras.m_visual), + m_parent(p_parent) { + Q_ASSERT(m_notebook); -Node::Node(Flags p_flags, - const QString &p_name, - Notebook *p_notebook, - Node *p_parent) - : m_notebook(p_notebook), - m_flags(p_flags), - m_name(p_name), - m_parent(p_parent) -{ - Q_ASSERT(m_notebook); + checkSignature(); } -Node::~Node() -{ +Node::Node(Flags p_flags, const QString &p_name, Notebook *p_notebook, Node *p_parent) + : m_notebook(p_notebook), m_flags(p_flags), m_name(p_name), m_parent(p_parent) { + Q_ASSERT(m_notebook); } -bool Node::isLoaded() const -{ - return m_loaded; -} +Node::~Node() {} + +bool Node::isLoaded() const { return m_loaded; } void Node::loadCompleteInfo(const NodeParameters &p_paras, - const QVector> &p_children) -{ - Q_ASSERT(!m_loaded); - - m_id = p_paras.m_id; - m_signature = p_paras.m_signature; - m_createdTimeUtc = p_paras.m_createdTimeUtc; - m_modifiedTimeUtc = p_paras.m_modifiedTimeUtc; - Q_ASSERT(p_paras.m_tags.isEmpty()); - Q_ASSERT(p_paras.m_attachmentFolder.isEmpty()); - - m_visual = p_paras.m_visual; - - m_children = p_children; - m_loaded = true; - - checkSignature(); -} + const QVector> &p_children) { + Q_ASSERT(!m_loaded); -bool Node::isRoot() const -{ - return !m_parent && m_use == Use::Root; -} + m_id = p_paras.m_id; + m_signature = p_paras.m_signature; + m_createdTimeUtc = p_paras.m_createdTimeUtc; + m_modifiedTimeUtc = p_paras.m_modifiedTimeUtc; + Q_ASSERT(p_paras.m_tags.isEmpty()); + Q_ASSERT(p_paras.m_attachmentFolder.isEmpty()); -const QString &Node::getName() const -{ - return m_name; -} + m_visual = p_paras.m_visual; + + m_children = p_children; + m_loaded = true; -void Node::setName(const QString &p_name) -{ - m_name = p_name; + checkSignature(); } -void Node::updateName(const QString &p_name) -{ - if (m_name == p_name) { - return; - } +bool Node::isRoot() const { return !m_parent && m_use == Use::Root; } - getConfigMgr()->renameNode(this, p_name); - Q_ASSERT(m_name == p_name); +const QString &Node::getName() const { return m_name; } - emit m_notebook->nodeUpdated(this); +void Node::setName(const QString &p_name) { m_name = p_name; } + +void Node::updateName(const QString &p_name) { + if (m_name == p_name) { + return; + } + + getConfigMgr()->renameNode(this, p_name); + Q_ASSERT(m_name == p_name); + + emit m_notebook->nodeUpdated(this); } -bool Node::containsChild(const QString &p_name, bool p_caseSensitive) const -{ - return findChild(p_name, p_caseSensitive) != nullptr; +bool Node::containsChild(const QString &p_name, bool p_caseSensitive) const { + return findChild(p_name, p_caseSensitive) != nullptr; } -bool Node::containsChild(const QSharedPointer &p_node) const -{ - return m_children.indexOf(p_node) != -1; +bool Node::containsChild(const QSharedPointer &p_node) const { + return m_children.indexOf(p_node) != -1; } -bool Node::isLegalNameForNewChild(const QString &p_name) const -{ - if (p_name.isEmpty()) { - return false; - } +bool Node::isLegalNameForNewChild(const QString &p_name) const { + if (p_name.isEmpty()) { + return false; + } - auto mgr = getConfigMgr(); - if (mgr->isBuiltInFile(this, p_name) || mgr->isBuiltInFolder(this, p_name)) { - return false; - } + auto mgr = getConfigMgr(); + if (mgr->isBuiltInFile(this, p_name) || mgr->isBuiltInFolder(this, p_name)) { + return false; + } - if (containsChild(p_name, false)) { - return false; - } + if (containsChild(p_name, false)) { + return false; + } - return true; + return true; } -QSharedPointer Node::findChild(const QString &p_name, bool p_caseSensitive) const -{ - auto targetName = p_caseSensitive ? p_name : p_name.toLower(); - for (const auto &child : m_children) { - if (p_caseSensitive ? child->getName() == targetName - : child->getName().toLower() == targetName) { - return child; - } +QSharedPointer Node::findChild(const QString &p_name, bool p_caseSensitive) const { + auto targetName = p_caseSensitive ? p_name : p_name.toLower(); + for (const auto &child : m_children) { + if (p_caseSensitive ? child->getName() == targetName + : child->getName().toLower() == targetName) { + return child; } + } - return nullptr; + return nullptr; } -void Node::setParent(Node *p_parent) -{ - m_parent = p_parent; -} +void Node::setParent(Node *p_parent) { m_parent = p_parent; } -Node *Node::getParent() const -{ - return m_parent; -} +Node *Node::getParent() const { return m_parent; } -Node::Flags Node::getFlags() const -{ - return m_flags; -} +Node::Flags Node::getFlags() const { return m_flags; } -Node::Use Node::getUse() const -{ - return m_use; -} +Node::Use Node::getUse() const { return m_use; } -void Node::setUse(Node::Use p_use) -{ - m_use = p_use; -} +void Node::setUse(Node::Use p_use) { m_use = p_use; } -ID Node::getId() const -{ - return m_id; -} +ID Node::getId() const { return m_id; } -void Node::updateId(ID p_id) -{ - if (m_id == p_id) { - return; - } +void Node::updateId(ID p_id) { + if (m_id == p_id) { + return; + } - m_id = p_id; - save(); - emit m_notebook->nodeUpdated(this); + m_id = p_id; + save(); + emit m_notebook->nodeUpdated(this); } -ID Node::getSignature() const -{ - return m_signature; -} +ID Node::getSignature() const { return m_signature; } -const QDateTime &Node::getCreatedTimeUtc() const -{ - return m_createdTimeUtc; -} +const QDateTime &Node::getCreatedTimeUtc() const { return m_createdTimeUtc; } -const QDateTime &Node::getModifiedTimeUtc() const -{ - return m_modifiedTimeUtc; -} +const QDateTime &Node::getModifiedTimeUtc() const { return m_modifiedTimeUtc; } -void Node::setModifiedTimeUtc() -{ - m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); -} +void Node::setModifiedTimeUtc() { m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); } -const QVector> &Node::getChildrenRef() const -{ - return m_children; -} +const QVector> &Node::getChildrenRef() const { return m_children; } -QVector> Node::getChildren() const -{ - return m_children; -} +QVector> Node::getChildren() const { return m_children; } -int Node::getChildrenCount() const -{ - return m_children.size(); -} +int Node::getChildrenCount() const { return m_children.size(); } -void Node::addChild(const QSharedPointer &p_node) -{ - insertChild(m_children.size(), p_node); -} +void Node::addChild(const QSharedPointer &p_node) { insertChild(m_children.size(), p_node); } -void Node::insertChild(int p_idx, const QSharedPointer &p_node) -{ - Q_ASSERT(isContainer()); +void Node::insertChild(int p_idx, const QSharedPointer &p_node) { + Q_ASSERT(isContainer()); - p_node->setParent(this); + p_node->setParent(this); - m_children.insert(p_idx, p_node); + m_children.insert(p_idx, p_node); } -void Node::removeChild(const QSharedPointer &p_child) -{ - if (m_children.removeOne(p_child)) { - p_child->setParent(nullptr); - } +void Node::removeChild(const QSharedPointer &p_child) { + if (m_children.removeOne(p_child)) { + p_child->setParent(nullptr); + } } -Notebook *Node::getNotebook() const -{ - return m_notebook; -} +Notebook *Node::getNotebook() const { return m_notebook; } -bool Node::isAncestor(const Node *p_ancestor, const Node *p_child) -{ - if (!p_ancestor || !p_child) { - return false; - } +bool Node::isAncestor(const Node *p_ancestor, const Node *p_child) { + if (!p_ancestor || !p_child) { + return false; + } - while (p_child) { - p_child = p_child->getParent(); - if (p_child == p_ancestor) { - return true; - } + while (p_child) { + p_child = p_child->getParent(); + if (p_child == p_ancestor) { + return true; } + } - return false; + return false; } -const QStringList &Node::getTags() const -{ - return m_tags; -} +const QStringList &Node::getTags() const { return m_tags; } -void Node::updateTags(const QStringList &p_tags) -{ - if (p_tags == m_tags) { - return; - } +void Node::updateTags(const QStringList &p_tags) { + if (p_tags == m_tags) { + return; + } - m_tags = p_tags; - save(); - emit m_notebook->nodeUpdated(this); + m_tags = p_tags; + save(); + emit m_notebook->nodeUpdated(this); } -bool Node::isReadOnly() const -{ - return m_flags & Flag::ReadOnly; -} +bool Node::isReadOnly() const { return m_flags & Flag::ReadOnly; } -void Node::setReadOnly(bool p_readOnly) -{ - if (p_readOnly) { - m_flags |= Flag::ReadOnly; - } else { - m_flags &= ~Flag::ReadOnly; - } +void Node::setReadOnly(bool p_readOnly) { + if (p_readOnly) { + m_flags |= Flag::ReadOnly; + } else { + m_flags &= ~Flag::ReadOnly; + } } -QString Node::fetchPath() const -{ - if (!m_parent) { - return QString(); - } else { - return PathUtils::concatenateFilePath(m_parent->fetchPath(), m_name); - } +QString Node::fetchPath() const { + if (!m_parent) { + return QString(); + } else { + return PathUtils::concatenateFilePath(m_parent->fetchPath(), m_name); + } } -bool Node::isContainer() const -{ - return m_flags & Flag::Container; -} +bool Node::isContainer() const { return m_flags & Flag::Container; } -bool Node::hasContent() const -{ - return m_flags & Flag::Content; -} +bool Node::hasContent() const { return m_flags & Flag::Content; } -QDir Node::toDir() const -{ - if (isContainer()) { - return QDir(fetchAbsolutePath()); - } - Q_ASSERT(false); - return QDir(); +QDir Node::toDir() const { + if (isContainer()) { + return QDir(fetchAbsolutePath()); + } + Q_ASSERT(false); + return QDir(); } -void Node::load() -{ - if (isLoaded()) { - return; - } +void Node::load() { + if (isLoaded()) { + return; + } - getConfigMgr()->loadNode(this); + getConfigMgr()->loadNode(this); } -void Node::save() -{ - getConfigMgr()->saveNode(this); -} +void Node::save() { getConfigMgr()->saveNode(this); } -INotebookConfigMgr *Node::getConfigMgr() const -{ - return m_notebook->getConfigMgr().data(); -} +INotebookConfigMgr *Node::getConfigMgr() const { return m_notebook->getConfigMgr().data(); } -const QString &Node::getAttachmentFolder() const -{ - return m_attachmentFolder; -} +const QString &Node::getAttachmentFolder() const { return m_attachmentFolder; } -void Node::setAttachmentFolder(const QString &p_attachmentFolder) -{ - m_attachmentFolder = p_attachmentFolder; +void Node::setAttachmentFolder(const QString &p_attachmentFolder) { + m_attachmentFolder = p_attachmentFolder; } -QString Node::fetchAttachmentFolderPath() -{ - return getConfigMgr()->fetchNodeAttachmentFolderPath(this); +QString Node::fetchAttachmentFolderPath() { + return getConfigMgr()->fetchNodeAttachmentFolderPath(this); } -INotebookBackend *Node::getBackend() const -{ - return m_notebook->getBackend().data(); -} +INotebookBackend *Node::getBackend() const { return m_notebook->getBackend().data(); } -bool Node::canRename(const QString &p_newName) const -{ - if (p_newName == m_name) { - return true; - } +bool Node::canRename(const QString &p_newName) const { + if (p_newName == m_name) { + return true; + } - if (p_newName.isEmpty()) { - return false; - } + if (p_newName.isEmpty()) { + return false; + } - Q_ASSERT(m_parent); - if (p_newName.toLower() == m_name.toLower()) { - if (m_parent->containsChild(p_newName, true)) { - return false; - } else { - return true; - } + Q_ASSERT(m_parent); + if (p_newName.toLower() == m_name.toLower()) { + if (m_parent->containsChild(p_newName, true)) { + return false; + } else { + return true; } + } - if (!m_parent->isLegalNameForNewChild(p_newName)) { - return false; - } + if (!m_parent->isLegalNameForNewChild(p_newName)) { + return false; + } - return true; + return true; } -void Node::sortChildren(const QVector &p_beforeIdx, const QVector &p_afterIdx) -{ - Q_ASSERT(isContainer()); +void Node::sortChildren(const QVector &p_beforeIdx, const QVector &p_afterIdx) { + Q_ASSERT(isContainer()); - Q_ASSERT(p_beforeIdx.size() == p_afterIdx.size()); + Q_ASSERT(p_beforeIdx.size() == p_afterIdx.size()); - if (p_beforeIdx == p_afterIdx) { - return; - } + if (p_beforeIdx == p_afterIdx) { + return; + } - auto ori = m_children; - for (int i = 0; i < p_beforeIdx.size(); ++i) { - if (p_beforeIdx[i] != p_afterIdx[i]) { - m_children[p_beforeIdx[i]] = ori[p_afterIdx[i]]; - } + auto ori = m_children; + for (int i = 0; i < p_beforeIdx.size(); ++i) { + if (p_beforeIdx[i] != p_afterIdx[i]) { + m_children[p_beforeIdx[i]] = ori[p_afterIdx[i]]; } + } - save(); + save(); } -QVector> Node::fetchExternalChildren() const -{ - return getConfigMgr()->fetchExternalChildren(const_cast(this)); +QVector> Node::fetchExternalChildren() const { + return getConfigMgr()->fetchExternalChildren(const_cast(this)); } -bool Node::containsContainerChild(const QString &p_name) const -{ - // TODO: we assume that m_children is sorted first the container children. - for (auto &child : m_children) { - if (!child->isContainer()) { - break; - } - - if (child->getName() == p_name) { - return true; - } +bool Node::containsContainerChild(const QString &p_name) const { + // TODO: we assume that m_children is sorted first the container children. + for (auto &child : m_children) { + if (!child->isContainer()) { + break; } - return false; + if (child->getName() == p_name) { + return true; + } + } + + return false; } -bool Node::containsContentChild(const QString &p_name) const -{ - // TODO: we assume that m_children is sorted: first the container children then content children. - for (int i = m_children.size() - 1; i >= 0; --i) { - if (m_children[i]->isContainer()) { - break; - } - - if (m_children[i]->getName() == p_name) { - return true; - } +bool Node::containsContentChild(const QString &p_name) const { + // TODO: we assume that m_children is sorted: first the container children then content children. + for (int i = m_children.size() - 1; i >= 0; --i) { + if (m_children[i]->isContainer()) { + break; } - return false; -} + if (m_children[i]->getName() == p_name) { + return true; + } + } -bool Node::exists() const -{ - return m_flags & Flag::Exists; + return false; } -void Node::setExists(bool p_exists) -{ - if (p_exists) { - m_flags |= Flag::Exists; - } else { - m_flags &= ~Flag::Exists; - } +bool Node::exists() const { return m_flags & Flag::Exists; } + +void Node::setExists(bool p_exists) { + if (p_exists) { + m_flags |= Flag::Exists; + } else { + m_flags &= ~Flag::Exists; + } } -bool Node::checkExists() -{ - bool before = exists(); - bool after = getConfigMgr()->checkNodeExists(this); - if (before != after) { - emit m_notebook->nodeUpdated(this); - } - return after; +bool Node::checkExists() { + bool before = exists(); + bool after = getConfigMgr()->checkNodeExists(this); + if (before != after) { + emit m_notebook->nodeUpdated(this); + } + return after; } -QList> Node::collectFiles() -{ - QList> files; +QList> Node::collectFiles() { + QList> files; - load(); + load(); - if (hasContent()) { - files.append(getContentFile()); - } + if (hasContent()) { + files.append(getContentFile()); + } - if (isContainer()) { - for (const auto &child : m_children) { - files.append(child->collectFiles()); - } + if (isContainer()) { + for (const auto &child : m_children) { + files.append(child->collectFiles()); } + } - return files; + return files; } -ID Node::generateSignature() -{ - return static_cast(QDateTime::currentDateTime().toSecsSinceEpoch() + (static_cast(QRandomGenerator::global()->generate()) << 32)); +ID Node::generateSignature() { + return static_cast(QDateTime::currentDateTime().toSecsSinceEpoch() + + (static_cast(QRandomGenerator::global()->generate()) << 32)); } -void Node::checkSignature() -{ - if (m_signature == InvalidId) { - m_signature = generateSignature(); - } +void Node::checkSignature() { + if (m_signature == InvalidId) { + m_signature = generateSignature(); + } } // 视觉效果相关方法 -const NodeVisual &Node::getVisual() const -{ - return m_visual; -} +const NodeVisual &Node::getVisual() const { return m_visual; } -void Node::setVisual(const NodeVisual &p_visual) -{ - m_visual = p_visual; -} +void Node::setVisual(const NodeVisual &p_visual) { m_visual = p_visual; } // 视觉效果便捷访问方法 -const QString &Node::getBackgroundColor() const -{ - return m_visual.getBackgroundColor(); -} +const QString &Node::getBackgroundColor() const { return m_visual.getBackgroundColor(); } -void Node::setBackgroundColor(const QString &p_backgroundColor) -{ - m_visual.setBackgroundColor(p_backgroundColor); +void Node::setBackgroundColor(const QString &p_backgroundColor) { + m_visual.setBackgroundColor(p_backgroundColor); } -const QString &Node::getBorderColor() const -{ - return m_visual.getBorderColor(); -} +const QString &Node::getBorderColor() const { return m_visual.getBorderColor(); } -void Node::setBorderColor(const QString &p_borderColor) -{ - m_visual.setBorderColor(p_borderColor); -} +void Node::setBorderColor(const QString &p_borderColor) { m_visual.setBorderColor(p_borderColor); } -const QString &Node::getNameColor() const -{ - return m_visual.getNameColor(); -} +const QString &Node::getNameColor() const { return m_visual.getNameColor(); } -void Node::setNameColor(const QString &p_nameColor) -{ - m_visual.setNameColor(p_nameColor); -} +void Node::setNameColor(const QString &p_nameColor) { m_visual.setNameColor(p_nameColor); } -QString Node::getEffectiveBackgroundColor() const -{ - return getBackgroundColor(); -} +QString Node::getEffectiveBackgroundColor() const { return getBackgroundColor(); } -QString Node::getEffectiveBorderColor() const -{ - return getBorderColor(); -} +QString Node::getEffectiveBorderColor() const { return getBorderColor(); } -void Node::updateNodeVisual(const NodeVisual &p_visual) -{ - if (m_visual.getBackgroundColor() == p_visual.getBackgroundColor() && - m_visual.getBorderColor() == p_visual.getBorderColor() && - m_visual.getNameColor() == p_visual.getNameColor()) { - return; - } +void Node::updateNodeVisual(const NodeVisual &p_visual) { + if (m_visual.getBackgroundColor() == p_visual.getBackgroundColor() && + m_visual.getBorderColor() == p_visual.getBorderColor() && + m_visual.getNameColor() == p_visual.getNameColor()) { + return; + } - m_visual = p_visual; + m_visual = p_visual; - // 持久化更新 - getConfigMgr()->updateNodeVisual(this, p_visual); + // 持久化更新 + getConfigMgr()->updateNodeVisual(this, p_visual); - // 界面更新 - emit m_notebook->nodeUpdated(this); + // 界面更新 + emit m_notebook->nodeUpdated(this); } diff --git a/src/core/notebook/node.h b/src/core/notebook/node.h index 4b562eddd7..bee4a47fdb 100644 --- a/src/core/notebook/node.h +++ b/src/core/notebook/node.h @@ -2,237 +2,227 @@ #define NODE_H #include -#include -#include #include #include +#include +#include -#include #include "nodevisual.h" +#include -namespace vnotex -{ - class Notebook; - class INotebookConfigMgr; - class INotebookBackend; - class File; - class ExternalNode; - class NodeParameters; +namespace vnotex { +class Notebook; +class INotebookConfigMgr; +class INotebookBackend; +class File; +class ExternalNode; +class NodeParameters; - // Node of notebook. - class Node : public QEnableSharedFromThis - { - public: - enum Flag { - None = 0, - // A node with content. - Content = 0x1, - // A node with children. - Container = 0x2, - ReadOnly = 0x4, - // Whether a node exists on disk. - Exists = 0x10 - }; - Q_DECLARE_FLAGS(Flags, Flag) +// Node of notebook. +class Node : public QEnableSharedFromThis { +public: + enum Flag { + None = 0, + // A node with content. + Content = 0x1, + // A node with children. + Container = 0x2, + ReadOnly = 0x4, + // Whether a node exists on disk. + Exists = 0x10 + }; + Q_DECLARE_FLAGS(Flags, Flag) - enum Use { - Normal, - Root - }; + enum Use { Normal, Root }; - enum { InvalidId = 0 }; + enum { InvalidId = 0 }; - // Constructor with all information loaded. - Node(Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras, - Notebook *p_notebook, - Node *p_parent); + // Constructor with all information loaded. + Node(Flags p_flags, const QString &p_name, const NodeParameters &p_paras, Notebook *p_notebook, + Node *p_parent); - // Constructor not loaded. - Node(Flags p_flags, - const QString &p_name, - Notebook *p_notebook, - Node *p_parent); + // Constructor not loaded. + Node(Flags p_flags, const QString &p_name, Notebook *p_notebook, Node *p_parent); - virtual ~Node(); + virtual ~Node(); - bool isLoaded() const; + bool isLoaded() const; - bool isRoot() const; + bool isRoot() const; - const QString &getName() const; - void setName(const QString &p_name); + const QString &getName() const; + void setName(const QString &p_name); - void updateName(const QString &p_name); + void updateName(const QString &p_name); - // Fetch path of this node within notebook. - // This may not be the same as the actual file path. It depends on the config mgr. - virtual QString fetchPath() const; + // Fetch path of this node within notebook. + // This may not be the same as the actual file path. It depends on the config mgr. + virtual QString fetchPath() const; - // Fetch absolute file path if available. - virtual QString fetchAbsolutePath() const = 0; + // Fetch absolute file path if available. + virtual QString fetchAbsolutePath() const = 0; - bool isContainer() const; + bool isContainer() const; - bool hasContent() const; + bool hasContent() const; - // Whether the node exists on disk (without real check). - bool exists() const; + // Whether the node exists on disk (without real check). + bool exists() const; - bool checkExists(); + bool checkExists(); - void setExists(bool p_exists); + void setExists(bool p_exists); - Node::Flags getFlags() const; + Node::Flags getFlags() const; - Node::Use getUse() const; - void setUse(Node::Use p_use); + Node::Use getUse() const; + void setUse(Node::Use p_use); - ID getId() const; - void updateId(ID p_id); + ID getId() const; + void updateId(ID p_id); - ID getSignature() const; + ID getSignature() const; - const QDateTime &getCreatedTimeUtc() const; + const QDateTime &getCreatedTimeUtc() const; - const QDateTime &getModifiedTimeUtc() const; - void setModifiedTimeUtc(); + const QDateTime &getModifiedTimeUtc() const; + void setModifiedTimeUtc(); - const QVector> &getChildrenRef() const; - QVector> getChildren() const; - int getChildrenCount() const; + const QVector> &getChildrenRef() const; + QVector> getChildren() const; + int getChildrenCount() const; - QSharedPointer findChild(const QString &p_name, bool p_caseSensitive = true) const; + QSharedPointer findChild(const QString &p_name, bool p_caseSensitive = true) const; - bool containsChild(const QString &p_name, bool p_caseSensitive = true) const; + bool containsChild(const QString &p_name, bool p_caseSensitive = true) const; - bool containsChild(const QSharedPointer &p_node) const; + bool containsChild(const QSharedPointer &p_node) const; - // Case sensitive. - bool containsContainerChild(const QString &p_name) const; + // Case sensitive. + bool containsContainerChild(const QString &p_name) const; - // Case sensitive. - bool containsContentChild(const QString &p_name) const; + // Case sensitive. + bool containsContentChild(const QString &p_name) const; - bool isLegalNameForNewChild(const QString &p_name) const; + bool isLegalNameForNewChild(const QString &p_name) const; - void addChild(const QSharedPointer &p_node); + void addChild(const QSharedPointer &p_node); - void insertChild(int p_idx, const QSharedPointer &p_node); + void insertChild(int p_idx, const QSharedPointer &p_node); - void removeChild(const QSharedPointer &p_node); + void removeChild(const QSharedPointer &p_node); - QVector> fetchExternalChildren() const; + QVector> fetchExternalChildren() const; - void setParent(Node *p_parent); - Node *getParent() const; + void setParent(Node *p_parent); + Node *getParent() const; - Notebook *getNotebook() const; + Notebook *getNotebook() const; - virtual void load(); - virtual void save(); + virtual void load(); + virtual void save(); - const QStringList &getTags() const; - void updateTags(const QStringList &p_tags); + const QStringList &getTags() const; + void updateTags(const QStringList &p_tags); - const QString &getAttachmentFolder() const; - void setAttachmentFolder(const QString &p_attachmentFolder); + const QString &getAttachmentFolder() const; + void setAttachmentFolder(const QString &p_attachmentFolder); - QString fetchAttachmentFolderPath(); + QString fetchAttachmentFolderPath(); - // 视觉效果相关方法 - const NodeVisual &getVisual() const; - void setVisual(const NodeVisual &p_visual); + // 视觉效果相关方法 + const NodeVisual &getVisual() const; + void setVisual(const NodeVisual &p_visual); - // 视觉效果便捷访问方法 - const QString &getBackgroundColor() const; - void setBackgroundColor(const QString &p_backgroundColor); + // 视觉效果便捷访问方法 + const QString &getBackgroundColor() const; + void setBackgroundColor(const QString &p_backgroundColor); - const QString &getBorderColor() const; - void setBorderColor(const QString &p_borderColor); + const QString &getBorderColor() const; + void setBorderColor(const QString &p_borderColor); - const QString &getNameColor() const; - void setNameColor(const QString &p_nameColor); + const QString &getNameColor() const; + void setNameColor(const QString &p_nameColor); - // 获取有效颜色(直接返回设置的颜色) - QString getEffectiveBackgroundColor() const; - QString getEffectiveBorderColor() const; + // 获取有效颜色(直接返回设置的颜色) + QString getEffectiveBackgroundColor() const; + QString getEffectiveBorderColor() const; - void updateNodeVisual(const NodeVisual &p_visual); + void updateNodeVisual(const NodeVisual &p_visual); - virtual QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) = 0; + virtual QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) = 0; - virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0; + virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0; - virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0; + virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0; - virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0; + virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0; - virtual void removeAttachment(const QStringList &p_paths) = 0; + virtual void removeAttachment(const QStringList &p_paths) = 0; - QDir toDir() const; + QDir toDir() const; - bool isReadOnly() const; - void setReadOnly(bool p_readOnly); + bool isReadOnly() const; + void setReadOnly(bool p_readOnly); - // Get File if this node has content. - virtual QSharedPointer getContentFile() = 0; + // Get File if this node has content. + virtual QSharedPointer getContentFile() = 0; - void loadCompleteInfo(const NodeParameters &p_paras, - const QVector> &p_children); + void loadCompleteInfo(const NodeParameters &p_paras, + const QVector> &p_children); - INotebookConfigMgr *getConfigMgr() const; + INotebookConfigMgr *getConfigMgr() const; - INotebookBackend *getBackend() const; + INotebookBackend *getBackend() const; - bool canRename(const QString &p_newName) const; + bool canRename(const QString &p_newName) const; - void sortChildren(const QVector &p_beforeIdx, const QVector &p_afterIdx); + void sortChildren(const QVector &p_beforeIdx, const QVector &p_afterIdx); - // Get content files recursively. - QList> collectFiles(); + // Get content files recursively. + QList> collectFiles(); - static bool isAncestor(const Node *p_ancestor, const Node *p_child); + static bool isAncestor(const Node *p_ancestor, const Node *p_child); - static ID generateSignature(); + static ID generateSignature(); - protected: - Notebook *m_notebook = nullptr; +protected: + Notebook *m_notebook = nullptr; - bool m_loaded = false; + bool m_loaded = false; - private: - void checkSignature(); +private: + void checkSignature(); - Flags m_flags = Flag::None; + Flags m_flags = Flag::None; - Use m_use = Use::Normal; + Use m_use = Use::Normal; - ID m_id = InvalidId; + ID m_id = InvalidId; - // A long random number created when the node is created. - // Use to avoid conflicts of m_id. - ID m_signature = InvalidId; + // A long random number created when the node is created. + // Use to avoid conflicts of m_id. + ID m_signature = InvalidId; - QString m_name; + QString m_name; - QDateTime m_createdTimeUtc; + QDateTime m_createdTimeUtc; - QDateTime m_modifiedTimeUtc; + QDateTime m_modifiedTimeUtc; - QStringList m_tags; + QStringList m_tags; - QString m_attachmentFolder; + QString m_attachmentFolder; - NodeVisual m_visual; + NodeVisual m_visual; - Node *m_parent = nullptr; + Node *m_parent = nullptr; - QVector> m_children; - }; + QVector> m_children; +}; - Q_DECLARE_OPERATORS_FOR_FLAGS(Node::Flags) -} // ns vnotex +Q_DECLARE_OPERATORS_FOR_FLAGS(Node::Flags) +} // namespace vnotex #endif // NODE_H diff --git a/src/core/notebook/nodeparameters.cpp b/src/core/notebook/nodeparameters.cpp index 3ed7068937..24506f62b5 100644 --- a/src/core/notebook/nodeparameters.cpp +++ b/src/core/notebook/nodeparameters.cpp @@ -2,7 +2,4 @@ using namespace vnotex; -NodeParameters::NodeParameters(ID p_id) - : m_id(p_id) -{ -} +NodeParameters::NodeParameters(ID p_id) : m_id(p_id) {} diff --git a/src/core/notebook/nodeparameters.h b/src/core/notebook/nodeparameters.h index c7010aed67..5f6ea7ce58 100644 --- a/src/core/notebook/nodeparameters.h +++ b/src/core/notebook/nodeparameters.h @@ -9,29 +9,27 @@ #include "node.h" #include "nodevisual.h" -namespace vnotex -{ - class NodeParameters - { - public: - NodeParameters() = default; +namespace vnotex { +class NodeParameters { +public: + NodeParameters() = default; - NodeParameters(ID p_id); + NodeParameters(ID p_id); - ID m_id = Node::InvalidId; + ID m_id = Node::InvalidId; - ID m_signature = Node::InvalidId; + ID m_signature = Node::InvalidId; - QDateTime m_createdTimeUtc = QDateTime::currentDateTimeUtc(); + QDateTime m_createdTimeUtc = QDateTime::currentDateTimeUtc(); - QDateTime m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); + QDateTime m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); - QStringList m_tags; + QStringList m_tags; - QString m_attachmentFolder; + QString m_attachmentFolder; - NodeVisual m_visual; - }; -} + NodeVisual m_visual; +}; +} // namespace vnotex #endif // NODEPARAMETERS_H diff --git a/src/core/notebook/nodevisual.cpp b/src/core/notebook/nodevisual.cpp index 4841ce031c..4e0978cebe 100644 --- a/src/core/notebook/nodevisual.cpp +++ b/src/core/notebook/nodevisual.cpp @@ -5,25 +5,17 @@ using namespace vnotex; -NodeVisual::NodeVisual(const QString &p_backgroundColor, - const QString &p_borderColor, +NodeVisual::NodeVisual(const QString &p_backgroundColor, const QString &p_borderColor, const QString &p_nameColor) - : m_backgroundColor(p_backgroundColor) - , m_borderColor(p_borderColor) - , m_nameColor(p_nameColor) -{ + : m_backgroundColor(p_backgroundColor), m_borderColor(p_borderColor), m_nameColor(p_nameColor) { } -bool NodeVisual::hasAnyVisualEffect() const -{ - return !m_backgroundColor.isEmpty() || - !m_borderColor.isEmpty() || - !m_nameColor.isEmpty(); +bool NodeVisual::hasAnyVisualEffect() const { + return !m_backgroundColor.isEmpty() || !m_borderColor.isEmpty() || !m_nameColor.isEmpty(); } -void NodeVisual::clearAllColors() -{ - m_backgroundColor.clear(); - m_borderColor.clear(); - m_nameColor.clear(); +void NodeVisual::clearAllColors() { + m_backgroundColor.clear(); + m_borderColor.clear(); + m_nameColor.clear(); } diff --git a/src/core/notebook/nodevisual.h b/src/core/notebook/nodevisual.h index 055d8dbc3e..03c694617f 100644 --- a/src/core/notebook/nodevisual.h +++ b/src/core/notebook/nodevisual.h @@ -8,41 +8,38 @@ * 自定义节点名称,背景颜色,边框颜色,节点名称颜色 * 支持清除所有颜色,包括背景颜色,边框颜色,节点名称颜色 * 支持级联修改,包括背景颜色,边框颜色,节点名称颜色 -*/ -namespace vnotex -{ - class NodeVisual - { - public: - NodeVisual() = default; - - NodeVisual(const QString &p_backgroundColor, - const QString &p_borderColor, - const QString &p_nameColor); - - // 背景颜色 - const QString &getBackgroundColor() const { return m_backgroundColor; } - void setBackgroundColor(const QString &p_color) { m_backgroundColor = p_color; } - - // 边框颜色 - const QString &getBorderColor() const { return m_borderColor; } - void setBorderColor(const QString &p_color) { m_borderColor = p_color; } - - // 节点名称颜色 - const QString &getNameColor() const { return m_nameColor; } - void setNameColor(const QString &p_color) { m_nameColor = p_color; } - - // 判断是否有任何视觉效果 - bool hasAnyVisualEffect() const; - - // 清除所有颜色 - void clearAllColors(); - - private: - QString m_backgroundColor; // 背景颜色 - QString m_borderColor; // 边框颜色 - QString m_nameColor; // 节点名称颜色 - }; -} + */ +namespace vnotex { +class NodeVisual { +public: + NodeVisual() = default; + + NodeVisual(const QString &p_backgroundColor, const QString &p_borderColor, + const QString &p_nameColor); + + // 背景颜色 + const QString &getBackgroundColor() const { return m_backgroundColor; } + void setBackgroundColor(const QString &p_color) { m_backgroundColor = p_color; } + + // 边框颜色 + const QString &getBorderColor() const { return m_borderColor; } + void setBorderColor(const QString &p_color) { m_borderColor = p_color; } + + // 节点名称颜色 + const QString &getNameColor() const { return m_nameColor; } + void setNameColor(const QString &p_color) { m_nameColor = p_color; } + + // 判断是否有任何视觉效果 + bool hasAnyVisualEffect() const; + + // 清除所有颜色 + void clearAllColors(); + +private: + QString m_backgroundColor; // 背景颜色 + QString m_borderColor; // 边框颜色 + QString m_nameColor; // 节点名称颜色 +}; +} // namespace vnotex #endif // NODEVISUAL_H diff --git a/src/core/notebook/notebook.cpp b/src/core/notebook/notebook.cpp index d83998fadf..c05cf27bf3 100644 --- a/src/core/notebook/notebook.cpp +++ b/src/core/notebook/notebook.cpp @@ -2,13 +2,13 @@ #include -#include +#include "nodeparameters.h" +#include #include #include -#include #include -#include -#include "nodeparameters.h" +#include +#include using namespace vnotex; @@ -18,391 +18,292 @@ const QString Notebook::c_defaultImageFolder = QStringLiteral("vx_images"); const QString Notebook::c_defaultRecycleBinFolder = QStringLiteral("vx_recycle_bin"); -static vnotex::ID generateNotebookID() -{ - static vnotex::ID id = Notebook::InvalidId; - return ++id; +static vnotex::ID generateNotebookID() { + static vnotex::ID id = Notebook::InvalidId; + return ++id; } -Notebook::Notebook(const NotebookParameters &p_paras, - QObject *p_parent) - : QObject(p_parent), - m_id(generateNotebookID()), - m_type(p_paras.m_type), - m_name(p_paras.m_name), - m_description(p_paras.m_description), - m_rootFolderPath(p_paras.m_rootFolderPath), - m_icon(p_paras.m_icon), - m_imageFolder(p_paras.m_imageFolder), - m_attachmentFolder(p_paras.m_attachmentFolder), - m_createdTimeUtc(p_paras.m_createdTimeUtc), - m_backend(p_paras.m_notebookBackend), - m_versionController(p_paras.m_versionController), - m_configMgr(p_paras.m_notebookConfigMgr) -{ - if (m_imageFolder.isEmpty()) { - m_imageFolder = c_defaultImageFolder; - } - if (m_attachmentFolder.isEmpty()) { - m_attachmentFolder = c_defaultAttachmentFolder; - } - if (m_recycleBinFolder.isEmpty()) { - m_recycleBinFolder = c_defaultRecycleBinFolder; - } +Notebook::Notebook(const NotebookParameters &p_paras, QObject *p_parent) + : QObject(p_parent), m_id(generateNotebookID()), m_type(p_paras.m_type), m_name(p_paras.m_name), + m_description(p_paras.m_description), m_rootFolderPath(p_paras.m_rootFolderPath), + m_icon(p_paras.m_icon), m_imageFolder(p_paras.m_imageFolder), + m_attachmentFolder(p_paras.m_attachmentFolder), m_createdTimeUtc(p_paras.m_createdTimeUtc), + m_backend(p_paras.m_notebookBackend), m_versionController(p_paras.m_versionController), + m_configMgr(p_paras.m_notebookConfigMgr) { + if (m_imageFolder.isEmpty()) { + m_imageFolder = c_defaultImageFolder; + } + if (m_attachmentFolder.isEmpty()) { + m_attachmentFolder = c_defaultAttachmentFolder; + } + if (m_recycleBinFolder.isEmpty()) { + m_recycleBinFolder = c_defaultRecycleBinFolder; + } - m_configMgr->setNotebook(this); + m_configMgr->setNotebook(this); } -Notebook::Notebook(const QString &p_name, QObject *p_parent) - : QObject(p_parent), - m_name(p_name) -{ -} +Notebook::Notebook(const QString &p_name, QObject *p_parent) : QObject(p_parent), m_name(p_name) {} -Notebook::~Notebook() -{ -} +Notebook::~Notebook() {} -void Notebook::initialize() -{ - if (m_initialized) { - return; - } +void Notebook::initialize() { + if (m_initialized) { + return; + } - m_initialized = true; - initializeInternal(); + m_initialized = true; + initializeInternal(); } -vnotex::ID Notebook::getId() const -{ - return m_id; -} +vnotex::ID Notebook::getId() const { return m_id; } -const QString &Notebook::getType() const -{ - return m_type; -} +const QString &Notebook::getType() const { return m_type; } -const QString &Notebook::getName() const -{ - return m_name; -} +const QString &Notebook::getName() const { return m_name; } -void Notebook::setName(const QString &p_name) -{ - m_name = p_name; -} +void Notebook::setName(const QString &p_name) { m_name = p_name; } -void Notebook::updateName(const QString &p_name) -{ - Q_ASSERT(!p_name.isEmpty()); - if (p_name == m_name) { - return; - } +void Notebook::updateName(const QString &p_name) { + Q_ASSERT(!p_name.isEmpty()); + if (p_name == m_name) { + return; + } - m_name = p_name; - updateNotebookConfig(); - emit updated(); + m_name = p_name; + updateNotebookConfig(); + emit updated(); } -const QString &Notebook::getDescription() const -{ - return m_description; -} +const QString &Notebook::getDescription() const { return m_description; } -void Notebook::setDescription(const QString &p_description) -{ - m_description = p_description; -} +void Notebook::setDescription(const QString &p_description) { m_description = p_description; } -void Notebook::updateDescription(const QString &p_description) -{ - if (p_description == m_description) { - return; - } +void Notebook::updateDescription(const QString &p_description) { + if (p_description == m_description) { + return; + } - m_description = p_description; - updateNotebookConfig(); - emit updated(); + m_description = p_description; + updateNotebookConfig(); + emit updated(); } -const QString &Notebook::getRootFolderPath() const -{ - return m_rootFolderPath; -} +const QString &Notebook::getRootFolderPath() const { return m_rootFolderPath; } -QString Notebook::getRootFolderAbsolutePath() const -{ - return PathUtils::absolutePath(m_rootFolderPath); +QString Notebook::getRootFolderAbsolutePath() const { + return PathUtils::absolutePath(m_rootFolderPath); } -QString Notebook::getConfigFolderAbsolutePath() const -{ - const auto &folderPath = m_configMgr->getConfigFolderPath(); - if (folderPath.isEmpty()) { - return QString(); - } +QString Notebook::getConfigFolderAbsolutePath() const { + const auto &folderPath = m_configMgr->getConfigFolderPath(); + if (folderPath.isEmpty()) { + return QString(); + } - return getBackend()->getFullPath(folderPath); + return getBackend()->getFullPath(folderPath); } -const QIcon &Notebook::getIcon() const -{ - return m_icon; -} +const QIcon &Notebook::getIcon() const { return m_icon; } -void Notebook::setIcon(const QIcon &p_icon) -{ - m_icon = p_icon; -} +void Notebook::setIcon(const QIcon &p_icon) { m_icon = p_icon; } -const QString &Notebook::getImageFolder() const -{ - return m_imageFolder; -} +const QString &Notebook::getImageFolder() const { return m_imageFolder; } -const QString &Notebook::getAttachmentFolder() const -{ - return m_attachmentFolder; -} +const QString &Notebook::getAttachmentFolder() const { return m_attachmentFolder; } -const QString &Notebook::getRecycleBinFolder() const -{ - return m_recycleBinFolder; -} +const QString &Notebook::getRecycleBinFolder() const { return m_recycleBinFolder; } -QString Notebook::getRecycleBinFolderAbsolutePath() const -{ - if (QDir::isAbsolutePath(m_recycleBinFolder)) { - if (!QFileInfo::exists(m_recycleBinFolder)) { - QDir dir(m_recycleBinFolder); - dir.mkpath(m_recycleBinFolder); - } - return m_recycleBinFolder; - } else { - auto folderPath = getBackend()->getFullPath(m_recycleBinFolder); - if (!getBackend()->exists(m_recycleBinFolder)) { - getBackend()->makePath(m_recycleBinFolder); - } - return folderPath; +QString Notebook::getRecycleBinFolderAbsolutePath() const { + if (QDir::isAbsolutePath(m_recycleBinFolder)) { + if (!QFileInfo::exists(m_recycleBinFolder)) { + QDir dir(m_recycleBinFolder); + dir.mkpath(m_recycleBinFolder); } + return m_recycleBinFolder; + } else { + auto folderPath = getBackend()->getFullPath(m_recycleBinFolder); + if (!getBackend()->exists(m_recycleBinFolder)) { + getBackend()->makePath(m_recycleBinFolder); + } + return folderPath; + } } -const QSharedPointer &Notebook::getBackend() const -{ - return m_backend; -} - -const QSharedPointer &Notebook::getVersionController() const -{ - return m_versionController; -} +const QSharedPointer &Notebook::getBackend() const { return m_backend; } -const QSharedPointer &Notebook::getConfigMgr() const -{ - return m_configMgr; +const QSharedPointer &Notebook::getVersionController() const { + return m_versionController; } -const QSharedPointer &Notebook::getRootNode() const -{ - if (!m_root) { - const_cast(this)->m_root = m_configMgr->loadRootNode(); - Q_ASSERT(m_root->isRoot()); - } +const QSharedPointer &Notebook::getConfigMgr() const { return m_configMgr; } - return m_root; -} +const QSharedPointer &Notebook::getRootNode() const { + if (!m_root) { + const_cast(this)->m_root = m_configMgr->loadRootNode(); + Q_ASSERT(m_root->isRoot()); + } -QSharedPointer Notebook::newNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const QString &p_content) -{ - return m_configMgr->newNode(p_parent, p_flags, p_name, p_content); + return m_root; } -const QDateTime &Notebook::getCreatedTimeUtc() const -{ - return m_createdTimeUtc; +QSharedPointer Notebook::newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const QString &p_content) { + return m_configMgr->newNode(p_parent, p_flags, p_name, p_content); } -QSharedPointer Notebook::loadNodeByPath(const QString &p_path) -{ - if (!PathUtils::pathContains(m_rootFolderPath, p_path)) { - return nullptr; - } +const QDateTime &Notebook::getCreatedTimeUtc() const { return m_createdTimeUtc; } - QString relativePath; - QFileInfo fi(p_path); - if (fi.isAbsolute()) { - if (!fi.exists()) { - return nullptr; - } +QSharedPointer Notebook::loadNodeByPath(const QString &p_path) { + if (!PathUtils::pathContains(m_rootFolderPath, p_path)) { + return nullptr; + } - relativePath = PathUtils::relativePath(m_rootFolderPath, p_path); - } else { - relativePath = p_path; + QString relativePath; + QFileInfo fi(p_path); + if (fi.isAbsolute()) { + if (!fi.exists()) { + return nullptr; } - return m_configMgr->loadNodeByPath(getRootNode(), relativePath); + relativePath = PathUtils::relativePath(m_rootFolderPath, p_path); + } else { + relativePath = p_path; + } + + return m_configMgr->loadNodeByPath(getRootNode(), relativePath); } -QSharedPointer Notebook::copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, bool p_move) -{ - Q_ASSERT(p_src != p_dest); - Q_ASSERT(p_dest->getNotebook() == this); +QSharedPointer Notebook::copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move) { + Q_ASSERT(p_src != p_dest); + Q_ASSERT(p_dest->getNotebook() == this); - if (Node::isAncestor(p_src.data(), p_dest)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("source (%1) is the ancestor of destination (%2)") - .arg(p_src->fetchPath(), p_dest->fetchPath())); - return nullptr; - } + if (Node::isAncestor(p_src.data(), p_dest)) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("source (%1) is the ancestor of destination (%2)") + .arg(p_src->fetchPath(), p_dest->fetchPath())); + return nullptr; + } - if (p_src->getParent() == p_dest && p_move) { - return p_src; - } + if (p_src->getParent() == p_dest && p_move) { + return p_src; + } - return m_configMgr->copyNodeAsChildOf(p_src, p_dest, p_move); + return m_configMgr->copyNodeAsChildOf(p_src, p_dest, p_move); } -void Notebook::removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly) -{ - Q_ASSERT(p_node && !p_node->isRoot()); - Q_ASSERT(p_node->getNotebook() == this); - m_configMgr->removeNode(p_node, p_force, p_configOnly); +void Notebook::removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly) { + Q_ASSERT(p_node && !p_node->isRoot()); + Q_ASSERT(p_node->getNotebook() == this); + m_configMgr->removeNode(p_node, p_force, p_configOnly); } -void Notebook::removeNode(Node *p_node, bool p_force, bool p_configOnly) -{ - Q_ASSERT(p_node); - removeNode(p_node->sharedFromThis(), p_force, p_configOnly); +void Notebook::removeNode(Node *p_node, bool p_force, bool p_configOnly) { + Q_ASSERT(p_node); + removeNode(p_node->sharedFromThis(), p_force, p_configOnly); } -void Notebook::moveNodeToRecycleBin(Node *p_node) -{ - moveNodeToRecycleBin(p_node->sharedFromThis()); +void Notebook::moveNodeToRecycleBin(Node *p_node) { + moveNodeToRecycleBin(p_node->sharedFromThis()); } -void Notebook::moveNodeToRecycleBin(const QSharedPointer &p_node) -{ - Q_ASSERT(p_node && !p_node->isRoot()); - m_configMgr->removeNodeToFolder(p_node, getOrCreateRecycleBinDateFolder()); +void Notebook::moveNodeToRecycleBin(const QSharedPointer &p_node) { + Q_ASSERT(p_node && !p_node->isRoot()); + m_configMgr->removeNodeToFolder(p_node, getOrCreateRecycleBinDateFolder()); } -QString Notebook::getOrCreateRecycleBinDateFolder() -{ - // Name after date. - auto dateFolderName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd")); - auto folderPath = PathUtils::concatenateFilePath(getRecycleBinFolder(), dateFolderName); - if (QDir::isAbsolutePath(folderPath)) { - qDebug() << "using absolute recycle bin folder" << folderPath; - QDir dir(folderPath); - if (dir.exists()) { - dir.mkpath(folderPath); - } - } else { - if (!getBackend()->exists(folderPath)) { - getBackend()->makePath(folderPath); - } +QString Notebook::getOrCreateRecycleBinDateFolder() { + // Name after date. + auto dateFolderName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd")); + auto folderPath = PathUtils::concatenateFilePath(getRecycleBinFolder(), dateFolderName); + if (QDir::isAbsolutePath(folderPath)) { + qDebug() << "using absolute recycle bin folder" << folderPath; + QDir dir(folderPath); + if (dir.exists()) { + dir.mkpath(folderPath); + } + } else { + if (!getBackend()->exists(folderPath)) { + getBackend()->makePath(folderPath); } + } - return folderPath; + return folderPath; } -void Notebook::moveFileToRecycleBin(const QString &p_filePath) -{ - auto destFilePath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_filePath)); - destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); - m_backend->copyFile(p_filePath, destFilePath, true); +void Notebook::moveFileToRecycleBin(const QString &p_filePath) { + auto destFilePath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), + PathUtils::fileName(p_filePath)); + destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); + m_backend->copyFile(p_filePath, destFilePath, true); } -void Notebook::moveDirToRecycleBin(const QString &p_dirPath) -{ - auto destDirPath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_dirPath)); - destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath); - m_backend->copyDir(p_dirPath, destDirPath, true); +void Notebook::moveDirToRecycleBin(const QString &p_dirPath) { + auto destDirPath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), + PathUtils::fileName(p_dirPath)); + destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath); + m_backend->copyDir(p_dirPath, destDirPath, true); } -QSharedPointer Notebook::addAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras) -{ - return m_configMgr->addAsNode(p_parent, p_flags, p_name, p_paras); +QSharedPointer Notebook::addAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const NodeParameters &p_paras) { + return m_configMgr->addAsNode(p_parent, p_flags, p_name, p_paras); } -bool Notebook::isBuiltInFile(const Node *p_node, const QString &p_name) const -{ - return m_configMgr->isBuiltInFile(p_node, p_name); +bool Notebook::isBuiltInFile(const Node *p_node, const QString &p_name) const { + return m_configMgr->isBuiltInFile(p_node, p_name); } -bool Notebook::isBuiltInFolder(const Node *p_node, const QString &p_name) const -{ - return m_configMgr->isBuiltInFolder(p_node, p_name); +bool Notebook::isBuiltInFolder(const Node *p_node, const QString &p_name) const { + return m_configMgr->isBuiltInFolder(p_node, p_name); } -QSharedPointer Notebook::copyAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_path) -{ - return m_configMgr->copyAsNode(p_parent, p_flags, p_path); +QSharedPointer Notebook::copyAsNode(Node *p_parent, Node::Flags p_flags, + const QString &p_path) { + return m_configMgr->copyAsNode(p_parent, p_flags, p_path); } -void Notebook::reloadNodes() -{ - m_root.clear(); - getRootNode(); +void Notebook::reloadNodes() { + m_root.clear(); + getRootNode(); } -QJsonObject Notebook::getExtraConfig(const QString &p_key) const -{ - const auto &configs = getExtraConfigs(); - return configs.value(p_key).toObject(); +QJsonObject Notebook::getExtraConfig(const QString &p_key) const { + const auto &configs = getExtraConfigs(); + return configs.value(p_key).toObject(); } -QList> Notebook::collectFiles() -{ - QList> files; +QList> Notebook::collectFiles() { + QList> files; - auto rootNode = getRootNode(); + auto rootNode = getRootNode(); - const auto &children = rootNode->getChildrenRef(); - for (const auto &child : children) { - if (child->getUse() != Node::Use::Normal) { - continue; - } - files.append(child->collectFiles()); + const auto &children = rootNode->getChildrenRef(); + for (const auto &child : children) { + if (child->getUse() != Node::Use::Normal) { + continue; } + files.append(child->collectFiles()); + } - return files; + return files; } -QStringList Notebook::scanAndImportExternalFiles() -{ - return m_configMgr->scanAndImportExternalFiles(getRootNode().data()); +QStringList Notebook::scanAndImportExternalFiles() { + return m_configMgr->scanAndImportExternalFiles(getRootNode().data()); } -bool Notebook::rebuildDatabase() -{ - return false; -} +bool Notebook::rebuildDatabase() { return false; } -HistoryI *Notebook::history() -{ - return nullptr; -} +HistoryI *Notebook::history() { return nullptr; } -TagI *Notebook::tag() -{ - return nullptr; -} +TagI *Notebook::tag() { return nullptr; } -void Notebook::emptyRecycleBin() -{ - QDir dir(getRecycleBinFolderAbsolutePath()); - auto children = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); - for (const auto &child : children) { - FileUtils::removeDir(dir.filePath(child)); - } +void Notebook::emptyRecycleBin() { + QDir dir(getRecycleBinFolderAbsolutePath()); + auto children = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); + for (const auto &child : children) { + FileUtils::removeDir(dir.filePath(child)); + } } diff --git a/src/core/notebook/notebook.h b/src/core/notebook/notebook.h index 5abff31f22..c335c0b446 100644 --- a/src/core/notebook/notebook.h +++ b/src/core/notebook/notebook.h @@ -1,218 +1,211 @@ #ifndef NOTEBOOK_H #define NOTEBOOK_H -#include #include +#include #include +#include "node.h" #include "notebookparameters.h" #include -#include "node.h" -namespace vnotex -{ - class INotebookBackend; - class IVersionController; - class INotebookConfigMgr; - class NodeParameters; - class File; - class HistoryI; - class TagI; +namespace vnotex { +class INotebookBackend; +class IVersionController; +class INotebookConfigMgr; +class NodeParameters; +class File; +class HistoryI; +class TagI; - // Base class of notebook. - class Notebook : public QObject - { - Q_OBJECT - public: - Notebook(const NotebookParameters &p_paras, - QObject *p_parent = nullptr); +// Base class of notebook. +class Notebook : public QObject { + Q_OBJECT +public: + Notebook(const NotebookParameters &p_paras, QObject *p_parent = nullptr); - // Used for UT only. - Notebook(const QString &p_name, QObject *p_parent = nullptr); + // Used for UT only. + Notebook(const QString &p_name, QObject *p_parent = nullptr); - virtual ~Notebook(); + virtual ~Notebook(); - void initialize(); + void initialize(); - enum { InvalidId = 0 }; + enum { InvalidId = 0 }; - ID getId() const; + ID getId() const; - const QString &getType() const; + const QString &getType() const; - const QString &getName() const; - void setName(const QString &p_name); - // Change the config and backend file as well. - void updateName(const QString &p_name); + const QString &getName() const; + void setName(const QString &p_name); + // Change the config and backend file as well. + void updateName(const QString &p_name); - const QString &getDescription() const; - void setDescription(const QString &p_description); - void updateDescription(const QString &p_description); + const QString &getDescription() const; + void setDescription(const QString &p_description); + void updateDescription(const QString &p_description); - // Use getRootFolderAbsolutePath() instead for access. - const QString &getRootFolderPath() const; + // Use getRootFolderAbsolutePath() instead for access. + const QString &getRootFolderPath() const; - QString getRootFolderAbsolutePath() const; + QString getRootFolderAbsolutePath() const; - // Get the absolute path of the config folder if applicable. - QString getConfigFolderAbsolutePath() const; + // Get the absolute path of the config folder if applicable. + QString getConfigFolderAbsolutePath() const; - const QIcon &getIcon() const; - void setIcon(const QIcon &p_icon); + const QIcon &getIcon() const; + void setIcon(const QIcon &p_icon); - const QString &getImageFolder() const; + const QString &getImageFolder() const; - const QString &getAttachmentFolder() const; + const QString &getAttachmentFolder() const; - const QString &getRecycleBinFolder() const; + const QString &getRecycleBinFolder() const; - QString getRecycleBinFolderAbsolutePath() const; + QString getRecycleBinFolderAbsolutePath() const; - const QDateTime &getCreatedTimeUtc() const; + const QDateTime &getCreatedTimeUtc() const; - const QSharedPointer &getBackend() const; + const QSharedPointer &getBackend() const; - const QSharedPointer &getVersionController() const; + const QSharedPointer &getVersionController() const; - const QSharedPointer &getConfigMgr() const; + const QSharedPointer &getConfigMgr() const; - const QSharedPointer &getRootNode() const; + const QSharedPointer &getRootNode() const; - QSharedPointer newNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const QString &p_content = QString()); + QSharedPointer newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const QString &p_content = QString()); - // Add @p_name under @p_parent to add as a new node @p_type. - QSharedPointer addAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras); + // Add @p_name under @p_parent to add as a new node @p_type. + QSharedPointer addAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const NodeParameters &p_paras); - // Copy @p_path to @p_parent and add as a new node @p_type. - QSharedPointer copyAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_path); + // Copy @p_path to @p_parent and add as a new node @p_type. + QSharedPointer copyAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_path); - virtual void updateNotebookConfig() = 0; + virtual void updateNotebookConfig() = 0; - virtual void removeNotebookConfig() = 0; + virtual void removeNotebookConfig() = 0; - // @p_path could be absolute or relative. - virtual QSharedPointer loadNodeByPath(const QString &p_path); + // @p_path could be absolute or relative. + virtual QSharedPointer loadNodeByPath(const QString &p_path); - // Copy @p_src as a child of @p_dest. They may belong to different notebooks. - virtual QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, bool p_move); + // Copy @p_src as a child of @p_dest. They may belong to different notebooks. + virtual QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move); - // Remove @p_node and delete all related files from disk. - // @p_force: if true, will delete all files including files not tracked by configmgr. - // @p_configOnly: if true, will just remove node from config. - void removeNode(const QSharedPointer &p_node, bool p_force = false, bool p_configOnly = false); + // Remove @p_node and delete all related files from disk. + // @p_force: if true, will delete all files including files not tracked by configmgr. + // @p_configOnly: if true, will just remove node from config. + void removeNode(const QSharedPointer &p_node, bool p_force = false, + bool p_configOnly = false); - void removeNode(Node *p_node, bool p_force = false, bool p_configOnly = false); + void removeNode(Node *p_node, bool p_force = false, bool p_configOnly = false); - void moveNodeToRecycleBin(const QSharedPointer &p_node); + void moveNodeToRecycleBin(const QSharedPointer &p_node); - void moveNodeToRecycleBin(Node *p_node); + void moveNodeToRecycleBin(Node *p_node); - // Move @p_filePath to the recycle bin, without adding it as a child node. - void moveFileToRecycleBin(const QString &p_filePath); + // Move @p_filePath to the recycle bin, without adding it as a child node. + void moveFileToRecycleBin(const QString &p_filePath); - // Move @p_dirPath to the recycle bin, without adding it as a child node. - void moveDirToRecycleBin(const QString &p_dirPath); + // Move @p_dirPath to the recycle bin, without adding it as a child node. + void moveDirToRecycleBin(const QString &p_dirPath); - virtual void emptyRecycleBin(); + virtual void emptyRecycleBin(); - // Remove all files of this notebook from disk. - virtual void remove() = 0; + // Remove all files of this notebook from disk. + virtual void remove() = 0; - // Whether @p_name is a built-in file under @p_node. - bool isBuiltInFile(const Node *p_node, const QString &p_name) const; + // Whether @p_name is a built-in file under @p_node. + bool isBuiltInFile(const Node *p_node, const QString &p_name) const; - bool isBuiltInFolder(const Node *p_node, const QString &p_name) const; + bool isBuiltInFolder(const Node *p_node, const QString &p_name) const; - void reloadNodes(); + void reloadNodes(); - // Hold extra 3rd party configs. - virtual const QJsonObject &getExtraConfigs() const = 0; - QJsonObject getExtraConfig(const QString &p_key) const; - virtual void setExtraConfig(const QString &p_key, const QJsonObject &p_obj) = 0; + // Hold extra 3rd party configs. + virtual const QJsonObject &getExtraConfigs() const = 0; + QJsonObject getExtraConfig(const QString &p_key) const; + virtual void setExtraConfig(const QString &p_key, const QJsonObject &p_obj) = 0; - // Get content files recursively. - QList> collectFiles(); + // Get content files recursively. + QList> collectFiles(); - QStringList scanAndImportExternalFiles(); + QStringList scanAndImportExternalFiles(); - virtual bool rebuildDatabase(); + virtual bool rebuildDatabase(); - static const QString c_defaultAttachmentFolder; + static const QString c_defaultAttachmentFolder; - static const QString c_defaultImageFolder; + static const QString c_defaultImageFolder; - static const QString c_defaultRecycleBinFolder; + static const QString c_defaultRecycleBinFolder; - public: - // Return null if history is not suported. - virtual HistoryI *history(); +public: + // Return null if history is not suported. + virtual HistoryI *history(); - // Return null if tag is not suported. - virtual TagI *tag(); + // Return null if tag is not suported. + virtual TagI *tag(); - signals: - void updated(); +signals: + void updated(); - void nodeUpdated(const Node *p_node); + void nodeUpdated(const Node *p_node); - void tagsUpdated(); + void tagsUpdated(); - protected: - virtual void initializeInternal() = 0; +protected: + virtual void initializeInternal() = 0; - private: - QString getOrCreateRecycleBinDateFolder(); +private: + QString getOrCreateRecycleBinDateFolder(); - bool m_initialized = false; + bool m_initialized = false; - // ID of this notebook. - // Will be assigned uniquely once loaded. - ID m_id; + // ID of this notebook. + // Will be assigned uniquely once loaded. + ID m_id; - // Type of this notebook. - QString m_type; + // Type of this notebook. + QString m_type; - // Name of this notebook. - QString m_name; + // Name of this notebook. + QString m_name; - // Description of this notebook. - QString m_description; + // Description of this notebook. + QString m_description; - // Path of the notebook root folder. - QString m_rootFolderPath; + // Path of the notebook root folder. + QString m_rootFolderPath; - QIcon m_icon; + QIcon m_icon; - // Name of the folder to hold images. - QString m_imageFolder; + // Name of the folder to hold images. + QString m_imageFolder; - // Name of the folder to hold attachments. - QString m_attachmentFolder; + // Name of the folder to hold attachments. + QString m_attachmentFolder; - // Name or path of the folder to hold deleted files. - QString m_recycleBinFolder; + // Name or path of the folder to hold deleted files. + QString m_recycleBinFolder; - QDateTime m_createdTimeUtc; + QDateTime m_createdTimeUtc; - // Backend for file access and synchronization. - QSharedPointer m_backend; + // Backend for file access and synchronization. + QSharedPointer m_backend; - // Version controller. - QSharedPointer m_versionController; + // Version controller. + QSharedPointer m_versionController; - // Config manager to read/wirte config files. - QSharedPointer m_configMgr; + // Config manager to read/wirte config files. + QSharedPointer m_configMgr; - QSharedPointer m_root; - }; -} // ns vnotex + QSharedPointer m_root; +}; +} // namespace vnotex #endif // NOTEBOOK_H diff --git a/src/core/notebook/notebookdatabaseaccess.cpp b/src/core/notebook/notebookdatabaseaccess.cpp index 3e6b77ffb1..e4f89a1745 100644 --- a/src/core/notebook/notebookdatabaseaccess.cpp +++ b/src/core/notebook/notebookdatabaseaccess.cpp @@ -1,13 +1,13 @@ #include "notebookdatabaseaccess.h" -#include #include #include +#include #include -#include "notebook.h" #include "node.h" +#include "notebook.h" using namespace vnotex; @@ -17,767 +17,757 @@ static QString c_tagTableName = "tag"; static QString c_nodeTagTableName = "tag_node"; -NotebookDatabaseAccess::NotebookDatabaseAccess(Notebook *p_notebook, const QString &p_databaseFile, QObject *p_parent) - : QObject(p_parent), - m_notebook(p_notebook), - m_databaseFile(p_databaseFile), - m_connectionName(p_databaseFile) -{ -} - -bool NotebookDatabaseAccess::open() -{ - auto db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName); - db.setDatabaseName(m_databaseFile); - if (!db.open()) { - qWarning() << QStringLiteral("failed to open notebook database (%1) (%2)").arg(m_databaseFile, db.lastError().text()); - return false; - } - - { - // Enable foreign key support. - QSqlQuery query(db); - if (!query.exec("PRAGMA foreign_keys = ON")) { - qWarning() << "failed to turn on foreign key support" << query.lastError().text(); - return false; - } +NotebookDatabaseAccess::NotebookDatabaseAccess(Notebook *p_notebook, const QString &p_databaseFile, + QObject *p_parent) + : QObject(p_parent), m_notebook(p_notebook), m_databaseFile(p_databaseFile), + m_connectionName(p_databaseFile) {} + +bool NotebookDatabaseAccess::open() { + auto db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName); + db.setDatabaseName(m_databaseFile); + if (!db.open()) { + qWarning() << QStringLiteral("failed to open notebook database (%1) (%2)") + .arg(m_databaseFile, db.lastError().text()); + return false; + } + + { + // Enable foreign key support. + QSqlQuery query(db); + if (!query.exec("PRAGMA foreign_keys = ON")) { + qWarning() << "failed to turn on foreign key support" << query.lastError().text(); + return false; } + } - m_valid = true; - m_fresh = db.tables().isEmpty(); - return true; + m_valid = true; + m_fresh = db.tables().isEmpty(); + return true; } -bool NotebookDatabaseAccess::isFresh() const -{ - return m_fresh; -} +bool NotebookDatabaseAccess::isFresh() const { return m_fresh; } -bool NotebookDatabaseAccess::isValid() const -{ - return m_valid; -} +bool NotebookDatabaseAccess::isValid() const { return m_valid; } // Maybe insert new table according to @p_configVersion. -void NotebookDatabaseAccess::setupTables(QSqlDatabase &p_db, int p_configVersion) -{ - Q_UNUSED(p_configVersion); - - if (!m_valid) { - return; - } - - QSqlQuery query(p_db); - - if (m_fresh) { - // Node. - bool ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n" - " id INTEGER PRIMARY KEY,\n" - " name TEXT NOT NULL,\n" - " signature INTEGER NOT NULL,\n" - " parent_id INTEGER NULL REFERENCES %1(id) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTableName)); - if (!ret) { - qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_nodeTableName, query.lastError().text()); - m_valid = false; - return; - } - - // Tag. - ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n" - " name TEXT PRIMARY KEY,\n" - " parent_name TEXT NULL REFERENCES %1(name) ON DELETE CASCADE ON UPDATE CASCADE) WITHOUT ROWID\n").arg(c_tagTableName)); - if (!ret) { - qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_tagTableName, query.lastError().text()); - m_valid = false; - return; - } - - // Node_Tag. - ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n" - " node_id INTEGER REFERENCES %2(id) ON DELETE CASCADE ON UPDATE CASCADE,\n" - " tag_name TEXT REFERENCES %3(name) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTagTableName, - c_nodeTableName, - c_tagTableName)); - if (!ret) { - qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_nodeTagTableName, query.lastError().text()); - m_valid = false; - return; - } +void NotebookDatabaseAccess::setupTables(QSqlDatabase &p_db, int p_configVersion) { + Q_UNUSED(p_configVersion); + + if (!m_valid) { + return; + } + + QSqlQuery query(p_db); + + if (m_fresh) { + // Node. + bool ret = query.exec( + QStringLiteral( + "CREATE TABLE %1 (\n" + " id INTEGER PRIMARY KEY,\n" + " name TEXT NOT NULL,\n" + " signature INTEGER NOT NULL,\n" + " parent_id INTEGER NULL REFERENCES %1(id) ON DELETE CASCADE ON UPDATE CASCADE)\n") + .arg(c_nodeTableName)); + if (!ret) { + qWarning() << QStringLiteral("failed to create database table (%1) (%2)") + .arg(c_nodeTableName, query.lastError().text()); + m_valid = false; + return; + } + + // Tag. + ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n" + " name TEXT PRIMARY KEY,\n" + " parent_name TEXT NULL REFERENCES %1(name) ON DELETE " + "CASCADE ON UPDATE CASCADE) WITHOUT ROWID\n") + .arg(c_tagTableName)); + if (!ret) { + qWarning() << QStringLiteral("failed to create database table (%1) (%2)") + .arg(c_tagTableName, query.lastError().text()); + m_valid = false; + return; + } + + // Node_Tag. + ret = query.exec( + QStringLiteral( + "CREATE TABLE %1 (\n" + " node_id INTEGER REFERENCES %2(id) ON DELETE CASCADE ON UPDATE CASCADE,\n" + " tag_name TEXT REFERENCES %3(name) ON DELETE CASCADE ON UPDATE CASCADE)\n") + .arg(c_nodeTagTableName, c_nodeTableName, c_tagTableName)); + if (!ret) { + qWarning() << QStringLiteral("failed to create database table (%1) (%2)") + .arg(c_nodeTagTableName, query.lastError().text()); + m_valid = false; + return; } + } } -void NotebookDatabaseAccess::initialize(int p_configVersion) -{ - open(); +void NotebookDatabaseAccess::initialize(int p_configVersion) { + open(); - auto db = getDatabase(); - setupTables(db, p_configVersion); + auto db = getDatabase(); + setupTables(db, p_configVersion); } -void NotebookDatabaseAccess::close() -{ - getDatabase().close(); - QSqlDatabase::removeDatabase(m_connectionName); - m_valid = false; +void NotebookDatabaseAccess::close() { + getDatabase().close(); + QSqlDatabase::removeDatabase(m_connectionName); + m_valid = false; } -bool NotebookDatabaseAccess::addNode(Node *p_node, bool p_ignoreId) -{ - p_node->load(); +bool NotebookDatabaseAccess::addNode(Node *p_node, bool p_ignoreId) { + p_node->load(); - Q_ASSERT(p_node->getSignature() != Node::InvalidId); + Q_ASSERT(p_node->getSignature() != Node::InvalidId); - auto db = getDatabase(); - QSqlQuery query(db); - if (p_ignoreId) { - query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n" - " VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName)); - query.bindValue(":name", p_node->getName()); - query.bindValue(":signature", p_node->getSignature()); - query.bindValue(":parent_id", p_node->getParent() ? p_node->getParent()->getId() : QVariant()); - } else { - bool useNewId = false; - if (p_node->getId() != InvalidId) { - auto nodeRec = queryNode(p_node->getId()); - if (nodeRec) { - auto nodePath = queryNodeParentPath(p_node->getId()); - if (existsNode(p_node, nodeRec.data(), nodePath)) { - return true; - } - - if (nodePath.isEmpty()) { - useNewId = true; - m_obsoleteNodes.insert(nodeRec->m_id); - } else { - auto relativePath = nodePath.join(QLatin1Char('/')); - auto oldNode = m_notebook->loadNodeByPath(relativePath); - Q_ASSERT(oldNode != p_node); - if (oldNode) { - // The node with the same id still exists. - useNewId = true; - } else if (nodeRec->m_signature == p_node->getSignature() && nodeRec->m_name == p_node->getName()) { - // @p_node should be the same node as @nodeRec. - return updateNode(p_node); - } else { - // @nodeRec is now an obsolete node. - useNewId = true; - m_obsoleteNodes.insert(nodeRec->m_id); - } - } - } - } else { - useNewId = true; + auto db = getDatabase(); + QSqlQuery query(db); + if (p_ignoreId) { + query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n" + " VALUES (:name, :signature, :parent_id)") + .arg(c_nodeTableName)); + query.bindValue(":name", p_node->getName()); + query.bindValue(":signature", p_node->getSignature()); + query.bindValue(":parent_id", p_node->getParent() ? p_node->getParent()->getId() : QVariant()); + } else { + bool useNewId = false; + if (p_node->getId() != InvalidId) { + auto nodeRec = queryNode(p_node->getId()); + if (nodeRec) { + auto nodePath = queryNodeParentPath(p_node->getId()); + if (existsNode(p_node, nodeRec.data(), nodePath)) { + return true; } - if (useNewId) { - query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n" - " VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName)); + if (nodePath.isEmpty()) { + useNewId = true; + m_obsoleteNodes.insert(nodeRec->m_id); } else { - query.prepare(QStringLiteral("INSERT INTO %1 (id, name, signature, parent_id)\n" - " VALUES (:id, :name, :signature, :parent_id)").arg(c_nodeTableName)); - query.bindValue(":id", p_node->getId()); + auto relativePath = nodePath.join(QLatin1Char('/')); + auto oldNode = m_notebook->loadNodeByPath(relativePath); + Q_ASSERT(oldNode != p_node); + if (oldNode) { + // The node with the same id still exists. + useNewId = true; + } else if (nodeRec->m_signature == p_node->getSignature() && + nodeRec->m_name == p_node->getName()) { + // @p_node should be the same node as @nodeRec. + return updateNode(p_node); + } else { + // @nodeRec is now an obsolete node. + useNewId = true; + m_obsoleteNodes.insert(nodeRec->m_id); + } } - query.bindValue(":name", p_node->getName()); - query.bindValue(":signature", p_node->getSignature()); - query.bindValue(":parent_id", p_node->getParent() ? p_node->getParent()->getId() : QVariant()); - } - - if (!query.exec()) { - qWarning() << "failed to add node" << query.executedQuery() << query.lastError().text(); - return false; - } - - const ID id = query.lastInsertId().toULongLong(); - p_node->updateId(id); - - qDebug() << "added node id" << id << p_node->getName(); - return true; -} - -bool NotebookDatabaseAccess::addNodeRecursively(Node *p_node, bool p_ignoreId) -{ - if (!p_node) { - return false; - } - - auto paNode = p_node->getParent(); - if (paNode && !addNodeRecursively(paNode, p_ignoreId)) { - return false; - } - - return addNode(p_node, p_ignoreId); -} - -QSharedPointer NotebookDatabaseAccess::queryNode(ID p_id) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("SELECT id, name, signature, parent_id FROM %1 WHERE id = :id").arg(c_nodeTableName)); - query.bindValue(":id", p_id); - if (!query.exec()) { - qWarning() << "failed to query node" << query.executedQuery() << query.lastError().text(); - return nullptr; - } - - if (query.next()) { - auto nodeRec = QSharedPointer::create(); - nodeRec->m_id = query.value(0).toULongLong(); - nodeRec->m_name = query.value(1).toString(); - nodeRec->m_signature = query.value(2).toULongLong(); - nodeRec->m_parentId = query.value(3).toULongLong(); - return nodeRec; - } - - return nullptr; -} - -QSqlDatabase NotebookDatabaseAccess::getDatabase() const -{ - return QSqlDatabase::database(m_connectionName); -} - -bool NotebookDatabaseAccess::existsNode(const Node *p_node) -{ - if (!p_node) { - return false; - } - - return existsNode(p_node, - queryNode(p_node->getId()).data(), - queryNodeParentPath(p_node->getId())); -} - -bool NotebookDatabaseAccess::existsNode(const Node *p_node, const NodeRecord *p_rec, const QStringList &p_nodePath) -{ - if (p_nodePath.isEmpty()) { - return false; - } - - if (!nodeEqual(p_rec, p_node)) { - return false; - } - - return checkNodePath(p_node, p_nodePath); -} - -QStringList NotebookDatabaseAccess::queryNodeParentPath(ID p_id) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("WITH RECURSIVE cte_parents(id, name, parent_id) AS (\n" - " SELECT node.id, node.name, node.parent_id\n" - " FROM %1 node\n" - " WHERE node.id = :id\n" - " UNION ALL\n" - " SELECT node.id, node.name, node.parent_id\n" - " FROM %1 node\n" - " JOIN cte_parents cte ON node.id = cte.parent_id\n" - " LIMIT 5000)\n" - "SELECT id, name, parent_id FROM cte_parents").arg(c_nodeTableName)); - query.bindValue(":id", p_id); - if (!query.exec()) { - qWarning() << "failed to query node's path" << query.executedQuery() << query.lastError().text(); - return QStringList(); - } - - QStringList ret; - ID lastParentId = p_id; - bool hasResult = false; - while (query.next()) { - hasResult = true; - Q_ASSERT(lastParentId == query.value(0).toULongLong()); - ret.prepend(query.value(1).toString()); - lastParentId = query.value(2).toULongLong(); - } - Q_ASSERT(!hasResult || lastParentId == InvalidId); - return ret; -} - -QString NotebookDatabaseAccess::queryNodePath(ID p_id) -{ - auto parentPath = queryNodeParentPath(p_id); - if (parentPath.isEmpty()) { - return QString(); + } + } else { + useNewId = true; } - if (parentPath.size() == 1) { - return parentPath.first(); + if (useNewId) { + query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n" + " VALUES (:name, :signature, :parent_id)") + .arg(c_nodeTableName)); + } else { + query.prepare(QStringLiteral("INSERT INTO %1 (id, name, signature, parent_id)\n" + " VALUES (:id, :name, :signature, :parent_id)") + .arg(c_nodeTableName)); + query.bindValue(":id", p_node->getId()); } - - QString relativePath = parentPath.join(QLatin1Char('/')); - Q_ASSERT(relativePath[0] == QLatin1Char('/')); - return relativePath.mid(1); -} - -bool NotebookDatabaseAccess::updateNode(const Node *p_node) -{ - Q_ASSERT(p_node->getParent()); - - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("UPDATE %1\n" - "SET name = :name,\n" - " signature = :signature,\n" - " parent_id = :parent_id\n" - "WHERE id = :id").arg(c_nodeTableName)); query.bindValue(":name", p_node->getName()); query.bindValue(":signature", p_node->getSignature()); - query.bindValue(":parent_id", p_node->getParent()->getId()); - query.bindValue(":id", p_node->getId()); - if (!query.exec()) { - qWarning() << "failed to update node" << query.executedQuery() << query.lastError().text(); - return false; - } + query.bindValue(":parent_id", p_node->getParent() ? p_node->getParent()->getId() : QVariant()); + } - qDebug() << "updated node" - << p_node->getId() - << p_node->getSignature() - << p_node->getName() - << p_node->getParent()->getId(); + if (!query.exec()) { + qWarning() << "failed to add node" << query.executedQuery() << query.lastError().text(); + return false; + } - return true; -} + const ID id = query.lastInsertId().toULongLong(); + p_node->updateId(id); -void NotebookDatabaseAccess::clearObsoleteNodes() -{ - if (m_obsoleteNodes.isEmpty()) { - return; - } - - for (auto it : m_obsoleteNodes) { - if (!removeNode(it)) { - qWarning() << "failed to clear obsolete node" << it; - continue; - } - } - - m_obsoleteNodes.clear(); + qDebug() << "added node id" << id << p_node->getName(); + return true; } -bool NotebookDatabaseAccess::removeNode(const Node *p_node) -{ - if (existsNode(p_node)) { - return removeNode(p_node->getId()); - } +bool NotebookDatabaseAccess::addNodeRecursively(Node *p_node, bool p_ignoreId) { + if (!p_node) { + return false; + } - return true; -} + auto paNode = p_node->getParent(); + if (paNode && !addNodeRecursively(paNode, p_ignoreId)) { + return false; + } -bool NotebookDatabaseAccess::removeNode(ID p_id) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("DELETE FROM %1\n" - "WHERE id = :id").arg(c_nodeTableName)); - query.bindValue(":id", p_id); - if (!query.exec()) { - qWarning() << "failed to remove node" << query.executedQuery() << query.lastError().text(); - return false; - } - qDebug() << "removed node" << p_id; - return true; + return addNode(p_node, p_ignoreId); } -bool NotebookDatabaseAccess::nodeEqual(const NodeRecord *p_rec, const Node *p_node) const -{ - if (!p_rec) { - if (p_node) { - return false; - } else { - return true; - } - } else if (!p_node) { - return false; - } - - if (p_rec->m_id != p_node->getId()) { - return false; - } - if (p_rec->m_name != p_node->getName()) { - return false; - } - if (p_rec->m_signature != p_node->getSignature()) { - return false; - } - if (p_node->getParent()) { - if (p_rec->m_parentId != p_node->getParent()->getId()) { - return false; - } - } else if (p_rec->m_parentId != Node::InvalidId) { - return false; +QSharedPointer NotebookDatabaseAccess::queryNode(ID p_id) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("SELECT id, name, signature, parent_id FROM %1 WHERE id = :id") + .arg(c_nodeTableName)); + query.bindValue(":id", p_id); + if (!query.exec()) { + qWarning() << "failed to query node" << query.executedQuery() << query.lastError().text(); + return nullptr; + } + + if (query.next()) { + auto nodeRec = QSharedPointer::create(); + nodeRec->m_id = query.value(0).toULongLong(); + nodeRec->m_name = query.value(1).toString(); + nodeRec->m_signature = query.value(2).toULongLong(); + nodeRec->m_parentId = query.value(3).toULongLong(); + return nodeRec; + } + + return nullptr; +} + +QSqlDatabase NotebookDatabaseAccess::getDatabase() const { + return QSqlDatabase::database(m_connectionName); +} + +bool NotebookDatabaseAccess::existsNode(const Node *p_node) { + if (!p_node) { + return false; + } + + return existsNode(p_node, queryNode(p_node->getId()).data(), + queryNodeParentPath(p_node->getId())); +} + +bool NotebookDatabaseAccess::existsNode(const Node *p_node, const NodeRecord *p_rec, + const QStringList &p_nodePath) { + if (p_nodePath.isEmpty()) { + return false; + } + + if (!nodeEqual(p_rec, p_node)) { + return false; + } + + return checkNodePath(p_node, p_nodePath); +} + +QStringList NotebookDatabaseAccess::queryNodeParentPath(ID p_id) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("WITH RECURSIVE cte_parents(id, name, parent_id) AS (\n" + " SELECT node.id, node.name, node.parent_id\n" + " FROM %1 node\n" + " WHERE node.id = :id\n" + " UNION ALL\n" + " SELECT node.id, node.name, node.parent_id\n" + " FROM %1 node\n" + " JOIN cte_parents cte ON node.id = cte.parent_id\n" + " LIMIT 5000)\n" + "SELECT id, name, parent_id FROM cte_parents") + .arg(c_nodeTableName)); + query.bindValue(":id", p_id); + if (!query.exec()) { + qWarning() << "failed to query node's path" << query.executedQuery() + << query.lastError().text(); + return QStringList(); + } + + QStringList ret; + ID lastParentId = p_id; + bool hasResult = false; + while (query.next()) { + hasResult = true; + Q_ASSERT(lastParentId == query.value(0).toULongLong()); + ret.prepend(query.value(1).toString()); + lastParentId = query.value(2).toULongLong(); + } + Q_ASSERT(!hasResult || lastParentId == InvalidId); + return ret; +} + +QString NotebookDatabaseAccess::queryNodePath(ID p_id) { + auto parentPath = queryNodeParentPath(p_id); + if (parentPath.isEmpty()) { + return QString(); + } + + if (parentPath.size() == 1) { + return parentPath.first(); + } + + QString relativePath = parentPath.join(QLatin1Char('/')); + Q_ASSERT(relativePath[0] == QLatin1Char('/')); + return relativePath.mid(1); +} + +bool NotebookDatabaseAccess::updateNode(const Node *p_node) { + Q_ASSERT(p_node->getParent()); + + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("UPDATE %1\n" + "SET name = :name,\n" + " signature = :signature,\n" + " parent_id = :parent_id\n" + "WHERE id = :id") + .arg(c_nodeTableName)); + query.bindValue(":name", p_node->getName()); + query.bindValue(":signature", p_node->getSignature()); + query.bindValue(":parent_id", p_node->getParent()->getId()); + query.bindValue(":id", p_node->getId()); + if (!query.exec()) { + qWarning() << "failed to update node" << query.executedQuery() << query.lastError().text(); + return false; + } + + qDebug() << "updated node" << p_node->getId() << p_node->getSignature() << p_node->getName() + << p_node->getParent()->getId(); + + return true; +} + +void NotebookDatabaseAccess::clearObsoleteNodes() { + if (m_obsoleteNodes.isEmpty()) { + return; + } + + for (auto it : m_obsoleteNodes) { + if (!removeNode(it)) { + qWarning() << "failed to clear obsolete node" << it; + continue; + } + } + + m_obsoleteNodes.clear(); +} + +bool NotebookDatabaseAccess::removeNode(const Node *p_node) { + if (existsNode(p_node)) { + return removeNode(p_node->getId()); + } + + return true; +} + +bool NotebookDatabaseAccess::removeNode(ID p_id) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("DELETE FROM %1\n" + "WHERE id = :id") + .arg(c_nodeTableName)); + query.bindValue(":id", p_id); + if (!query.exec()) { + qWarning() << "failed to remove node" << query.executedQuery() << query.lastError().text(); + return false; + } + qDebug() << "removed node" << p_id; + return true; +} + +bool NotebookDatabaseAccess::nodeEqual(const NodeRecord *p_rec, const Node *p_node) const { + if (!p_rec) { + if (p_node) { + return false; + } else { + return true; + } + } else if (!p_node) { + return false; + } + + if (p_rec->m_id != p_node->getId()) { + return false; + } + if (p_rec->m_name != p_node->getName()) { + return false; + } + if (p_rec->m_signature != p_node->getSignature()) { + return false; + } + if (p_node->getParent()) { + if (p_rec->m_parentId != p_node->getParent()->getId()) { + return false; + } + } else if (p_rec->m_parentId != Node::InvalidId) { + return false; + } + + return true; +} + +bool NotebookDatabaseAccess::checkNodePath(const Node *p_node, + const QStringList &p_nodePath) const { + for (int i = p_nodePath.size() - 1; i >= 0; --i) { + if (!p_node) { + return false; } - return true; -} - -bool NotebookDatabaseAccess::checkNodePath(const Node *p_node, const QStringList &p_nodePath) const -{ - for (int i = p_nodePath.size() - 1; i >= 0; --i) { - if (!p_node) { - return false; - } - - if (p_nodePath[i] != p_node->getName()) { - return false; - } - p_node = p_node->getParent(); + if (p_nodePath[i] != p_node->getName()) { + return false; } + p_node = p_node->getParent(); + } - if (p_node) { - return false; - } + if (p_node) { + return false; + } - return true; + return true; } -bool NotebookDatabaseAccess::addTag(const QString &p_name, const QString &p_parentName) -{ - return addTag(p_name, p_parentName, true); +bool NotebookDatabaseAccess::addTag(const QString &p_name, const QString &p_parentName) { + return addTag(p_name, p_parentName, true); } -bool NotebookDatabaseAccess::addTag(const QString &p_name) -{ - return addTag(p_name, QString(), false); +bool NotebookDatabaseAccess::addTag(const QString &p_name) { + return addTag(p_name, QString(), false); } -bool NotebookDatabaseAccess::addTag(const QString &p_name, const QString &p_parentName, bool p_updateOnExists) -{ - { - auto tagRec = queryTag(p_name); - if (tagRec) { - if (!p_updateOnExists || tagRec->m_parentName == p_parentName) { - return true; - } - - return updateTagParent(p_name, p_parentName); - } - } +bool NotebookDatabaseAccess::addTag(const QString &p_name, const QString &p_parentName, + bool p_updateOnExists) { + { + auto tagRec = queryTag(p_name); + if (tagRec) { + if (!p_updateOnExists || tagRec->m_parentName == p_parentName) { + return true; + } + + return updateTagParent(p_name, p_parentName); + } + } + + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("INSERT INTO %1 (name, parent_name)\n" + " VALUES (:name, :parent_name)") + .arg(c_tagTableName)); + query.bindValue(":name", p_name); + query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName); + + if (!query.exec()) { + qWarning() << "failed to add tag" << query.executedQuery() << query.lastError().text(); + return false; + } + + qDebug() << "added tag" << p_name << "parentName" << p_parentName; + return true; +} + +QSharedPointer +NotebookDatabaseAccess::queryTag(const QString &p_name) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare( + QStringLiteral("SELECT name, parent_name FROM %1 WHERE name = :name").arg(c_tagTableName)); + query.bindValue(":name", p_name); + if (!query.exec()) { + qWarning() << "failed to query tag" << query.executedQuery() << query.lastError().text(); + return nullptr; + } - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("INSERT INTO %1 (name, parent_name)\n" - " VALUES (:name, :parent_name)").arg(c_tagTableName)); - query.bindValue(":name", p_name); - query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName); - - if (!query.exec()) { - qWarning() << "failed to add tag" << query.executedQuery() << query.lastError().text(); - return false; - } + if (query.next()) { + auto tagRec = QSharedPointer::create(); + tagRec->m_name = query.value(0).toString(); + tagRec->m_parentName = query.value(1).toString(); + return tagRec; + } - qDebug() << "added tag" << p_name << "parentName" << p_parentName; - return true; + return nullptr; } -QSharedPointer NotebookDatabaseAccess::queryTag(const QString &p_name) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("SELECT name, parent_name FROM %1 WHERE name = :name").arg(c_tagTableName)); - query.bindValue(":name", p_name); - if (!query.exec()) { - qWarning() << "failed to query tag" << query.executedQuery() << query.lastError().text(); - return nullptr; - } +bool NotebookDatabaseAccess::updateTagParent(const QString &p_name, const QString &p_parentName) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("UPDATE %1\n" + "SET parent_name = :parent_name\n" + "WHERE name = :name") + .arg(c_tagTableName)); + query.bindValue(":name", p_name); + query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName); + if (!query.exec()) { + qWarning() << "failed to update tag" << query.executedQuery() << query.lastError().text(); + return false; + } - if (query.next()) { - auto tagRec = QSharedPointer::create(); - tagRec->m_name = query.value(0).toString(); - tagRec->m_parentName = query.value(1).toString(); - return tagRec; - } + qDebug() << "updated tag parent" << p_name << p_parentName; - return nullptr; + return true; } -bool NotebookDatabaseAccess::updateTagParent(const QString &p_name, const QString &p_parentName) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("UPDATE %1\n" - "SET parent_name = :parent_name\n" - "WHERE name = :name").arg(c_tagTableName)); - query.bindValue(":name", p_name); - query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName); - if (!query.exec()) { - qWarning() << "failed to update tag" << query.executedQuery() << query.lastError().text(); - return false; - } - - qDebug() << "updated tag parent" << p_name << p_parentName; - +bool NotebookDatabaseAccess::renameTag(const QString &p_name, const QString &p_newName) { + Q_ASSERT(!p_newName.isEmpty()); + if (p_name == p_newName) { return true; -} + } -bool NotebookDatabaseAccess::renameTag(const QString &p_name, const QString &p_newName) -{ - Q_ASSERT(!p_newName.isEmpty()); - if (p_name == p_newName) { - return true; - } + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("UPDATE %1\n" + "SET name = :new_name\n" + "WHERE name = :name") + .arg(c_tagTableName)); + query.bindValue(":name", p_name); + query.bindValue(":new_name", p_newName); + if (!query.exec()) { + qWarning() << "failed to update tag" << query.executedQuery() << query.lastError().text(); + return false; + } - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("UPDATE %1\n" - "SET name = :new_name\n" - "WHERE name = :name").arg(c_tagTableName)); - query.bindValue(":name", p_name); - query.bindValue(":new_name", p_newName); - if (!query.exec()) { - qWarning() << "failed to update tag" << query.executedQuery() << query.lastError().text(); - return false; - } - - qDebug() << "updated tag name" << p_name << p_newName; + qDebug() << "updated tag name" << p_name << p_newName; - return true; + return true; } -bool NotebookDatabaseAccess::removeTag(const QString &p_name) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("DELETE FROM %1\n" - "WHERE name = :name").arg(c_tagTableName)); - query.bindValue(":name", p_name); - if (!query.exec()) { - qWarning() << "failed to remove tag" << query.executedQuery() << query.lastError().text(); - return false; - } - qDebug() << "removed tag" << p_name; - return true; +bool NotebookDatabaseAccess::removeTag(const QString &p_name) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("DELETE FROM %1\n" + "WHERE name = :name") + .arg(c_tagTableName)); + query.bindValue(":name", p_name); + if (!query.exec()) { + qWarning() << "failed to remove tag" << query.executedQuery() << query.lastError().text(); + return false; + } + qDebug() << "removed tag" << p_name; + return true; } -bool NotebookDatabaseAccess::updateNodeTags(Node *p_node) -{ - p_node->load(); - - if (p_node->getId() == Node::InvalidId) { - qWarning() << "failed to update tags of node with invalid id" << p_node->fetchPath(); - return false; - } - - const auto &nodeTags = p_node->getTags(); - - { - QStringList tagsList = queryNodeTags(p_node->getId()); - QSet tags; - for (const auto &s : tagsList) - { - tags.insert(s); - } - if (tags.isEmpty() && nodeTags.isEmpty()) { - return true; - } - - bool needUpdate = false; - if (tags.size() != nodeTags.size()) { - needUpdate = true; - } - - for (const auto &tag : nodeTags) { - if (tags.find(tag) == tags.end()) { - needUpdate = true; - - if (!addTag(tag)) { - qWarning() << "failed to add tag before addNodeTags" << p_node->getId() << tag; - return false; - } - } - } - - if (!needUpdate) { - return true; - } - } - - bool ret = removeNodeTags(p_node->getId()); - if (!ret) { - return false; - } - - return addNodeTags(p_node->getId(), nodeTags); -} +bool NotebookDatabaseAccess::updateNodeTags(Node *p_node) { + p_node->load(); -QStringList NotebookDatabaseAccess::queryNodeTags(ID p_id) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("SELECT tag_name FROM %1 WHERE node_id = :node_id").arg(c_nodeTagTableName)); - query.bindValue(":node_id", p_id); - if (!query.exec()) { - qWarning() << "failed to query node's tags" << query.executedQuery() << query.lastError().text(); - return QStringList(); - } + if (p_node->getId() == Node::InvalidId) { + qWarning() << "failed to update tags of node with invalid id" << p_node->fetchPath(); + return false; + } - QStringList tags; - while (query.next()) { - tags.append(query.value(0).toString()); - } - return tags; -} + const auto &nodeTags = p_node->getTags(); -bool NotebookDatabaseAccess::removeNodeTags(ID p_id) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("DELETE FROM %1\n" - "WHERE node_id = :node_id").arg(c_nodeTagTableName)); - query.bindValue(":node_id", p_id); - if (!query.exec()) { - qWarning() << "failed to remove tags of node" << query.executedQuery() << query.lastError().text(); - return false; + { + QStringList tagsList = queryNodeTags(p_node->getId()); + QSet tags; + for (const auto &s : tagsList) { + tags.insert(s); } - qDebug() << "removed tags of node" << p_id; - return true; -} - -bool NotebookDatabaseAccess::addNodeTags(ID p_id, const QStringList &p_tags) -{ - Q_ASSERT(p_id != Node::InvalidId); - if (p_tags.isEmpty()) { - return true; + if (tags.isEmpty() && nodeTags.isEmpty()) { + return true; } - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("INSERT INTO %1 (node_id, tag_name)\n" - " VALUES (?, ?)").arg(c_nodeTagTableName)); - - QVariantList ids; - QVariantList tagNames; - for (const auto &tag : p_tags) { - ids << p_id; - tagNames << tag; + bool needUpdate = false; + if (tags.size() != nodeTags.size()) { + needUpdate = true; } - query.addBindValue(ids); - query.addBindValue(tagNames); - - if (!query.execBatch()) { - qWarning() << "failed to add tags of node" << query.executedQuery() << query.lastError().text(); - return false; - } + for (const auto &tag : nodeTags) { + if (tags.find(tag) == tags.end()) { + needUpdate = true; - qDebug() << "added tags of node" << p_id << p_tags; + if (!addTag(tag)) { + qWarning() << "failed to add tag before addNodeTags" << p_node->getId() << tag; + return false; + } + } + } + + if (!needUpdate) { + return true; + } + } + + bool ret = removeNodeTags(p_node->getId()); + if (!ret) { + return false; + } + + return addNodeTags(p_node->getId(), nodeTags); +} + +QStringList NotebookDatabaseAccess::queryNodeTags(ID p_id) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare( + QStringLiteral("SELECT tag_name FROM %1 WHERE node_id = :node_id").arg(c_nodeTagTableName)); + query.bindValue(":node_id", p_id); + if (!query.exec()) { + qWarning() << "failed to query node's tags" << query.executedQuery() + << query.lastError().text(); + return QStringList(); + } + + QStringList tags; + while (query.next()) { + tags.append(query.value(0).toString()); + } + return tags; +} + +bool NotebookDatabaseAccess::removeNodeTags(ID p_id) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("DELETE FROM %1\n" + "WHERE node_id = :node_id") + .arg(c_nodeTagTableName)); + query.bindValue(":node_id", p_id); + if (!query.exec()) { + qWarning() << "failed to remove tags of node" << query.executedQuery() + << query.lastError().text(); + return false; + } + qDebug() << "removed tags of node" << p_id; + return true; +} + +bool NotebookDatabaseAccess::addNodeTags(ID p_id, const QStringList &p_tags) { + Q_ASSERT(p_id != Node::InvalidId); + if (p_tags.isEmpty()) { return true; -} - -QList NotebookDatabaseAccess::queryTagNodes(const QString &p_tag) -{ - QList nodes; - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("SELECT node_id FROM %1 WHERE tag_name = :tag_name").arg(c_nodeTagTableName)); - query.bindValue(":tag_name", p_tag); - if (!query.exec()) { - qWarning() << "failed to query nodes of tag" << query.executedQuery() << query.lastError().text(); - return nodes; - } - - while (query.next()) { - nodes.append(query.value(0).toULongLong()); - } + } + + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("INSERT INTO %1 (node_id, tag_name)\n" + " VALUES (?, ?)") + .arg(c_nodeTagTableName)); + + QVariantList ids; + QVariantList tagNames; + for (const auto &tag : p_tags) { + ids << p_id; + tagNames << tag; + } + + query.addBindValue(ids); + query.addBindValue(tagNames); + + if (!query.execBatch()) { + qWarning() << "failed to add tags of node" << query.executedQuery() << query.lastError().text(); + return false; + } + + qDebug() << "added tags of node" << p_id << p_tags; + return true; +} + +QList NotebookDatabaseAccess::queryTagNodes(const QString &p_tag) { + QList nodes; + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare( + QStringLiteral("SELECT node_id FROM %1 WHERE tag_name = :tag_name").arg(c_nodeTagTableName)); + query.bindValue(":tag_name", p_tag); + if (!query.exec()) { + qWarning() << "failed to query nodes of tag" << query.executedQuery() + << query.lastError().text(); return nodes; -} + } + + while (query.next()) { + nodes.append(query.value(0).toULongLong()); + } + return nodes; +} + +QList NotebookDatabaseAccess::queryTagNodesRecursive(const QString &p_tag) { + auto tags = queryTagAndChildren(p_tag); + if (tags.size() <= 1) { + return queryTagNodes(p_tag); + } + + QSet allIds; + for (const auto &tag : tags) { + auto ids = queryTagNodes(tag); + for (const auto &id : ids) { + allIds.insert(id); + } + } + + return allIds.values(); +} + +QStringList NotebookDatabaseAccess::queryTagAndChildren(const QString &p_tag) { + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("WITH RECURSIVE cte_children(name, parent_name) AS (\n" + " SELECT tag.name, tag.parent_name\n" + " FROM %1 tag\n" + " WHERE tag.name = :name\n" + " UNION ALL\n" + " SELECT tag.name, tag.parent_name\n" + " FROM %1 tag\n" + " JOIN cte_children cte ON tag.parent_name = cte.name\n" + " LIMIT 5000)\n" + "SELECT name FROM cte_children") + .arg(c_tagTableName)); + query.bindValue(":name", p_tag); + if (!query.exec()) { + qWarning() << "failed to query tag and its children" << query.executedQuery() + << query.lastError().text(); + return QStringList(); + } + + QStringList ret; + while (query.next()) { + ret.append(query.value(0).toString()); + } + + qDebug() << "tag and its children" << p_tag << ret; + return ret; +} + +QStringList NotebookDatabaseAccess::getNodesOfTags(const QStringList &p_tags) { + QStringList ret; + if (p_tags.isEmpty()) { + return ret; + } -QList NotebookDatabaseAccess::queryTagNodesRecursive(const QString &p_tag) -{ - auto tags = queryTagAndChildren(p_tag); - if (tags.size() <= 1) { - return queryTagNodes(p_tag); - } + QList nodeIds; + if (p_tags.size() == 1) { + nodeIds = queryTagNodesRecursive(p_tags.first()); + } else { QSet allIds; - for (const auto &tag : tags) { - auto ids = queryTagNodes(tag); - for (const auto &id : ids) { - allIds.insert(id); - } - } - - return allIds.values(); -} - -QStringList NotebookDatabaseAccess::queryTagAndChildren(const QString &p_tag) -{ - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("WITH RECURSIVE cte_children(name, parent_name) AS (\n" - " SELECT tag.name, tag.parent_name\n" - " FROM %1 tag\n" - " WHERE tag.name = :name\n" - " UNION ALL\n" - " SELECT tag.name, tag.parent_name\n" - " FROM %1 tag\n" - " JOIN cte_children cte ON tag.parent_name = cte.name\n" - " LIMIT 5000)\n" - "SELECT name FROM cte_children").arg(c_tagTableName)); - query.bindValue(":name", p_tag); - if (!query.exec()) { - qWarning() << "failed to query tag and its children" << query.executedQuery() << query.lastError().text(); - return QStringList(); - } - - QStringList ret; - while (query.next()) { - ret.append(query.value(0).toString()); - } - - qDebug() << "tag and its children" << p_tag << ret; - return ret; -} - -QStringList NotebookDatabaseAccess::getNodesOfTags(const QStringList &p_tags) -{ - QStringList ret; - if (p_tags.isEmpty()) { - return ret; + for (const auto &tag : p_tags) { + auto ids = queryTagNodesRecursive(tag); + for (const auto &id : ids) { + allIds.insert(id); + } } + nodeIds = allIds.values(); + } - QList nodeIds; - - if (p_tags.size() == 1) { - nodeIds = queryTagNodesRecursive(p_tags.first()); - } else { - QSet allIds; - for (const auto &tag : p_tags) { - auto ids = queryTagNodesRecursive(tag); - for (const auto &id : ids) { - allIds.insert(id); - } - } - nodeIds = allIds.values(); + for (const auto &id : nodeIds) { + auto nodePath = queryNodePath(id); + if (nodePath.isNull()) { + continue; } - for (const auto &id : nodeIds) { - auto nodePath = queryNodePath(id); - if (nodePath.isNull()) { - continue; - } + ret.append(nodePath); + } - ret.append(nodePath); - } - - return ret; + return ret; } -QList NotebookDatabaseAccess::getAllTags() -{ - QList ret; - - auto db = getDatabase(); - QSqlQuery query(db); - query.prepare(QStringLiteral("SELECT name, parent_name FROM %1 ORDER BY parent_name, name").arg(c_tagTableName)); - if (!query.exec()) { - qWarning() << "failed to query tags" << query.executedQuery() << query.lastError().text(); - return ret; - } +QList NotebookDatabaseAccess::getAllTags() { + QList ret; - while (query.next()) { - ret.append(TagRecord()); - ret.last().m_name = query.value(0).toString(); - ret.last().m_parentName = query.value(1).toString(); - } + auto db = getDatabase(); + QSqlQuery query(db); + query.prepare(QStringLiteral("SELECT name, parent_name FROM %1 ORDER BY parent_name, name") + .arg(c_tagTableName)); + if (!query.exec()) { + qWarning() << "failed to query tags" << query.executedQuery() << query.lastError().text(); return ret; + } + + while (query.next()) { + ret.append(TagRecord()); + ret.last().m_name = query.value(0).toString(); + ret.last().m_parentName = query.value(1).toString(); + } + return ret; } diff --git a/src/core/notebook/notebookdatabaseaccess.h b/src/core/notebook/notebookdatabaseaccess.h index c67291c645..957519a165 100644 --- a/src/core/notebook/notebookdatabaseaccess.h +++ b/src/core/notebook/notebookdatabaseaccess.h @@ -2,149 +2,147 @@ #define NOTEBOOKDATABASEACCESS_H #include +#include #include #include -#include #include -namespace tests -{ - class TestNotebookDatabase; +namespace tests { +class TestNotebookDatabase; } -namespace vnotex -{ - class Node; - class Notebook; +namespace vnotex { +class Node; +class Notebook; - class NotebookDatabaseAccess : public QObject - { - Q_OBJECT - public: - enum { InvalidId = 0 }; +class NotebookDatabaseAccess : public QObject { + Q_OBJECT +public: + enum { InvalidId = 0 }; - struct TagRecord - { - QString m_name; + struct TagRecord { + QString m_name; - QString m_parentName; - }; + QString m_parentName; + }; - friend class tests::TestNotebookDatabase; + friend class tests::TestNotebookDatabase; - NotebookDatabaseAccess(Notebook *p_notebook, const QString &p_databaseFile, QObject *p_parent = nullptr); + NotebookDatabaseAccess(Notebook *p_notebook, const QString &p_databaseFile, + QObject *p_parent = nullptr); - bool isFresh() const; + bool isFresh() const; - bool isValid() const; + bool isValid() const; - void initialize(int p_configVersion); + void initialize(int p_configVersion); - bool open(); + bool open(); - void close(); + void close(); - // Node table. - public: - bool addNode(Node *p_node, bool p_ignoreId); + // Node table. +public: + bool addNode(Node *p_node, bool p_ignoreId); - bool addNodeRecursively(Node *p_node, bool p_ignoreId); + bool addNodeRecursively(Node *p_node, bool p_ignoreId); - // Whether there is a record with the same ID in DB and has the same path. - bool existsNode(const Node *p_node); + // Whether there is a record with the same ID in DB and has the same path. + bool existsNode(const Node *p_node); - void clearObsoleteNodes(); + void clearObsoleteNodes(); - bool updateNode(const Node *p_node); + bool updateNode(const Node *p_node); - bool removeNode(const Node *p_node); + bool removeNode(const Node *p_node); - // Tag table. - public: - // Will update the tag if exists. - bool addTag(const QString &p_name, const QString &p_parentName); + // Tag table. +public: + // Will update the tag if exists. + bool addTag(const QString &p_name, const QString &p_parentName); - bool addTag(const QString &p_name); + bool addTag(const QString &p_name); - bool renameTag(const QString &p_name, const QString &p_newName); + bool renameTag(const QString &p_name, const QString &p_newName); - bool removeTag(const QString &p_name); + bool removeTag(const QString &p_name); - // Sorted by parent_name. - QList getAllTags(); + // Sorted by parent_name. + QList getAllTags(); - QStringList queryTagAndChildren(const QString &p_tag); + QStringList queryTagAndChildren(const QString &p_tag); - // Node_tag table. - public: - bool updateNodeTags(Node *p_node); + // Node_tag table. +public: + bool updateNodeTags(Node *p_node); - // Return the relative path of nodes of tags @p_tags. - QStringList getNodesOfTags(const QStringList &p_tags); + // Return the relative path of nodes of tags @p_tags. + QStringList getNodesOfTags(const QStringList &p_tags); - private: - struct NodeRecord - { - ID m_id = InvalidId; +private: + struct NodeRecord { + ID m_id = InvalidId; - QString m_name; + QString m_name; - ID m_signature = InvalidId; + ID m_signature = InvalidId; - ID m_parentId = InvalidId; - }; + ID m_parentId = InvalidId; + }; - void setupTables(QSqlDatabase &p_db, int p_configVersion); + void setupTables(QSqlDatabase &p_db, int p_configVersion); - QSqlDatabase getDatabase() const; + QSqlDatabase getDatabase() const; - // Return null if not exists. - QSharedPointer queryNode(ID p_id); + // Return null if not exists. + QSharedPointer queryNode(ID p_id); - QStringList queryNodeParentPath(ID p_id); + QStringList queryNodeParentPath(ID p_id); - QString queryNodePath(ID p_id); + QString queryNodePath(ID p_id); - bool nodeEqual(const NodeRecord *p_rec, const Node *p_node) const; + bool nodeEqual(const NodeRecord *p_rec, const Node *p_node) const; - bool existsNode(const Node *p_node, const NodeRecord *p_rec, const QStringList &p_nodePath); + bool existsNode(const Node *p_node, const NodeRecord *p_rec, const QStringList &p_nodePath); - bool checkNodePath(const Node *p_node, const QStringList &p_nodePath) const; + bool checkNodePath(const Node *p_node, const QStringList &p_nodePath) const; - bool removeNode(ID p_id); + bool removeNode(ID p_id); - // Return null if not exists. - QSharedPointer queryTag(const QString &p_name); + // Return null if not exists. + QSharedPointer queryTag(const QString &p_name); - bool updateTagParent(const QString &p_name, const QString &p_parentName); + bool updateTagParent(const QString &p_name, const QString &p_parentName); - bool addTag(const QString &p_name, const QString &p_parentName, bool p_updateOnExists); + bool addTag(const QString &p_name, const QString &p_parentName, bool p_updateOnExists); - QStringList queryNodeTags(ID p_id); + QStringList queryNodeTags(ID p_id); - QList queryTagNodes(const QString &p_tag); + QList queryTagNodes(const QString &p_tag); - QList queryTagNodesRecursive(const QString &p_tag); + QList queryTagNodesRecursive(const QString &p_tag); - bool removeNodeTags(ID p_id); + bool removeNodeTags(ID p_id); - bool addNodeTags(ID p_id, const QStringList &p_tags); + bool addNodeTags(ID p_id, const QStringList &p_tags); - Notebook *m_notebook = nullptr; + Notebook *m_notebook = nullptr; - QString m_databaseFile; + QString m_databaseFile; - // From Qt's docs: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. - QString m_connectionName; + // From Qt's docs: It is highly recommended that you do not keep a copy of the QSqlDatabase around + // as a member of a class, as this will prevent the instance from being correctly cleaned up on + // shutdown. + QString m_connectionName; - // Whether it is a new data base whether any tables. - bool m_fresh = false; + // Whether it is a new data base whether any tables. + bool m_fresh = false; - bool m_valid = false; + bool m_valid = false; - QSet m_obsoleteNodes; - }; -} + QSet m_obsoleteNodes; +}; +} // namespace vnotex #endif // NOTEBOOKDATABASEACCESS_H diff --git a/src/core/notebook/notebookparameters.cpp b/src/core/notebook/notebookparameters.cpp index 08f3b0ef39..c1d82425a8 100644 --- a/src/core/notebook/notebookparameters.cpp +++ b/src/core/notebook/notebookparameters.cpp @@ -5,60 +5,34 @@ using namespace vnotex; QSharedPointer NotebookParameters::createNotebookParameters( - const NotebookMgr &p_mgr, - const QString &p_type, - const QString &p_name, - const QString &p_description, - const QString &p_rootFolderPath, - const QIcon &p_icon, - const QString &p_imageFolder, - const QString &p_attachmentFolder, - const QDateTime &p_createdTimeUtc, - const QString &p_backend, - const QString &p_versionController, - const QString &p_configMgr) -{ - auto backend = p_mgr.createNotebookBackend(p_backend, p_rootFolderPath); - return createNotebookParameters(p_mgr, - backend, - p_type, - p_name, - p_description, - p_rootFolderPath, - p_icon, - p_imageFolder, - p_attachmentFolder, - p_createdTimeUtc, - p_versionController, - p_configMgr); + const NotebookMgr &p_mgr, const QString &p_type, const QString &p_name, + const QString &p_description, const QString &p_rootFolderPath, const QIcon &p_icon, + const QString &p_imageFolder, const QString &p_attachmentFolder, + const QDateTime &p_createdTimeUtc, const QString &p_backend, const QString &p_versionController, + const QString &p_configMgr) { + auto backend = p_mgr.createNotebookBackend(p_backend, p_rootFolderPath); + return createNotebookParameters(p_mgr, backend, p_type, p_name, p_description, p_rootFolderPath, + p_icon, p_imageFolder, p_attachmentFolder, p_createdTimeUtc, + p_versionController, p_configMgr); } QSharedPointer NotebookParameters::createNotebookParameters( - const NotebookMgr &p_mgr, - const QSharedPointer &p_backend, - const QString &p_type, - const QString &p_name, - const QString &p_description, - const QString &p_rootFolderPath, - const QIcon &p_icon, - const QString &p_imageFolder, - const QString &p_attachmentFolder, - const QDateTime &p_createdTimeUtc, - const QString &p_versionController, - const QString &p_configMgr) -{ - auto paras = QSharedPointer::create(); - paras->m_type = p_type; - paras->m_name = p_name; - paras->m_description = p_description; - paras->m_rootFolderPath = p_rootFolderPath; - paras->m_icon = p_icon; - paras->m_imageFolder = p_imageFolder; - paras->m_attachmentFolder = p_attachmentFolder; - paras->m_createdTimeUtc = p_createdTimeUtc; - paras->m_notebookBackend = p_backend; - paras->m_versionController = p_mgr.createVersionController(p_versionController); - paras->m_notebookConfigMgr = p_mgr.createNotebookConfigMgr(p_configMgr, - paras->m_notebookBackend); - return paras; + const NotebookMgr &p_mgr, const QSharedPointer &p_backend, + const QString &p_type, const QString &p_name, const QString &p_description, + const QString &p_rootFolderPath, const QIcon &p_icon, const QString &p_imageFolder, + const QString &p_attachmentFolder, const QDateTime &p_createdTimeUtc, + const QString &p_versionController, const QString &p_configMgr) { + auto paras = QSharedPointer::create(); + paras->m_type = p_type; + paras->m_name = p_name; + paras->m_description = p_description; + paras->m_rootFolderPath = p_rootFolderPath; + paras->m_icon = p_icon; + paras->m_imageFolder = p_imageFolder; + paras->m_attachmentFolder = p_attachmentFolder; + paras->m_createdTimeUtc = p_createdTimeUtc; + paras->m_notebookBackend = p_backend; + paras->m_versionController = p_mgr.createVersionController(p_versionController); + paras->m_notebookConfigMgr = p_mgr.createNotebookConfigMgr(p_configMgr, paras->m_notebookBackend); + return paras; } diff --git a/src/core/notebook/notebookparameters.h b/src/core/notebook/notebookparameters.h index b22a14b726..7535a3cd26 100644 --- a/src/core/notebook/notebookparameters.h +++ b/src/core/notebook/notebookparameters.h @@ -1,70 +1,55 @@ #ifndef NOTEBOOKPARAMETERS_H #define NOTEBOOKPARAMETERS_H -#include -#include #include +#include +#include -namespace vnotex -{ - class NotebookMgr; - class INotebookBackend; - class IVersionController; - class INotebookConfigMgr; - - // Used to new a notebook. - class NotebookParameters - { - public: - virtual ~NotebookParameters() {} - - static QSharedPointer createNotebookParameters( - const NotebookMgr &p_mgr, - const QString &p_type, - const QString &p_name, - const QString &p_description, - const QString &p_rootFolderPath, - const QIcon &p_icon, - const QString &p_imageFolder, - const QString &p_attachmentFolder, - const QDateTime &p_createdTimeUtc, - const QString &p_backend, - const QString &p_versionController, - const QString &p_configMgr); - - static QSharedPointer createNotebookParameters( - const NotebookMgr &p_mgr, - const QSharedPointer &p_backend, - const QString &p_type, - const QString &p_name, - const QString &p_description, - const QString &p_rootFolderPath, - const QIcon &p_icon, - const QString &p_imageFolder, - const QString &p_attachmentFolder, - const QDateTime &p_createdTimeUtc, - const QString &p_versionController, - const QString &p_configMgr); - - QString m_type; - QString m_name; - QString m_description; - QString m_rootFolderPath; - QIcon m_icon; - - // Name of image folder. - QString m_imageFolder; - - // Name of attachment folder. - QString m_attachmentFolder; - - QDateTime m_createdTimeUtc; - QSharedPointer m_notebookBackend; - QSharedPointer m_versionController; - QSharedPointer m_notebookConfigMgr; - - bool m_ensureEmptyRootFolder = true; - }; -} // ns vnotex +namespace vnotex { +class NotebookMgr; +class INotebookBackend; +class IVersionController; +class INotebookConfigMgr; + +// Used to new a notebook. +class NotebookParameters { +public: + virtual ~NotebookParameters() {} + + static QSharedPointer + createNotebookParameters(const NotebookMgr &p_mgr, const QString &p_type, const QString &p_name, + const QString &p_description, const QString &p_rootFolderPath, + const QIcon &p_icon, const QString &p_imageFolder, + const QString &p_attachmentFolder, const QDateTime &p_createdTimeUtc, + const QString &p_backend, const QString &p_versionController, + const QString &p_configMgr); + + static QSharedPointer createNotebookParameters( + const NotebookMgr &p_mgr, const QSharedPointer &p_backend, + const QString &p_type, const QString &p_name, const QString &p_description, + const QString &p_rootFolderPath, const QIcon &p_icon, const QString &p_imageFolder, + const QString &p_attachmentFolder, const QDateTime &p_createdTimeUtc, + const QString &p_versionController, const QString &p_configMgr); + + QString m_type; + QString m_name; + QString m_description; + QString m_rootFolderPath; + QIcon m_icon; + + // Name of image folder. + QString m_imageFolder; + + // Name of attachment folder. + QString m_attachmentFolder; + + QDateTime m_createdTimeUtc; + QSharedPointer m_notebookBackend; + QSharedPointer m_versionController; + QSharedPointer m_notebookConfigMgr; + + bool m_ensureEmptyRootFolder = true; +}; +} // namespace vnotex #endif // NOTEBOOKPARAMETERS_H diff --git a/src/core/notebook/notebooktagmgr.cpp b/src/core/notebook/notebooktagmgr.cpp index 9aa1d83796..0c54f3de3c 100644 --- a/src/core/notebook/notebooktagmgr.cpp +++ b/src/core/notebook/notebooktagmgr.cpp @@ -9,314 +9,298 @@ using namespace vnotex; NotebookTagMgr::NotebookTagMgr(BundleNotebook *p_notebook) - : QObject(p_notebook), - m_notebook(p_notebook) -{ - update(); + : QObject(p_notebook), m_notebook(p_notebook) { + update(); } -QVector NotebookTagMgr::stringToTagGraph(const QString &p_text) -{ - // parent>chlid;parent2>chlid2. - QVector tagGraph; - auto pairs = p_text.split(QLatin1Char(';')); - for (const auto &pa : pairs) { - if (pa.isEmpty()) { - continue; - } - - auto paCh = pa.split(QLatin1Char('>')); - if (paCh.size() != 2 || paCh[0].isEmpty() || paCh[1].isEmpty()) { - qWarning() << "ignore invalid tag pair" << pa; - continue; - } - - TagGraphPair tagPair; - tagPair.m_parent = paCh[0]; - tagPair.m_child = paCh[1]; - tagGraph.push_back(tagPair); +QVector NotebookTagMgr::stringToTagGraph(const QString &p_text) { + // parent>chlid;parent2>chlid2. + QVector tagGraph; + auto pairs = p_text.split(QLatin1Char(';')); + for (const auto &pa : pairs) { + if (pa.isEmpty()) { + continue; } - return tagGraph; -} - -QString NotebookTagMgr::tagGraphToString(const QVector &p_tagGraph) -{ - QString text; - if (p_tagGraph.isEmpty()) { - return text; + auto paCh = pa.split(QLatin1Char('>')); + if (paCh.size() != 2 || paCh[0].isEmpty() || paCh[1].isEmpty()) { + qWarning() << "ignore invalid tag pair" << pa; + continue; } - text = p_tagGraph[0].m_parent + QLatin1Char('>') + p_tagGraph[0].m_child; - for (int i = 1; i < p_tagGraph.size(); ++i) { - text += QLatin1Char(';') + p_tagGraph[i].m_parent + QLatin1Char('>') + p_tagGraph[i].m_child; - } + TagGraphPair tagPair; + tagPair.m_parent = paCh[0]; + tagPair.m_child = paCh[1]; + tagGraph.push_back(tagPair); + } - return text; + return tagGraph; } -const QVector> &NotebookTagMgr::getTopLevelTags() const -{ - return m_topLevelTags; -} +QString NotebookTagMgr::tagGraphToString(const QVector &p_tagGraph) { + QString text; + if (p_tagGraph.isEmpty()) { + return text; + } -void NotebookTagMgr::update() -{ - auto db = m_notebook->getDatabaseAccess(); - const auto allTags = db->getAllTags(); + text = p_tagGraph[0].m_parent + QLatin1Char('>') + p_tagGraph[0].m_child; + for (int i = 1; i < p_tagGraph.size(); ++i) { + text += QLatin1Char(';') + p_tagGraph[i].m_parent + QLatin1Char('>') + p_tagGraph[i].m_child; + } - update(allTags); + return text; } -void NotebookTagMgr::update(const QList &p_allTags) -{ - m_topLevelTags.clear(); +const QVector> &NotebookTagMgr::getTopLevelTags() const { + return m_topLevelTags; +} - QHash nameToTag; +void NotebookTagMgr::update() { + auto db = m_notebook->getDatabaseAccess(); + const auto allTags = db->getAllTags(); - QVector todoIdx; - todoIdx.reserve(p_allTags.size()); - for (int i = 0; i < p_allTags.size(); ++i) { - todoIdx.push_back(i); - } + update(allTags); +} - while (!todoIdx.isEmpty()) { - QVector pendingIdx; - pendingIdx.reserve(p_allTags.size()); - - for (int i = 0; i < todoIdx.size(); ++i) { - const auto &rec = p_allTags[todoIdx[i]]; - Q_ASSERT(!nameToTag.contains(rec.m_name)); - QSharedPointer newTag; - if (rec.m_parentName.isEmpty()) { - // Top level. - newTag = QSharedPointer::create(rec.m_name); - m_topLevelTags.push_back(newTag); - } else { - auto parentIt = nameToTag.find(rec.m_parentName); - if (parentIt == nameToTag.end()) { - // Need to process its parent first. - pendingIdx.push_back(todoIdx[i]); - continue; - } else { - newTag = QSharedPointer::create(rec.m_name); - parentIt.value()->addChild(newTag); - } - } - - nameToTag.insert(newTag->name(), newTag.data()); +void NotebookTagMgr::update(const QList &p_allTags) { + m_topLevelTags.clear(); + + QHash nameToTag; + + QVector todoIdx; + todoIdx.reserve(p_allTags.size()); + for (int i = 0; i < p_allTags.size(); ++i) { + todoIdx.push_back(i); + } + + while (!todoIdx.isEmpty()) { + QVector pendingIdx; + pendingIdx.reserve(p_allTags.size()); + + for (int i = 0; i < todoIdx.size(); ++i) { + const auto &rec = p_allTags[todoIdx[i]]; + Q_ASSERT(!nameToTag.contains(rec.m_name)); + QSharedPointer newTag; + if (rec.m_parentName.isEmpty()) { + // Top level. + newTag = QSharedPointer::create(rec.m_name); + m_topLevelTags.push_back(newTag); + } else { + auto parentIt = nameToTag.find(rec.m_parentName); + if (parentIt == nameToTag.end()) { + // Need to process its parent first. + pendingIdx.push_back(todoIdx[i]); + continue; + } else { + newTag = QSharedPointer::create(rec.m_name); + parentIt.value()->addChild(newTag); } + } - if (todoIdx.size() == pendingIdx.size()) { - qWarning() << "cyclic parent-chlid tag definition detected"; - break; - } + nameToTag.insert(newTag->name(), newTag.data()); + } - todoIdx = pendingIdx; + if (todoIdx.size() == pendingIdx.size()) { + qWarning() << "cyclic parent-chlid tag definition detected"; + break; } -} -QStringList NotebookTagMgr::findNodesOfTag(const QString &p_name) -{ - auto db = m_notebook->getDatabaseAccess(); - return db->getNodesOfTags(QStringList(p_name)); + todoIdx = pendingIdx; + } } -QSharedPointer NotebookTagMgr::findTag(const QString &p_name) -{ - QSharedPointer tag; - forEachTag([&tag, p_name](const QSharedPointer &p_tag) { - if (p_tag->name() == p_name) { - tag = p_tag; - return false; - } - return true; - }); - - return tag; +QStringList NotebookTagMgr::findNodesOfTag(const QString &p_name) { + auto db = m_notebook->getDatabaseAccess(); + return db->getNodesOfTags(QStringList(p_name)); } -void NotebookTagMgr::forEachTag(const TagFinder &p_func) const -{ - for (const auto &tag : m_topLevelTags) { - if (!forEachTag(tag, p_func)) { - return; - } +QSharedPointer NotebookTagMgr::findTag(const QString &p_name) { + QSharedPointer tag; + forEachTag([&tag, p_name](const QSharedPointer &p_tag) { + if (p_tag->name() == p_name) { + tag = p_tag; + return false; } + return true; + }); + + return tag; } -bool NotebookTagMgr::forEachTag(const QSharedPointer &p_tag, const TagFinder &p_func) const -{ - if (!p_func(p_tag)) { - return false; +void NotebookTagMgr::forEachTag(const TagFinder &p_func) const { + for (const auto &tag : m_topLevelTags) { + if (!forEachTag(tag, p_func)) { + return; } + } +} - for (const auto &child : p_tag->getChildren()) { - if (!forEachTag(child, p_func)) { - return false; - } +bool NotebookTagMgr::forEachTag(const QSharedPointer &p_tag, const TagFinder &p_func) const { + if (!p_func(p_tag)) { + return false; + } + + for (const auto &child : p_tag->getChildren()) { + if (!forEachTag(child, p_func)) { + return false; } + } - return true; + return true; } -bool NotebookTagMgr::newTag(const QString &p_name, const QString &p_parentName) -{ - if (p_name.isEmpty()) { - return false; - } +bool NotebookTagMgr::newTag(const QString &p_name, const QString &p_parentName) { + if (p_name.isEmpty()) { + return false; + } - auto db = m_notebook->getDatabaseAccess(); - bool ret = db->addTag(p_name, p_parentName); - if (ret) { - const auto allTags = db->getAllTags(); - update(allTags); - if (!p_parentName.isEmpty()) { - updateNotebookTagGraph(allTags); - } - emit m_notebook->tagsUpdated(); - return true; - } else { - qWarning() << "failed to new tag" << p_name << p_parentName; - return false; + auto db = m_notebook->getDatabaseAccess(); + bool ret = db->addTag(p_name, p_parentName); + if (ret) { + const auto allTags = db->getAllTags(); + update(allTags); + if (!p_parentName.isEmpty()) { + updateNotebookTagGraph(allTags); } + emit m_notebook->tagsUpdated(); + return true; + } else { + qWarning() << "failed to new tag" << p_name << p_parentName; + return false; + } } -bool NotebookTagMgr::updateNodeTags(Node *p_node) -{ - auto db = m_notebook->getDatabaseAccess(); +bool NotebookTagMgr::updateNodeTags(Node *p_node) { + auto db = m_notebook->getDatabaseAccess(); - // Make sure the node exists in DB. - if (!db->addNodeRecursively(p_node, false)) { - qWarning() << "failed to add node to DB" << p_node->fetchPath() << p_node->getId() << (p_node->getParent() ? p_node->getParent()->getId() : -1); - return false; - } + // Make sure the node exists in DB. + if (!db->addNodeRecursively(p_node, false)) { + qWarning() << "failed to add node to DB" << p_node->fetchPath() << p_node->getId() + << (p_node->getParent() ? p_node->getParent()->getId() : -1); + return false; + } - if (db->updateNodeTags(p_node)) { - update(); - emit m_notebook->tagsUpdated(); - return true; - } + if (db->updateNodeTags(p_node)) { + update(); + emit m_notebook->tagsUpdated(); + return true; + } - return false; + return false; } -bool NotebookTagMgr::updateNodeTags(Node *p_node, const QStringList &p_newTags) -{ - p_node->updateTags(p_newTags); - return updateNodeTags(p_node); +bool NotebookTagMgr::updateNodeTags(Node *p_node, const QStringList &p_newTags) { + p_node->updateTags(p_newTags); + return updateNodeTags(p_node); } -bool NotebookTagMgr::renameTag(const QString &p_name, const QString &p_newName) -{ - const auto nodePaths = findNodesOfTag(p_name); +bool NotebookTagMgr::renameTag(const QString &p_name, const QString &p_newName) { + const auto nodePaths = findNodesOfTag(p_name); - auto db = m_notebook->getDatabaseAccess(); - if (!db->renameTag(p_name, p_newName)) { - return false; - } + auto db = m_notebook->getDatabaseAccess(); + if (!db->renameTag(p_name, p_newName)) { + return false; + } - const auto allTags = db->getAllTags(); - update(allTags); + const auto allTags = db->getAllTags(); + update(allTags); - updateNotebookTagGraph(allTags); + updateNotebookTagGraph(allTags); - // Update node tag. - for (const auto &pa : nodePaths) { - auto node = m_notebook->loadNodeByPath(pa); - if (!node) { - qWarning() << "node belongs to tag in DB but not exists" << p_name << pa; - continue; - } + // Update node tag. + for (const auto &pa : nodePaths) { + auto node = m_notebook->loadNodeByPath(pa); + if (!node) { + qWarning() << "node belongs to tag in DB but not exists" << p_name << pa; + continue; + } - auto tags = node->getTags(); - for (auto &tag : tags) { - if (tag == p_name) { - tag = p_newName; - break; - } - } - node->updateTags(tags); + auto tags = node->getTags(); + for (auto &tag : tags) { + if (tag == p_name) { + tag = p_newName; + break; + } } + node->updateTags(tags); + } - emit m_notebook->tagsUpdated(); - return true; + emit m_notebook->tagsUpdated(); + return true; } -void NotebookTagMgr::updateNotebookTagGraph(const QList &p_allTags) -{ - QVector graph; - graph.reserve(p_allTags.size()); - for (const auto &tag : p_allTags) { - if (tag.m_parentName.isEmpty()) { - continue; - } - TagGraphPair pa; - pa.m_parent = tag.m_parentName; - pa.m_child = tag.m_name; - graph.push_back(pa); +void NotebookTagMgr::updateNotebookTagGraph( + const QList &p_allTags) { + QVector graph; + graph.reserve(p_allTags.size()); + for (const auto &tag : p_allTags) { + if (tag.m_parentName.isEmpty()) { + continue; } - m_notebook->updateTagGraph(tagGraphToString(graph)); + TagGraphPair pa; + pa.m_parent = tag.m_parentName; + pa.m_child = tag.m_name; + graph.push_back(pa); + } + m_notebook->updateTagGraph(tagGraphToString(graph)); } -bool NotebookTagMgr::removeTag(const QString &p_name) -{ - const auto nodePaths = findNodesOfTag(p_name); - - auto db = m_notebook->getDatabaseAccess(); - QStringList tagsAndChildren; - if (!nodePaths.isEmpty()) { - tagsAndChildren = db->queryTagAndChildren(p_name); - if (tagsAndChildren.isEmpty()) { - qWarning() << "failed to query tag and its children" << p_name; - return false; - } - } +bool NotebookTagMgr::removeTag(const QString &p_name) { + const auto nodePaths = findNodesOfTag(p_name); - if (!db->removeTag(p_name)) { - return false; + auto db = m_notebook->getDatabaseAccess(); + QStringList tagsAndChildren; + if (!nodePaths.isEmpty()) { + tagsAndChildren = db->queryTagAndChildren(p_name); + if (tagsAndChildren.isEmpty()) { + qWarning() << "failed to query tag and its children" << p_name; + return false; } + } - const auto allTags = db->getAllTags(); - update(allTags); + if (!db->removeTag(p_name)) { + return false; + } - updateNotebookTagGraph(allTags); + const auto allTags = db->getAllTags(); + update(allTags); - // Update node tag. - for (const auto &pa : nodePaths) { - auto node = m_notebook->loadNodeByPath(pa); - if (!node) { - qWarning() << "node belongs to tag in DB but not exists" << p_name << pa; - continue; - } + updateNotebookTagGraph(allTags); - const auto &tags = node->getTags(); - QStringList newTags; - for (const auto &tag : tags) { - if (tagsAndChildren.contains(tag)) { - continue; - } - newTags.append(tag); - } - node->updateTags(newTags); + // Update node tag. + for (const auto &pa : nodePaths) { + auto node = m_notebook->loadNodeByPath(pa); + if (!node) { + qWarning() << "node belongs to tag in DB but not exists" << p_name << pa; + continue; } - emit m_notebook->tagsUpdated(); - return true; + const auto &tags = node->getTags(); + QStringList newTags; + for (const auto &tag : tags) { + if (tagsAndChildren.contains(tag)) { + continue; + } + newTags.append(tag); + } + node->updateTags(newTags); + } + + emit m_notebook->tagsUpdated(); + return true; } -bool NotebookTagMgr::moveTag(const QString &p_name, const QString &p_newParentName) -{ - auto db = m_notebook->getDatabaseAccess(); - if (!db->addTag(p_name, p_newParentName)) { - return false; - } +bool NotebookTagMgr::moveTag(const QString &p_name, const QString &p_newParentName) { + auto db = m_notebook->getDatabaseAccess(); + if (!db->addTag(p_name, p_newParentName)) { + return false; + } - const auto allTags = db->getAllTags(); - update(allTags); + const auto allTags = db->getAllTags(); + update(allTags); - updateNotebookTagGraph(allTags); + updateNotebookTagGraph(allTags); - emit m_notebook->tagsUpdated(); - return true; + emit m_notebook->tagsUpdated(); + return true; } diff --git a/src/core/notebook/notebooktagmgr.h b/src/core/notebook/notebooktagmgr.h index ffdd499025..2385914fb4 100644 --- a/src/core/notebook/notebooktagmgr.h +++ b/src/core/notebook/notebooktagmgr.h @@ -7,72 +7,69 @@ #include -#include #include +#include #include "notebookdatabaseaccess.h" -namespace vnotex -{ - class BundleNotebook; - class Tag; +namespace vnotex { +class BundleNotebook; +class Tag; - class NotebookTagMgr : public QObject, public TagI - { - Q_OBJECT - public: - struct TagGraphPair - { - QString m_parent; +class NotebookTagMgr : public QObject, public TagI { + Q_OBJECT +public: + struct TagGraphPair { + QString m_parent; - QString m_child; - }; + QString m_child; + }; - explicit NotebookTagMgr(BundleNotebook *p_notebook); + explicit NotebookTagMgr(BundleNotebook *p_notebook); - void update(); + void update(); - static QVector stringToTagGraph(const QString &p_text); + static QVector stringToTagGraph(const QString &p_text); - static QString tagGraphToString(const QVector &p_tagGraph); + static QString tagGraphToString(const QVector &p_tagGraph); - // TagI. - public: - const QVector> &getTopLevelTags() const Q_DECL_OVERRIDE; + // TagI. +public: + const QVector> &getTopLevelTags() const Q_DECL_OVERRIDE; - QStringList findNodesOfTag(const QString &p_name) Q_DECL_OVERRIDE; + QStringList findNodesOfTag(const QString &p_name) Q_DECL_OVERRIDE; - QSharedPointer findTag(const QString &p_name) Q_DECL_OVERRIDE; + QSharedPointer findTag(const QString &p_name) Q_DECL_OVERRIDE; - bool newTag(const QString &p_name, const QString &p_parentName) Q_DECL_OVERRIDE; + bool newTag(const QString &p_name, const QString &p_parentName) Q_DECL_OVERRIDE; - bool renameTag(const QString &p_name, const QString &p_newName) Q_DECL_OVERRIDE; + bool renameTag(const QString &p_name, const QString &p_newName) Q_DECL_OVERRIDE; - bool updateNodeTags(Node *p_node) Q_DECL_OVERRIDE; + bool updateNodeTags(Node *p_node) Q_DECL_OVERRIDE; - bool updateNodeTags(Node *p_node, const QStringList &p_newTags) Q_DECL_OVERRIDE; + bool updateNodeTags(Node *p_node, const QStringList &p_newTags) Q_DECL_OVERRIDE; - bool removeTag(const QString &p_name) Q_DECL_OVERRIDE; + bool removeTag(const QString &p_name) Q_DECL_OVERRIDE; - bool moveTag(const QString &p_name, const QString &p_newParentName) Q_DECL_OVERRIDE; + bool moveTag(const QString &p_name, const QString &p_newParentName) Q_DECL_OVERRIDE; - private: - typedef std::function &p_tag)> TagFinder; +private: + typedef std::function &p_tag)> TagFinder; - // @p_func: return false to abort the search. - void forEachTag(const TagFinder &p_func) const; + // @p_func: return false to abort the search. + void forEachTag(const TagFinder &p_func) const; - // Return false if abort. - bool forEachTag(const QSharedPointer &p_tag, const TagFinder &p_func) const; + // Return false if abort. + bool forEachTag(const QSharedPointer &p_tag, const TagFinder &p_func) const; - void update(const QList &p_allTags); + void update(const QList &p_allTags); - void updateNotebookTagGraph(const QList &p_allTags); + void updateNotebookTagGraph(const QList &p_allTags); - BundleNotebook *m_notebook = nullptr; + BundleNotebook *m_notebook = nullptr; - QVector> m_topLevelTags; - }; -} + QVector> m_topLevelTags; +}; +} // namespace vnotex #endif // NOTEBOOKTAGMGR_H diff --git a/src/core/notebook/tag.cpp b/src/core/notebook/tag.cpp index 6db2375161..01ad49e4b7 100644 --- a/src/core/notebook/tag.cpp +++ b/src/core/notebook/tag.cpp @@ -6,42 +6,27 @@ using namespace vnotex; -Tag::Tag(const QString &p_name) - : m_name(p_name) -{ -} +Tag::Tag(const QString &p_name) : m_name(p_name) {} -const QVector> &Tag::getChildren() const -{ - return m_children; -} +const QVector> &Tag::getChildren() const { return m_children; } -void Tag::addChild(const QSharedPointer &p_tag) -{ - p_tag->m_parent = this; - m_children.push_back(p_tag); +void Tag::addChild(const QSharedPointer &p_tag) { + p_tag->m_parent = this; + m_children.push_back(p_tag); } -const QString &Tag::name() const -{ - return m_name; -} +const QString &Tag::name() const { return m_name; } -Tag *Tag::getParent() const -{ - return m_parent; -} +Tag *Tag::getParent() const { return m_parent; } -QString Tag::fetchPath() const -{ - if (!m_parent) { - return m_name; - } else { - return PathUtils::concatenateFilePath(m_parent->fetchPath(), m_name); - } +QString Tag::fetchPath() const { + if (!m_parent) { + return m_name; + } else { + return PathUtils::concatenateFilePath(m_parent->fetchPath(), m_name); + } } -bool Tag::isValidName(const QString &p_name) -{ - return !p_name.isEmpty() && !p_name.contains(QRegularExpression("[>/]")); +bool Tag::isValidName(const QString &p_name) { + return !p_name.isEmpty() && !p_name.contains(QRegularExpression("[>/]")); } diff --git a/src/core/notebook/tag.h b/src/core/notebook/tag.h index 341b01c56c..7655ea5ef1 100644 --- a/src/core/notebook/tag.h +++ b/src/core/notebook/tag.h @@ -1,37 +1,35 @@ #ifndef TAG_H #define TAG_H +#include +#include #include #include -#include -#include -namespace vnotex -{ - class Tag : public QEnableSharedFromThis - { - public: - Tag(const QString &p_name); +namespace vnotex { +class Tag : public QEnableSharedFromThis { +public: + Tag(const QString &p_name); - const QVector> &getChildren() const; + const QVector> &getChildren() const; - const QString &name() const; + const QString &name() const; - Tag *getParent() const; + Tag *getParent() const; - void addChild(const QSharedPointer &p_tag); + void addChild(const QSharedPointer &p_tag); - QString fetchPath() const; + QString fetchPath() const; - static bool isValidName(const QString &p_name); + static bool isValidName(const QString &p_name); - private: - Tag *m_parent = nullptr; +private: + Tag *m_parent = nullptr; - QString m_name; + QString m_name; - QVector> m_children; - }; -} + QVector> m_children; +}; +} // namespace vnotex #endif // TAG_H diff --git a/src/core/notebook/tagi.h b/src/core/notebook/tagi.h index 665a0240ab..ea17540a59 100644 --- a/src/core/notebook/tagi.h +++ b/src/core/notebook/tagi.h @@ -5,33 +5,31 @@ #include "tag.h" -namespace vnotex -{ - class Node; +namespace vnotex { +class Node; - // Tag interface for notebook. - class TagI - { - public: - virtual ~TagI() = default; +// Tag interface for notebook. +class TagI { +public: + virtual ~TagI() = default; - virtual const QVector> &getTopLevelTags() const = 0; + virtual const QVector> &getTopLevelTags() const = 0; - virtual QStringList findNodesOfTag(const QString &p_name) = 0; + virtual QStringList findNodesOfTag(const QString &p_name) = 0; - virtual QSharedPointer findTag(const QString &p_name) = 0; + virtual QSharedPointer findTag(const QString &p_name) = 0; - virtual bool newTag(const QString &p_name, const QString &p_parentName) = 0; + virtual bool newTag(const QString &p_name, const QString &p_parentName) = 0; - virtual bool renameTag(const QString &p_name, const QString &p_newName) = 0; + virtual bool renameTag(const QString &p_name, const QString &p_newName) = 0; - virtual bool updateNodeTags(Node *p_node) = 0; + virtual bool updateNodeTags(Node *p_node) = 0; - virtual bool updateNodeTags(Node *p_node, const QStringList &p_newTags) = 0; + virtual bool updateNodeTags(Node *p_node, const QStringList &p_newTags) = 0; - virtual bool removeTag(const QString &p_name) = 0; + virtual bool removeTag(const QString &p_name) = 0; - virtual bool moveTag(const QString &p_name, const QString &p_newParentName) = 0; - }; -} + virtual bool moveTag(const QString &p_name, const QString &p_newParentName) = 0; +}; +} // namespace vnotex #endif // TAGI_H diff --git a/src/core/notebook/vxnode.cpp b/src/core/notebook/vxnode.cpp index 1e4756d90b..4230ba375f 100644 --- a/src/core/notebook/vxnode.cpp +++ b/src/core/notebook/vxnode.cpp @@ -2,109 +2,86 @@ #include -#include -#include -#include #include "notebook.h" #include "vxnodefile.h" +#include +#include +#include using namespace vnotex; -VXNode::VXNode(const QString &p_name, - const NodeParameters &p_paras, - Notebook *p_notebook, +VXNode::VXNode(const QString &p_name, const NodeParameters &p_paras, Notebook *p_notebook, Node *p_parent) - : Node(Node::Flag::Content, - p_name, - p_paras, - p_notebook, - p_parent) -{ -} + : Node(Node::Flag::Content, p_name, p_paras, p_notebook, p_parent) {} -VXNode::VXNode(const QString &p_name, - Notebook *p_notebook, - Node *p_parent) - : Node(Node::Flag::Container, - p_name, - p_notebook, - p_parent) -{ -} +VXNode::VXNode(const QString &p_name, Notebook *p_notebook, Node *p_parent) + : Node(Node::Flag::Container, p_name, p_notebook, p_parent) {} -QString VXNode::fetchAbsolutePath() const -{ - return PathUtils::concatenateFilePath(m_notebook->getRootFolderAbsolutePath(), - fetchPath()); +QString VXNode::fetchAbsolutePath() const { + return PathUtils::concatenateFilePath(m_notebook->getRootFolderAbsolutePath(), fetchPath()); } -QSharedPointer VXNode::getContentFile() -{ - Q_ASSERT(hasContent()); - // We should not keep the shared ptr of VXNodeFile, or there is a cyclic ref. - return QSharedPointer::create(sharedFromThis().dynamicCast()); +QSharedPointer VXNode::getContentFile() { + Q_ASSERT(hasContent()); + // We should not keep the shared ptr of VXNodeFile, or there is a cyclic ref. + return QSharedPointer::create(sharedFromThis().dynamicCast()); } -QStringList VXNode::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) -{ - Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); - - auto backend = getBackend(); - QStringList addedFiles; - for (const auto &file : p_files) { - if (PathUtils::isDir(file)) { - qWarning() << "skip adding folder as attachment" << file; - continue; - } - - auto destFilePath = backend->renameIfExistsCaseInsensitive( - PathUtils::concatenateFilePath(p_destFolderPath, PathUtils::fileName(file))); - backend->copyFile(file, destFilePath); - addedFiles << destFilePath; +QStringList VXNode::addAttachment(const QString &p_destFolderPath, const QStringList &p_files) { + Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); + + auto backend = getBackend(); + QStringList addedFiles; + for (const auto &file : p_files) { + if (PathUtils::isDir(file)) { + qWarning() << "skip adding folder as attachment" << file; + continue; } - return addedFiles; + auto destFilePath = backend->renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(p_destFolderPath, PathUtils::fileName(file))); + backend->copyFile(file, destFilePath); + addedFiles << destFilePath; + } + + return addedFiles; } -QString VXNode::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); +QString VXNode::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); - auto backend = getBackend(); - auto destFilePath = backend->renameIfExistsCaseInsensitive( - PathUtils::concatenateFilePath(p_destFolderPath, p_name)); - backend->writeFile(destFilePath, QByteArray()); - return destFilePath; + auto backend = getBackend(); + auto destFilePath = backend->renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(p_destFolderPath, p_name)); + backend->writeFile(destFilePath, QByteArray()); + return destFilePath; } -QString VXNode::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); +QString VXNode::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath)); - auto backend = getBackend(); - auto destFilePath = backend->renameIfExistsCaseInsensitive( - PathUtils::concatenateFilePath(p_destFolderPath, p_name)); - backend->makePath(destFilePath); - return destFilePath; + auto backend = getBackend(); + auto destFilePath = backend->renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(p_destFolderPath, p_name)); + backend->makePath(destFilePath); + return destFilePath; } -QString VXNode::renameAttachment(const QString &p_path, const QString &p_name) -{ - Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_path)); - getBackend()->renameFile(p_path, p_name); - return p_name; +QString VXNode::renameAttachment(const QString &p_path, const QString &p_name) { + Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_path)); + getBackend()->renameFile(p_path, p_name); + return p_name; } -void VXNode::removeAttachment(const QStringList &p_paths) -{ - auto attaFolderPath = fetchAttachmentFolderPath(); - // Just move it to recycle bin but not added as a child node of recycle bin. - for (const auto &pa : p_paths) { - Q_ASSERT(PathUtils::pathContains(attaFolderPath, pa)); - if (QFileInfo(pa).isDir()) { - m_notebook->moveDirToRecycleBin(pa); - } else { - m_notebook->moveFileToRecycleBin(pa); - } +void VXNode::removeAttachment(const QStringList &p_paths) { + auto attaFolderPath = fetchAttachmentFolderPath(); + // Just move it to recycle bin but not added as a child node of recycle bin. + for (const auto &pa : p_paths) { + Q_ASSERT(PathUtils::pathContains(attaFolderPath, pa)); + if (QFileInfo(pa).isDir()) { + m_notebook->moveDirToRecycleBin(pa); + } else { + m_notebook->moveFileToRecycleBin(pa); } + } } diff --git a/src/core/notebook/vxnode.h b/src/core/notebook/vxnode.h index 52be6237ea..e418e18f4b 100644 --- a/src/core/notebook/vxnode.h +++ b/src/core/notebook/vxnode.h @@ -3,37 +3,33 @@ #include "node.h" -namespace vnotex -{ - // Node of VXNotebookConfigMgr. - class VXNode : public Node - { - public: - // For content node. - VXNode(const QString &p_name, - const NodeParameters &p_paras, - Notebook *p_notebook, - Node *p_parent); +namespace vnotex { +// Node of VXNotebookConfigMgr. +class VXNode : public Node { +public: + // For content node. + VXNode(const QString &p_name, const NodeParameters &p_paras, Notebook *p_notebook, + Node *p_parent); - // For container node. - VXNode(const QString &p_name, - Notebook *p_notebook, - Node *p_parent); + // For container node. + VXNode(const QString &p_name, Notebook *p_notebook, Node *p_parent); - QString fetchAbsolutePath() const Q_DECL_OVERRIDE; + QString fetchAbsolutePath() const Q_DECL_OVERRIDE; - QSharedPointer getContentFile() Q_DECL_OVERRIDE; + QSharedPointer getContentFile() Q_DECL_OVERRIDE; - QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE; + QStringList addAttachment(const QString &p_destFolderPath, + const QStringList &p_files) Q_DECL_OVERRIDE; - QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; - QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE; + QString newAttachmentFolder(const QString &p_destFolderPath, + const QString &p_name) Q_DECL_OVERRIDE; - QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; + QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE; - void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; - }; -} + void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // VXNODE_H diff --git a/src/core/notebook/vxnodefile.cpp b/src/core/notebook/vxnodefile.cpp index 9cf4161fed..fe995a3387 100644 --- a/src/core/notebook/vxnodefile.cpp +++ b/src/core/notebook/vxnodefile.cpp @@ -2,92 +2,66 @@ #include +#include "notebook.h" +#include "vxnode.h" #include #include #include #include -#include "vxnode.h" -#include "notebook.h" using namespace vnotex; -VXNodeFile::VXNodeFile(const QSharedPointer &p_node) - : m_node(p_node) -{ - Q_ASSERT(m_node && m_node->hasContent()); - setContentType(FileTypeHelper::getInst().getFileType(getContentPath()).m_type); +VXNodeFile::VXNodeFile(const QSharedPointer &p_node) : m_node(p_node) { + Q_ASSERT(m_node && m_node->hasContent()); + setContentType(FileTypeHelper::getInst().getFileType(getContentPath()).m_type); } -QString VXNodeFile::read() const -{ - return m_node->getBackend()->readTextFile(m_node->fetchPath()); -} +QString VXNodeFile::read() const { return m_node->getBackend()->readTextFile(m_node->fetchPath()); } -void VXNodeFile::write(const QString &p_content) -{ - m_node->getBackend()->writeFile(m_node->fetchPath(), p_content); +void VXNodeFile::write(const QString &p_content) { + m_node->getBackend()->writeFile(m_node->fetchPath(), p_content); - m_node->setModifiedTimeUtc(); - m_node->save(); + m_node->setModifiedTimeUtc(); + m_node->save(); } -QString VXNodeFile::getName() const -{ - return m_node->getName(); -} +QString VXNodeFile::getName() const { return m_node->getName(); } -QString VXNodeFile::getFilePath() const -{ - return m_node->fetchAbsolutePath(); -} +QString VXNodeFile::getFilePath() const { return m_node->fetchAbsolutePath(); } -QString VXNodeFile::getContentPath() const -{ - return m_node->fetchAbsolutePath(); -} +QString VXNodeFile::getContentPath() const { return m_node->fetchAbsolutePath(); } -QString VXNodeFile::getResourcePath() const -{ - return PathUtils::parentDirPath(getContentPath()); -} +QString VXNodeFile::getResourcePath() const { return PathUtils::parentDirPath(getContentPath()); } -IFileWithImage *VXNodeFile::getImageInterface() -{ - return this; -} +IFileWithImage *VXNodeFile::getImageInterface() { return this; } -Node *VXNodeFile::getNode() const -{ - return m_node.data(); -} +Node *VXNodeFile::getNode() const { return m_node.data(); } -QString VXNodeFile::fetchImageFolderPath() -{ - auto configMgr = dynamic_cast(m_node->getConfigMgr()); - return configMgr->fetchNodeImageFolderPath(m_node.data()); +QString VXNodeFile::fetchImageFolderPath() { + auto configMgr = dynamic_cast(m_node->getConfigMgr()); + return configMgr->fetchNodeImageFolderPath(m_node.data()); } -QString VXNodeFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) -{ - auto backend = m_node->getBackend(); - const auto imageFolderPath = fetchImageFolderPath(); - auto destFilePath = backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); - backend->copyFile(p_srcImagePath, destFilePath); - return destFilePath; +QString VXNodeFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) { + auto backend = m_node->getBackend(); + const auto imageFolderPath = fetchImageFolderPath(); + auto destFilePath = backend->renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); + backend->copyFile(p_srcImagePath, destFilePath); + return destFilePath; } -QString VXNodeFile::insertImage(const QImage &p_image, const QString &p_imageFileName) -{ - auto backend = m_node->getBackend(); - const auto imageFolderPath = fetchImageFolderPath(); - auto destFilePath = backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); - p_image.save(destFilePath); - backend->addFile(destFilePath); - return destFilePath; +QString VXNodeFile::insertImage(const QImage &p_image, const QString &p_imageFileName) { + auto backend = m_node->getBackend(); + const auto imageFolderPath = fetchImageFolderPath(); + auto destFilePath = backend->renameIfExistsCaseInsensitive( + PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); + p_image.save(destFilePath); + backend->addFile(destFilePath); + return destFilePath; } -void VXNodeFile::removeImage(const QString &p_imagePath) -{ - // Just move it to recycle bin but not added as a child node of recycle bin. - m_node->getNotebook()->moveFileToRecycleBin(p_imagePath); +void VXNodeFile::removeImage(const QString &p_imagePath) { + // Just move it to recycle bin but not added as a child node of recycle bin. + m_node->getNotebook()->moveFileToRecycleBin(p_imagePath); } diff --git a/src/core/notebook/vxnodefile.h b/src/core/notebook/vxnodefile.h index 77a87ae965..48875e5443 100644 --- a/src/core/notebook/vxnodefile.h +++ b/src/core/notebook/vxnodefile.h @@ -5,48 +5,47 @@ #include -namespace vnotex -{ - class VXNode; +namespace vnotex { +class VXNode; - // File from VXNode. - class VXNodeFile : public File, public IFileWithImage - { - public: - explicit VXNodeFile(const QSharedPointer &p_node); +// File from VXNode. +class VXNodeFile : public File, public IFileWithImage { +public: + explicit VXNodeFile(const QSharedPointer &p_node); - QString read() const Q_DECL_OVERRIDE; + QString read() const Q_DECL_OVERRIDE; - void write(const QString &p_content) Q_DECL_OVERRIDE; + void write(const QString &p_content) Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getFilePath() const Q_DECL_OVERRIDE; + QString getFilePath() const Q_DECL_OVERRIDE; - QString getContentPath() const Q_DECL_OVERRIDE; + QString getContentPath() const Q_DECL_OVERRIDE; - QString getResourcePath() const Q_DECL_OVERRIDE; + QString getResourcePath() const Q_DECL_OVERRIDE; - IFileWithImage *getImageInterface() Q_DECL_OVERRIDE; + IFileWithImage *getImageInterface() Q_DECL_OVERRIDE; - // Get the corresponding node if available. - Node *getNode() const Q_DECL_OVERRIDE; + // Get the corresponding node if available. + Node *getNode() const Q_DECL_OVERRIDE; - // IFileWithImage interfaces. - public: - QString fetchImageFolderPath() Q_DECL_OVERRIDE; + // IFileWithImage interfaces. +public: + QString fetchImageFolderPath() Q_DECL_OVERRIDE; - // Insert image from @p_srcImagePath. - // Return inserted image file path. - QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE; + // Insert image from @p_srcImagePath. + // Return inserted image file path. + QString insertImage(const QString &p_srcImagePath, + const QString &p_imageFileName) Q_DECL_OVERRIDE; - QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; + QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE; - void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; + void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE; - private: - QSharedPointer m_node; - }; -} +private: + QSharedPointer m_node; +}; +} // namespace vnotex #endif // VXNODEFILE_H diff --git a/src/core/notebookbackend/inotebookbackend.cpp b/src/core/notebookbackend/inotebookbackend.cpp index ae908cb044..5130be072f 100644 --- a/src/core/notebookbackend/inotebookbackend.cpp +++ b/src/core/notebookbackend/inotebookbackend.cpp @@ -7,23 +7,20 @@ using namespace vnotex; -void INotebookBackend::constrainPath(const QString &p_path) const -{ - if (!PathUtils::pathContains(m_rootPath, p_path)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("path (%1) does not locate in root folder (%2)") - .arg(p_path, m_rootPath)); - } +void INotebookBackend::constrainPath(const QString &p_path) const { + if (!PathUtils::pathContains(m_rootPath, p_path)) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("path (%1) does not locate in root folder (%2)").arg(p_path, m_rootPath)); + } } -QString INotebookBackend::getFullPath(const QString &p_path) const -{ - constrainPath(p_path); - return QDir(m_rootPath).filePath(p_path); +QString INotebookBackend::getFullPath(const QString &p_path) const { + constrainPath(p_path); + return QDir(m_rootPath).filePath(p_path); } -QString INotebookBackend::getRelativePath(const QString &p_path) const -{ - constrainPath(p_path); - return PathUtils::relativePath(m_rootPath, p_path); +QString INotebookBackend::getRelativePath(const QString &p_path) const { + constrainPath(p_path); + return PathUtils::relativePath(m_rootPath, p_path); } diff --git a/src/core/notebookbackend/inotebookbackend.h b/src/core/notebookbackend/inotebookbackend.h index a3ed296089..7060de533c 100644 --- a/src/core/notebookbackend/inotebookbackend.h +++ b/src/core/notebookbackend/inotebookbackend.h @@ -8,110 +8,100 @@ class QByteArray; class QJsonObject; -namespace vnotex -{ - // Abstract class for notebook backend, which is responsible for file access - // and synchronization. - class INotebookBackend : public QObject - { - Q_OBJECT - public: - INotebookBackend(const QString &p_rootPath, QObject *p_parent = nullptr) - : QObject(p_parent), - m_rootPath(PathUtils::absolutePath(p_rootPath)) - { - } +namespace vnotex { +// Abstract class for notebook backend, which is responsible for file access +// and synchronization. +class INotebookBackend : public QObject { + Q_OBJECT +public: + INotebookBackend(const QString &p_rootPath, QObject *p_parent = nullptr) + : QObject(p_parent), m_rootPath(PathUtils::absolutePath(p_rootPath)) {} - virtual ~INotebookBackend() - { - } + virtual ~INotebookBackend() {} - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; + virtual QString getDescription() const = 0; - const QString &getRootPath() const - { - return m_rootPath; - } + const QString &getRootPath() const { return m_rootPath; } - void setRootPath(const QString &p_rootPath) - { - m_rootPath = p_rootPath; - } + void setRootPath(const QString &p_rootPath) { m_rootPath = p_rootPath; } - // Whether @p_dirPath is an empty directory. - virtual bool isEmptyDir(const QString &p_dirPath) const = 0; + // Whether @p_dirPath is an empty directory. + virtual bool isEmptyDir(const QString &p_dirPath) const = 0; - // Create the directory path @p_dirPath. Create all parent directories if necessary. - virtual void makePath(const QString &p_dirPath) = 0; + // Create the directory path @p_dirPath. Create all parent directories if necessary. + virtual void makePath(const QString &p_dirPath) = 0; - // Write @p_data to @p_filePath. - virtual void writeFile(const QString &p_filePath, const QByteArray &p_data) = 0; + // Write @p_data to @p_filePath. + virtual void writeFile(const QString &p_filePath, const QByteArray &p_data) = 0; - // Write @p_text to @p_filePath. - virtual void writeFile(const QString &p_filePath, const QString &p_text) = 0; + // Write @p_text to @p_filePath. + virtual void writeFile(const QString &p_filePath, const QString &p_text) = 0; - // Write @p_jobj to @p_filePath. - virtual void writeFile(const QString &p_filePath, const QJsonObject &p_jobj) = 0; + // Write @p_jobj to @p_filePath. + virtual void writeFile(const QString &p_filePath, const QJsonObject &p_jobj) = 0; - // Read content from @p_filePath. - virtual QString readTextFile(const QString &p_filePath) = 0; + // Read content from @p_filePath. + virtual QString readTextFile(const QString &p_filePath) = 0; - // Read file @p_filePath. - virtual QByteArray readFile(const QString &p_filePath) = 0; + // Read file @p_filePath. + virtual QByteArray readFile(const QString &p_filePath) = 0; - QString getFullPath(const QString &p_path) const; + QString getFullPath(const QString &p_path) const; - QString getRelativePath(const QString &p_path) const; + QString getRelativePath(const QString &p_path) const; - virtual bool exists(const QString &p_path) const = 0; + virtual bool exists(const QString &p_path) const = 0; - virtual bool existsFile(const QString &p_path) const = 0; + virtual bool existsFile(const QString &p_path) const = 0; - virtual bool existsDir(const QString &p_path) const = 0; + virtual bool existsDir(const QString &p_path) const = 0; - virtual bool childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name) const = 0; + virtual bool childExistsCaseInsensitive(const QString &p_dirPath, + const QString &p_name) const = 0; - virtual bool isFile(const QString &p_path) const = 0; + virtual bool isFile(const QString &p_path) const = 0; - virtual void renameFile(const QString &p_filePath, const QString &p_name) = 0; + virtual void renameFile(const QString &p_filePath, const QString &p_name) = 0; - virtual void renameDir(const QString &p_dirPath, const QString &p_name) = 0; + virtual void renameDir(const QString &p_dirPath, const QString &p_name) = 0; - // Copy @p_filePath to @p_destPath. - // @p_filePath could be outside notebook. - virtual void copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move = false) = 0; + // Copy @p_filePath to @p_destPath. + // @p_filePath could be outside notebook. + virtual void copyFile(const QString &p_filePath, const QString &p_destPath, + bool p_move = false) = 0; - // Delete @p_filePath from disk. - virtual void removeFile(const QString &p_filePath) = 0; + // Delete @p_filePath from disk. + virtual void removeFile(const QString &p_filePath) = 0; - // Copy @p_dirPath to as @p_destPath. - virtual void copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move = false) = 0; + // Copy @p_dirPath to as @p_destPath. + virtual void copyDir(const QString &p_dirPath, const QString &p_destPath, + bool p_move = false) = 0; - // Delete @p_dirPath from disk if it is empty. - // Return false if it is not deleted due to non-empty. - virtual bool removeDirIfEmpty(const QString &p_dirPath) = 0; + // Delete @p_dirPath from disk if it is empty. + // Return false if it is not deleted due to non-empty. + virtual bool removeDirIfEmpty(const QString &p_dirPath) = 0; - virtual void removeDir(const QString &p_dirPath) = 0; + virtual void removeDir(const QString &p_dirPath) = 0; - virtual QString renameIfExistsCaseInsensitive(const QString &p_path) const = 0; + virtual QString renameIfExistsCaseInsensitive(const QString &p_path) const = 0; - // Add one file to backend. - virtual void addFile(const QString &p_path) = 0; + // Add one file to backend. + virtual void addFile(const QString &p_path) = 0; - virtual void removeEmptyDir(const QString &p_dirPath) = 0; + virtual void removeEmptyDir(const QString &p_dirPath) = 0; - protected: - // Constrain @p_path within root path of the notebook. - void constrainPath(const QString &p_path) const; +protected: + // Constrain @p_path within root path of the notebook. + void constrainPath(const QString &p_path) const; - private: - // Root path of the notebook. - QString m_rootPath; - }; -} // ns vnotex +private: + // Root path of the notebook. + QString m_rootPath; +}; +} // namespace vnotex #endif // INOTEBOOKBACKEND_H diff --git a/src/core/notebookbackend/inotebookbackendfactory.h b/src/core/notebookbackend/inotebookbackendfactory.h index 17cad3735d..ba42dbf3e6 100644 --- a/src/core/notebookbackend/inotebookbackendfactory.h +++ b/src/core/notebookbackend/inotebookbackendfactory.h @@ -3,29 +3,23 @@ #include -namespace vnotex -{ - class INotebookBackend; +namespace vnotex { +class INotebookBackend; - class INotebookBackendFactory - { - public: - INotebookBackendFactory() - { - } +class INotebookBackendFactory { +public: + INotebookBackendFactory() {} - virtual ~INotebookBackendFactory() - { - } + virtual ~INotebookBackendFactory() {} - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; + virtual QString getDescription() const = 0; - virtual QSharedPointer createNotebookBackend(const QString &p_rootPath) = 0; - }; -} // ns vnotex + virtual QSharedPointer createNotebookBackend(const QString &p_rootPath) = 0; +}; +} // namespace vnotex #endif // INOTEBOOKBACKENDFACTORY_H diff --git a/src/core/notebookbackend/localnotebookbackend.cpp b/src/core/notebookbackend/localnotebookbackend.cpp index fb72887cff..9ed396405a 100644 --- a/src/core/notebookbackend/localnotebookbackend.cpp +++ b/src/core/notebookbackend/localnotebookbackend.cpp @@ -2,218 +2,185 @@ #include #include -#include -#include #include +#include +#include #include -#include -#include -#include "exception.h" -#include "coreconfig.h" #include "configmgr.h" +#include "coreconfig.h" +#include "exception.h" +#include +#include using namespace vnotex; -LocalNotebookBackend::LocalNotebookBackend(const QString &p_name, - const QString &p_displayName, - const QString &p_description, - const QString &p_rootPath, +LocalNotebookBackend::LocalNotebookBackend(const QString &p_name, const QString &p_displayName, + const QString &p_description, const QString &p_rootPath, QObject *p_parent) - : INotebookBackend(p_rootPath, p_parent), - m_info(p_name, p_displayName, p_description) -{ -} + : INotebookBackend(p_rootPath, p_parent), m_info(p_name, p_displayName, p_description) {} -QString LocalNotebookBackend::getName() const -{ - return m_info.m_name; -} +QString LocalNotebookBackend::getName() const { return m_info.m_name; } -QString LocalNotebookBackend::getDisplayName() const -{ - return m_info.m_displayName; -} +QString LocalNotebookBackend::getDisplayName() const { return m_info.m_displayName; } -QString LocalNotebookBackend::getDescription() const -{ - return m_info.m_description; -} +QString LocalNotebookBackend::getDescription() const { return m_info.m_description; } -bool LocalNotebookBackend::isEmptyDir(const QString &p_dirPath) const -{ - return PathUtils::isEmptyDir(getFullPath(p_dirPath)); +bool LocalNotebookBackend::isEmptyDir(const QString &p_dirPath) const { + return PathUtils::isEmptyDir(getFullPath(p_dirPath)); } -void LocalNotebookBackend::makePath(const QString &p_dirPath) -{ - constrainPath(p_dirPath); - QDir dir(getRootPath()); - if (!dir.mkpath(p_dirPath)) { - Exception::throwOne(Exception::Type::FailToCreateDir, - QStringLiteral("fail to create directory: %1").arg(p_dirPath)); - } +void LocalNotebookBackend::makePath(const QString &p_dirPath) { + constrainPath(p_dirPath); + QDir dir(getRootPath()); + if (!dir.mkpath(p_dirPath)) { + Exception::throwOne(Exception::Type::FailToCreateDir, + QStringLiteral("fail to create directory: %1").arg(p_dirPath)); + } } -void LocalNotebookBackend::writeFile(const QString &p_filePath, const QByteArray &p_data) -{ - const auto filePath = getFullPath(p_filePath); - FileUtils::writeFile(filePath, p_data); +void LocalNotebookBackend::writeFile(const QString &p_filePath, const QByteArray &p_data) { + const auto filePath = getFullPath(p_filePath); + FileUtils::writeFile(filePath, p_data); } -void LocalNotebookBackend::writeFile(const QString &p_filePath, const QString &p_text) -{ - const auto filePath = getFullPath(p_filePath); - FileUtils::writeFile(filePath, p_text); +void LocalNotebookBackend::writeFile(const QString &p_filePath, const QString &p_text) { + const auto filePath = getFullPath(p_filePath); + FileUtils::writeFile(filePath, p_text); } -void LocalNotebookBackend::writeFile(const QString &p_filePath, const QJsonObject &p_jobj) -{ - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - auto data = QJsonDocument(p_jobj).toJson(); - vte::LineEnding before = vte::LineEnding::LF; - QString text; - switch (coreConfig.getLineEndingPolicy()) { - case LineEndingPolicy::Platform: +void LocalNotebookBackend::writeFile(const QString &p_filePath, const QJsonObject &p_jobj) { + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + auto data = QJsonDocument(p_jobj).toJson(); + vte::LineEnding before = vte::LineEnding::LF; + QString text; + switch (coreConfig.getLineEndingPolicy()) { + case LineEndingPolicy::Platform: #if defined(Q_OS_WIN) - text = QString::fromUtf8(data); - vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CRLF); + text = QString::fromUtf8(data); + vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CRLF); #endif - break; + break; - case LineEndingPolicy::File: - // Not supported. - Q_FALLTHROUGH(); - case LineEndingPolicy::LF: - break; + case LineEndingPolicy::File: + // Not supported. + Q_FALLTHROUGH(); + case LineEndingPolicy::LF: + break; - case LineEndingPolicy::CRLF: - text = QString::fromUtf8(data); - vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CRLF); - break; + case LineEndingPolicy::CRLF: + text = QString::fromUtf8(data); + vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CRLF); + break; - case LineEndingPolicy::CR: - text = QString::fromUtf8(data); - vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CR); - break; - } + case LineEndingPolicy::CR: + text = QString::fromUtf8(data); + vte::TextUtils::transformLineEnding(text, before, vte::LineEnding::CR); + break; + } - if (!text.isEmpty()) { - writeFile(p_filePath, text); - } else { - writeFile(p_filePath, data); - } + if (!text.isEmpty()) { + writeFile(p_filePath, text); + } else { + writeFile(p_filePath, data); + } } -QString LocalNotebookBackend::readTextFile(const QString &p_filePath) -{ - const auto filePath = getFullPath(p_filePath); - return FileUtils::readTextFile(filePath); +QString LocalNotebookBackend::readTextFile(const QString &p_filePath) { + const auto filePath = getFullPath(p_filePath); + return FileUtils::readTextFile(filePath); } -QByteArray LocalNotebookBackend::readFile(const QString &p_filePath) -{ - const auto filePath = getFullPath(p_filePath); - return FileUtils::readFile(filePath); +QByteArray LocalNotebookBackend::readFile(const QString &p_filePath) { + const auto filePath = getFullPath(p_filePath); + return FileUtils::readFile(filePath); } -bool LocalNotebookBackend::exists(const QString &p_path) const -{ - return QFileInfo::exists(getFullPath(p_path)); +bool LocalNotebookBackend::exists(const QString &p_path) const { + return QFileInfo::exists(getFullPath(p_path)); } -bool LocalNotebookBackend::existsFile(const QString &p_path) const -{ - QFileInfo fi(getFullPath(p_path)); - return fi.exists() && fi.isFile(); +bool LocalNotebookBackend::existsFile(const QString &p_path) const { + QFileInfo fi(getFullPath(p_path)); + return fi.exists() && fi.isFile(); } -bool LocalNotebookBackend::existsDir(const QString &p_path) const -{ - QFileInfo fi(getFullPath(p_path)); - return fi.exists() && fi.isDir(); +bool LocalNotebookBackend::existsDir(const QString &p_path) const { + QFileInfo fi(getFullPath(p_path)); + return fi.exists() && fi.isDir(); } -bool LocalNotebookBackend::childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name) const -{ - return FileUtils::childExistsCaseInsensitive(getFullPath(p_dirPath), p_name); +bool LocalNotebookBackend::childExistsCaseInsensitive(const QString &p_dirPath, + const QString &p_name) const { + return FileUtils::childExistsCaseInsensitive(getFullPath(p_dirPath), p_name); } -bool LocalNotebookBackend::isFile(const QString &p_path) const -{ - QFileInfo fi(getFullPath(p_path)); - return fi.isFile(); +bool LocalNotebookBackend::isFile(const QString &p_path) const { + QFileInfo fi(getFullPath(p_path)); + return fi.isFile(); } -void LocalNotebookBackend::renameFile(const QString &p_filePath, const QString &p_name) -{ - Q_ASSERT(isFile(p_filePath)); - const auto filePath = getFullPath(p_filePath); - FileUtils::renameFile(filePath, p_name); +void LocalNotebookBackend::renameFile(const QString &p_filePath, const QString &p_name) { + Q_ASSERT(isFile(p_filePath)); + const auto filePath = getFullPath(p_filePath); + FileUtils::renameFile(filePath, p_name); } -void LocalNotebookBackend::renameDir(const QString &p_dirPath, const QString &p_name) -{ - Q_ASSERT(!isFile(p_dirPath)); - const auto dirPath = getFullPath(p_dirPath); - FileUtils::renameFile(dirPath, p_name); +void LocalNotebookBackend::renameDir(const QString &p_dirPath, const QString &p_name) { + Q_ASSERT(!isFile(p_dirPath)); + const auto dirPath = getFullPath(p_dirPath); + FileUtils::renameFile(dirPath, p_name); } -void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move) -{ - auto filePath = p_filePath; - if (QFileInfo(filePath).isRelative()) { - filePath = getFullPath(filePath); - } +void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_destPath, + bool p_move) { + auto filePath = p_filePath; + if (QFileInfo(filePath).isRelative()) { + filePath = getFullPath(filePath); + } - Q_ASSERT(QFileInfo(filePath).isFile()); + Q_ASSERT(QFileInfo(filePath).isFile()); - FileUtils::copyFile(filePath, getFullPath(p_destPath), p_move); + FileUtils::copyFile(filePath, getFullPath(p_destPath), p_move); } -void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move) -{ - auto dirPath = p_dirPath; - if (QFileInfo(dirPath).isRelative()) { - dirPath = getFullPath(dirPath); - } +void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_destPath, + bool p_move) { + auto dirPath = p_dirPath; + if (QFileInfo(dirPath).isRelative()) { + dirPath = getFullPath(dirPath); + } - Q_ASSERT(QFileInfo(dirPath).isDir()); + Q_ASSERT(QFileInfo(dirPath).isDir()); - FileUtils::copyDir(dirPath, getFullPath(p_destPath), p_move); + FileUtils::copyDir(dirPath, getFullPath(p_destPath), p_move); } -void LocalNotebookBackend::removeFile(const QString &p_filePath) -{ - Q_ASSERT(isFile(p_filePath)); - FileUtils::removeFile(getFullPath(p_filePath)); +void LocalNotebookBackend::removeFile(const QString &p_filePath) { + Q_ASSERT(isFile(p_filePath)); + FileUtils::removeFile(getFullPath(p_filePath)); } -bool LocalNotebookBackend::removeDirIfEmpty(const QString &p_dirPath) -{ - Q_ASSERT(!isFile(p_dirPath)); - return FileUtils::removeDirIfEmpty(getFullPath(p_dirPath)); +bool LocalNotebookBackend::removeDirIfEmpty(const QString &p_dirPath) { + Q_ASSERT(!isFile(p_dirPath)); + return FileUtils::removeDirIfEmpty(getFullPath(p_dirPath)); } -void LocalNotebookBackend::removeDir(const QString &p_dirPath) -{ - Q_ASSERT(!isFile(p_dirPath)); - return FileUtils::removeDir(getFullPath(p_dirPath)); +void LocalNotebookBackend::removeDir(const QString &p_dirPath) { + Q_ASSERT(!isFile(p_dirPath)); + return FileUtils::removeDir(getFullPath(p_dirPath)); } -QString LocalNotebookBackend::renameIfExistsCaseInsensitive(const QString &p_path) const -{ - return FileUtils::renameIfExistsCaseInsensitive(getFullPath(p_path)); +QString LocalNotebookBackend::renameIfExistsCaseInsensitive(const QString &p_path) const { + return FileUtils::renameIfExistsCaseInsensitive(getFullPath(p_path)); } -void LocalNotebookBackend::addFile(const QString &p_path) -{ - Q_UNUSED(p_path); - // Do nothing for now. +void LocalNotebookBackend::addFile(const QString &p_path) { + Q_UNUSED(p_path); + // Do nothing for now. } -void LocalNotebookBackend::removeEmptyDir(const QString &p_dirPath) -{ - FileUtils::removeEmptyDir(getFullPath(p_dirPath)); +void LocalNotebookBackend::removeEmptyDir(const QString &p_dirPath) { + FileUtils::removeEmptyDir(getFullPath(p_dirPath)); } diff --git a/src/core/notebookbackend/localnotebookbackend.h b/src/core/notebookbackend/localnotebookbackend.h index 09dc15d4af..18c0da8d13 100644 --- a/src/core/notebookbackend/localnotebookbackend.h +++ b/src/core/notebookbackend/localnotebookbackend.h @@ -5,84 +5,83 @@ #include "../global.h" -namespace vnotex -{ - // Backend to access local file system. - class LocalNotebookBackend : public INotebookBackend - { - Q_OBJECT - public: - explicit LocalNotebookBackend(const QString &p_name, - const QString &p_displayName, - const QString &p_description, - const QString &p_rootPath, - QObject *p_parent = nullptr); +namespace vnotex { +// Backend to access local file system. +class LocalNotebookBackend : public INotebookBackend { + Q_OBJECT +public: + explicit LocalNotebookBackend(const QString &p_name, const QString &p_displayName, + const QString &p_description, const QString &p_rootPath, + QObject *p_parent = nullptr); - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getDisplayName() const Q_DECL_OVERRIDE; + QString getDisplayName() const Q_DECL_OVERRIDE; - QString getDescription() const Q_DECL_OVERRIDE; + QString getDescription() const Q_DECL_OVERRIDE; - // Whether @p_dirPath is an empty directory. - bool isEmptyDir(const QString &p_dirPath) const Q_DECL_OVERRIDE; + // Whether @p_dirPath is an empty directory. + bool isEmptyDir(const QString &p_dirPath) const Q_DECL_OVERRIDE; - // Create the directory path @p_dirPath. Create all parent directories if necessary. - void makePath(const QString &p_dirPath) Q_DECL_OVERRIDE; + // Create the directory path @p_dirPath. Create all parent directories if necessary. + void makePath(const QString &p_dirPath) Q_DECL_OVERRIDE; - // Write @p_data to @p_filePath. - void writeFile(const QString &p_filePath, const QByteArray &p_data) Q_DECL_OVERRIDE; + // Write @p_data to @p_filePath. + void writeFile(const QString &p_filePath, const QByteArray &p_data) Q_DECL_OVERRIDE; - // Write @p_text to @p_filePath. - void writeFile(const QString &p_filePath, const QString &p_text) Q_DECL_OVERRIDE; + // Write @p_text to @p_filePath. + void writeFile(const QString &p_filePath, const QString &p_text) Q_DECL_OVERRIDE; - // Write @p_jobj to @p_filePath. - void writeFile(const QString &p_filePath, const QJsonObject &p_jobj) Q_DECL_OVERRIDE; + // Write @p_jobj to @p_filePath. + void writeFile(const QString &p_filePath, const QJsonObject &p_jobj) Q_DECL_OVERRIDE; - // Read content from @p_filePath. - QString readTextFile(const QString &p_filePath) Q_DECL_OVERRIDE; + // Read content from @p_filePath. + QString readTextFile(const QString &p_filePath) Q_DECL_OVERRIDE; - // Read file @p_filePath. - QByteArray readFile(const QString &p_filePath) Q_DECL_OVERRIDE; + // Read file @p_filePath. + QByteArray readFile(const QString &p_filePath) Q_DECL_OVERRIDE; - bool exists(const QString &p_path) const Q_DECL_OVERRIDE; + bool exists(const QString &p_path) const Q_DECL_OVERRIDE; - bool existsFile(const QString &p_path) const Q_DECL_OVERRIDE; + bool existsFile(const QString &p_path) const Q_DECL_OVERRIDE; - bool existsDir(const QString &p_path) const Q_DECL_OVERRIDE; + bool existsDir(const QString &p_path) const Q_DECL_OVERRIDE; - bool childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name) const Q_DECL_OVERRIDE; + bool childExistsCaseInsensitive(const QString &p_dirPath, + const QString &p_name) const Q_DECL_OVERRIDE; - bool isFile(const QString &p_path) const Q_DECL_OVERRIDE; + bool isFile(const QString &p_path) const Q_DECL_OVERRIDE; - void renameFile(const QString &p_filePath, const QString &p_name) Q_DECL_OVERRIDE; + void renameFile(const QString &p_filePath, const QString &p_name) Q_DECL_OVERRIDE; - void renameDir(const QString &p_dirPath, const QString &p_name) Q_DECL_OVERRIDE; + void renameDir(const QString &p_dirPath, const QString &p_name) Q_DECL_OVERRIDE; - // Delete @p_filePath from disk. - void removeFile(const QString &p_filePath) Q_DECL_OVERRIDE; + // Delete @p_filePath from disk. + void removeFile(const QString &p_filePath) Q_DECL_OVERRIDE; - // Delete @p_dirPath from disk if it is empty. - bool removeDirIfEmpty(const QString &p_dirPath) Q_DECL_OVERRIDE; + // Delete @p_dirPath from disk if it is empty. + bool removeDirIfEmpty(const QString &p_dirPath) Q_DECL_OVERRIDE; - void removeDir(const QString &p_dirPath) Q_DECL_OVERRIDE; + void removeDir(const QString &p_dirPath) Q_DECL_OVERRIDE; - // Copy @p_filePath to @p_destPath. - // @p_filePath may beyond this notebook backend. - void copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move = false) Q_DECL_OVERRIDE; + // Copy @p_filePath to @p_destPath. + // @p_filePath may beyond this notebook backend. + void copyFile(const QString &p_filePath, const QString &p_destPath, + bool p_move = false) Q_DECL_OVERRIDE; - // Copy @p_dirPath to as @p_destPath. - void copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move = false) Q_DECL_OVERRIDE; + // Copy @p_dirPath to as @p_destPath. + void copyDir(const QString &p_dirPath, const QString &p_destPath, + bool p_move = false) Q_DECL_OVERRIDE; - QString renameIfExistsCaseInsensitive(const QString &p_path) const Q_DECL_OVERRIDE; + QString renameIfExistsCaseInsensitive(const QString &p_path) const Q_DECL_OVERRIDE; - void addFile(const QString &p_path) Q_DECL_OVERRIDE; + void addFile(const QString &p_path) Q_DECL_OVERRIDE; - void removeEmptyDir(const QString &p_dirPath) Q_DECL_OVERRIDE; + void removeEmptyDir(const QString &p_dirPath) Q_DECL_OVERRIDE; - private: - Info m_info; - }; -} // ns vnotex +private: + Info m_info; +}; +} // namespace vnotex #endif // LOCALNOTEBOOKBACKEND_H diff --git a/src/core/notebookbackend/localnotebookbackendfactory.cpp b/src/core/notebookbackend/localnotebookbackendfactory.cpp index ce2b3e74c7..85d2c41c81 100644 --- a/src/core/notebookbackend/localnotebookbackendfactory.cpp +++ b/src/core/notebookbackend/localnotebookbackendfactory.cpp @@ -6,29 +6,20 @@ using namespace vnotex; -LocalNotebookBackendFactory::LocalNotebookBackendFactory() -{ -} +LocalNotebookBackendFactory::LocalNotebookBackendFactory() {} -QString LocalNotebookBackendFactory::getName() const -{ - return QStringLiteral("local.vnotex"); -} +QString LocalNotebookBackendFactory::getName() const { return QStringLiteral("local.vnotex"); } -QString LocalNotebookBackendFactory::getDisplayName() const -{ - return QObject::tr("Local Notebook Backend"); +QString LocalNotebookBackendFactory::getDisplayName() const { + return QObject::tr("Local Notebook Backend"); } -QString LocalNotebookBackendFactory::getDescription() const -{ - return QObject::tr("Local file system"); +QString LocalNotebookBackendFactory::getDescription() const { + return QObject::tr("Local file system"); } -QSharedPointer LocalNotebookBackendFactory::createNotebookBackend(const QString &p_rootPath) -{ - return QSharedPointer::create(getName(), - getDisplayName(), - getDescription(), - p_rootPath); +QSharedPointer +LocalNotebookBackendFactory::createNotebookBackend(const QString &p_rootPath) { + return QSharedPointer::create(getName(), getDisplayName(), getDescription(), + p_rootPath); } diff --git a/src/core/notebookbackend/localnotebookbackendfactory.h b/src/core/notebookbackend/localnotebookbackendfactory.h index 0e24e0cc08..8d29e528cb 100644 --- a/src/core/notebookbackend/localnotebookbackendfactory.h +++ b/src/core/notebookbackend/localnotebookbackendfactory.h @@ -3,22 +3,19 @@ #include "inotebookbackendfactory.h" +namespace vnotex { +class LocalNotebookBackendFactory : public INotebookBackendFactory { +public: + LocalNotebookBackendFactory(); -namespace vnotex -{ - class LocalNotebookBackendFactory : public INotebookBackendFactory - { - public: - LocalNotebookBackendFactory(); + QString getName() const Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getDisplayName() const Q_DECL_OVERRIDE; - QString getDisplayName() const Q_DECL_OVERRIDE; + QString getDescription() const Q_DECL_OVERRIDE; - QString getDescription()const Q_DECL_OVERRIDE; - - QSharedPointer createNotebookBackend(const QString &p_rootPath) Q_DECL_OVERRIDE; - }; -} // ns vnotex + QSharedPointer createNotebookBackend(const QString &p_rootPath) Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // LOCALNOTEBOOKBACKENDFACTORY_H diff --git a/src/core/notebookconfigmgr/bundlenotebookconfigmgr.cpp b/src/core/notebookconfigmgr/bundlenotebookconfigmgr.cpp index 6aa78554ec..521e9e7f0e 100644 --- a/src/core/notebookconfigmgr/bundlenotebookconfigmgr.cpp +++ b/src/core/notebookconfigmgr/bundlenotebookconfigmgr.cpp @@ -2,10 +2,10 @@ #include -#include -#include -#include #include "notebookconfig.h" +#include +#include +#include #include using namespace vnotex; @@ -16,98 +16,72 @@ const QString BundleNotebookConfigMgr::c_configName = "vx_notebook.json"; BundleNotebookConfigMgr::BundleNotebookConfigMgr(const QSharedPointer &p_backend, QObject *p_parent) - : INotebookConfigMgr(p_backend, p_parent) -{ -} + : INotebookConfigMgr(p_backend, p_parent) {} -void BundleNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras) -{ - getBackend()->makePath(BundleNotebookConfigMgr::c_configFolderName); +void BundleNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras) { + getBackend()->makePath(BundleNotebookConfigMgr::c_configFolderName); - auto config = NotebookConfig::fromNotebookParameters(getCodeVersion(), p_paras); - writeNotebookConfig(*config); + auto config = NotebookConfig::fromNotebookParameters(getCodeVersion(), p_paras); + writeNotebookConfig(*config); } -QSharedPointer BundleNotebookConfigMgr::readNotebookConfig() const -{ - return readNotebookConfig(getBackend()); +QSharedPointer BundleNotebookConfigMgr::readNotebookConfig() const { + return readNotebookConfig(getBackend()); } -void BundleNotebookConfigMgr::writeNotebookConfig() -{ - auto config = NotebookConfig::fromNotebook(getCodeVersion(), getBundleNotebook()); - writeNotebookConfig(*config); +void BundleNotebookConfigMgr::writeNotebookConfig() { + auto config = NotebookConfig::fromNotebook(getCodeVersion(), getBundleNotebook()); + writeNotebookConfig(*config); } -void BundleNotebookConfigMgr::writeNotebookConfig(const NotebookConfig &p_config) -{ - getBackend()->writeFile(getConfigFilePath(), p_config.toJson()); +void BundleNotebookConfigMgr::writeNotebookConfig(const NotebookConfig &p_config) { + getBackend()->writeFile(getConfigFilePath(), p_config.toJson()); } -void BundleNotebookConfigMgr::removeNotebookConfig() -{ - getBackend()->removeDir(getConfigFolderName()); +void BundleNotebookConfigMgr::removeNotebookConfig() { + getBackend()->removeDir(getConfigFolderName()); } -QSharedPointer BundleNotebookConfigMgr::readNotebookConfig( - const QSharedPointer &p_backend) -{ - auto data = p_backend->readFile(getConfigFilePath()); +QSharedPointer +BundleNotebookConfigMgr::readNotebookConfig(const QSharedPointer &p_backend) { + auto data = p_backend->readFile(getConfigFilePath()); - auto config = QSharedPointer::create(); - config->fromJson(QJsonDocument::fromJson(data).object()); + auto config = QSharedPointer::create(); + config->fromJson(QJsonDocument::fromJson(data).object()); - return config; + return config; } -const QString &BundleNotebookConfigMgr::getConfigFolderName() -{ - return c_configFolderName; -} +const QString &BundleNotebookConfigMgr::getConfigFolderName() { return c_configFolderName; } -const QString &BundleNotebookConfigMgr::getConfigName() -{ - return c_configName; -} +const QString &BundleNotebookConfigMgr::getConfigName() { return c_configName; } -QString BundleNotebookConfigMgr::getConfigFilePath() -{ - return PathUtils::concatenateFilePath(c_configFolderName, c_configName); +QString BundleNotebookConfigMgr::getConfigFilePath() { + return PathUtils::concatenateFilePath(c_configFolderName, c_configName); } -QString BundleNotebookConfigMgr::getDatabasePath() -{ - return PathUtils::concatenateFilePath(c_configFolderName, "notebook.db"); +QString BundleNotebookConfigMgr::getDatabasePath() { + return PathUtils::concatenateFilePath(c_configFolderName, "notebook.db"); } -BundleNotebook *BundleNotebookConfigMgr::getBundleNotebook() const -{ - return static_cast(getNotebook()); +BundleNotebook *BundleNotebookConfigMgr::getBundleNotebook() const { + return static_cast(getNotebook()); } -bool BundleNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p_name) const -{ - Q_UNUSED(p_node); - Q_UNUSED(p_name); - return false; +bool BundleNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p_name) const { + Q_UNUSED(p_node); + Q_UNUSED(p_name); + return false; } -bool BundleNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const -{ - if (p_node->isRoot()) { - const auto name = p_name.toLower(); - return (name == c_configFolderName - || name == getNotebook()->getRecycleBinFolder().toLower()); - } - return false; +bool BundleNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const { + if (p_node->isRoot()) { + const auto name = p_name.toLower(); + return (name == c_configFolderName || name == getNotebook()->getRecycleBinFolder().toLower()); + } + return false; } -int BundleNotebookConfigMgr::getCodeVersion() const -{ - return 3; -} +int BundleNotebookConfigMgr::getCodeVersion() const { return 3; } -QString BundleNotebookConfigMgr::getConfigFolderPath() const -{ - return c_configFolderName; -} +QString BundleNotebookConfigMgr::getConfigFolderPath() const { return c_configFolderName; } diff --git a/src/core/notebookconfigmgr/bundlenotebookconfigmgr.h b/src/core/notebookconfigmgr/bundlenotebookconfigmgr.h index d65215bbda..7e800005df 100644 --- a/src/core/notebookconfigmgr/bundlenotebookconfigmgr.h +++ b/src/core/notebookconfigmgr/bundlenotebookconfigmgr.h @@ -3,56 +3,55 @@ #include "inotebookconfigmgr.h" -namespace vnotex -{ - class BundleNotebook; +namespace vnotex { +class BundleNotebook; - class BundleNotebookConfigMgr : public INotebookConfigMgr - { - Q_OBJECT - public: - BundleNotebookConfigMgr(const QSharedPointer &p_backend, - QObject *p_parent = nullptr); +class BundleNotebookConfigMgr : public INotebookConfigMgr { + Q_OBJECT +public: + BundleNotebookConfigMgr(const QSharedPointer &p_backend, + QObject *p_parent = nullptr); - // Create an empty skeleton for an empty notebook. - virtual void createEmptySkeleton(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; + // Create an empty skeleton for an empty notebook. + virtual void createEmptySkeleton(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; - QSharedPointer readNotebookConfig() const; - void writeNotebookConfig(); + QSharedPointer readNotebookConfig() const; + void writeNotebookConfig(); - void removeNotebookConfig(); + void removeNotebookConfig(); - bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; + bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; - bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; + bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; - int getCodeVersion() const Q_DECL_OVERRIDE; + int getCodeVersion() const Q_DECL_OVERRIDE; - QString getConfigFolderPath() const Q_DECL_OVERRIDE; + QString getConfigFolderPath() const Q_DECL_OVERRIDE; - static const QString &getConfigFolderName(); + static const QString &getConfigFolderName(); - static const QString &getConfigName(); + static const QString &getConfigName(); - static QString getConfigFilePath(); + static QString getConfigFilePath(); - static QString getDatabasePath(); + static QString getDatabasePath(); - static QSharedPointer readNotebookConfig(const QSharedPointer &p_backend); + static QSharedPointer + readNotebookConfig(const QSharedPointer &p_backend); - protected: - BundleNotebook *getBundleNotebook() const; +protected: + BundleNotebook *getBundleNotebook() const; - private: - void writeNotebookConfig(const NotebookConfig &p_config); +private: + void writeNotebookConfig(const NotebookConfig &p_config); - // Folder name to store the notebook's config. - // This folder locates in the root folder of the notebook. - static const QString c_configFolderName; + // Folder name to store the notebook's config. + // This folder locates in the root folder of the notebook. + static const QString c_configFolderName; - // Name of the notebook's config file. - static const QString c_configName; - }; -} // ns vnotex + // Name of the notebook's config file. + static const QString c_configName; +}; +} // namespace vnotex #endif // BUNDLENOTEBOOKCONFIGMGR_H diff --git a/src/core/notebookconfigmgr/inotebookconfigmgr.cpp b/src/core/notebookconfigmgr/inotebookconfigmgr.cpp index 48b2e7f9b6..bd651df741 100644 --- a/src/core/notebookconfigmgr/inotebookconfigmgr.cpp +++ b/src/core/notebookconfigmgr/inotebookconfigmgr.cpp @@ -6,26 +6,12 @@ using namespace vnotex; INotebookConfigMgr::INotebookConfigMgr(const QSharedPointer &p_backend, QObject *p_parent) - : QObject(p_parent), - m_backend(p_backend) -{ -} + : QObject(p_parent), m_backend(p_backend) {} -INotebookConfigMgr::~INotebookConfigMgr() -{ -} +INotebookConfigMgr::~INotebookConfigMgr() {} -const QSharedPointer &INotebookConfigMgr::getBackend() const -{ - return m_backend; -} +const QSharedPointer &INotebookConfigMgr::getBackend() const { return m_backend; } -Notebook *INotebookConfigMgr::getNotebook() const -{ - return m_notebook; -} +Notebook *INotebookConfigMgr::getNotebook() const { return m_notebook; } -void INotebookConfigMgr::setNotebook(Notebook *p_notebook) -{ - m_notebook = p_notebook; -} +void INotebookConfigMgr::setNotebook(Notebook *p_notebook) { m_notebook = p_notebook; } diff --git a/src/core/notebookconfigmgr/inotebookconfigmgr.h b/src/core/notebookconfigmgr/inotebookconfigmgr.h index 9588bd40b3..4fbc8e3ee8 100644 --- a/src/core/notebookconfigmgr/inotebookconfigmgr.h +++ b/src/core/notebookconfigmgr/inotebookconfigmgr.h @@ -7,96 +7,89 @@ #include "notebook/node.h" #include "notebook/nodevisual.h" -namespace vnotex -{ - class NotebookConfig; - class INotebookBackend; - class NotebookParameters; - class Notebook; - class NodeParameters; +namespace vnotex { +class NotebookConfig; +class INotebookBackend; +class NotebookParameters; +class Notebook; +class NodeParameters; - // Abstract class for notebook config manager, which is responsible for config - // files access and note nodes access. - class INotebookConfigMgr : public QObject - { - Q_OBJECT - public: - INotebookConfigMgr(const QSharedPointer &p_backend, - QObject *p_parent = nullptr); +// Abstract class for notebook config manager, which is responsible for config +// files access and note nodes access. +class INotebookConfigMgr : public QObject { + Q_OBJECT +public: + INotebookConfigMgr(const QSharedPointer &p_backend, + QObject *p_parent = nullptr); - virtual ~INotebookConfigMgr(); + virtual ~INotebookConfigMgr(); - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; + virtual QString getDescription() const = 0; - // Create an empty skeleton for an empty notebook. - virtual void createEmptySkeleton(const NotebookParameters &p_paras) = 0; + // Create an empty skeleton for an empty notebook. + virtual void createEmptySkeleton(const NotebookParameters &p_paras) = 0; - const QSharedPointer &getBackend() const; + const QSharedPointer &getBackend() const; - virtual QSharedPointer loadRootNode() = 0; + virtual QSharedPointer loadRootNode() = 0; - virtual void loadNode(Node *p_node) = 0; - virtual void saveNode(const Node *p_node) = 0; + virtual void loadNode(Node *p_node) = 0; + virtual void saveNode(const Node *p_node) = 0; - virtual void renameNode(Node *p_node, const QString &p_name) = 0; + virtual void renameNode(Node *p_node, const QString &p_name) = 0; - virtual QSharedPointer newNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const QString &p_content) = 0; + virtual QSharedPointer newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const QString &p_content) = 0; - virtual QSharedPointer addAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras) = 0; + virtual QSharedPointer addAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const NodeParameters &p_paras) = 0; - virtual QSharedPointer copyAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_path) = 0; + virtual QSharedPointer copyAsNode(Node *p_parent, Node::Flags p_flags, + const QString &p_path) = 0; - Notebook *getNotebook() const; - void setNotebook(Notebook *p_notebook); + Notebook *getNotebook() const; + void setNotebook(Notebook *p_notebook); - virtual QSharedPointer loadNodeByPath(const QSharedPointer &p_root, - const QString &p_relativePath) = 0; + virtual QSharedPointer loadNodeByPath(const QSharedPointer &p_root, + const QString &p_relativePath) = 0; - virtual QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move) = 0; + virtual QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move) = 0; - virtual void removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly) = 0; + virtual void removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly) = 0; - virtual void removeNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder) = 0; + virtual void removeNodeToFolder(const QSharedPointer &p_node, + const QString &p_destFolder) = 0; - // Whether @p_name is a built-in file under @p_node. - virtual bool isBuiltInFile(const Node *p_node, const QString &p_name) const = 0; + // Whether @p_name is a built-in file under @p_node. + virtual bool isBuiltInFile(const Node *p_node, const QString &p_name) const = 0; - virtual bool isBuiltInFolder(const Node *p_node, const QString &p_name) const = 0; + virtual bool isBuiltInFolder(const Node *p_node, const QString &p_name) const = 0; - virtual QString fetchNodeAttachmentFolderPath(Node *p_node) = 0; + virtual QString fetchNodeAttachmentFolderPath(Node *p_node) = 0; - virtual QVector> fetchExternalChildren(Node *p_node) const = 0; + virtual QVector> fetchExternalChildren(Node *p_node) const = 0; - virtual bool checkNodeExists(Node *p_node) = 0; + virtual bool checkNodeExists(Node *p_node) = 0; - virtual QStringList scanAndImportExternalFiles(Node *p_node) = 0; + virtual QStringList scanAndImportExternalFiles(Node *p_node) = 0; - virtual void updateNodeVisual(Node *p_node, const NodeVisual &p_visual) = 0; + virtual void updateNodeVisual(Node *p_node, const NodeVisual &p_visual) = 0; - // Version of the config processing code. - virtual int getCodeVersion() const = 0; + // Version of the config processing code. + virtual int getCodeVersion() const = 0; - virtual QString getConfigFolderPath() const = 0; + virtual QString getConfigFolderPath() const = 0; - private: - QSharedPointer m_backend; +private: + QSharedPointer m_backend; - Notebook *m_notebook = nullptr; - }; -} // ns vnotex + Notebook *m_notebook = nullptr; +}; +} // namespace vnotex #endif // INOTEBOOKCONFIGMGR_H diff --git a/src/core/notebookconfigmgr/inotebookconfigmgrfactory.h b/src/core/notebookconfigmgr/inotebookconfigmgrfactory.h index e237c6f8ec..013c23b6c8 100644 --- a/src/core/notebookconfigmgr/inotebookconfigmgrfactory.h +++ b/src/core/notebookconfigmgr/inotebookconfigmgrfactory.h @@ -3,31 +3,25 @@ #include -namespace vnotex -{ - class INotebookConfigMgr; - class INotebookBackend; +namespace vnotex { +class INotebookConfigMgr; +class INotebookBackend; - class INotebookConfigMgrFactory - { - public: - INotebookConfigMgrFactory() - { - } +class INotebookConfigMgrFactory { +public: + INotebookConfigMgrFactory() {} - virtual ~INotebookConfigMgrFactory() - { - } + virtual ~INotebookConfigMgrFactory() {} - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; + virtual QString getDescription() const = 0; - virtual QSharedPointer createNotebookConfigMgr( - const QSharedPointer &p_backend) = 0; - }; -} // ns vnotex + virtual QSharedPointer + createNotebookConfigMgr(const QSharedPointer &p_backend) = 0; +}; +} // namespace vnotex #endif // INOTEBOOKCONFIGMGRFACTORY_H diff --git a/src/core/notebookconfigmgr/notebookconfig.cpp b/src/core/notebookconfigmgr/notebookconfig.cpp index 7299e0a8ee..9a6941d4bc 100644 --- a/src/core/notebookconfigmgr/notebookconfig.cpp +++ b/src/core/notebookconfigmgr/notebookconfig.cpp @@ -1,115 +1,110 @@ #include "notebookconfig.h" -#include -#include -#include -#include #include "exception.h" #include "global.h" +#include +#include +#include +#include using namespace vnotex; -QSharedPointer NotebookConfig::fromNotebookParameters(int p_version, - const NotebookParameters &p_paras) -{ - auto config = QSharedPointer::create(); - - config->m_version = p_version; - config->m_name = p_paras.m_name; - config->m_description = p_paras.m_description; - config->m_imageFolder = p_paras.m_imageFolder; - config->m_attachmentFolder = p_paras.m_attachmentFolder; - config->m_createdTimeUtc = p_paras.m_createdTimeUtc; - config->m_versionController = p_paras.m_versionController->getName(); - config->m_notebookConfigMgr = p_paras.m_notebookConfigMgr->getName(); - - return config; +QSharedPointer +NotebookConfig::fromNotebookParameters(int p_version, const NotebookParameters &p_paras) { + auto config = QSharedPointer::create(); + + config->m_version = p_version; + config->m_name = p_paras.m_name; + config->m_description = p_paras.m_description; + config->m_imageFolder = p_paras.m_imageFolder; + config->m_attachmentFolder = p_paras.m_attachmentFolder; + config->m_createdTimeUtc = p_paras.m_createdTimeUtc; + config->m_versionController = p_paras.m_versionController->getName(); + config->m_notebookConfigMgr = p_paras.m_notebookConfigMgr->getName(); + + return config; } -QJsonObject NotebookConfig::toJson() const -{ - QJsonObject jobj; +QJsonObject NotebookConfig::toJson() const { + QJsonObject jobj; - jobj[QStringLiteral("version")] = m_version; - jobj[QStringLiteral("name")] = m_name; - jobj[QStringLiteral("description")] = m_description; - jobj[QStringLiteral("image_folder")] = m_imageFolder; - jobj[QStringLiteral("attachment_folder")] = m_attachmentFolder; - jobj[QStringLiteral("created_time")] = Utils::dateTimeStringUniform(m_createdTimeUtc); - jobj[QStringLiteral("version_controller")] = m_versionController; - jobj[QStringLiteral("config_mgr")] = m_notebookConfigMgr; + jobj[QStringLiteral("version")] = m_version; + jobj[QStringLiteral("name")] = m_name; + jobj[QStringLiteral("description")] = m_description; + jobj[QStringLiteral("image_folder")] = m_imageFolder; + jobj[QStringLiteral("attachment_folder")] = m_attachmentFolder; + jobj[QStringLiteral("created_time")] = Utils::dateTimeStringUniform(m_createdTimeUtc); + jobj[QStringLiteral("version_controller")] = m_versionController; + jobj[QStringLiteral("config_mgr")] = m_notebookConfigMgr; - jobj[QStringLiteral("history")] = saveHistory(); + jobj[QStringLiteral("history")] = saveHistory(); - jobj[QStringLiteral("tag_graph")] = m_tagGraph; + jobj[QStringLiteral("tag_graph")] = m_tagGraph; - jobj[QStringLiteral("extra_configs")] = m_extraConfigs; + jobj[QStringLiteral("extra_configs")] = m_extraConfigs; - return jobj; + return jobj; } -void NotebookConfig::fromJson(const QJsonObject &p_jobj) -{ - if (!p_jobj.contains(QStringLiteral("version")) - || !p_jobj.contains(QStringLiteral("name")) - || !p_jobj.contains(QStringLiteral("created_time")) - || !p_jobj.contains(QStringLiteral("version_controller")) - || !p_jobj.contains(QStringLiteral("config_mgr"))) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to read notebook configuration from JSON (%1)").arg(QJsonObjectToString(p_jobj))); - return; - } - - m_version = p_jobj[QStringLiteral("version")].toInt(); - m_name = p_jobj[QStringLiteral("name")].toString(); - m_description = p_jobj[QStringLiteral("description")].toString(); - m_imageFolder = p_jobj[QStringLiteral("image_folder")].toString(); - m_attachmentFolder = p_jobj[QStringLiteral("attachment_folder")].toString(); - m_createdTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[QStringLiteral("created_time")].toString()); - m_versionController = p_jobj[QStringLiteral("version_controller")].toString(); - m_notebookConfigMgr = p_jobj[QStringLiteral("config_mgr")].toString(); - - loadHistory(p_jobj); - - m_tagGraph = p_jobj[QStringLiteral("tag_graph")].toString(); - - m_extraConfigs = p_jobj[QStringLiteral("extra_configs")].toObject(); +void NotebookConfig::fromJson(const QJsonObject &p_jobj) { + if (!p_jobj.contains(QStringLiteral("version")) || !p_jobj.contains(QStringLiteral("name")) || + !p_jobj.contains(QStringLiteral("created_time")) || + !p_jobj.contains(QStringLiteral("version_controller")) || + !p_jobj.contains(QStringLiteral("config_mgr"))) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("failed to read notebook configuration from JSON (%1)") + .arg(QJsonObjectToString(p_jobj))); + return; + } + + m_version = p_jobj[QStringLiteral("version")].toInt(); + m_name = p_jobj[QStringLiteral("name")].toString(); + m_description = p_jobj[QStringLiteral("description")].toString(); + m_imageFolder = p_jobj[QStringLiteral("image_folder")].toString(); + m_attachmentFolder = p_jobj[QStringLiteral("attachment_folder")].toString(); + m_createdTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[QStringLiteral("created_time")].toString()); + m_versionController = p_jobj[QStringLiteral("version_controller")].toString(); + m_notebookConfigMgr = p_jobj[QStringLiteral("config_mgr")].toString(); + + loadHistory(p_jobj); + + m_tagGraph = p_jobj[QStringLiteral("tag_graph")].toString(); + + m_extraConfigs = p_jobj[QStringLiteral("extra_configs")].toObject(); } QSharedPointer NotebookConfig::fromNotebook(int p_version, - const BundleNotebook *p_notebook) -{ - auto config = QSharedPointer::create(); - - config->m_version = p_version; - config->m_name = p_notebook->getName(); - config->m_description = p_notebook->getDescription(); - config->m_imageFolder = p_notebook->getImageFolder(); - config->m_attachmentFolder = p_notebook->getAttachmentFolder(); - config->m_createdTimeUtc = p_notebook->getCreatedTimeUtc(); - config->m_versionController = p_notebook->getVersionController()->getName(); - config->m_notebookConfigMgr = p_notebook->getConfigMgr()->getName(); - config->m_history = p_notebook->getHistory(); - config->m_tagGraph = p_notebook->getTagGraph(); - config->m_extraConfigs = p_notebook->getExtraConfigs(); - - return config; + const BundleNotebook *p_notebook) { + auto config = QSharedPointer::create(); + + config->m_version = p_version; + config->m_name = p_notebook->getName(); + config->m_description = p_notebook->getDescription(); + config->m_imageFolder = p_notebook->getImageFolder(); + config->m_attachmentFolder = p_notebook->getAttachmentFolder(); + config->m_createdTimeUtc = p_notebook->getCreatedTimeUtc(); + config->m_versionController = p_notebook->getVersionController()->getName(); + config->m_notebookConfigMgr = p_notebook->getConfigMgr()->getName(); + config->m_history = p_notebook->getHistory(); + config->m_tagGraph = p_notebook->getTagGraph(); + config->m_extraConfigs = p_notebook->getExtraConfigs(); + + return config; } -QJsonArray NotebookConfig::saveHistory() const -{ - QJsonArray arr; - for (const auto &item : m_history) { - arr.append(item.toJson()); - } - return arr; +QJsonArray NotebookConfig::saveHistory() const { + QJsonArray arr; + for (const auto &item : m_history) { + arr.append(item.toJson()); + } + return arr; } -void NotebookConfig::loadHistory(const QJsonObject &p_jobj) -{ - auto arr = p_jobj[QStringLiteral("history")].toArray(); - m_history.resize(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - m_history[i].fromJson(arr[i].toObject()); - } +void NotebookConfig::loadHistory(const QJsonObject &p_jobj) { + auto arr = p_jobj[QStringLiteral("history")].toArray(); + m_history.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_history[i].fromJson(arr[i].toObject()); + } } diff --git a/src/core/notebookconfigmgr/notebookconfig.h b/src/core/notebookconfigmgr/notebookconfig.h index f068a0f6a7..e66f1e8db7 100644 --- a/src/core/notebookconfigmgr/notebookconfig.h +++ b/src/core/notebookconfigmgr/notebookconfig.h @@ -1,66 +1,64 @@ #ifndef NOTEBOOKCONFIG_H #define NOTEBOOKCONFIG_H +#include +#include #include #include -#include #include -#include #include "bundlenotebookconfigmgr.h" #include #include -namespace vnotex -{ - class NotebookParameters; +namespace vnotex { +class NotebookParameters; - // Notebook config of BundleNotebook. - class NotebookConfig - { - public: - virtual ~NotebookConfig() {} +// Notebook config of BundleNotebook. +class NotebookConfig { +public: + virtual ~NotebookConfig() {} - static QSharedPointer fromNotebookParameters(int p_version, - const NotebookParameters &p_paras); + static QSharedPointer fromNotebookParameters(int p_version, + const NotebookParameters &p_paras); - static QSharedPointer fromNotebook(int p_version, - const BundleNotebook *p_notebook); + static QSharedPointer fromNotebook(int p_version, + const BundleNotebook *p_notebook); - virtual QJsonObject toJson() const; + virtual QJsonObject toJson() const; - virtual void fromJson(const QJsonObject &p_jobj); + virtual void fromJson(const QJsonObject &p_jobj); - int m_version = 0; + int m_version = 0; - QString m_name; + QString m_name; - QString m_description; + QString m_description; - QString m_imageFolder; + QString m_imageFolder; - QString m_attachmentFolder; + QString m_attachmentFolder; - QDateTime m_createdTimeUtc; + QDateTime m_createdTimeUtc; - QString m_versionController; + QString m_versionController; - QString m_notebookConfigMgr; + QString m_notebookConfigMgr; - QVector m_history; + QVector m_history; - // Graph of tags of this notebook like "parent>chlid;parent2>chlid2". - QString m_tagGraph; + // Graph of tags of this notebook like "parent>chlid;parent2>chlid2". + QString m_tagGraph; - // Hold all the extra configs for other components or 3rd party plugins. - // Use a unique name as the key and the value is a QJsonObject. - QJsonObject m_extraConfigs; + // Hold all the extra configs for other components or 3rd party plugins. + // Use a unique name as the key and the value is a QJsonObject. + QJsonObject m_extraConfigs; - private: - QJsonArray saveHistory() const; +private: + QJsonArray saveHistory() const; - void loadHistory(const QJsonObject &p_jobj); - }; -} // ns vnotex + void loadHistory(const QJsonObject &p_jobj); +}; +} // namespace vnotex #endif // NOTEBOOKCONFIG_H diff --git a/src/core/notebookconfigmgr/vxnodeconfig.cpp b/src/core/notebookconfigmgr/vxnodeconfig.cpp index 1782d62b55..b7a8822fa3 100644 --- a/src/core/notebookconfigmgr/vxnodeconfig.cpp +++ b/src/core/notebookconfigmgr/vxnodeconfig.cpp @@ -1,7 +1,7 @@ #include "vxnodeconfig.h" -#include #include +#include using namespace vnotex; @@ -33,237 +33,222 @@ const QString NodeConfig::c_borderColor = "border_color"; const QString NodeConfig::c_nameColor = "name_color"; -static ID stringToNodeId(const QString &p_idStr) -{ - auto ret = stringToID(p_idStr); - if (!ret.first) { - return Node::InvalidId; - } - return ret.second; +static ID stringToNodeId(const QString &p_idStr) { + auto ret = stringToID(p_idStr); + if (!ret.first) { + return Node::InvalidId; + } + return ret.second; } -QJsonObject NodeFileConfig::toJson() const -{ - QJsonObject jobj; - - jobj[NodeConfig::c_name] = m_name; - jobj[NodeConfig::c_id] = IDToString(m_id); - jobj[NodeConfig::c_signature] = IDToString(m_signature); - jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc); - jobj[NodeConfig::c_modifiedTimeUtc] = Utils::dateTimeStringUniform(m_modifiedTimeUtc); - jobj[NodeConfig::c_attachmentFolder] = m_attachmentFolder; - jobj[NodeConfig::c_tags] = QJsonArray::fromStringList(m_tags); - - // Visual settings - if (!m_backgroundColor.isEmpty()) { - jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; - } - if (!m_borderColor.isEmpty()) { - jobj[NodeConfig::c_borderColor] = m_borderColor; - } - if (!m_nameColor.isEmpty()) { - jobj[NodeConfig::c_nameColor] = m_nameColor; - } - - return jobj; +QJsonObject NodeFileConfig::toJson() const { + QJsonObject jobj; + + jobj[NodeConfig::c_name] = m_name; + jobj[NodeConfig::c_id] = IDToString(m_id); + jobj[NodeConfig::c_signature] = IDToString(m_signature); + jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc); + jobj[NodeConfig::c_modifiedTimeUtc] = Utils::dateTimeStringUniform(m_modifiedTimeUtc); + jobj[NodeConfig::c_attachmentFolder] = m_attachmentFolder; + jobj[NodeConfig::c_tags] = QJsonArray::fromStringList(m_tags); + + // Visual settings + if (!m_backgroundColor.isEmpty()) { + jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; + } + if (!m_borderColor.isEmpty()) { + jobj[NodeConfig::c_borderColor] = m_borderColor; + } + if (!m_nameColor.isEmpty()) { + jobj[NodeConfig::c_nameColor] = m_nameColor; + } + + return jobj; } -void NodeFileConfig::fromJson(const QJsonObject &p_jobj) -{ - m_name = p_jobj[NodeConfig::c_name].toString(); +void NodeFileConfig::fromJson(const QJsonObject &p_jobj) { + m_name = p_jobj[NodeConfig::c_name].toString(); - m_id = stringToNodeId(p_jobj[NodeConfig::c_id].toString()); - m_signature = stringToNodeId(p_jobj[NodeConfig::c_signature].toString()); + m_id = stringToNodeId(p_jobj[NodeConfig::c_id].toString()); + m_signature = stringToNodeId(p_jobj[NodeConfig::c_signature].toString()); - m_createdTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString()); - m_modifiedTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_modifiedTimeUtc].toString()); + m_createdTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString()); + m_modifiedTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_modifiedTimeUtc].toString()); - m_attachmentFolder = p_jobj[NodeConfig::c_attachmentFolder].toString(); + m_attachmentFolder = p_jobj[NodeConfig::c_attachmentFolder].toString(); - { - auto arr = p_jobj[NodeConfig::c_tags].toArray(); - for (int i = 0; i < arr.size(); ++i) { - m_tags << arr[i].toString(); - } + { + auto arr = p_jobj[NodeConfig::c_tags].toArray(); + for (int i = 0; i < arr.size(); ++i) { + m_tags << arr[i].toString(); } + } - // Visual settings (check if fields exist for backward compatibility) - if (p_jobj.contains(NodeConfig::c_backgroundColor)) { - m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_borderColor)) { - m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_nameColor)) { - m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); - } + // Visual settings (check if fields exist for backward compatibility) + if (p_jobj.contains(NodeConfig::c_backgroundColor)) { + m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_borderColor)) { + m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_nameColor)) { + m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); + } } -NodeParameters NodeFileConfig::toNodeParameters() const -{ - NodeParameters paras; - paras.m_id = m_id; - paras.m_signature = m_signature; - paras.m_createdTimeUtc = m_createdTimeUtc; - paras.m_modifiedTimeUtc = m_modifiedTimeUtc; - paras.m_tags = m_tags; - paras.m_attachmentFolder = m_attachmentFolder; - - // Visual settings - paras.m_visual.setBackgroundColor(m_backgroundColor); - paras.m_visual.setBorderColor(m_borderColor); - paras.m_visual.setNameColor(m_nameColor); - - return paras; +NodeParameters NodeFileConfig::toNodeParameters() const { + NodeParameters paras; + paras.m_id = m_id; + paras.m_signature = m_signature; + paras.m_createdTimeUtc = m_createdTimeUtc; + paras.m_modifiedTimeUtc = m_modifiedTimeUtc; + paras.m_tags = m_tags; + paras.m_attachmentFolder = m_attachmentFolder; + + // Visual settings + paras.m_visual.setBackgroundColor(m_backgroundColor); + paras.m_visual.setBorderColor(m_borderColor); + paras.m_visual.setNameColor(m_nameColor); + + return paras; } -QJsonObject NodeFolderConfig::toJson() const -{ - QJsonObject jobj; +QJsonObject NodeFolderConfig::toJson() const { + QJsonObject jobj; - jobj[NodeConfig::c_name] = m_name; + jobj[NodeConfig::c_name] = m_name; - // Visual settings - if (!m_backgroundColor.isEmpty()) { - jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; - } - if (!m_borderColor.isEmpty()) { - jobj[NodeConfig::c_borderColor] = m_borderColor; - } - if (!m_nameColor.isEmpty()) { - jobj[NodeConfig::c_nameColor] = m_nameColor; - } + // Visual settings + if (!m_backgroundColor.isEmpty()) { + jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; + } + if (!m_borderColor.isEmpty()) { + jobj[NodeConfig::c_borderColor] = m_borderColor; + } + if (!m_nameColor.isEmpty()) { + jobj[NodeConfig::c_nameColor] = m_nameColor; + } - return jobj; + return jobj; } -void NodeFolderConfig::fromJson(const QJsonObject &p_jobj) -{ - m_name = p_jobj[NodeConfig::c_name].toString(); - - // Visual settings (check if fields exist for backward compatibility) - if (p_jobj.contains(NodeConfig::c_backgroundColor)) { - m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_borderColor)) { - m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_nameColor)) { - m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); - } +void NodeFolderConfig::fromJson(const QJsonObject &p_jobj) { + m_name = p_jobj[NodeConfig::c_name].toString(); + + // Visual settings (check if fields exist for backward compatibility) + if (p_jobj.contains(NodeConfig::c_backgroundColor)) { + m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_borderColor)) { + m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_nameColor)) { + m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); + } } -NodeParameters NodeFolderConfig::toNodeParameters() const -{ - NodeParameters paras; - - // Visual settings - paras.m_visual.setBackgroundColor(m_backgroundColor); - paras.m_visual.setBorderColor(m_borderColor); - paras.m_visual.setNameColor(m_nameColor); - - return paras; -} +NodeParameters NodeFolderConfig::toNodeParameters() const { + NodeParameters paras; -NodeConfig::NodeConfig() -{ -} + // Visual settings + paras.m_visual.setBackgroundColor(m_backgroundColor); + paras.m_visual.setBorderColor(m_borderColor); + paras.m_visual.setNameColor(m_nameColor); -NodeConfig::NodeConfig(int p_version, - ID p_id, - ID p_signature, - const QDateTime &p_createdTimeUtc, - const QDateTime &p_modifiedTimeUtc) - : m_version(p_version), - m_id(p_id), - m_signature(p_signature), - m_createdTimeUtc(p_createdTimeUtc), - m_modifiedTimeUtc(p_modifiedTimeUtc) -{ + return paras; } -QJsonObject NodeConfig::toJson() const -{ - QJsonObject jobj; - - jobj[NodeConfig::c_version] = m_version; - jobj[NodeConfig::c_id] = IDToString(m_id); - jobj[NodeConfig::c_signature] = IDToString(m_signature); - jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc); - jobj[NodeConfig::c_modifiedTimeUtc] = Utils::dateTimeStringUniform(m_modifiedTimeUtc); +NodeConfig::NodeConfig() {} - QJsonArray files; - for (const auto &file : m_files) { - files.append(file.toJson()); - } - jobj[NodeConfig::c_files] = files; - - QJsonArray folders; - for (const auto& folder : m_folders) { - folders.append(folder.toJson()); - } - jobj[NodeConfig::c_folders] = folders; - - // Visual settings for the container node itself - if (!m_backgroundColor.isEmpty()) { - jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; - } - if (!m_borderColor.isEmpty()) { - jobj[NodeConfig::c_borderColor] = m_borderColor; - } - if (!m_nameColor.isEmpty()) { - jobj[NodeConfig::c_nameColor] = m_nameColor; - } - - return jobj; +NodeConfig::NodeConfig(int p_version, ID p_id, ID p_signature, const QDateTime &p_createdTimeUtc, + const QDateTime &p_modifiedTimeUtc) + : m_version(p_version), m_id(p_id), m_signature(p_signature), + m_createdTimeUtc(p_createdTimeUtc), m_modifiedTimeUtc(p_modifiedTimeUtc) {} + +QJsonObject NodeConfig::toJson() const { + QJsonObject jobj; + + jobj[NodeConfig::c_version] = m_version; + jobj[NodeConfig::c_id] = IDToString(m_id); + jobj[NodeConfig::c_signature] = IDToString(m_signature); + jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc); + jobj[NodeConfig::c_modifiedTimeUtc] = Utils::dateTimeStringUniform(m_modifiedTimeUtc); + + QJsonArray files; + for (const auto &file : m_files) { + files.append(file.toJson()); + } + jobj[NodeConfig::c_files] = files; + + QJsonArray folders; + for (const auto &folder : m_folders) { + folders.append(folder.toJson()); + } + jobj[NodeConfig::c_folders] = folders; + + // Visual settings for the container node itself + if (!m_backgroundColor.isEmpty()) { + jobj[NodeConfig::c_backgroundColor] = m_backgroundColor; + } + if (!m_borderColor.isEmpty()) { + jobj[NodeConfig::c_borderColor] = m_borderColor; + } + if (!m_nameColor.isEmpty()) { + jobj[NodeConfig::c_nameColor] = m_nameColor; + } + + return jobj; } -void NodeConfig::fromJson(const QJsonObject &p_jobj) -{ - m_version = p_jobj[NodeConfig::c_version].toInt(); - - m_id = stringToNodeId(p_jobj[NodeConfig::c_id].toString()); - m_signature = stringToNodeId(p_jobj[NodeConfig::c_signature].toString()); - - m_createdTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString()); - m_modifiedTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_modifiedTimeUtc].toString()); - - auto filesJson = p_jobj[NodeConfig::c_files].toArray(); - m_files.resize(filesJson.size()); - for (int i = 0; i < filesJson.size(); ++i) { - m_files[i].fromJson(filesJson[i].toObject()); - } +void NodeConfig::fromJson(const QJsonObject &p_jobj) { + m_version = p_jobj[NodeConfig::c_version].toInt(); + + m_id = stringToNodeId(p_jobj[NodeConfig::c_id].toString()); + m_signature = stringToNodeId(p_jobj[NodeConfig::c_signature].toString()); + + m_createdTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString()); + m_modifiedTimeUtc = + Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_modifiedTimeUtc].toString()); + + auto filesJson = p_jobj[NodeConfig::c_files].toArray(); + m_files.resize(filesJson.size()); + for (int i = 0; i < filesJson.size(); ++i) { + m_files[i].fromJson(filesJson[i].toObject()); + } + + auto foldersJson = p_jobj[NodeConfig::c_folders].toArray(); + m_folders.resize(foldersJson.size()); + for (int i = 0; i < foldersJson.size(); ++i) { + m_folders[i].fromJson(foldersJson[i].toObject()); + } + + // Visual settings for the container node itself (check if fields exist for backward + // compatibility) + if (p_jobj.contains(NodeConfig::c_backgroundColor)) { + m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_borderColor)) { + m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); + } + if (p_jobj.contains(NodeConfig::c_nameColor)) { + m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); + } +} - auto foldersJson = p_jobj[NodeConfig::c_folders].toArray(); - m_folders.resize(foldersJson.size()); - for (int i = 0; i < foldersJson.size(); ++i) { - m_folders[i].fromJson(foldersJson[i].toObject()); - } +NodeParameters NodeConfig::toNodeParameters() const { + NodeParameters paras; + paras.m_id = m_id; + paras.m_signature = m_signature; + paras.m_createdTimeUtc = m_createdTimeUtc; + paras.m_modifiedTimeUtc = m_modifiedTimeUtc; - // Visual settings for the container node itself (check if fields exist for backward compatibility) - if (p_jobj.contains(NodeConfig::c_backgroundColor)) { - m_backgroundColor = p_jobj[NodeConfig::c_backgroundColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_borderColor)) { - m_borderColor = p_jobj[NodeConfig::c_borderColor].toString(); - } - if (p_jobj.contains(NodeConfig::c_nameColor)) { - m_nameColor = p_jobj[NodeConfig::c_nameColor].toString(); - } -} + // Visual settings for the container node itself + paras.m_visual.setBackgroundColor(m_backgroundColor); + paras.m_visual.setBorderColor(m_borderColor); + paras.m_visual.setNameColor(m_nameColor); -NodeParameters NodeConfig::toNodeParameters() const -{ - NodeParameters paras; - paras.m_id = m_id; - paras.m_signature = m_signature; - paras.m_createdTimeUtc = m_createdTimeUtc; - paras.m_modifiedTimeUtc = m_modifiedTimeUtc; - - // Visual settings for the container node itself - paras.m_visual.setBackgroundColor(m_backgroundColor); - paras.m_visual.setBorderColor(m_borderColor); - paras.m_visual.setNameColor(m_nameColor); - - return paras; + return paras; } diff --git a/src/core/notebookconfigmgr/vxnodeconfig.h b/src/core/notebookconfigmgr/vxnodeconfig.h index 8df5504b6d..eb866aec58 100644 --- a/src/core/notebookconfigmgr/vxnodeconfig.h +++ b/src/core/notebookconfigmgr/vxnodeconfig.h @@ -1,130 +1,120 @@ #ifndef VXNODECONFIG_H #define VXNODECONFIG_H -#include #include +#include #include #include #include #include -namespace vnotex -{ - // Config structures for VXNotebookConfigMgr. - namespace vx_node_config - { - // Config of a file child. - struct NodeFileConfig - { - QJsonObject toJson() const; - - void fromJson(const QJsonObject &p_jobj); - - NodeParameters toNodeParameters() const; +namespace vnotex { +// Config structures for VXNotebookConfigMgr. +namespace vx_node_config { +// Config of a file child. +struct NodeFileConfig { + QJsonObject toJson() const; - QString m_name; + void fromJson(const QJsonObject &p_jobj); - ID m_id = Node::InvalidId; + NodeParameters toNodeParameters() const; - ID m_signature = Node::InvalidId; + QString m_name; - QDateTime m_createdTimeUtc; + ID m_id = Node::InvalidId; - QDateTime m_modifiedTimeUtc; + ID m_signature = Node::InvalidId; - QString m_attachmentFolder; + QDateTime m_createdTimeUtc; - QStringList m_tags; + QDateTime m_modifiedTimeUtc; - // Visual settings - QString m_backgroundColor; - QString m_borderColor; - QString m_nameColor; - }; + QString m_attachmentFolder; + QStringList m_tags; - // Config of a folder child. - struct NodeFolderConfig - { - QJsonObject toJson() const; + // Visual settings + QString m_backgroundColor; + QString m_borderColor; + QString m_nameColor; +}; - void fromJson(const QJsonObject &p_jobj); +// Config of a folder child. +struct NodeFolderConfig { + QJsonObject toJson() const; - NodeParameters toNodeParameters() const; + void fromJson(const QJsonObject &p_jobj); - QString m_name; + NodeParameters toNodeParameters() const; - // Visual settings - QString m_backgroundColor; - QString m_borderColor; - QString m_nameColor; - }; + QString m_name; + // Visual settings + QString m_backgroundColor; + QString m_borderColor; + QString m_nameColor; +}; - // Config of a folder node. - struct NodeConfig - { - NodeConfig(); +// Config of a folder node. +struct NodeConfig { + NodeConfig(); - NodeConfig(int p_version, - ID p_id, - ID p_signature, - const QDateTime &p_createdTimeUtc, - const QDateTime &p_modifiedTimeUtc); + NodeConfig(int p_version, ID p_id, ID p_signature, const QDateTime &p_createdTimeUtc, + const QDateTime &p_modifiedTimeUtc); - QJsonObject toJson() const; + QJsonObject toJson() const; - void fromJson(const QJsonObject &p_jobj); + void fromJson(const QJsonObject &p_jobj); - NodeParameters toNodeParameters() const; + NodeParameters toNodeParameters() const; - int m_version = 0; + int m_version = 0; - ID m_id = Node::InvalidId; + ID m_id = Node::InvalidId; - ID m_signature = Node::InvalidId; + ID m_signature = Node::InvalidId; - QDateTime m_createdTimeUtc; + QDateTime m_createdTimeUtc; - QDateTime m_modifiedTimeUtc; + QDateTime m_modifiedTimeUtc; - QVector m_files; + QVector m_files; - QVector m_folders; + QVector m_folders; - // Visual settings for the container node itself - QString m_backgroundColor; - QString m_borderColor; - QString m_nameColor; + // Visual settings for the container node itself + QString m_backgroundColor; + QString m_borderColor; + QString m_nameColor; - static const QString c_version; + static const QString c_version; - static const QString c_id; + static const QString c_id; - static const QString c_signature; + static const QString c_signature; - static const QString c_createdTimeUtc; + static const QString c_createdTimeUtc; - static const QString c_files; + static const QString c_files; - static const QString c_folders; + static const QString c_folders; - static const QString c_name; + static const QString c_name; - static const QString c_modifiedTimeUtc; + static const QString c_modifiedTimeUtc; - static const QString c_attachmentFolder; + static const QString c_attachmentFolder; - static const QString c_tags; + static const QString c_tags; - static const QString c_backgroundColor; + static const QString c_backgroundColor; - static const QString c_borderColor; + static const QString c_borderColor; - static const QString c_nameColor; - }; - } -} + static const QString c_nameColor; +}; +} // namespace vx_node_config +} // namespace vnotex #endif // VXNODECONFIG_H diff --git a/src/core/notebookconfigmgr/vxnotebookconfigmgr.cpp b/src/core/notebookconfigmgr/vxnotebookconfigmgr.cpp index 3b053ca59d..b1767b9650 100644 --- a/src/core/notebookconfigmgr/vxnotebookconfigmgr.cpp +++ b/src/core/notebookconfigmgr/vxnotebookconfigmgr.cpp @@ -1,25 +1,25 @@ #include "vxnotebookconfigmgr.h" -#include +#include #include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include #include -#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include #include @@ -36,1112 +36,1033 @@ bool VXNotebookConfigMgr::s_initialized = false; QVector VXNotebookConfigMgr::s_externalNodeExcludePatterns; -VXNotebookConfigMgr::VXNotebookConfigMgr(const QSharedPointer &p_backend, QObject *p_parent) - : BundleNotebookConfigMgr(p_backend, p_parent) -{ - if (!s_initialized) { - s_initialized = true; - - const auto &patterns = ConfigMgr::getInst().getCoreConfig().getExternalNodeExcludePatterns(); - s_externalNodeExcludePatterns.reserve(patterns.size()); - for (const auto &pat : patterns) { - if (!pat.isEmpty()) { - s_externalNodeExcludePatterns.push_back(QRegExp(pat, Qt::CaseInsensitive, QRegExp::Wildcard)); - } - } +VXNotebookConfigMgr::VXNotebookConfigMgr(const QSharedPointer &p_backend, + QObject *p_parent) + : BundleNotebookConfigMgr(p_backend, p_parent) { + if (!s_initialized) { + s_initialized = true; + + const auto &patterns = ConfigMgr::getInst().getCoreConfig().getExternalNodeExcludePatterns(); + s_externalNodeExcludePatterns.reserve(patterns.size()); + for (const auto &pat : patterns) { + if (!pat.isEmpty()) { + s_externalNodeExcludePatterns.push_back( + QRegExp(pat, Qt::CaseInsensitive, QRegExp::Wildcard)); + } } + } } -QString VXNotebookConfigMgr::getName() const -{ - return VXNotebookConfigMgrFactory::c_name; -} +QString VXNotebookConfigMgr::getName() const { return VXNotebookConfigMgrFactory::c_name; } -QString VXNotebookConfigMgr::getDisplayName() const -{ - return VXNotebookConfigMgrFactory::c_displayName; +QString VXNotebookConfigMgr::getDisplayName() const { + return VXNotebookConfigMgrFactory::c_displayName; } -QString VXNotebookConfigMgr::getDescription() const -{ - return VXNotebookConfigMgrFactory::c_description; +QString VXNotebookConfigMgr::getDescription() const { + return VXNotebookConfigMgrFactory::c_description; } -void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras) -{ - BundleNotebookConfigMgr::createEmptySkeleton(p_paras); +void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras) { + BundleNotebookConfigMgr::createEmptySkeleton(p_paras); - createEmptyRootNode(); + createEmptyRootNode(); } -void VXNotebookConfigMgr::createEmptyRootNode() -{ - auto currentTime = QDateTime::currentDateTimeUtc(); - NodeConfig node(getCodeVersion(), - Node::InvalidId, - Node::InvalidId, - currentTime, - currentTime); - writeNodeConfig(c_nodeConfigName, node); +void VXNotebookConfigMgr::createEmptyRootNode() { + auto currentTime = QDateTime::currentDateTimeUtc(); + NodeConfig node(getCodeVersion(), Node::InvalidId, Node::InvalidId, currentTime, currentTime); + writeNodeConfig(c_nodeConfigName, node); } -QSharedPointer VXNotebookConfigMgr::loadRootNode() -{ - auto nodeConfig = readNodeConfig(""); - QSharedPointer root = nodeConfigToNode(*nodeConfig, "", nullptr); - root->setUse(Node::Use::Root); - root->setExists(true); - Q_ASSERT(root->isLoaded()); +QSharedPointer VXNotebookConfigMgr::loadRootNode() { + auto nodeConfig = readNodeConfig(""); + QSharedPointer root = nodeConfigToNode(*nodeConfig, "", nullptr); + root->setUse(Node::Use::Root); + root->setExists(true); + Q_ASSERT(root->isLoaded()); - if (static_cast(getNotebook())->getConfigVersion() < 3) { - removeLegacyRecycleBinNode(root); - } + if (static_cast(getNotebook())->getConfigVersion() < 3) { + removeLegacyRecycleBinNode(root); + } - return root; + return root; } -void VXNotebookConfigMgr::removeLegacyRecycleBinNode(const QSharedPointer &p_root) -{ - // Do not support recycle bin node as it complicates everything. - auto node = p_root->findChild(QStringLiteral("vx_recycle_bin"), - FileUtils::isPlatformNameCaseSensitive()); - if (node) { - removeNode(node, true, true); - } +void VXNotebookConfigMgr::removeLegacyRecycleBinNode(const QSharedPointer &p_root) { + // Do not support recycle bin node as it complicates everything. + auto node = + p_root->findChild(QStringLiteral("vx_recycle_bin"), FileUtils::isPlatformNameCaseSensitive()); + if (node) { + removeNode(node, true, true); + } } -void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const -{ - if (p_node->isReadOnly()) { - return; - } +void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const { + if (p_node->isReadOnly()) { + return; + } - p_node->setReadOnly(true); - for (const auto &child : p_node->getChildrenRef()) { - markNodeReadOnly(child.data()); - } + p_node->setReadOnly(true); + for (const auto &child : p_node->getChildrenRef()) { + markNodeReadOnly(child.data()); + } } -QSharedPointer VXNotebookConfigMgr::readNodeConfig(const QString &p_path) const -{ - auto backend = getBackend(); - if (!backend->exists(p_path)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("node path (%1) does not exist").arg(p_path)); - } - - if (backend->isFile(p_path)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("node (%1) is a file node without config").arg(p_path)); - } else { - auto configPath = PathUtils::concatenateFilePath(p_path, c_nodeConfigName); - auto data = backend->readFile(configPath); - auto nodeConfig = QSharedPointer::create(); - nodeConfig->fromJson(QJsonDocument::fromJson(data).object()); - return nodeConfig; - } - - return nullptr; +QSharedPointer VXNotebookConfigMgr::readNodeConfig(const QString &p_path) const { + auto backend = getBackend(); + if (!backend->exists(p_path)) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("node path (%1) does not exist").arg(p_path)); + } + + if (backend->isFile(p_path)) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("node (%1) is a file node without config").arg(p_path)); + } else { + auto configPath = PathUtils::concatenateFilePath(p_path, c_nodeConfigName); + auto data = backend->readFile(configPath); + auto nodeConfig = QSharedPointer::create(); + nodeConfig->fromJson(QJsonDocument::fromJson(data).object()); + return nodeConfig; + } + + return nullptr; } -QString VXNotebookConfigMgr::getNodeConfigFilePath(const Node *p_node) const -{ - Q_ASSERT(p_node->isContainer()); - return PathUtils::concatenateFilePath(p_node->fetchPath(), c_nodeConfigName); +QString VXNotebookConfigMgr::getNodeConfigFilePath(const Node *p_node) const { + Q_ASSERT(p_node->isContainer()); + return PathUtils::concatenateFilePath(p_node->fetchPath(), c_nodeConfigName); } -void VXNotebookConfigMgr::writeNodeConfig(const QString &p_path, const NodeConfig &p_config) const -{ - getBackend()->writeFile(p_path, p_config.toJson()); +void VXNotebookConfigMgr::writeNodeConfig(const QString &p_path, const NodeConfig &p_config) const { + getBackend()->writeFile(p_path, p_config.toJson()); } -void VXNotebookConfigMgr::writeNodeConfig(const Node *p_node) -{ - auto config = nodeToNodeConfig(p_node); - writeNodeConfig(getNodeConfigFilePath(p_node), *config); +void VXNotebookConfigMgr::writeNodeConfig(const Node *p_node) { + auto config = nodeToNodeConfig(p_node); + writeNodeConfig(getNodeConfigFilePath(p_node), *config); } QSharedPointer VXNotebookConfigMgr::nodeConfigToNode(const NodeConfig &p_config, - const QString &p_name, - Node *p_parent) -{ - auto node = QSharedPointer::create(p_name, getNotebook(), p_parent); - loadFolderNode(node.data(), p_config); - return node; + const QString &p_name, Node *p_parent) { + auto node = QSharedPointer::create(p_name, getNotebook(), p_parent); + loadFolderNode(node.data(), p_config); + return node; } -void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_config) -{ - QSet seenNames; - - QVector> children; - children.reserve(p_config.m_files.size() + p_config.m_folders.size()); - const auto basePath = p_node->fetchPath(); - - bool needUpdateConfig = false; - - for (const auto &folder : p_config.m_folders) { - if (folder.m_name.isEmpty()) { - // Skip empty name node. - qWarning() << "skipped loading node with empty name under" << p_node->fetchPath(); - continue; - } - - if (seenNames.contains(folder.m_name)) { - qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath(); - continue; - } - seenNames.insert(folder.m_name); - - auto folderNode = QSharedPointer::create(folder.m_name, - getNotebook(), - p_node); - inheritNodeFlags(p_node, folderNode.data()); - folderNode->setExists(getBackend()->existsDir(PathUtils::concatenateFilePath(basePath, folder.m_name))); - - // 设置视觉效果信息 - NodeParameters visualParams = folder.toNodeParameters(); - folderNode->setVisual(visualParams.m_visual); - children.push_back(folderNode); - } +void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_config) { + QSet seenNames; + + QVector> children; + children.reserve(p_config.m_files.size() + p_config.m_folders.size()); + const auto basePath = p_node->fetchPath(); - for (const auto &file : p_config.m_files) { - if (file.m_name.isEmpty()) { - // Skip empty name node. - qWarning() << "skipped loading node with empty name under" << p_node->fetchPath(); - continue; - } - - if (seenNames.contains(file.m_name)) { - qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath(); - continue; - } - seenNames.insert(file.m_name); - - // For compability only. - needUpdateConfig = needUpdateConfig || file.m_signature == Node::InvalidId; - - auto fileNode = QSharedPointer::create(file.m_name, - file.toNodeParameters(), - getNotebook(), - p_node); - inheritNodeFlags(p_node, fileNode.data()); - fileNode->setExists(getBackend()->existsFile(PathUtils::concatenateFilePath(basePath, file.m_name))); - children.push_back(fileNode); + bool needUpdateConfig = false; + + for (const auto &folder : p_config.m_folders) { + if (folder.m_name.isEmpty()) { + // Skip empty name node. + qWarning() << "skipped loading node with empty name under" << p_node->fetchPath(); + continue; } - p_node->loadCompleteInfo(p_config.toNodeParameters(), children); + if (seenNames.contains(folder.m_name)) { + qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath(); + continue; + } + seenNames.insert(folder.m_name); + + auto folderNode = QSharedPointer::create(folder.m_name, getNotebook(), p_node); + inheritNodeFlags(p_node, folderNode.data()); + folderNode->setExists( + getBackend()->existsDir(PathUtils::concatenateFilePath(basePath, folder.m_name))); + + // 设置视觉效果信息 + NodeParameters visualParams = folder.toNodeParameters(); + folderNode->setVisual(visualParams.m_visual); + children.push_back(folderNode); + } + + for (const auto &file : p_config.m_files) { + if (file.m_name.isEmpty()) { + // Skip empty name node. + qWarning() << "skipped loading node with empty name under" << p_node->fetchPath(); + continue; + } - needUpdateConfig = needUpdateConfig || p_config.m_signature == Node::InvalidId; - if (needUpdateConfig) { - writeNodeConfig(p_node); + if (seenNames.contains(file.m_name)) { + qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath(); + continue; } + seenNames.insert(file.m_name); + + // For compability only. + needUpdateConfig = needUpdateConfig || file.m_signature == Node::InvalidId; + + auto fileNode = + QSharedPointer::create(file.m_name, file.toNodeParameters(), getNotebook(), p_node); + inheritNodeFlags(p_node, fileNode.data()); + fileNode->setExists( + getBackend()->existsFile(PathUtils::concatenateFilePath(basePath, file.m_name))); + children.push_back(fileNode); + } + + p_node->loadCompleteInfo(p_config.toNodeParameters(), children); + + needUpdateConfig = needUpdateConfig || p_config.m_signature == Node::InvalidId; + if (needUpdateConfig) { + writeNodeConfig(p_node); + } } -QSharedPointer VXNotebookConfigMgr::newNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const QString &p_content) -{ - Q_ASSERT(p_parent && p_parent->isContainer() && !p_name.isEmpty()); +QSharedPointer VXNotebookConfigMgr::newNode(Node *p_parent, Node::Flags p_flags, + const QString &p_name, const QString &p_content) { + Q_ASSERT(p_parent && p_parent->isContainer() && !p_name.isEmpty()); - QSharedPointer node; + QSharedPointer node; - if (p_flags & Node::Flag::Content) { - Q_ASSERT(!(p_flags & Node::Flag::Container)); - node = newFileNode(p_parent, p_name, p_content, true, NodeParameters()); - } else { - node = newFolderNode(p_parent, p_name, true, NodeParameters()); - } + if (p_flags & Node::Flag::Content) { + Q_ASSERT(!(p_flags & Node::Flag::Container)); + node = newFileNode(p_parent, p_name, p_content, true, NodeParameters()); + } else { + node = newFolderNode(p_parent, p_name, true, NodeParameters()); + } - return node; + return node; } -QSharedPointer VXNotebookConfigMgr::addAsNode(Node *p_parent, - Node::Flags p_flags, +QSharedPointer VXNotebookConfigMgr::addAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, - const NodeParameters &p_paras) -{ - Q_ASSERT(p_parent && p_parent->isContainer()); - - // TODO: reuse the config if available. - QSharedPointer node; - if (p_flags & Node::Flag::Content) { - Q_ASSERT(!(p_flags & Node::Flag::Container)); - node = newFileNode(p_parent, p_name, "", false, p_paras); - } else { - node = newFolderNode(p_parent, p_name, false, p_paras); - } - - return node; + const NodeParameters &p_paras) { + Q_ASSERT(p_parent && p_parent->isContainer()); + + // TODO: reuse the config if available. + QSharedPointer node; + if (p_flags & Node::Flag::Content) { + Q_ASSERT(!(p_flags & Node::Flag::Container)); + node = newFileNode(p_parent, p_name, "", false, p_paras); + } else { + node = newFolderNode(p_parent, p_name, false, p_paras); + } + + return node; } -QSharedPointer VXNotebookConfigMgr::copyAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_path) -{ - Q_ASSERT(p_parent && p_parent->isContainer()); +QSharedPointer VXNotebookConfigMgr::copyAsNode(Node *p_parent, Node::Flags p_flags, + const QString &p_path) { + Q_ASSERT(p_parent && p_parent->isContainer()); - QSharedPointer node; - if (p_flags & Node::Flag::Content) { - Q_ASSERT(!(p_flags & Node::Flag::Container)); - node = copyFileAsChildOf(p_path, p_parent); - } else { - node = copyFolderAsChildOf(p_path, p_parent); - } + QSharedPointer node; + if (p_flags & Node::Flag::Content) { + Q_ASSERT(!(p_flags & Node::Flag::Container)); + node = copyFileAsChildOf(p_path, p_parent); + } else { + node = copyFolderAsChildOf(p_path, p_parent); + } - return node; + return node; } -QSharedPointer VXNotebookConfigMgr::newFileNode(Node *p_parent, - const QString &p_name, - const QString &p_content, - bool p_create, - const NodeParameters &p_paras) -{ - ensureNodeInDatabase(p_parent); - - auto notebook = getNotebook(); - - // Create file node. - auto node = QSharedPointer::create(p_name, - p_paras, - notebook, - p_parent); - - // Write empty file. - if (p_create) { - if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) { - // File already exists. Exception. - Exception::throwOne(Exception::Type::FileExistsOnCreate, - QStringLiteral("file (%1) already exists when creating new node").arg(node->fetchPath())); - return nullptr; - } - - getBackend()->writeFile(node->fetchPath(), p_content); - node->setExists(true); - } else { - node->setExists(getBackend()->existsFile(node->fetchPath())); +QSharedPointer VXNotebookConfigMgr::newFileNode(Node *p_parent, const QString &p_name, + const QString &p_content, bool p_create, + const NodeParameters &p_paras) { + ensureNodeInDatabase(p_parent); + + auto notebook = getNotebook(); + + // Create file node. + auto node = QSharedPointer::create(p_name, p_paras, notebook, p_parent); + + // Write empty file. + if (p_create) { + if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) { + // File already exists. Exception. + Exception::throwOne( + Exception::Type::FileExistsOnCreate, + QStringLiteral("file (%1) already exists when creating new node").arg(node->fetchPath())); + return nullptr; } - addChildNode(p_parent, node); - writeNodeConfig(p_parent); + getBackend()->writeFile(node->fetchPath(), p_content); + node->setExists(true); + } else { + node->setExists(getBackend()->existsFile(node->fetchPath())); + } + + addChildNode(p_parent, node); + writeNodeConfig(p_parent); - addNodeToDatabase(node.data()); + addNodeToDatabase(node.data()); - return node; + return node; } -QSharedPointer VXNotebookConfigMgr::newFolderNode(Node *p_parent, - const QString &p_name, +QSharedPointer VXNotebookConfigMgr::newFolderNode(Node *p_parent, const QString &p_name, bool p_create, - const NodeParameters &p_paras) -{ - ensureNodeInDatabase(p_parent); - - auto notebook = getNotebook(); - - // Create folder node. - auto node = QSharedPointer::create(p_name, notebook, p_parent); - node->loadCompleteInfo(p_paras, QVector>()); - - // Make folder. - if (p_create) { - if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) { - // Dir already exists. Exception. - Exception::throwOne(Exception::Type::DirExistsOnCreate, - QStringLiteral("dir (%1) already exists when creating new node").arg(node->fetchPath())); - return nullptr; - } - - getBackend()->makePath(node->fetchPath()); - node->setExists(true); - } else { - node->setExists(getBackend()->existsDir(node->fetchPath())); + const NodeParameters &p_paras) { + ensureNodeInDatabase(p_parent); + + auto notebook = getNotebook(); + + // Create folder node. + auto node = QSharedPointer::create(p_name, notebook, p_parent); + node->loadCompleteInfo(p_paras, QVector>()); + + // Make folder. + if (p_create) { + if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) { + // Dir already exists. Exception. + Exception::throwOne( + Exception::Type::DirExistsOnCreate, + QStringLiteral("dir (%1) already exists when creating new node").arg(node->fetchPath())); + return nullptr; } - writeNodeConfig(node.data()); + getBackend()->makePath(node->fetchPath()); + node->setExists(true); + } else { + node->setExists(getBackend()->existsDir(node->fetchPath())); + } + + writeNodeConfig(node.data()); - addChildNode(p_parent, node); - writeNodeConfig(p_parent); + addChildNode(p_parent, node); + writeNodeConfig(p_parent); - addNodeToDatabase(node.data()); + addNodeToDatabase(node.data()); - return node; + return node; } -QSharedPointer VXNotebookConfigMgr::nodeToNodeConfig(const Node *p_node) const -{ - Q_ASSERT(p_node->isContainer()); - Q_ASSERT(p_node->isLoaded()); - - auto config = QSharedPointer::create(getCodeVersion(), - p_node->getId(), - p_node->getSignature(), - p_node->getCreatedTimeUtc(), - p_node->getModifiedTimeUtc()); - - // Set visual settings for the container node itself - config->m_backgroundColor = p_node->getBackgroundColor(); - config->m_borderColor = p_node->getBorderColor(); - config->m_nameColor = p_node->getNameColor(); - - for (const auto &child : p_node->getChildrenRef()) { - if (child->hasContent()) { - NodeFileConfig fileConfig; - fileConfig.m_name = child->getName(); - fileConfig.m_id = child->getId(); - fileConfig.m_signature = child->getSignature(); - fileConfig.m_createdTimeUtc = child->getCreatedTimeUtc(); - fileConfig.m_modifiedTimeUtc = child->getModifiedTimeUtc(); - fileConfig.m_attachmentFolder = child->getAttachmentFolder(); - fileConfig.m_tags = child->getTags(); - - // Visual settings - fileConfig.m_backgroundColor = child->getBackgroundColor(); - fileConfig.m_borderColor = child->getBorderColor(); - fileConfig.m_nameColor = child->getNameColor(); - - config->m_files.push_back(fileConfig); - } else { - Q_ASSERT(child->isContainer()); - NodeFolderConfig folderConfig; - folderConfig.m_name = child->getName(); - - // Visual settings - folderConfig.m_backgroundColor = child->getBackgroundColor(); - folderConfig.m_borderColor = child->getBorderColor(); - folderConfig.m_nameColor = child->getNameColor(); - - config->m_folders.push_back(folderConfig); - } - } +QSharedPointer VXNotebookConfigMgr::nodeToNodeConfig(const Node *p_node) const { + Q_ASSERT(p_node->isContainer()); + Q_ASSERT(p_node->isLoaded()); + + auto config = + QSharedPointer::create(getCodeVersion(), p_node->getId(), p_node->getSignature(), + p_node->getCreatedTimeUtc(), p_node->getModifiedTimeUtc()); + + // Set visual settings for the container node itself + config->m_backgroundColor = p_node->getBackgroundColor(); + config->m_borderColor = p_node->getBorderColor(); + config->m_nameColor = p_node->getNameColor(); + + for (const auto &child : p_node->getChildrenRef()) { + if (child->hasContent()) { + NodeFileConfig fileConfig; + fileConfig.m_name = child->getName(); + fileConfig.m_id = child->getId(); + fileConfig.m_signature = child->getSignature(); + fileConfig.m_createdTimeUtc = child->getCreatedTimeUtc(); + fileConfig.m_modifiedTimeUtc = child->getModifiedTimeUtc(); + fileConfig.m_attachmentFolder = child->getAttachmentFolder(); + fileConfig.m_tags = child->getTags(); + + // Visual settings + fileConfig.m_backgroundColor = child->getBackgroundColor(); + fileConfig.m_borderColor = child->getBorderColor(); + fileConfig.m_nameColor = child->getNameColor(); + + config->m_files.push_back(fileConfig); + } else { + Q_ASSERT(child->isContainer()); + NodeFolderConfig folderConfig; + folderConfig.m_name = child->getName(); - return config; -} + // Visual settings + folderConfig.m_backgroundColor = child->getBackgroundColor(); + folderConfig.m_borderColor = child->getBorderColor(); + folderConfig.m_nameColor = child->getNameColor(); -void VXNotebookConfigMgr::loadNode(Node *p_node) -{ - if (p_node->isLoaded() || !p_node->exists()) { - return; + config->m_folders.push_back(folderConfig); } + } - auto config = readNodeConfig(p_node->fetchPath()); - Q_ASSERT(p_node->isContainer()); - loadFolderNode(p_node, *config); + return config; } -void VXNotebookConfigMgr::saveNode(const Node *p_node) -{ - if (p_node->isContainer()) { - writeNodeConfig(p_node); - } else { - Q_ASSERT(!p_node->isRoot()); - writeNodeConfig(p_node->getParent()); - } +void VXNotebookConfigMgr::loadNode(Node *p_node) { + if (p_node->isLoaded() || !p_node->exists()) { + return; + } + + auto config = readNodeConfig(p_node->fetchPath()); + Q_ASSERT(p_node->isContainer()); + loadFolderNode(p_node, *config); } -void VXNotebookConfigMgr::renameNode(Node *p_node, const QString &p_name) -{ +void VXNotebookConfigMgr::saveNode(const Node *p_node) { + if (p_node->isContainer()) { + writeNodeConfig(p_node); + } else { Q_ASSERT(!p_node->isRoot()); + writeNodeConfig(p_node->getParent()); + } +} - if (p_node->isContainer()) { - getBackend()->renameDir(p_node->fetchPath(), p_name); - } else { - getBackend()->renameFile(p_node->fetchPath(), p_name); - } +void VXNotebookConfigMgr::renameNode(Node *p_node, const QString &p_name) { + Q_ASSERT(!p_node->isRoot()); - p_node->setName(p_name); - writeNodeConfig(p_node->getParent()); + if (p_node->isContainer()) { + getBackend()->renameDir(p_node->fetchPath(), p_name); + } else { + getBackend()->renameFile(p_node->fetchPath(), p_name); + } - ensureNodeInDatabase(p_node); - updateNodeInDatabase(p_node); + p_node->setName(p_name); + writeNodeConfig(p_node->getParent()); + + ensureNodeInDatabase(p_node); + updateNodeInDatabase(p_node); } // Do not touch DB here since it will be called at different scenarios. -void VXNotebookConfigMgr::addChildNode(Node *p_parent, const QSharedPointer &p_child) const -{ - if (p_child->isContainer()) { - int idx = 0; - const auto &children = p_parent->getChildrenRef(); - for (; idx < children.size(); ++idx) { - if (!children[idx]->isContainer()) { - break; - } - } - - p_parent->insertChild(idx, p_child); - } else { - p_parent->addChild(p_child); +void VXNotebookConfigMgr::addChildNode(Node *p_parent, const QSharedPointer &p_child) const { + if (p_child->isContainer()) { + int idx = 0; + const auto &children = p_parent->getChildrenRef(); + for (; idx < children.size(); ++idx) { + if (!children[idx]->isContainer()) { + break; + } } - inheritNodeFlags(p_parent, p_child.data()); + p_parent->insertChild(idx, p_child); + } else { + p_parent->addChild(p_child); + } + + inheritNodeFlags(p_parent, p_child.data()); } -QSharedPointer VXNotebookConfigMgr::loadNodeByPath(const QSharedPointer &p_root, const QString &p_relativePath) -{ - auto p = PathUtils::cleanPath(p_relativePath); - if (p == ".") { - return p_root; +QSharedPointer VXNotebookConfigMgr::loadNodeByPath(const QSharedPointer &p_root, + const QString &p_relativePath) { + auto p = PathUtils::cleanPath(p_relativePath); + if (p == ".") { + return p_root; + } + + auto paths = p.split('/', Qt::SkipEmptyParts); + auto node = p_root; + for (auto &pa : paths) { + // Find child @pa in @node. + if (!node->isLoaded()) { + loadNode(node.data()); } - auto paths = p.split('/', Qt::SkipEmptyParts); - auto node = p_root; - for (auto &pa : paths) { - // Find child @pa in @node. - if (!node->isLoaded()) { - loadNode(node.data()); - } - - auto child = node->findChild(pa, FileUtils::isPlatformNameCaseSensitive()); - if (!child) { - return nullptr; - } - - node = child; + auto child = node->findChild(pa, FileUtils::isPlatformNameCaseSensitive()); + if (!child) { + return nullptr; } - return node; + node = child; + } + + return node; } // @p_src may belong to different notebook or different kind of configmgr. // TODO: we could constrain @p_src within the same configrmgr? QSharedPointer VXNotebookConfigMgr::copyNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move) -{ - return copyNodeAsChildOf(p_src, p_dest, p_move, true); + Node *p_dest, bool p_move) { + return copyNodeAsChildOf(p_src, p_dest, p_move, true); } QSharedPointer VXNotebookConfigMgr::copyNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase) -{ - Q_ASSERT(p_dest->isContainer()); - - if (!p_src->exists()) { - if (p_move) { - // It is OK to always update the database. - p_src->getNotebook()->removeNode(p_src); - } - return nullptr; - } + Node *p_dest, bool p_move, + bool p_updateDatabase) { + Q_ASSERT(p_dest->isContainer()); - QSharedPointer node; - if (p_src->isContainer()) { - node = copyFolderNodeAsChildOf(p_src, p_dest, p_move, p_updateDatabase); - } else { - node = copyFileNodeAsChildOf(p_src, p_dest, p_move, p_updateDatabase); + if (!p_src->exists()) { + if (p_move) { + // It is OK to always update the database. + p_src->getNotebook()->removeNode(p_src); } + return nullptr; + } - return node; + QSharedPointer node; + if (p_src->isContainer()) { + node = copyFolderNodeAsChildOf(p_src, p_dest, p_move, p_updateDatabase); + } else { + node = copyFileNodeAsChildOf(p_src, p_dest, p_move, p_updateDatabase); + } + + return node; } QSharedPointer VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase) -{ - QString destFilePath; - QString attachmentFolder; - copyFilesOfFileNode(p_src, p_dest->fetchPath(), destFilePath, attachmentFolder); - - // Create a file node. - auto notebook = getNotebook(); - const bool sameNotebook = p_src->getNotebook() == notebook; - - if (p_updateDatabase) { - ensureNodeInDatabase(p_dest); - if (sameNotebook) { - ensureNodeInDatabase(p_src.data()); - } - } + Node *p_dest, bool p_move, + bool p_updateDatabase) { + QString destFilePath; + QString attachmentFolder; + copyFilesOfFileNode(p_src, p_dest->fetchPath(), destFilePath, attachmentFolder); - NodeParameters paras; - if (p_move && sameNotebook) { - paras.m_id = p_src->getId(); - paras.m_signature = p_src->getSignature(); + // Create a file node. + auto notebook = getNotebook(); + const bool sameNotebook = p_src->getNotebook() == notebook; + + if (p_updateDatabase) { + ensureNodeInDatabase(p_dest); + if (sameNotebook) { + ensureNodeInDatabase(p_src.data()); } - paras.m_createdTimeUtc = p_src->getCreatedTimeUtc(); - paras.m_modifiedTimeUtc = p_src->getModifiedTimeUtc(); - paras.m_tags = p_src->getTags(); - paras.m_attachmentFolder = attachmentFolder; - auto destNode = QSharedPointer::create(PathUtils::fileName(destFilePath), - paras, - notebook, - p_dest); - destNode->setExists(true); - - addChildNode(p_dest, destNode); - writeNodeConfig(p_dest); - - if (p_updateDatabase) { - if (p_move && sameNotebook) { - updateNodeInDatabase(destNode.data()); - } else { - addNodeToDatabase(destNode.data()); - } - - Q_ASSERT(nodeExistsInDatabase(destNode.data())); + } + + NodeParameters paras; + if (p_move && sameNotebook) { + paras.m_id = p_src->getId(); + paras.m_signature = p_src->getSignature(); + } + paras.m_createdTimeUtc = p_src->getCreatedTimeUtc(); + paras.m_modifiedTimeUtc = p_src->getModifiedTimeUtc(); + paras.m_tags = p_src->getTags(); + paras.m_attachmentFolder = attachmentFolder; + auto destNode = + QSharedPointer::create(PathUtils::fileName(destFilePath), paras, notebook, p_dest); + destNode->setExists(true); + + addChildNode(p_dest, destNode); + writeNodeConfig(p_dest); + + if (p_updateDatabase) { + if (p_move && sameNotebook) { + updateNodeInDatabase(destNode.data()); + } else { + addNodeToDatabase(destNode.data()); } - if (p_move) { - if (sameNotebook) { - // The same notebook. Do not directly call removeNode() since we already update the record - // in database directly. - removeNode(p_src, false, false, false); - } else { - p_src->getNotebook()->removeNode(p_src); - } + Q_ASSERT(nodeExistsInDatabase(destNode.data())); + } + + if (p_move) { + if (sameNotebook) { + // The same notebook. Do not directly call removeNode() since we already update the record + // in database directly. + removeNode(p_src, false, false, false); + } else { + p_src->getNotebook()->removeNode(p_src); } + } - return destNode; + return destNode; } QSharedPointer VXNotebookConfigMgr::copyFolderNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase) -{ - auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(), p_src->getName()); - destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); + Node *p_dest, bool p_move, + bool p_updateDatabase) { + auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(), p_src->getName()); + destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); - // Make folder. - getBackend()->makePath(destFolderPath); + // Make folder. + getBackend()->makePath(destFolderPath); - // Create a folder node. - auto notebook = getNotebook(); - const bool sameNotebook = p_src->getNotebook() == notebook; + // Create a folder node. + auto notebook = getNotebook(); + const bool sameNotebook = p_src->getNotebook() == notebook; - if (p_updateDatabase) { - ensureNodeInDatabase(p_dest); - if (sameNotebook) { - ensureNodeInDatabase(p_src.data()); - } + if (p_updateDatabase) { + ensureNodeInDatabase(p_dest); + if (sameNotebook) { + ensureNodeInDatabase(p_src.data()); } + } - auto destNode = QSharedPointer::create(PathUtils::fileName(destFolderPath), - notebook, - p_dest); - { - NodeParameters paras; - if (p_move && sameNotebook) { - paras.m_id = p_src->getId(); - paras.m_signature = p_src->getSignature(); - } - paras.m_createdTimeUtc = p_src->getCreatedTimeUtc(); - paras.m_modifiedTimeUtc = p_src->getModifiedTimeUtc(); - destNode->loadCompleteInfo(paras, QVector>()); + auto destNode = + QSharedPointer::create(PathUtils::fileName(destFolderPath), notebook, p_dest); + { + NodeParameters paras; + if (p_move && sameNotebook) { + paras.m_id = p_src->getId(); + paras.m_signature = p_src->getSignature(); } + paras.m_createdTimeUtc = p_src->getCreatedTimeUtc(); + paras.m_modifiedTimeUtc = p_src->getModifiedTimeUtc(); + destNode->loadCompleteInfo(paras, QVector>()); + } - destNode->setExists(true); - writeNodeConfig(destNode.data()); + destNode->setExists(true); + writeNodeConfig(destNode.data()); - addChildNode(p_dest, destNode); - writeNodeConfig(p_dest); + addChildNode(p_dest, destNode); + writeNodeConfig(p_dest); - if (p_updateDatabase) { - if (p_move && sameNotebook) { - p_updateDatabase = false; - updateNodeInDatabase(destNode.data()); - } else { - addNodeToDatabase(destNode.data()); - } + if (p_updateDatabase) { + if (p_move && sameNotebook) { + p_updateDatabase = false; + updateNodeInDatabase(destNode.data()); + } else { + addNodeToDatabase(destNode.data()); } + } - // Copy children node. - auto children = p_src->getChildren(); - for (const auto &childNode : children) { - copyNodeAsChildOf(childNode, destNode.data(), p_move, p_updateDatabase); - } + // Copy children node. + auto children = p_src->getChildren(); + for (const auto &childNode : children) { + copyNodeAsChildOf(childNode, destNode.data(), p_move, p_updateDatabase); + } - if (p_move) { - if (sameNotebook) { - removeNode(p_src, false, false, false); - } else { - p_src->getNotebook()->removeNode(p_src); - } + if (p_move) { + if (sameNotebook) { + removeNode(p_src, false, false, false); + } else { + p_src->getNotebook()->removeNode(p_src); } + } - return destNode; + return destNode; } -void VXNotebookConfigMgr::removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly) -{ - removeNode(p_node, p_force, p_configOnly, true); +void VXNotebookConfigMgr::removeNode(const QSharedPointer &p_node, bool p_force, + bool p_configOnly) { + removeNode(p_node, p_force, p_configOnly, true); } -void VXNotebookConfigMgr::removeNode(const QSharedPointer &p_node, - bool p_force, - bool p_configOnly, - bool p_updateDatabase) -{ - if (!p_configOnly && p_node->exists()) { - // Remove all children. - auto children = p_node->getChildren(); - for (const auto &childNode : children) { - // With DELETE CASCADE, we could just touch the DB at parent level. - removeNode(childNode, p_force, p_configOnly, false); - } - - try { - removeFilesOfNode(p_node.data(), p_force); - } catch (Exception &p_e) { - qWarning() << "failed to remove files of node" << p_node->fetchPath() << p_e.what(); - } +void VXNotebookConfigMgr::removeNode(const QSharedPointer &p_node, bool p_force, + bool p_configOnly, bool p_updateDatabase) { + if (!p_configOnly && p_node->exists()) { + // Remove all children. + auto children = p_node->getChildren(); + for (const auto &childNode : children) { + // With DELETE CASCADE, we could just touch the DB at parent level. + removeNode(childNode, p_force, p_configOnly, false); } - if (p_updateDatabase) { - // Remove it from data base before modifying the parent. - removeNodeFromDatabase(p_node.data()); + try { + removeFilesOfNode(p_node.data(), p_force); + } catch (Exception &p_e) { + qWarning() << "failed to remove files of node" << p_node->fetchPath() << p_e.what(); } + } - if (auto parentNode = p_node->getParent()) { - parentNode->removeChild(p_node); - writeNodeConfig(parentNode); - } + if (p_updateDatabase) { + // Remove it from data base before modifying the parent. + removeNodeFromDatabase(p_node.data()); + } + + if (auto parentNode = p_node->getParent()) { + parentNode->removeChild(p_node); + writeNodeConfig(parentNode); + } } -void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force) -{ - Q_ASSERT(p_node->getNotebook() == getNotebook()); - if (!p_node->isContainer()) { - // Delete attachment. - if (!p_node->getAttachmentFolder().isEmpty()) { - getBackend()->removeDir(p_node->fetchAttachmentFolderPath()); - } - - // Delete media files fetched from content. - ContentMediaUtils::removeMediaFiles(p_node); - - // Delete node file itself. - auto filePath = p_node->fetchPath(); - getBackend()->removeFile(filePath); - } else { - Q_ASSERT(p_node->getChildrenCount() == 0); - // Delete node config file and the dir if it is empty. - auto configFilePath = getNodeConfigFilePath(p_node); - getBackend()->removeFile(configFilePath); - auto folderPath = p_node->fetchPath(); - if (p_force) { - getBackend()->removeDir(folderPath); - } else { - getBackend()->removeEmptyDir(folderPath); - bool deleted = getBackend()->removeDirIfEmpty(folderPath); - if (!deleted) { - qWarning() << "folder is not deleted since it is not empty" << folderPath; - } - } +void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force) { + Q_ASSERT(p_node->getNotebook() == getNotebook()); + if (!p_node->isContainer()) { + // Delete attachment. + if (!p_node->getAttachmentFolder().isEmpty()) { + getBackend()->removeDir(p_node->fetchAttachmentFolderPath()); } -} -void VXNotebookConfigMgr::removeNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder) -{ - if (p_node->isContainer()) { - removeFolderNodeToFolder(p_node, p_destFolder); + // Delete media files fetched from content. + ContentMediaUtils::removeMediaFiles(p_node); + + // Delete node file itself. + auto filePath = p_node->fetchPath(); + getBackend()->removeFile(filePath); + } else { + Q_ASSERT(p_node->getChildrenCount() == 0); + // Delete node config file and the dir if it is empty. + auto configFilePath = getNodeConfigFilePath(p_node); + getBackend()->removeFile(configFilePath); + auto folderPath = p_node->fetchPath(); + if (p_force) { + getBackend()->removeDir(folderPath); } else { - removeFileNodeToFolder(p_node, p_destFolder); + getBackend()->removeEmptyDir(folderPath); + bool deleted = getBackend()->removeDirIfEmpty(folderPath); + if (!deleted) { + qWarning() << "folder is not deleted since it is not empty" << folderPath; + } } + } } -void VXNotebookConfigMgr::removeFolderNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder) -{ - auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName()); - destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); +void VXNotebookConfigMgr::removeNodeToFolder(const QSharedPointer &p_node, + const QString &p_destFolder) { + if (p_node->isContainer()) { + removeFolderNodeToFolder(p_node, p_destFolder); + } else { + removeFileNodeToFolder(p_node, p_destFolder); + } +} - // Make folder. - getBackend()->makePath(destFolderPath); +void VXNotebookConfigMgr::removeFolderNodeToFolder(const QSharedPointer &p_node, + const QString &p_destFolder) { + auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName()); + destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); - // Children. - auto children = p_node->getChildren(); - for (const auto &child : children) { - removeNodeToFolder(child, destFolderPath); - } + // Make folder. + getBackend()->makePath(destFolderPath); - removeNode(p_node, false, false); + // Children. + auto children = p_node->getChildren(); + for (const auto &child : children) { + removeNodeToFolder(child, destFolderPath); + } + + removeNode(p_node, false, false); } -void VXNotebookConfigMgr::removeFileNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder) -{ - // Use a wrapper folder. - auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName()); - destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); +void VXNotebookConfigMgr::removeFileNodeToFolder(const QSharedPointer &p_node, + const QString &p_destFolder) { + // Use a wrapper folder. + auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName()); + destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); - // Make folder. - getBackend()->makePath(destFolderPath); + // Make folder. + getBackend()->makePath(destFolderPath); - QString destFilePath; - QString attachmentFolder; - copyFilesOfFileNode(p_node, destFolderPath, destFilePath, attachmentFolder); + QString destFilePath; + QString attachmentFolder; + copyFilesOfFileNode(p_node, destFolderPath, destFilePath, attachmentFolder); - removeNode(p_node, false, false); + removeNode(p_node, false, false); } void VXNotebookConfigMgr::copyFilesOfFileNode(const QSharedPointer &p_node, - const QString &p_destFolder, - QString &p_destFilePath, - QString &p_attachmentFolder) -{ - // Copy source file itself. - auto nodeFilePath = p_node->fetchAbsolutePath(); - p_destFilePath = PathUtils::concatenateFilePath(p_destFolder, PathUtils::fileName(nodeFilePath)); - p_destFilePath = getBackend()->renameIfExistsCaseInsensitive(p_destFilePath); - getBackend()->copyFile(nodeFilePath, p_destFilePath); - - // Copy media files fetched from content. - ContentMediaUtils::copyMediaFiles(p_node.data(), getBackend().data(), p_destFilePath); - - // Copy attachment folder. Rename attachment folder if conflicts. - p_attachmentFolder = p_node->getAttachmentFolder(); - if (!p_attachmentFolder.isEmpty()) { - auto destAttachmentFolderPath = fetchNodeAttachmentFolder(p_destFilePath, p_attachmentFolder); - ContentMediaUtils::copyAttachment(p_node.data(), getBackend().data(), p_destFilePath, destAttachmentFolderPath); - } + const QString &p_destFolder, QString &p_destFilePath, + QString &p_attachmentFolder) { + // Copy source file itself. + auto nodeFilePath = p_node->fetchAbsolutePath(); + p_destFilePath = PathUtils::concatenateFilePath(p_destFolder, PathUtils::fileName(nodeFilePath)); + p_destFilePath = getBackend()->renameIfExistsCaseInsensitive(p_destFilePath); + getBackend()->copyFile(nodeFilePath, p_destFilePath); + + // Copy media files fetched from content. + ContentMediaUtils::copyMediaFiles(p_node.data(), getBackend().data(), p_destFilePath); + + // Copy attachment folder. Rename attachment folder if conflicts. + p_attachmentFolder = p_node->getAttachmentFolder(); + if (!p_attachmentFolder.isEmpty()) { + auto destAttachmentFolderPath = fetchNodeAttachmentFolder(p_destFilePath, p_attachmentFolder); + ContentMediaUtils::copyAttachment(p_node.data(), getBackend().data(), p_destFilePath, + destAttachmentFolderPath); + } } -QString VXNotebookConfigMgr::fetchNodeImageFolderPath(Node *p_node) -{ - auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()), - getNotebook()->getImageFolder()); - // Do not make the folder when it is a folder node request. - if (p_node->hasContent()) { - getBackend()->makePath(pa); - } - return pa; +QString VXNotebookConfigMgr::fetchNodeImageFolderPath(Node *p_node) { + auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()), + getNotebook()->getImageFolder()); + // Do not make the folder when it is a folder node request. + if (p_node->hasContent()) { + getBackend()->makePath(pa); + } + return pa; } -QString VXNotebookConfigMgr::fetchNodeAttachmentFolderPath(Node *p_node) -{ - auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()), - getNotebook()->getAttachmentFolder()); - if (p_node->hasContent()) { - auto nodeFolder = p_node->getAttachmentFolder(); - if (nodeFolder.isEmpty()) { - auto folderPath = fetchNodeAttachmentFolder(p_node->fetchAbsolutePath(), nodeFolder); - p_node->setAttachmentFolder(nodeFolder); - saveNode(p_node); - - getBackend()->makePath(folderPath); - return folderPath; - } else { - return PathUtils::concatenateFilePath(notebookFolder, nodeFolder); - } +QString VXNotebookConfigMgr::fetchNodeAttachmentFolderPath(Node *p_node) { + auto notebookFolder = PathUtils::concatenateFilePath( + PathUtils::parentDirPath(p_node->fetchAbsolutePath()), getNotebook()->getAttachmentFolder()); + if (p_node->hasContent()) { + auto nodeFolder = p_node->getAttachmentFolder(); + if (nodeFolder.isEmpty()) { + auto folderPath = fetchNodeAttachmentFolder(p_node->fetchAbsolutePath(), nodeFolder); + p_node->setAttachmentFolder(nodeFolder); + saveNode(p_node); + + getBackend()->makePath(folderPath); + return folderPath; } else { - // Do not make the folder when it is a folder node request. - return notebookFolder; + return PathUtils::concatenateFilePath(notebookFolder, nodeFolder); } + } else { + // Do not make the folder when it is a folder node request. + return notebookFolder; + } } -QString VXNotebookConfigMgr::fetchNodeAttachmentFolder(const QString &p_nodePath, QString &p_folderName) -{ - auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_nodePath), - getNotebook()->getAttachmentFolder()); - if (p_folderName.isEmpty()) { - p_folderName = FileUtils::generateUniqueFileName(notebookFolder, QString(), QString()); - } else if (FileUtils::childExistsCaseInsensitive(notebookFolder, p_folderName)) { - p_folderName = FileUtils::generateFileNameWithSequence(notebookFolder, p_folderName, QString()); - } - return PathUtils::concatenateFilePath(notebookFolder, p_folderName); +QString VXNotebookConfigMgr::fetchNodeAttachmentFolder(const QString &p_nodePath, + QString &p_folderName) { + auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_nodePath), + getNotebook()->getAttachmentFolder()); + if (p_folderName.isEmpty()) { + p_folderName = FileUtils::generateUniqueFileName(notebookFolder, QString(), QString()); + } else if (FileUtils::childExistsCaseInsensitive(notebookFolder, p_folderName)) { + p_folderName = FileUtils::generateFileNameWithSequence(notebookFolder, p_folderName, QString()); + } + return PathUtils::concatenateFilePath(notebookFolder, p_folderName); } -bool VXNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p_name) const -{ - static const QString backupFileExtension = ConfigMgr::getInst().getEditorConfig().getBackupFileExtension().toLower(); +bool VXNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p_name) const { + static const QString backupFileExtension = + ConfigMgr::getInst().getEditorConfig().getBackupFileExtension().toLower(); - const auto name = p_name.toLower(); - if (name == c_nodeConfigName - || name == QStringLiteral("_vnote.json") - || name.endsWith(backupFileExtension)) { - return true; - } - return BundleNotebookConfigMgr::isBuiltInFile(p_node, p_name); + const auto name = p_name.toLower(); + if (name == c_nodeConfigName || name == QStringLiteral("_vnote.json") || + name.endsWith(backupFileExtension)) { + return true; + } + return BundleNotebookConfigMgr::isBuiltInFile(p_node, p_name); } -bool VXNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const -{ - const auto name = p_name.toLower(); - const auto &nb = getNotebook(); - if (name == nb->getImageFolder().toLower() - || name == nb->getAttachmentFolder().toLower() - || name == QStringLiteral("_v_images") - || name == QStringLiteral("_v_attachments") - || name == QStringLiteral("vx_images") - || name == QStringLiteral("vx_attachments")) { - return true; - } - return BundleNotebookConfigMgr::isBuiltInFolder(p_node, p_name); +bool VXNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const { + const auto name = p_name.toLower(); + const auto &nb = getNotebook(); + if (name == nb->getImageFolder().toLower() || name == nb->getAttachmentFolder().toLower() || + name == QStringLiteral("_v_images") || name == QStringLiteral("_v_attachments") || + name == QStringLiteral("vx_images") || name == QStringLiteral("vx_attachments")) { + return true; + } + return BundleNotebookConfigMgr::isBuiltInFolder(p_node, p_name); } -QSharedPointer VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_srcPath, Node *p_dest) -{ - // Skip copy if it already locates in dest folder. - auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchAbsolutePath(), - PathUtils::fileName(p_srcPath)); - if (!PathUtils::areSamePaths(p_srcPath, destFilePath)) { - // Copy source file itself. - destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); - getBackend()->copyFile(p_srcPath, destFilePath); - - // Copy media files fetched from content. - ContentMediaUtils::copyMediaFiles(p_srcPath, getBackend().data(), destFilePath); - } +QSharedPointer VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_srcPath, + Node *p_dest) { + // Skip copy if it already locates in dest folder. + auto destFilePath = + PathUtils::concatenateFilePath(p_dest->fetchAbsolutePath(), PathUtils::fileName(p_srcPath)); + if (!PathUtils::areSamePaths(p_srcPath, destFilePath)) { + // Copy source file itself. + destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); + getBackend()->copyFile(p_srcPath, destFilePath); - ensureNodeInDatabase(p_dest); + // Copy media files fetched from content. + ContentMediaUtils::copyMediaFiles(p_srcPath, getBackend().data(), destFilePath); + } - const auto name = PathUtils::fileName(destFilePath); - auto destNode = p_dest->findChild(name, true); - if (destNode) { - // Already have the node. - ensureNodeInDatabase(destNode.data()); - return destNode; - } + ensureNodeInDatabase(p_dest); - // Create a file node. - destNode = QSharedPointer::create(name, - NodeParameters(), - getNotebook(), - p_dest); - destNode->setExists(true); - addChildNode(p_dest, destNode); - writeNodeConfig(p_dest); + const auto name = PathUtils::fileName(destFilePath); + auto destNode = p_dest->findChild(name, true); + if (destNode) { + // Already have the node. + ensureNodeInDatabase(destNode.data()); + return destNode; + } - addNodeToDatabase(destNode.data()); + // Create a file node. + destNode = QSharedPointer::create(name, NodeParameters(), getNotebook(), p_dest); + destNode->setExists(true); + addChildNode(p_dest, destNode); + writeNodeConfig(p_dest); - return destNode; + addNodeToDatabase(destNode.data()); + + return destNode; } -QSharedPointer VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_srcPath, Node *p_dest) -{ - // Skip copy if it already locates in dest folder. - auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchAbsolutePath(), - PathUtils::fileName(p_srcPath)); - if (!PathUtils::areSamePaths(p_srcPath, destFolderPath)) { - destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); +QSharedPointer VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_srcPath, + Node *p_dest) { + // Skip copy if it already locates in dest folder. + auto destFolderPath = + PathUtils::concatenateFilePath(p_dest->fetchAbsolutePath(), PathUtils::fileName(p_srcPath)); + if (!PathUtils::areSamePaths(p_srcPath, destFolderPath)) { + destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); - // Copy folder. - getBackend()->copyDir(p_srcPath, destFolderPath); - } + // Copy folder. + getBackend()->copyDir(p_srcPath, destFolderPath); + } - ensureNodeInDatabase(p_dest); + ensureNodeInDatabase(p_dest); - const auto name = PathUtils::fileName(destFolderPath); - auto destNode = p_dest->findChild(name, true); - if (destNode) { - // Already have the node. - ensureNodeInDatabase(destNode.data()); - return destNode; - } + const auto name = PathUtils::fileName(destFolderPath); + auto destNode = p_dest->findChild(name, true); + if (destNode) { + // Already have the node. + ensureNodeInDatabase(destNode.data()); + return destNode; + } - // Create a folder node. - auto notebook = getNotebook(); - destNode = QSharedPointer::create(name, notebook, p_dest); - destNode->loadCompleteInfo(NodeParameters(), QVector>()); - destNode->setExists(true); + // Create a folder node. + auto notebook = getNotebook(); + destNode = QSharedPointer::create(name, notebook, p_dest); + destNode->loadCompleteInfo(NodeParameters(), QVector>()); + destNode->setExists(true); - writeNodeConfig(destNode.data()); + writeNodeConfig(destNode.data()); - addChildNode(p_dest, destNode); - writeNodeConfig(p_dest); + addChildNode(p_dest, destNode); + writeNodeConfig(p_dest); - addNodeToDatabase(destNode.data()); + addNodeToDatabase(destNode.data()); - return destNode; + return destNode; } -void VXNotebookConfigMgr::inheritNodeFlags(const Node *p_node, Node *p_child) const -{ - if (p_node->isReadOnly()) { - markNodeReadOnly(p_child); - } +void VXNotebookConfigMgr::inheritNodeFlags(const Node *p_node, Node *p_child) const { + if (p_node->isReadOnly()) { + markNodeReadOnly(p_child); + } } -QVector> VXNotebookConfigMgr::fetchExternalChildren(Node *p_node) const -{ - Q_ASSERT(p_node->isContainer()); - QVector> externalNodes; +QVector> +VXNotebookConfigMgr::fetchExternalChildren(Node *p_node) const { + Q_ASSERT(p_node->isContainer()); + QVector> externalNodes; - auto dir = p_node->toDir(); + auto dir = p_node->toDir(); - // Folders. - { - const auto folders = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); - for (const auto &folder : folders) { - if (isBuiltInFolder(p_node, folder)) { - continue; - } + // Folders. + { + const auto folders = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); + for (const auto &folder : folders) { + if (isBuiltInFolder(p_node, folder)) { + continue; + } - if (isExcludedFromExternalNode(folder)) { - continue; - } + if (isExcludedFromExternalNode(folder)) { + continue; + } - if (p_node->containsContainerChild(folder)) { - continue; - } + if (p_node->containsContainerChild(folder)) { + continue; + } - externalNodes.push_back(QSharedPointer::create(p_node, folder, ExternalNode::Type::Folder)); - } + externalNodes.push_back( + QSharedPointer::create(p_node, folder, ExternalNode::Type::Folder)); } + } - // Files. - { - const auto files = dir.entryList(QDir::Files); - for (const auto &file : files) { - if (isBuiltInFile(p_node, file)) { - continue; - } + // Files. + { + const auto files = dir.entryList(QDir::Files); + for (const auto &file : files) { + if (isBuiltInFile(p_node, file)) { + continue; + } - if (isExcludedFromExternalNode(file)) { - continue; - } + if (isExcludedFromExternalNode(file)) { + continue; + } - if (p_node->containsContentChild(file)) { - continue; - } + if (p_node->containsContentChild(file)) { + continue; + } - externalNodes.push_back(QSharedPointer::create(p_node, file, ExternalNode::Type::File)); - } + externalNodes.push_back( + QSharedPointer::create(p_node, file, ExternalNode::Type::File)); } + } - return externalNodes; + return externalNodes; } -bool VXNotebookConfigMgr::isExcludedFromExternalNode(const QString &p_name) const -{ - for (const auto ®Exp : s_externalNodeExcludePatterns) { - if (regExp.exactMatch(p_name)) { - return true; - } +bool VXNotebookConfigMgr::isExcludedFromExternalNode(const QString &p_name) const { + for (const auto ®Exp : s_externalNodeExcludePatterns) { + if (regExp.exactMatch(p_name)) { + return true; } - return false; + } + return false; } -bool VXNotebookConfigMgr::checkNodeExists(Node *p_node) -{ - bool exists = getBackend()->exists(p_node->fetchPath()); - p_node->setExists(exists); - return exists; +bool VXNotebookConfigMgr::checkNodeExists(Node *p_node) { + bool exists = getBackend()->exists(p_node->fetchPath()); + p_node->setExists(exists); + return exists; } -QStringList VXNotebookConfigMgr::scanAndImportExternalFiles(Node *p_node) -{ - QStringList files; - if (!p_node->isContainer()) { - return files; +QStringList VXNotebookConfigMgr::scanAndImportExternalFiles(Node *p_node) { + QStringList files; + if (!p_node->isContainer()) { + return files; + } + + // External nodes. + auto dir = p_node->toDir(); + auto externalNodes = fetchExternalChildren(p_node); + for (const auto &node : externalNodes) { + Node::Flags flags = Node::Flag::Content; + if (node->isFolder()) { + if (isLikelyImageFolder(dir.filePath(node->getName()))) { + qWarning() << "skip importing folder containing only images" << node->getName(); + continue; + } + flags = Node::Flag::Container; } - // External nodes. - auto dir = p_node->toDir(); - auto externalNodes = fetchExternalChildren(p_node); - for (const auto &node : externalNodes) { - Node::Flags flags = Node::Flag::Content; - if (node->isFolder()) { - if (isLikelyImageFolder(dir.filePath(node->getName()))) { - qWarning() << "skip importing folder containing only images" << node->getName(); - continue; - } - flags = Node::Flag::Container; - } - - addAsNode(p_node, flags, node->getName(), NodeParameters()); - files << dir.filePath(node->getName()); - } + addAsNode(p_node, flags, node->getName(), NodeParameters()); + files << dir.filePath(node->getName()); + } - // Children folders (including newly-added external nodes). - for (const auto &child : p_node->getChildrenRef()) { - if (child->isContainer()) { - files << scanAndImportExternalFiles(child.data()); - } + // Children folders (including newly-added external nodes). + for (const auto &child : p_node->getChildrenRef()) { + if (child->isContainer()) { + files << scanAndImportExternalFiles(child.data()); } + } - return files; + return files; } -bool VXNotebookConfigMgr::isLikelyImageFolder(const QString &p_dirPath) -{ - QDir dir(p_dirPath); - const auto folders = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); - if (!folders.isEmpty()) { - return false; - } +bool VXNotebookConfigMgr::isLikelyImageFolder(const QString &p_dirPath) { + QDir dir(p_dirPath); + const auto folders = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); + if (!folders.isEmpty()) { + return false; + } - const auto files = dir.entryList(QDir::Files); - if (files.isEmpty()) { - return false; - } + const auto files = dir.entryList(QDir::Files); + if (files.isEmpty()) { + return false; + } - for (const auto &file : files) { - if (!FileUtils::isImage(dir.filePath(file))) { - return false; - } + for (const auto &file : files) { + if (!FileUtils::isImage(dir.filePath(file))) { + return false; } + } - return true; + return true; } -NotebookDatabaseAccess *VXNotebookConfigMgr::getDatabaseAccess() const -{ - return static_cast(getNotebook())->getDatabaseAccess(); +NotebookDatabaseAccess *VXNotebookConfigMgr::getDatabaseAccess() const { + return static_cast(getNotebook())->getDatabaseAccess(); } -void VXNotebookConfigMgr::updateNodeInDatabase(Node *p_node) -{ - Q_ASSERT(sameNotebook(p_node)); - getDatabaseAccess()->updateNode(p_node); +void VXNotebookConfigMgr::updateNodeInDatabase(Node *p_node) { + Q_ASSERT(sameNotebook(p_node)); + getDatabaseAccess()->updateNode(p_node); } -void VXNotebookConfigMgr::ensureNodeInDatabase(Node *p_node) -{ - if (!p_node) { - return; - } +void VXNotebookConfigMgr::ensureNodeInDatabase(Node *p_node) { + if (!p_node) { + return; + } - Q_ASSERT(sameNotebook(p_node)); + Q_ASSERT(sameNotebook(p_node)); - auto db = getDatabaseAccess(); - if (db->existsNode(p_node)) { - return; - } + auto db = getDatabaseAccess(); + if (db->existsNode(p_node)) { + return; + } - ensureNodeInDatabase(p_node->getParent()); - db->addNode(p_node, false); - db->clearObsoleteNodes(); + ensureNodeInDatabase(p_node->getParent()); + db->addNode(p_node, false); + db->clearObsoleteNodes(); } -void VXNotebookConfigMgr::addNodeToDatabase(Node *p_node) -{ - Q_ASSERT(sameNotebook(p_node)); - auto db = getDatabaseAccess(); - db->addNode(p_node, false); - db->clearObsoleteNodes(); +void VXNotebookConfigMgr::addNodeToDatabase(Node *p_node) { + Q_ASSERT(sameNotebook(p_node)); + auto db = getDatabaseAccess(); + db->addNode(p_node, false); + db->clearObsoleteNodes(); } -bool VXNotebookConfigMgr::nodeExistsInDatabase(const Node *p_node) -{ - Q_ASSERT(sameNotebook(p_node)); - return getDatabaseAccess()->existsNode(p_node); +bool VXNotebookConfigMgr::nodeExistsInDatabase(const Node *p_node) { + Q_ASSERT(sameNotebook(p_node)); + return getDatabaseAccess()->existsNode(p_node); } -void VXNotebookConfigMgr::removeNodeFromDatabase(const Node *p_node) -{ - Q_ASSERT(sameNotebook(p_node)); - getDatabaseAccess()->removeNode(p_node); +void VXNotebookConfigMgr::removeNodeFromDatabase(const Node *p_node) { + Q_ASSERT(sameNotebook(p_node)); + getDatabaseAccess()->removeNode(p_node); } -bool VXNotebookConfigMgr::sameNotebook(const Node *p_node) const -{ - return p_node ? p_node->getNotebook() == getNotebook() : true; +bool VXNotebookConfigMgr::sameNotebook(const Node *p_node) const { + return p_node ? p_node->getNotebook() == getNotebook() : true; } -void VXNotebookConfigMgr::updateNodeVisual(Node *p_node, const NodeVisual &p_visual) -{ - Q_ASSERT(sameNotebook(p_node)); - - p_node->setVisual(p_visual); - - if (p_node->isRoot()) { - return; - } - - saveNode(p_node); +void VXNotebookConfigMgr::updateNodeVisual(Node *p_node, const NodeVisual &p_visual) { + Q_ASSERT(sameNotebook(p_node)); + + p_node->setVisual(p_visual); + + if (p_node->isRoot()) { + return; + } + + saveNode(p_node); } diff --git a/src/core/notebookconfigmgr/vxnotebookconfigmgr.h b/src/core/notebookconfigmgr/vxnotebookconfigmgr.h index ee4578db1a..351760e1a2 100644 --- a/src/core/notebookconfigmgr/vxnotebookconfigmgr.h +++ b/src/core/notebookconfigmgr/vxnotebookconfigmgr.h @@ -4,189 +4,167 @@ #include "bundlenotebookconfigmgr.h" #include -#include #include +#include #include class QJsonObject; -namespace vnotex -{ - namespace vx_node_config - { - struct NodeFileConfig; - struct NodeFolderConfig; - struct NodeConfig; - } +namespace vnotex { +namespace vx_node_config { +struct NodeFileConfig; +struct NodeFolderConfig; +struct NodeConfig; +} // namespace vx_node_config - class NotebookDatabaseAccess; +class NotebookDatabaseAccess; - // Config manager for VNoteX's bundle notebook. - class VXNotebookConfigMgr : public BundleNotebookConfigMgr - { - Q_OBJECT - public: - VXNotebookConfigMgr(const QSharedPointer &p_backend, QObject *p_parent = nullptr); +// Config manager for VNoteX's bundle notebook. +class VXNotebookConfigMgr : public BundleNotebookConfigMgr { + Q_OBJECT +public: + VXNotebookConfigMgr(const QSharedPointer &p_backend, + QObject *p_parent = nullptr); - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getDisplayName() const Q_DECL_OVERRIDE; + QString getDisplayName() const Q_DECL_OVERRIDE; - QString getDescription() const Q_DECL_OVERRIDE; + QString getDescription() const Q_DECL_OVERRIDE; - void createEmptySkeleton(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; + void createEmptySkeleton(const NotebookParameters &p_paras) Q_DECL_OVERRIDE; - QSharedPointer loadRootNode() Q_DECL_OVERRIDE; + QSharedPointer loadRootNode() Q_DECL_OVERRIDE; - void loadNode(Node *p_node) Q_DECL_OVERRIDE; - void saveNode(const Node *p_node) Q_DECL_OVERRIDE; + void loadNode(Node *p_node) Q_DECL_OVERRIDE; + void saveNode(const Node *p_node) Q_DECL_OVERRIDE; - void renameNode(Node *p_node, const QString &p_name) Q_DECL_OVERRIDE; + void renameNode(Node *p_node, const QString &p_name) Q_DECL_OVERRIDE; - QSharedPointer newNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const QString &p_content) Q_DECL_OVERRIDE; + QSharedPointer newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const QString &p_content) Q_DECL_OVERRIDE; - QSharedPointer addAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_name, - const NodeParameters &p_paras) Q_DECL_OVERRIDE; + QSharedPointer addAsNode(Node *p_parent, Node::Flags p_flags, const QString &p_name, + const NodeParameters &p_paras) Q_DECL_OVERRIDE; - QSharedPointer copyAsNode(Node *p_parent, - Node::Flags p_flags, - const QString &p_path) Q_DECL_OVERRIDE; + QSharedPointer copyAsNode(Node *p_parent, Node::Flags p_flags, + const QString &p_path) Q_DECL_OVERRIDE; - QSharedPointer loadNodeByPath(const QSharedPointer &p_root, - const QString &p_relativePath) Q_DECL_OVERRIDE; + QSharedPointer loadNodeByPath(const QSharedPointer &p_root, + const QString &p_relativePath) Q_DECL_OVERRIDE; - QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move) Q_DECL_OVERRIDE; + QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move) Q_DECL_OVERRIDE; - void removeNode(const QSharedPointer &p_node, bool p_force = false, bool p_configOnly = false) Q_DECL_OVERRIDE; + void removeNode(const QSharedPointer &p_node, bool p_force = false, + bool p_configOnly = false) Q_DECL_OVERRIDE; - void removeNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder) Q_DECL_OVERRIDE; + void removeNodeToFolder(const QSharedPointer &p_node, + const QString &p_destFolder) Q_DECL_OVERRIDE; - bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; + bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; - bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; + bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; - QString fetchNodeImageFolderPath(Node *p_node); + QString fetchNodeImageFolderPath(Node *p_node); - QString fetchNodeAttachmentFolderPath(Node *p_node) Q_DECL_OVERRIDE; + QString fetchNodeAttachmentFolderPath(Node *p_node) Q_DECL_OVERRIDE; - QVector> fetchExternalChildren(Node *p_node) const Q_DECL_OVERRIDE; + QVector> fetchExternalChildren(Node *p_node) const Q_DECL_OVERRIDE; - bool checkNodeExists(Node *p_node) Q_DECL_OVERRIDE; + bool checkNodeExists(Node *p_node) Q_DECL_OVERRIDE; - QStringList scanAndImportExternalFiles(Node *p_node) Q_DECL_OVERRIDE; + QStringList scanAndImportExternalFiles(Node *p_node) Q_DECL_OVERRIDE; - void updateNodeVisual(Node *p_node, const NodeVisual &p_visual) Q_DECL_OVERRIDE; + void updateNodeVisual(Node *p_node, const NodeVisual &p_visual) Q_DECL_OVERRIDE; - private: - void createEmptyRootNode(); +private: + void createEmptyRootNode(); - QSharedPointer readNodeConfig(const QString &p_path) const; - void writeNodeConfig(const QString &p_path, const vx_node_config::NodeConfig &p_config) const; + QSharedPointer readNodeConfig(const QString &p_path) const; + void writeNodeConfig(const QString &p_path, const vx_node_config::NodeConfig &p_config) const; - void writeNodeConfig(const Node *p_node); + void writeNodeConfig(const Node *p_node); - QSharedPointer nodeConfigToNode(const vx_node_config::NodeConfig &p_config, - const QString &p_name, - Node *p_parent = nullptr); + QSharedPointer nodeConfigToNode(const vx_node_config::NodeConfig &p_config, + const QString &p_name, Node *p_parent = nullptr); - void loadFolderNode(Node *p_node, const vx_node_config::NodeConfig &p_config); + void loadFolderNode(Node *p_node, const vx_node_config::NodeConfig &p_config); - QSharedPointer nodeToNodeConfig(const Node *p_node) const; + QSharedPointer nodeToNodeConfig(const Node *p_node) const; - QSharedPointer newFileNode(Node *p_parent, - const QString &p_name, - const QString &p_content, - bool p_create, - const NodeParameters &p_paras); + QSharedPointer newFileNode(Node *p_parent, const QString &p_name, const QString &p_content, + bool p_create, const NodeParameters &p_paras); - QSharedPointer newFolderNode(Node *p_parent, - const QString &p_name, - bool p_create, - const NodeParameters &p_paras); + QSharedPointer newFolderNode(Node *p_parent, const QString &p_name, bool p_create, + const NodeParameters &p_paras); - QString getNodeConfigFilePath(const Node *p_node) const; + QString getNodeConfigFilePath(const Node *p_node) const; - void addChildNode(Node *p_parent, const QSharedPointer &p_child) const; + void addChildNode(Node *p_parent, const QSharedPointer &p_child) const; - QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase); + QSharedPointer copyNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move, bool p_updateDatabase); - QSharedPointer copyFileNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase); + QSharedPointer copyFileNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move, bool p_updateDatabase); - QSharedPointer copyFolderNodeAsChildOf(const QSharedPointer &p_src, - Node *p_dest, - bool p_move, - bool p_updateDatabase); + QSharedPointer copyFolderNodeAsChildOf(const QSharedPointer &p_src, Node *p_dest, + bool p_move, bool p_updateDatabase); - QSharedPointer copyFileAsChildOf(const QString &p_srcPath, Node *p_dest); + QSharedPointer copyFileAsChildOf(const QString &p_srcPath, Node *p_dest); - QSharedPointer copyFolderAsChildOf(const QString &p_srcPath, Node *p_dest); + QSharedPointer copyFolderAsChildOf(const QString &p_srcPath, Node *p_dest); - void removeFilesOfNode(Node *p_node, bool p_force); + void removeFilesOfNode(Node *p_node, bool p_force); - void markNodeReadOnly(Node *p_node) const; + void markNodeReadOnly(Node *p_node) const; - void removeLegacyRecycleBinNode(const QSharedPointer &p_root); + void removeLegacyRecycleBinNode(const QSharedPointer &p_root); - // Generate node attachment folder. - // @p_folderName: suggested folder name if not empty, may be renamed due to conflicts. - // Return the attachment folder path. - QString fetchNodeAttachmentFolder(const QString &p_nodePath, QString &p_folderName); + // Generate node attachment folder. + // @p_folderName: suggested folder name if not empty, may be renamed due to conflicts. + // Return the attachment folder path. + QString fetchNodeAttachmentFolder(const QString &p_nodePath, QString &p_folderName); - void inheritNodeFlags(const Node *p_node, Node *p_child) const; + void inheritNodeFlags(const Node *p_node, Node *p_child) const; - bool isExcludedFromExternalNode(const QString &p_name) const; + bool isExcludedFromExternalNode(const QString &p_name) const; - void removeNode(const QSharedPointer &p_node, - bool p_force, - bool p_configOnly, - bool p_updateDatabase); + void removeNode(const QSharedPointer &p_node, bool p_force, bool p_configOnly, + bool p_updateDatabase); - NotebookDatabaseAccess *getDatabaseAccess() const; + NotebookDatabaseAccess *getDatabaseAccess() const; - void updateNodeInDatabase(Node *p_node); + void updateNodeInDatabase(Node *p_node); - void ensureNodeInDatabase(Node *p_node); + void ensureNodeInDatabase(Node *p_node); - void addNodeToDatabase(Node *p_node); + void addNodeToDatabase(Node *p_node); - bool nodeExistsInDatabase(const Node *p_node); + bool nodeExistsInDatabase(const Node *p_node); - void removeNodeFromDatabase(const Node *p_node); + void removeNodeFromDatabase(const Node *p_node); - bool sameNotebook(const Node *p_node) const; + bool sameNotebook(const Node *p_node) const; - void removeFolderNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder); + void removeFolderNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder); - void removeFileNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder); + void removeFileNodeToFolder(const QSharedPointer &p_node, const QString &p_destFolder); - void copyFilesOfFileNode(const QSharedPointer &p_node, - const QString &p_destFolder, - QString &p_destFilePath, - QString &p_attachmentFolder); + void copyFilesOfFileNode(const QSharedPointer &p_node, const QString &p_destFolder, + QString &p_destFilePath, QString &p_attachmentFolder); - static bool isLikelyImageFolder(const QString &p_dirPath); + static bool isLikelyImageFolder(const QString &p_dirPath); - static bool s_initialized; + static bool s_initialized; - static QVector s_externalNodeExcludePatterns; + static QVector s_externalNodeExcludePatterns; - // Name of the node's config file. - static const QString c_nodeConfigName; - }; -} // ns vnotex + // Name of the node's config file. + static const QString c_nodeConfigName; +}; +} // namespace vnotex #endif // VXNOTEBOOKCONFIGMGR_H diff --git a/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.cpp b/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.cpp index de9c781bb3..1e77cc9718 100644 --- a/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.cpp +++ b/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.cpp @@ -2,37 +2,28 @@ #include -#include "vxnotebookconfigmgr.h" #include "../notebookbackend/inotebookbackend.h" +#include "vxnotebookconfigmgr.h" using namespace vnotex; const QString VXNotebookConfigMgrFactory::c_name = QStringLiteral("vx.vnotex"); -const QString VXNotebookConfigMgrFactory::c_displayName = QObject::tr("VNoteX Notebook Configuration"); +const QString VXNotebookConfigMgrFactory::c_displayName = + QObject::tr("VNoteX Notebook Configuration"); -const QString VXNotebookConfigMgrFactory::c_description = QObject::tr("Built-in VNoteX notebook configuration"); +const QString VXNotebookConfigMgrFactory::c_description = + QObject::tr("Built-in VNoteX notebook configuration"); -VXNotebookConfigMgrFactory::VXNotebookConfigMgrFactory() -{ -} +VXNotebookConfigMgrFactory::VXNotebookConfigMgrFactory() {} -QString VXNotebookConfigMgrFactory::getName() const -{ - return c_name; -} +QString VXNotebookConfigMgrFactory::getName() const { return c_name; } -QString VXNotebookConfigMgrFactory::getDisplayName() const -{ - return c_displayName; -} +QString VXNotebookConfigMgrFactory::getDisplayName() const { return c_displayName; } -QString VXNotebookConfigMgrFactory::getDescription() const -{ - return c_description; -} +QString VXNotebookConfigMgrFactory::getDescription() const { return c_description; } -QSharedPointer VXNotebookConfigMgrFactory::createNotebookConfigMgr(const QSharedPointer &p_backend) -{ - return QSharedPointer::create(p_backend); +QSharedPointer VXNotebookConfigMgrFactory::createNotebookConfigMgr( + const QSharedPointer &p_backend) { + return QSharedPointer::create(p_backend); } diff --git a/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.h b/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.h index 02f67b5738..bfebb77314 100644 --- a/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.h +++ b/src/core/notebookconfigmgr/vxnotebookconfigmgrfactory.h @@ -1,31 +1,28 @@ #ifndef VXNOTEBOOKCONFIGMGRFACTORY_H #define VXNOTEBOOKCONFIGMGRFACTORY_H - #include "inotebookconfigmgrfactory.h" +namespace vnotex { +class VXNotebookConfigMgrFactory : public INotebookConfigMgrFactory { +public: + VXNotebookConfigMgrFactory(); -namespace vnotex -{ - class VXNotebookConfigMgrFactory : public INotebookConfigMgrFactory - { - public: - VXNotebookConfigMgrFactory(); - - QString getName() const Q_DECL_OVERRIDE; + QString getName() const Q_DECL_OVERRIDE; - QString getDisplayName() const Q_DECL_OVERRIDE; + QString getDisplayName() const Q_DECL_OVERRIDE; - QString getDescription()const Q_DECL_OVERRIDE; + QString getDescription() const Q_DECL_OVERRIDE; - QSharedPointer createNotebookConfigMgr(const QSharedPointer &p_backend) Q_DECL_OVERRIDE; + QSharedPointer + createNotebookConfigMgr(const QSharedPointer &p_backend) Q_DECL_OVERRIDE; - static const QString c_name; + static const QString c_name; - static const QString c_displayName; + static const QString c_displayName; - static const QString c_description; - }; -} // ns vnotex + static const QString c_description; +}; +} // namespace vnotex #endif // VXNOTEBOOKCONFIGMGRFACTORY_H diff --git a/src/core/notebookmgr.cpp b/src/core/notebookmgr.cpp index 258e6422e7..bc35ea8eaf 100644 --- a/src/core/notebookmgr.cpp +++ b/src/core/notebookmgr.cpp @@ -1,413 +1,370 @@ #include "notebookmgr.h" -#include -#include -#include -#include -#include -#include +#include "configmgr.h" +#include "exception.h" #include #include #include -#include "exception.h" -#include "configmgr.h" +#include +#include +#include +#include #include +#include +#include using namespace vnotex; NotebookMgr::NotebookMgr(QObject *p_parent) - : QObject(p_parent), - m_currentNotebookId(Notebook::InvalidId) -{ -} + : QObject(p_parent), m_currentNotebookId(Notebook::InvalidId) {} -void NotebookMgr::close() -{ - m_notebooks.clear(); - m_currentNotebookId = -1; +void NotebookMgr::close() { + m_notebooks.clear(); + m_currentNotebookId = -1; } -void NotebookMgr::init() -{ - initVersionControllerServer(); +void NotebookMgr::init() { + initVersionControllerServer(); - initConfigMgrServer(); + initConfigMgrServer(); - initBackendServer(); + initBackendServer(); - initNotebookServer(); + initNotebookServer(); } -void NotebookMgr::initVersionControllerServer() -{ - m_versionControllerServer.reset(new NameBasedServer); +void NotebookMgr::initVersionControllerServer() { + m_versionControllerServer.reset(new NameBasedServer); - // Dummy Version Controller. - auto dummyFactory = QSharedPointer::create(); - m_versionControllerServer->registerItem(dummyFactory->getName(), dummyFactory); + // Dummy Version Controller. + auto dummyFactory = QSharedPointer::create(); + m_versionControllerServer->registerItem(dummyFactory->getName(), dummyFactory); } -void NotebookMgr::initConfigMgrServer() -{ - m_configMgrServer.reset(new NameBasedServer); - - // VX Notebook Config Manager. - auto vxFactory = QSharedPointer::create(); - m_configMgrServer->registerItem(vxFactory->getName(), vxFactory); +void NotebookMgr::initConfigMgrServer() { + m_configMgrServer.reset(new NameBasedServer); + // VX Notebook Config Manager. + auto vxFactory = QSharedPointer::create(); + m_configMgrServer->registerItem(vxFactory->getName(), vxFactory); } -void NotebookMgr::initBackendServer() -{ - m_backendServer.reset(new NameBasedServer); +void NotebookMgr::initBackendServer() { + m_backendServer.reset(new NameBasedServer); - // Local Notebook Backend. - auto localFactory = QSharedPointer::create(); - m_backendServer->registerItem(localFactory->getName(), localFactory); + // Local Notebook Backend. + auto localFactory = QSharedPointer::create(); + m_backendServer->registerItem(localFactory->getName(), localFactory); } -void NotebookMgr::initNotebookServer() -{ - m_notebookServer.reset(new NameBasedServer); +void NotebookMgr::initNotebookServer() { + m_notebookServer.reset(new NameBasedServer); - // Bundle Notebook. - auto bundleFacotry = QSharedPointer::create(); - m_notebookServer->registerItem(bundleFacotry->getName(), bundleFacotry); + // Bundle Notebook. + auto bundleFacotry = QSharedPointer::create(); + m_notebookServer->registerItem(bundleFacotry->getName(), bundleFacotry); } -QSharedPointer NotebookMgr::getBundleNotebookFactory() const -{ - return m_notebookServer->getItem(QStringLiteral("bundle.vnotex")); +QSharedPointer NotebookMgr::getBundleNotebookFactory() const { + return m_notebookServer->getItem(QStringLiteral("bundle.vnotex")); } -QList> NotebookMgr::getAllNotebookFactories() const -{ - return m_notebookServer->getAllItems(); +QList> NotebookMgr::getAllNotebookFactories() const { + return m_notebookServer->getAllItems(); } -QList> NotebookMgr::getAllVersionControllerFactories() const -{ - return m_versionControllerServer->getAllItems(); +QList> +NotebookMgr::getAllVersionControllerFactories() const { + return m_versionControllerServer->getAllItems(); } -QList> NotebookMgr::getAllNotebookConfigMgrFactories() const -{ - return m_configMgrServer->getAllItems(); +QList> +NotebookMgr::getAllNotebookConfigMgrFactories() const { + return m_configMgrServer->getAllItems(); } -QList> NotebookMgr::getAllNotebookBackendFactories() const -{ - return m_backendServer->getAllItems(); +QList> NotebookMgr::getAllNotebookBackendFactories() const { + return m_backendServer->getAllItems(); } -QSharedPointer NotebookMgr::createNotebookBackend(const QString &p_backendName, - const QString &p_rootFolderPath) const -{ - auto factory = m_backendServer->getItem(p_backendName); - if (factory) { - return factory->createNotebookBackend(p_rootFolderPath); - } else { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to find notebook backend factory %1").arg(p_backendName)); - } +QSharedPointer +NotebookMgr::createNotebookBackend(const QString &p_backendName, + const QString &p_rootFolderPath) const { + auto factory = m_backendServer->getItem(p_backendName); + if (factory) { + return factory->createNotebookBackend(p_rootFolderPath); + } else { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("failed to find notebook backend factory %1").arg(p_backendName)); + } - return nullptr; + return nullptr; } -QSharedPointer NotebookMgr::createVersionController(const QString &p_controllerName) const -{ - auto factory = m_versionControllerServer->getItem(p_controllerName); - if (factory) { - return factory->createVersionController(); - } else { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to find version controller factory %1").arg(p_controllerName)); - } +QSharedPointer +NotebookMgr::createVersionController(const QString &p_controllerName) const { + auto factory = m_versionControllerServer->getItem(p_controllerName); + if (factory) { + return factory->createVersionController(); + } else { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("failed to find version controller factory %1").arg(p_controllerName)); + } - return nullptr; + return nullptr; } -QSharedPointer NotebookMgr::createNotebookConfigMgr(const QString &p_mgrName, - const QSharedPointer &p_backend) const -{ - auto factory = m_configMgrServer->getItem(p_mgrName); - if (factory) { - return factory->createNotebookConfigMgr(p_backend); - } else { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to find notebook config manager factory %1").arg(p_mgrName)); - } +QSharedPointer +NotebookMgr::createNotebookConfigMgr(const QString &p_mgrName, + const QSharedPointer &p_backend) const { + auto factory = m_configMgrServer->getItem(p_mgrName); + if (factory) { + return factory->createNotebookConfigMgr(p_backend); + } else { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("failed to find notebook config manager factory %1").arg(p_mgrName)); + } - return nullptr; + return nullptr; } -void NotebookMgr::loadNotebooks() -{ - readNotebooksFromConfig(); +void NotebookMgr::loadNotebooks() { + readNotebooksFromConfig(); - loadCurrentNotebookId(); + loadCurrentNotebookId(); } -static SessionConfig &getSessionConfig() -{ - return ConfigMgr::getInst().getSessionConfig(); -} +static SessionConfig &getSessionConfig() { return ConfigMgr::getInst().getSessionConfig(); } -void NotebookMgr::loadCurrentNotebookId() -{ - auto &rootFolderPath = getSessionConfig().getCurrentNotebookRootFolderPath(); - auto notebook = findNotebookByRootFolderPath(rootFolderPath); - if (notebook) { - m_currentNotebookId = notebook->getId(); - } else { - m_currentNotebookId = Notebook::InvalidId; - } +void NotebookMgr::loadCurrentNotebookId() { + auto &rootFolderPath = getSessionConfig().getCurrentNotebookRootFolderPath(); + auto notebook = findNotebookByRootFolderPath(rootFolderPath); + if (notebook) { + m_currentNotebookId = notebook->getId(); + } else { + m_currentNotebookId = Notebook::InvalidId; + } - emit currentNotebookChanged(notebook); + emit currentNotebookChanged(notebook); } -QSharedPointer NotebookMgr::newNotebook(const QSharedPointer &p_parameters) -{ - auto factory = m_notebookServer->getItem(p_parameters->m_type); - if (!factory) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to find notebook factory %1").arg(p_parameters->m_type)); - } +QSharedPointer +NotebookMgr::newNotebook(const QSharedPointer &p_parameters) { + auto factory = m_notebookServer->getItem(p_parameters->m_type); + if (!factory) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("failed to find notebook factory %1").arg(p_parameters->m_type)); + } - auto notebook = factory->newNotebook(*p_parameters); - addNotebook(notebook); + auto notebook = factory->newNotebook(*p_parameters); + addNotebook(notebook); - saveNotebooksToConfig(); + saveNotebooksToConfig(); - emit notebooksUpdated(); + emit notebooksUpdated(); - setCurrentNotebook(notebook->getId()); + setCurrentNotebook(notebook->getId()); - return notebook; + return notebook; } -void NotebookMgr::importNotebook(const QSharedPointer &p_notebook) -{ - Q_ASSERT(p_notebook); - if (m_notebooks.indexOf(p_notebook) != -1) { - return; - } +void NotebookMgr::importNotebook(const QSharedPointer &p_notebook) { + Q_ASSERT(p_notebook); + if (m_notebooks.indexOf(p_notebook) != -1) { + return; + } - addNotebook(p_notebook); + addNotebook(p_notebook); - saveNotebooksToConfig(); + saveNotebooksToConfig(); - emit notebooksUpdated(); + emit notebooksUpdated(); - setCurrentNotebook(p_notebook->getId()); + setCurrentNotebook(p_notebook->getId()); } -static SessionConfig::NotebookItem notebookToSessionConfig(const QSharedPointer &p_notebook) -{ - SessionConfig::NotebookItem item; - item.m_type = p_notebook->getType(); - item.m_rootFolderPath = p_notebook->getRootFolderPath(); - item.m_backend = p_notebook->getBackend()->getName(); - return item; +static SessionConfig::NotebookItem +notebookToSessionConfig(const QSharedPointer &p_notebook) { + SessionConfig::NotebookItem item; + item.m_type = p_notebook->getType(); + item.m_rootFolderPath = p_notebook->getRootFolderPath(); + item.m_backend = p_notebook->getBackend()->getName(); + return item; } -void NotebookMgr::saveNotebooksToConfig() const -{ - QVector items; - items.reserve(m_notebooks.size()); - for (auto &nb : m_notebooks) { - items.push_back(notebookToSessionConfig(nb)); - } +void NotebookMgr::saveNotebooksToConfig() const { + QVector items; + items.reserve(m_notebooks.size()); + for (auto &nb : m_notebooks) { + items.push_back(notebookToSessionConfig(nb)); + } + + getSessionConfig().setNotebooks(items); +} - getSessionConfig().setNotebooks(items); -} - -void NotebookMgr::readNotebooksFromConfig() -{ - Q_ASSERT(m_notebooks.isEmpty()); - auto items = getSessionConfig().getNotebooks(); - for (auto &item : items) { - try { - auto nb = readNotebookFromConfig(item); - addNotebook(nb); - } catch (Exception &p_e) { - qCritical("failed to read notebook (%s) from config (%s)", - item.m_rootFolderPath.toStdString().c_str(), - p_e.what()); - m_notebooksFailedToLoad.push_back(item.m_rootFolderPath); - } +void NotebookMgr::readNotebooksFromConfig() { + Q_ASSERT(m_notebooks.isEmpty()); + auto items = getSessionConfig().getNotebooks(); + for (auto &item : items) { + try { + auto nb = readNotebookFromConfig(item); + addNotebook(nb); + } catch (Exception &p_e) { + qCritical("failed to read notebook (%s) from config (%s)", + item.m_rootFolderPath.toStdString().c_str(), p_e.what()); + m_notebooksFailedToLoad.push_back(item.m_rootFolderPath); } + } - emit notebooksUpdated(); + emit notebooksUpdated(); } -QSharedPointer NotebookMgr::readNotebookFromConfig(const SessionConfig::NotebookItem &p_item) -{ - auto factory = m_notebookServer->getItem(p_item.m_type); - if (!factory) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("failed to find notebook factory %1").arg(p_item.m_type)); - } +QSharedPointer +NotebookMgr::readNotebookFromConfig(const SessionConfig::NotebookItem &p_item) { + auto factory = m_notebookServer->getItem(p_item.m_type); + if (!factory) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("failed to find notebook factory %1").arg(p_item.m_type)); + } - auto backend = createNotebookBackend(p_item.m_backend, p_item.m_rootFolderPath); + auto backend = createNotebookBackend(p_item.m_backend, p_item.m_rootFolderPath); - auto notebook = factory->createNotebook(*this, p_item.m_rootFolderPath, backend); - return notebook; + auto notebook = factory->createNotebook(*this, p_item.m_rootFolderPath, backend); + return notebook; } -const QVector> &NotebookMgr::getNotebooks() const -{ - return m_notebooks; -} +const QVector> &NotebookMgr::getNotebooks() const { return m_notebooks; } -ID NotebookMgr::getCurrentNotebookId() const -{ - return m_currentNotebookId; -} +ID NotebookMgr::getCurrentNotebookId() const { return m_currentNotebookId; } -QSharedPointer NotebookMgr::getCurrentNotebook() const -{ - return findNotebookById(m_currentNotebookId); +QSharedPointer NotebookMgr::getCurrentNotebook() const { + return findNotebookById(m_currentNotebookId); } -void NotebookMgr::setCurrentNotebook(ID p_notebookId) -{ - auto lastId = m_currentNotebookId; - m_currentNotebookId = p_notebookId; - auto nb = findNotebookById(p_notebookId); - if (!nb) { - m_currentNotebookId = Notebook::InvalidId; - } +void NotebookMgr::setCurrentNotebook(ID p_notebookId) { + auto lastId = m_currentNotebookId; + m_currentNotebookId = p_notebookId; + auto nb = findNotebookById(p_notebookId); + if (!nb) { + m_currentNotebookId = Notebook::InvalidId; + } - if (lastId != m_currentNotebookId) { - emit currentNotebookChanged(nb); - } + if (lastId != m_currentNotebookId) { + emit currentNotebookChanged(nb); + } - getSessionConfig().setCurrentNotebookRootFolderPath(nb ? nb->getRootFolderPath() : ""); + getSessionConfig().setCurrentNotebookRootFolderPath(nb ? nb->getRootFolderPath() : ""); } -QSharedPointer NotebookMgr::findNotebookByRootFolderPath(const QString &p_rootFolderPath) const -{ - for (auto &nb : m_notebooks) { - if (PathUtils::areSamePaths(nb->getRootFolderPath(), p_rootFolderPath)) { - return nb; - } +QSharedPointer +NotebookMgr::findNotebookByRootFolderPath(const QString &p_rootFolderPath) const { + for (auto &nb : m_notebooks) { + if (PathUtils::areSamePaths(nb->getRootFolderPath(), p_rootFolderPath)) { + return nb; } + } - return nullptr; + return nullptr; } -QSharedPointer NotebookMgr::findNotebookById(ID p_id) const -{ - for (auto &nb : m_notebooks) { - if (nb->getId() == p_id) { - return nb; - } +QSharedPointer NotebookMgr::findNotebookById(ID p_id) const { + for (auto &nb : m_notebooks) { + if (nb->getId() == p_id) { + return nb; } + } - return nullptr; + return nullptr; } -void NotebookMgr::closeNotebook(ID p_id) -{ - auto it = std::find_if(m_notebooks.begin(), - m_notebooks.end(), - [p_id](const QSharedPointer &p_nb) { - return p_nb->getId() == p_id; - }); - if (it == m_notebooks.end()) { - qWarning() << "failed to find notebook of given id to close" << p_id; - return; - } +void NotebookMgr::closeNotebook(ID p_id) { + auto it = + std::find_if(m_notebooks.begin(), m_notebooks.end(), + [p_id](const QSharedPointer &p_nb) { return p_nb->getId() == p_id; }); + if (it == m_notebooks.end()) { + qWarning() << "failed to find notebook of given id to close" << p_id; + return; + } - auto notebookToClose = *it; - emit notebookAboutToClose(notebookToClose.data()); + auto notebookToClose = *it; + emit notebookAboutToClose(notebookToClose.data()); - m_notebooks.erase(it); + m_notebooks.erase(it); - saveNotebooksToConfig(); + saveNotebooksToConfig(); - emit notebooksUpdated(); - setCurrentNotebookAfterUpdate(); + emit notebooksUpdated(); + setCurrentNotebookAfterUpdate(); - qInfo() << QStringLiteral("notebook %1 (%2) is closed").arg(notebookToClose->getName(), - notebookToClose->getRootFolderPath()); + qInfo() << QStringLiteral("notebook %1 (%2) is closed") + .arg(notebookToClose->getName(), notebookToClose->getRootFolderPath()); } -void NotebookMgr::removeNotebook(ID p_id) -{ - auto it = std::find_if(m_notebooks.begin(), - m_notebooks.end(), - [p_id](const QSharedPointer &p_nb) { - return p_nb->getId() == p_id; - }); - if (it == m_notebooks.end()) { - qWarning() << "failed to find notebook of given id to remove" << p_id; - return; - } +void NotebookMgr::removeNotebook(ID p_id) { + auto it = + std::find_if(m_notebooks.begin(), m_notebooks.end(), + [p_id](const QSharedPointer &p_nb) { return p_nb->getId() == p_id; }); + if (it == m_notebooks.end()) { + qWarning() << "failed to find notebook of given id to remove" << p_id; + return; + } - auto nbToRemove = *it; - emit notebookAboutToRemove(nbToRemove.data()); + auto nbToRemove = *it; + emit notebookAboutToRemove(nbToRemove.data()); - m_notebooks.erase(it); + m_notebooks.erase(it); - saveNotebooksToConfig(); + saveNotebooksToConfig(); - emit notebooksUpdated(); - setCurrentNotebookAfterUpdate(); + emit notebooksUpdated(); + setCurrentNotebookAfterUpdate(); - try { - nbToRemove->remove(); - } catch (Exception &p_e) { - qWarning() << QStringLiteral("failed to remove notebook %1 (%2) (%3)").arg(nbToRemove->getName(), - nbToRemove->getRootFolderPath(), - p_e.what()); - throw; - } + try { + nbToRemove->remove(); + } catch (Exception &p_e) { + qWarning() << QStringLiteral("failed to remove notebook %1 (%2) (%3)") + .arg(nbToRemove->getName(), nbToRemove->getRootFolderPath(), p_e.what()); + throw; + } - qInfo() << QStringLiteral("notebook %1 (%2) is removed").arg(nbToRemove->getName(), - nbToRemove->getRootFolderPath()); + qInfo() << QStringLiteral("notebook %1 (%2) is removed") + .arg(nbToRemove->getName(), nbToRemove->getRootFolderPath()); } -void NotebookMgr::setCurrentNotebookAfterUpdate() -{ - if (!m_notebooks.isEmpty()) { - setCurrentNotebook(m_notebooks.first()->getId()); - } else { - setCurrentNotebook(Notebook::InvalidId); - } +void NotebookMgr::setCurrentNotebookAfterUpdate() { + if (!m_notebooks.isEmpty()) { + setCurrentNotebook(m_notebooks.first()->getId()); + } else { + setCurrentNotebook(Notebook::InvalidId); + } } -void NotebookMgr::addNotebook(const QSharedPointer &p_notebook) -{ - p_notebook->initialize(); - m_notebooks.push_back(p_notebook); - auto notebook = p_notebook.data(); - connect(p_notebook.data(), &Notebook::updated, - this, [this, notebook]() { - emit notebookUpdated(notebook); - }); -} - -QSharedPointer NotebookMgr::loadNodeByPath(const QString &p_path) -{ - for (const auto &nb : m_notebooks) { - auto node = nb->loadNodeByPath(p_path); - if (node) { - return node; - } +void NotebookMgr::addNotebook(const QSharedPointer &p_notebook) { + p_notebook->initialize(); + m_notebooks.push_back(p_notebook); + auto notebook = p_notebook.data(); + connect(p_notebook.data(), &Notebook::updated, this, + [this, notebook]() { emit notebookUpdated(notebook); }); +} + +QSharedPointer NotebookMgr::loadNodeByPath(const QString &p_path) { + for (const auto &nb : m_notebooks) { + auto node = nb->loadNodeByPath(p_path); + if (node) { + return node; } + } - return nullptr; + return nullptr; } -const QStringList &NotebookMgr::getNotebooksFailedToLoad() const -{ - return m_notebooksFailedToLoad; -} +const QStringList &NotebookMgr::getNotebooksFailedToLoad() const { return m_notebooksFailedToLoad; } -void NotebookMgr::clearNotebooksFailedToLoad() -{ - m_notebooksFailedToLoad.clear(); - saveNotebooksToConfig(); +void NotebookMgr::clearNotebooksFailedToLoad() { + m_notebooksFailedToLoad.clear(); + saveNotebooksToConfig(); } diff --git a/src/core/notebookmgr.h b/src/core/notebookmgr.h index 667d6018ec..1f1a19a032 100644 --- a/src/core/notebookmgr.h +++ b/src/core/notebookmgr.h @@ -1,133 +1,132 @@ #ifndef NOTEBOOKMGR_H #define NOTEBOOKMGR_H +#include #include #include -#include #include -#include "namebasedserver.h" -#include "sessionconfig.h" #include "global.h" -#include "notebook/notebook.h" +#include "namebasedserver.h" #include "noncopyable.h" +#include "notebook/notebook.h" +#include "sessionconfig.h" -namespace vnotex -{ - class IVersionController; - class IVersionControllerFactory; - class INotebookConfigMgr; - class INotebookConfigMgrFactory; - class INotebookBackend; - class INotebookBackendFactory; - class INotebookFactory; - class NotebookParameters; - class Node; +namespace vnotex { +class IVersionController; +class IVersionControllerFactory; +class INotebookConfigMgr; +class INotebookConfigMgrFactory; +class INotebookBackend; +class INotebookBackendFactory; +class INotebookFactory; +class NotebookParameters; +class Node; - class NotebookMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - explicit NotebookMgr(QObject *p_parent = nullptr); +class NotebookMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + explicit NotebookMgr(QObject *p_parent = nullptr); - void init(); + void init(); - void close(); + void close(); - QSharedPointer getBundleNotebookFactory() const; + QSharedPointer getBundleNotebookFactory() const; - QList> getAllNotebookFactories() const; + QList> getAllNotebookFactories() const; - QList> getAllVersionControllerFactories() const; + QList> getAllVersionControllerFactories() const; - QList> getAllNotebookConfigMgrFactories() const; + QList> getAllNotebookConfigMgrFactories() const; - QList> getAllNotebookBackendFactories() const; + QList> getAllNotebookBackendFactories() const; - QSharedPointer createNotebookBackend(const QString &p_backendName, - const QString &p_rootFolderPath) const; + QSharedPointer createNotebookBackend(const QString &p_backendName, + const QString &p_rootFolderPath) const; - QSharedPointer createVersionController(const QString &p_controllerName) const; + QSharedPointer createVersionController(const QString &p_controllerName) const; - QSharedPointer createNotebookConfigMgr(const QString &p_mgrName, - const QSharedPointer &p_backend) const; + QSharedPointer + createNotebookConfigMgr(const QString &p_mgrName, + const QSharedPointer &p_backend) const; - void loadNotebooks(); + void loadNotebooks(); - QSharedPointer newNotebook(const QSharedPointer &p_parameters); + QSharedPointer newNotebook(const QSharedPointer &p_parameters); - void importNotebook(const QSharedPointer &p_notebook); + void importNotebook(const QSharedPointer &p_notebook); - const QVector> &getNotebooks() const; + const QVector> &getNotebooks() const; - ID getCurrentNotebookId() const; + ID getCurrentNotebookId() const; - QSharedPointer getCurrentNotebook() const; + QSharedPointer getCurrentNotebook() const; - // Find the notebook with the same directory as root folder. - QSharedPointer findNotebookByRootFolderPath(const QString &p_rootFolderPath) const; + // Find the notebook with the same directory as root folder. + QSharedPointer findNotebookByRootFolderPath(const QString &p_rootFolderPath) const; - QSharedPointer findNotebookById(ID p_id) const; + QSharedPointer findNotebookById(ID p_id) const; - void closeNotebook(ID p_id); + void closeNotebook(ID p_id); - void removeNotebook(ID p_id); + void removeNotebook(ID p_id); - // Try to load @p_path as a node if it is within one notebook. - QSharedPointer loadNodeByPath(const QString &p_path); + // Try to load @p_path as a node if it is within one notebook. + QSharedPointer loadNodeByPath(const QString &p_path); - const QStringList &getNotebooksFailedToLoad() const; + const QStringList &getNotebooksFailedToLoad() const; - void clearNotebooksFailedToLoad(); + void clearNotebooksFailedToLoad(); - public slots: - void setCurrentNotebook(ID p_notebookId); +public slots: + void setCurrentNotebook(ID p_notebookId); - signals: - void notebooksUpdated(); +signals: + void notebooksUpdated(); - void notebookUpdated(const Notebook *p_notebook); + void notebookUpdated(const Notebook *p_notebook); - void notebookAboutToClose(const Notebook *p_notebook); + void notebookAboutToClose(const Notebook *p_notebook); - void notebookAboutToRemove(const Notebook *p_notebook); + void notebookAboutToRemove(const Notebook *p_notebook); - void currentNotebookChanged(const QSharedPointer &p_notebook); + void currentNotebookChanged(const QSharedPointer &p_notebook); - private: - void initVersionControllerServer(); +private: + void initVersionControllerServer(); - void initConfigMgrServer(); + void initConfigMgrServer(); - void initBackendServer(); + void initBackendServer(); - void initNotebookServer(); + void initNotebookServer(); - void saveNotebooksToConfig() const; - void readNotebooksFromConfig(); + void saveNotebooksToConfig() const; + void readNotebooksFromConfig(); - void loadCurrentNotebookId(); + void loadCurrentNotebookId(); - QSharedPointer readNotebookFromConfig(const SessionConfig::NotebookItem &p_item); + QSharedPointer readNotebookFromConfig(const SessionConfig::NotebookItem &p_item); - void setCurrentNotebookAfterUpdate(); + void setCurrentNotebookAfterUpdate(); - void addNotebook(const QSharedPointer &p_notebook); + void addNotebook(const QSharedPointer &p_notebook); - QScopedPointer> m_versionControllerServer; + QScopedPointer> m_versionControllerServer; - QScopedPointer> m_configMgrServer; + QScopedPointer> m_configMgrServer; - QScopedPointer> m_backendServer; + QScopedPointer> m_backendServer; - QScopedPointer> m_notebookServer; + QScopedPointer> m_notebookServer; - QVector> m_notebooks; + QVector> m_notebooks; - ID m_currentNotebookId = 0; + ID m_currentNotebookId = 0; - QStringList m_notebooksFailedToLoad; - }; -} // ns vnotex + QStringList m_notebooksFailedToLoad; +}; +} // namespace vnotex #endif // NOTEBOOKMGR_H diff --git a/src/core/pdfviewerconfig.cpp b/src/core/pdfviewerconfig.cpp index 4b16e48a16..5d1731dc72 100644 --- a/src/core/pdfviewerconfig.cpp +++ b/src/core/pdfviewerconfig.cpp @@ -9,53 +9,42 @@ using namespace vnotex; PdfViewerConfig::PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig) -{ - m_sessionName = QStringLiteral("pdf_viewer"); + : IConfig(p_mgr, p_topConfig) { + m_sessionName = QStringLiteral("pdf_viewer"); } -void PdfViewerConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void PdfViewerConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - loadViewerResource(appObj, userObj); + loadViewerResource(appObj, userObj); } -QJsonObject PdfViewerConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("viewer_resource")] = saveViewerResource(); - return obj; +QJsonObject PdfViewerConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("viewer_resource")] = saveViewerResource(); + return obj; } -void PdfViewerConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user) -{ - const QString name(QStringLiteral("viewer_resource")); - - if (MainConfig::isVersionChanged()) { - bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); - if (needOverride) { - qInfo() << "override \"viewer_resource\" in user configuration due to version change"; - m_viewerResource.init(p_app[name].toObject()); - return; - } - } +void PdfViewerConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user) { + const QString name(QStringLiteral("viewer_resource")); - if (p_user.contains(name)) { - m_viewerResource.init(p_user[name].toObject()); - } else { - m_viewerResource.init(p_app[name].toObject()); + if (MainConfig::isVersionChanged()) { + bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool(); + if (needOverride) { + qInfo() << "override \"viewer_resource\" in user configuration due to version change"; + m_viewerResource.init(p_app[name].toObject()); + return; } -} + } -QJsonObject PdfViewerConfig::saveViewerResource() const -{ - return m_viewerResource.toJson(); + if (p_user.contains(name)) { + m_viewerResource.init(p_user[name].toObject()); + } else { + m_viewerResource.init(p_app[name].toObject()); + } } -const WebResource &PdfViewerConfig::getViewerResource() const -{ - return m_viewerResource; -} +QJsonObject PdfViewerConfig::saveViewerResource() const { return m_viewerResource.toJson(); } + +const WebResource &PdfViewerConfig::getViewerResource() const { return m_viewerResource; } diff --git a/src/core/pdfviewerconfig.h b/src/core/pdfviewerconfig.h index 6f67d9d087..5d00bd64f0 100644 --- a/src/core/pdfviewerconfig.h +++ b/src/core/pdfviewerconfig.h @@ -5,27 +5,25 @@ #include "webresource.h" -namespace vnotex -{ - class PdfViewerConfig : public IConfig - { - public: - PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); +namespace vnotex { +class PdfViewerConfig : public IConfig { +public: + PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - const WebResource &getViewerResource() const; + const WebResource &getViewerResource() const; - private: - friend class MainConfig; +private: + friend class MainConfig; - void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user); - QJsonObject saveViewerResource() const; + void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user); + QJsonObject saveViewerResource() const; - WebResource m_viewerResource; - }; -} + WebResource m_viewerResource; +}; +} // namespace vnotex #endif // PDFVIEWERCONFIG_H diff --git a/src/core/quickaccesshelper.cpp b/src/core/quickaccesshelper.cpp index c6cc2f7909..72255da956 100644 --- a/src/core/quickaccesshelper.cpp +++ b/src/core/quickaccesshelper.cpp @@ -5,16 +5,15 @@ using namespace vnotex; -void QuickAccessHelper::pinToQuickAccess(const QStringList &p_files) -{ - if (p_files.isEmpty()) { - return; - } +void QuickAccessHelper::pinToQuickAccess(const QStringList &p_files) { + if (p_files.isEmpty()) { + return; + } - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - sessionConfig.tryCorrectQuickAccessFiles(); - auto qaFiles = sessionConfig.getQuickAccessFiles(); - qaFiles.append(p_files); - qaFiles.removeDuplicates(); - sessionConfig.setQuickAccessFiles(qaFiles); + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + sessionConfig.tryCorrectQuickAccessFiles(); + auto qaFiles = sessionConfig.getQuickAccessFiles(); + qaFiles.append(p_files); + qaFiles.removeDuplicates(); + sessionConfig.setQuickAccessFiles(qaFiles); } diff --git a/src/core/quickaccesshelper.h b/src/core/quickaccesshelper.h index 09378562e7..945678aefe 100644 --- a/src/core/quickaccesshelper.h +++ b/src/core/quickaccesshelper.h @@ -3,15 +3,13 @@ #include -namespace vnotex -{ - class QuickAccessHelper - { - public: - QuickAccessHelper() = delete; - - static void pinToQuickAccess(const QStringList &p_files); - }; -} +namespace vnotex { +class QuickAccessHelper { +public: + QuickAccessHelper() = delete; + + static void pinToQuickAccess(const QStringList &p_files); +}; +} // namespace vnotex #endif // QUICKACCESSHELPER_H diff --git a/src/core/sessionconfig.cpp b/src/core/sessionconfig.cpp index e493bffaaa..09f28b7c1f 100644 --- a/src/core/sessionconfig.cpp +++ b/src/core/sessionconfig.cpp @@ -1,685 +1,592 @@ #include "sessionconfig.h" -#include #include +#include #include #include -#include #include +#include #include #include #include #include "configmgr.h" -#include "mainconfig.h" #include "historymgr.h" +#include "mainconfig.h" using namespace vnotex; -bool SessionConfig::NotebookItem::operator==(const NotebookItem &p_other) const -{ - return m_type == p_other.m_type - && m_rootFolderPath == p_other.m_rootFolderPath - && m_backend == p_other.m_backend; +bool SessionConfig::NotebookItem::operator==(const NotebookItem &p_other) const { + return m_type == p_other.m_type && m_rootFolderPath == p_other.m_rootFolderPath && + m_backend == p_other.m_backend; } -void SessionConfig::NotebookItem::fromJson(const QJsonObject &p_jobj) -{ - m_type = p_jobj[QStringLiteral("type")].toString(); - m_rootFolderPath = p_jobj[QStringLiteral("root_folder")].toString(); - m_backend = p_jobj[QStringLiteral("backend")].toString(); +void SessionConfig::NotebookItem::fromJson(const QJsonObject &p_jobj) { + m_type = p_jobj[QStringLiteral("type")].toString(); + m_rootFolderPath = p_jobj[QStringLiteral("root_folder")].toString(); + m_backend = p_jobj[QStringLiteral("backend")].toString(); } -QJsonObject SessionConfig::NotebookItem::toJson() const -{ - QJsonObject jobj; +QJsonObject SessionConfig::NotebookItem::toJson() const { + QJsonObject jobj; - jobj[QStringLiteral("type")] = m_type; - jobj[QStringLiteral("root_folder")] = m_rootFolderPath; - jobj[QStringLiteral("backend")] = m_backend; + jobj[QStringLiteral("type")] = m_type; + jobj[QStringLiteral("root_folder")] = m_rootFolderPath; + jobj[QStringLiteral("backend")] = m_backend; - return jobj; + return jobj; } -bool SessionConfig::QuickNoteScheme::operator==(const QuickNoteScheme &p_other) const -{ - return m_name == p_other.m_name && - m_folderPath == p_other.m_folderPath && - m_noteName == p_other.m_noteName && - m_template == p_other.m_template; +bool SessionConfig::QuickNoteScheme::operator==(const QuickNoteScheme &p_other) const { + return m_name == p_other.m_name && m_folderPath == p_other.m_folderPath && + m_noteName == p_other.m_noteName && m_template == p_other.m_template; } -void SessionConfig::QuickNoteScheme::fromJson(const QJsonObject &p_jobj) -{ - m_name = p_jobj[QStringLiteral("name")].toString(); - m_folderPath = p_jobj[QStringLiteral("folder_path")].toString(); - m_noteName = p_jobj[QStringLiteral("note_name")].toString(); - m_template = p_jobj[QStringLiteral("template")].toString(); +void SessionConfig::QuickNoteScheme::fromJson(const QJsonObject &p_jobj) { + m_name = p_jobj[QStringLiteral("name")].toString(); + m_folderPath = p_jobj[QStringLiteral("folder_path")].toString(); + m_noteName = p_jobj[QStringLiteral("note_name")].toString(); + m_template = p_jobj[QStringLiteral("template")].toString(); } -QJsonObject SessionConfig::QuickNoteScheme::toJson() const -{ - QJsonObject jobj; +QJsonObject SessionConfig::QuickNoteScheme::toJson() const { + QJsonObject jobj; - jobj[QStringLiteral("name")] = m_name; - jobj[QStringLiteral("folder_path")] = m_folderPath; - jobj[QStringLiteral("note_name")] = m_noteName; - jobj[QStringLiteral("template")] = m_template; + jobj[QStringLiteral("name")] = m_name; + jobj[QStringLiteral("folder_path")] = m_folderPath; + jobj[QStringLiteral("note_name")] = m_noteName; + jobj[QStringLiteral("template")] = m_template; - return jobj; + return jobj; } -void SessionConfig::ExternalProgram::fromJson(const QJsonObject &p_jobj) -{ - m_name = p_jobj[QStringLiteral("name")].toString(); - m_command = p_jobj[QStringLiteral("command")].toString(); - m_shortcut = p_jobj[QStringLiteral("shortcut")].toString(); +void SessionConfig::ExternalProgram::fromJson(const QJsonObject &p_jobj) { + m_name = p_jobj[QStringLiteral("name")].toString(); + m_command = p_jobj[QStringLiteral("command")].toString(); + m_shortcut = p_jobj[QStringLiteral("shortcut")].toString(); } -QJsonObject SessionConfig::ExternalProgram::toJson() const -{ - QJsonObject jobj; - - jobj[QStringLiteral("name")] = m_name; - jobj[QStringLiteral("command")] = m_command; - jobj[QStringLiteral("shortcut")] = m_shortcut; +QJsonObject SessionConfig::ExternalProgram::toJson() const { + QJsonObject jobj; - return jobj; -} + jobj[QStringLiteral("name")] = m_name; + jobj[QStringLiteral("command")] = m_command; + jobj[QStringLiteral("shortcut")] = m_shortcut; -QString SessionConfig::ExternalProgram::fetchCommand(const QString &p_file) const -{ - auto command(m_command); - command.replace(QStringLiteral("%1"), QStringLiteral("\"%1\"").arg(p_file)); - return command; + return jobj; } -SessionConfig::SessionConfig(ConfigMgr *p_mgr) - : IConfig(p_mgr, nullptr) -{ +QString SessionConfig::ExternalProgram::fetchCommand(const QString &p_file) const { + auto command(m_command); + command.replace(QStringLiteral("%1"), QStringLiteral("\"%1\"").arg(p_file)); + return command; } -SessionConfig::~SessionConfig() -{ +SessionConfig::SessionConfig(ConfigMgr *p_mgr) : IConfig(p_mgr, nullptr) {} -} +SessionConfig::~SessionConfig() {} -void SessionConfig::init() -{ - auto mgr = getMgr(); - auto sessionSettings = mgr->getSettings(ConfigMgr::Source::Session); - const auto &sessionJobj = sessionSettings->getJson(); +void SessionConfig::init() { + auto mgr = getMgr(); + auto sessionSettings = mgr->getSettings(ConfigMgr::Source::Session); + const auto &sessionJobj = sessionSettings->getJson(); - loadCore(sessionJobj); + loadCore(sessionJobj); - loadStateAndGeometry(sessionJobj); + loadStateAndGeometry(sessionJobj); - loadExportOption(sessionJobj); + loadExportOption(sessionJobj); - m_searchOption.fromJson(sessionJobj[QStringLiteral("search_option")].toObject()); + m_searchOption.fromJson(sessionJobj[QStringLiteral("search_option")].toObject()); - m_viewAreaSession = readByteArray(sessionJobj, QStringLiteral("viewarea_session")); + m_viewAreaSession = readByteArray(sessionJobj, QStringLiteral("viewarea_session")); - m_notebookExplorerSession = readByteArray(sessionJobj, QStringLiteral("notebook_explorer_session")); + m_notebookExplorerSession = + readByteArray(sessionJobj, QStringLiteral("notebook_explorer_session")); - loadExternalPrograms(sessionJobj); + loadExternalPrograms(sessionJobj); - loadNotebooks(sessionJobj); + loadNotebooks(sessionJobj); - loadHistory(sessionJobj); + loadHistory(sessionJobj); - loadQuickNoteSchemes(sessionJobj); + loadQuickNoteSchemes(sessionJobj); - if (MainConfig::isVersionChanged()) { - doVersionSpecificOverride(); - } + if (MainConfig::isVersionChanged()) { + doVersionSpecificOverride(); + } } -void SessionConfig::loadCore(const QJsonObject &p_session) -{ - const auto coreObj = p_session.value(QStringLiteral("core")).toObject(); - m_newNotebookDefaultRootFolderPath = readString(coreObj, - QStringLiteral("new_notebook_default_root_folder_path")); - if (m_newNotebookDefaultRootFolderPath.isEmpty()) { - m_newNotebookDefaultRootFolderPath = QDir::homePath(); - } +void SessionConfig::loadCore(const QJsonObject &p_session) { + const auto coreObj = p_session.value(QStringLiteral("core")).toObject(); + m_newNotebookDefaultRootFolderPath = + readString(coreObj, QStringLiteral("new_notebook_default_root_folder_path")); + if (m_newNotebookDefaultRootFolderPath.isEmpty()) { + m_newNotebookDefaultRootFolderPath = QDir::homePath(); + } - m_currentNotebookRootFolderPath = readString(coreObj, QStringLiteral("current_notebook_root_folder_path")); + m_currentNotebookRootFolderPath = + readString(coreObj, QStringLiteral("current_notebook_root_folder_path")); - { - auto option = readString(coreObj, QStringLiteral("opengl")); - m_openGL = stringToOpenGL(option); - } + { + auto option = readString(coreObj, QStringLiteral("opengl")); + m_openGL = stringToOpenGL(option); + } - if (!isUndefinedKey(coreObj, QStringLiteral("system_title_bar"))) { - m_systemTitleBarEnabled = readBool(coreObj, QStringLiteral("system_title_bar")); - } else { - m_systemTitleBarEnabled = true; - } + if (!isUndefinedKey(coreObj, QStringLiteral("system_title_bar"))) { + m_systemTitleBarEnabled = readBool(coreObj, QStringLiteral("system_title_bar")); + } else { + m_systemTitleBarEnabled = true; + } - if (!isUndefinedKey(coreObj, QStringLiteral("minimize_to_system_tray"))) { - m_minimizeToSystemTray = readBool(coreObj, QStringLiteral("minimize_to_system_tray")) ? 1 : 0; - } + if (!isUndefinedKey(coreObj, QStringLiteral("minimize_to_system_tray"))) { + m_minimizeToSystemTray = readBool(coreObj, QStringLiteral("minimize_to_system_tray")) ? 1 : 0; + } - m_flashPage = readString(coreObj, QStringLiteral("flash_page")); + m_flashPage = readString(coreObj, QStringLiteral("flash_page")); - m_quickAccessFiles = readStringList(coreObj, QStringLiteral("quick_access")); + m_quickAccessFiles = readStringList(coreObj, QStringLiteral("quick_access")); - m_externalMediaDefaultPath = readString(coreObj, QStringLiteral("external_media_default_path")); - if (m_externalMediaDefaultPath.isEmpty()) { - m_externalMediaDefaultPath = QDir::homePath(); - } + m_externalMediaDefaultPath = readString(coreObj, QStringLiteral("external_media_default_path")); + if (m_externalMediaDefaultPath.isEmpty()) { + m_externalMediaDefaultPath = QDir::homePath(); + } } -QJsonObject SessionConfig::saveCore() const -{ - QJsonObject coreObj; - coreObj[QStringLiteral("new_notebook_default_root_folder_path")] = m_newNotebookDefaultRootFolderPath; - coreObj[QStringLiteral("current_notebook_root_folder_path")] = m_currentNotebookRootFolderPath; - coreObj[QStringLiteral("opengl")] = openGLToString(m_openGL); - coreObj[QStringLiteral("system_title_bar")] = m_systemTitleBarEnabled; - if (m_minimizeToSystemTray != -1) { - coreObj[QStringLiteral("minimize_to_system_tray")] = m_minimizeToSystemTray > 0; - } - coreObj[QStringLiteral("flash_page")] = m_flashPage; - writeStringList(coreObj, QStringLiteral("quick_access"), m_quickAccessFiles); - coreObj[QStringLiteral("external_media_default_path")] = m_externalMediaDefaultPath; - return coreObj; +QJsonObject SessionConfig::saveCore() const { + QJsonObject coreObj; + coreObj[QStringLiteral("new_notebook_default_root_folder_path")] = + m_newNotebookDefaultRootFolderPath; + coreObj[QStringLiteral("current_notebook_root_folder_path")] = m_currentNotebookRootFolderPath; + coreObj[QStringLiteral("opengl")] = openGLToString(m_openGL); + coreObj[QStringLiteral("system_title_bar")] = m_systemTitleBarEnabled; + if (m_minimizeToSystemTray != -1) { + coreObj[QStringLiteral("minimize_to_system_tray")] = m_minimizeToSystemTray > 0; + } + coreObj[QStringLiteral("flash_page")] = m_flashPage; + writeStringList(coreObj, QStringLiteral("quick_access"), m_quickAccessFiles); + coreObj[QStringLiteral("external_media_default_path")] = m_externalMediaDefaultPath; + return coreObj; } -const QString &SessionConfig::getNewNotebookDefaultRootFolderPath() const -{ - return m_newNotebookDefaultRootFolderPath; +const QString &SessionConfig::getNewNotebookDefaultRootFolderPath() const { + return m_newNotebookDefaultRootFolderPath; } -void SessionConfig::setNewNotebookDefaultRootFolderPath(const QString &p_path) -{ - updateConfig(m_newNotebookDefaultRootFolderPath, - p_path, - this); +void SessionConfig::setNewNotebookDefaultRootFolderPath(const QString &p_path) { + updateConfig(m_newNotebookDefaultRootFolderPath, p_path, this); } -const QString &SessionConfig::getExternalMediaDefaultPath() const -{ - return m_externalMediaDefaultPath; +const QString &SessionConfig::getExternalMediaDefaultPath() const { + return m_externalMediaDefaultPath; } -void SessionConfig::setExternalMediaDefaultPath(const QString &p_path) -{ - updateConfig(m_externalMediaDefaultPath, p_path, this); +void SessionConfig::setExternalMediaDefaultPath(const QString &p_path) { + updateConfig(m_externalMediaDefaultPath, p_path, this); } -const QVector &SessionConfig::getNotebooks() const -{ - return m_notebooks; +const QVector &SessionConfig::getNotebooks() const { + return m_notebooks; } -void SessionConfig::setNotebooks(const QVector &p_notebooks) -{ - updateConfig(m_notebooks, - p_notebooks, - this); +void SessionConfig::setNotebooks(const QVector &p_notebooks) { + updateConfig(m_notebooks, p_notebooks, this); } -void SessionConfig::loadNotebooks(const QJsonObject &p_session) -{ - const auto notebooksJson = p_session.value(QStringLiteral("notebooks")).toArray(); - m_notebooks.resize(notebooksJson.size()); - for (int i = 0; i < notebooksJson.size(); ++i) { - m_notebooks[i].fromJson(notebooksJson[i].toObject()); - } +void SessionConfig::loadNotebooks(const QJsonObject &p_session) { + const auto notebooksJson = p_session.value(QStringLiteral("notebooks")).toArray(); + m_notebooks.resize(notebooksJson.size()); + for (int i = 0; i < notebooksJson.size(); ++i) { + m_notebooks[i].fromJson(notebooksJson[i].toObject()); + } } -QJsonArray SessionConfig::saveNotebooks() const -{ - QJsonArray nbArray; - for (const auto &nb : m_notebooks) { - nbArray.append(nb.toJson()); - } - return nbArray; +QJsonArray SessionConfig::saveNotebooks() const { + QJsonArray nbArray; + for (const auto &nb : m_notebooks) { + nbArray.append(nb.toJson()); + } + return nbArray; } -const QString &SessionConfig::getCurrentNotebookRootFolderPath() const -{ - return m_currentNotebookRootFolderPath; +const QString &SessionConfig::getCurrentNotebookRootFolderPath() const { + return m_currentNotebookRootFolderPath; } -void SessionConfig::setCurrentNotebookRootFolderPath(const QString &p_path) -{ - updateConfig(m_currentNotebookRootFolderPath, - p_path, - this); +void SessionConfig::setCurrentNotebookRootFolderPath(const QString &p_path) { + updateConfig(m_currentNotebookRootFolderPath, p_path, this); } -void SessionConfig::writeToSettings() const -{ - getMgr()->writeSessionSettings(toJson()); -} +void SessionConfig::writeToSettings() const { getMgr()->writeSessionSettings(toJson()); } -QJsonObject SessionConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("core")] = saveCore(); - obj[QStringLiteral("notebooks")] = saveNotebooks(); - obj[QStringLiteral("state_geometry")] = saveStateAndGeometry(); - obj[QStringLiteral("export")] = saveExportOption(); - obj[QStringLiteral("search_option")] = m_searchOption.toJson(); - writeByteArray(obj, QStringLiteral("viewarea_session"), m_viewAreaSession); - writeByteArray(obj, QStringLiteral("notebook_explorer_session"), m_notebookExplorerSession); - obj[QStringLiteral("external_programs")] = saveExternalPrograms(); - obj[QStringLiteral("history")] = saveHistory(); - obj[QStringLiteral("quick_note_schemes")] = saveQuickNoteSchemes(); - return obj; +QJsonObject SessionConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("core")] = saveCore(); + obj[QStringLiteral("notebooks")] = saveNotebooks(); + obj[QStringLiteral("state_geometry")] = saveStateAndGeometry(); + obj[QStringLiteral("export")] = saveExportOption(); + obj[QStringLiteral("search_option")] = m_searchOption.toJson(); + writeByteArray(obj, QStringLiteral("viewarea_session"), m_viewAreaSession); + writeByteArray(obj, QStringLiteral("notebook_explorer_session"), m_notebookExplorerSession); + obj[QStringLiteral("external_programs")] = saveExternalPrograms(); + obj[QStringLiteral("history")] = saveHistory(); + obj[QStringLiteral("quick_note_schemes")] = saveQuickNoteSchemes(); + return obj; } -QJsonObject SessionConfig::saveStateAndGeometry() const -{ - QJsonObject obj; - writeByteArray(obj, QStringLiteral("main_window_state"), m_mainWindowStateGeometry.m_mainState); - writeByteArray(obj, QStringLiteral("main_window_geometry"), m_mainWindowStateGeometry.m_mainGeometry); - writeStringList(obj, QStringLiteral("visible_docks_before_expand"), m_mainWindowStateGeometry.m_visibleDocksBeforeExpand); - writeByteArray(obj, QStringLiteral("tag_explorer_state"), m_mainWindowStateGeometry.m_tagExplorerState); - writeByteArray(obj, QStringLiteral("notebook_explorer_state"), m_mainWindowStateGeometry.m_notebookExplorerState); - writeByteArray(obj, QStringLiteral("location_list_state"), m_mainWindowStateGeometry.m_locationListState); - return obj; +QJsonObject SessionConfig::saveStateAndGeometry() const { + QJsonObject obj; + writeByteArray(obj, QStringLiteral("main_window_state"), m_mainWindowStateGeometry.m_mainState); + writeByteArray(obj, QStringLiteral("main_window_geometry"), + m_mainWindowStateGeometry.m_mainGeometry); + writeStringList(obj, QStringLiteral("visible_docks_before_expand"), + m_mainWindowStateGeometry.m_visibleDocksBeforeExpand); + writeByteArray(obj, QStringLiteral("tag_explorer_state"), + m_mainWindowStateGeometry.m_tagExplorerState); + writeByteArray(obj, QStringLiteral("notebook_explorer_state"), + m_mainWindowStateGeometry.m_notebookExplorerState); + writeByteArray(obj, QStringLiteral("location_list_state"), + m_mainWindowStateGeometry.m_locationListState); + return obj; } -SessionConfig::MainWindowStateGeometry SessionConfig::getMainWindowStateGeometry() const -{ - return m_mainWindowStateGeometry; +SessionConfig::MainWindowStateGeometry SessionConfig::getMainWindowStateGeometry() const { + return m_mainWindowStateGeometry; } -void SessionConfig::setMainWindowStateGeometry(const SessionConfig::MainWindowStateGeometry &p_state) -{ - updateConfig(m_mainWindowStateGeometry, p_state, this); +void SessionConfig::setMainWindowStateGeometry( + const SessionConfig::MainWindowStateGeometry &p_state) { + updateConfig(m_mainWindowStateGeometry, p_state, this); } -SessionConfig::OpenGL SessionConfig::getOpenGLAtBootstrap() -{ - auto userConfigFile = ConfigMgr::locateSessionConfigFilePathAtBootstrap(); - if (!userConfigFile.isEmpty()) { - auto bytes = FileUtils::readFile(userConfigFile); - auto obj = QJsonDocument::fromJson(bytes).object(); - auto coreObj = obj.value(QStringLiteral("core")).toObject(); - auto str = coreObj.value(QStringLiteral("opengl")).toString(); - return stringToOpenGL(str); - } +SessionConfig::OpenGL SessionConfig::getOpenGLAtBootstrap() { + auto userConfigFile = ConfigMgr::locateSessionConfigFilePathAtBootstrap(); + if (!userConfigFile.isEmpty()) { + auto bytes = FileUtils::readFile(userConfigFile); + auto obj = QJsonDocument::fromJson(bytes).object(); + auto coreObj = obj.value(QStringLiteral("core")).toObject(); + auto str = coreObj.value(QStringLiteral("opengl")).toString(); + return stringToOpenGL(str); + } - return OpenGL::None; + return OpenGL::None; } -SessionConfig::OpenGL SessionConfig::getOpenGL() const -{ - return m_openGL; -} +SessionConfig::OpenGL SessionConfig::getOpenGL() const { return m_openGL; } -void SessionConfig::setOpenGL(OpenGL p_option) -{ - updateConfig(m_openGL, p_option, this); -} +void SessionConfig::setOpenGL(OpenGL p_option) { updateConfig(m_openGL, p_option, this); } -QString SessionConfig::openGLToString(OpenGL p_option) -{ - switch (p_option) { - case OpenGL::Desktop: - return QStringLiteral("desktop"); +QString SessionConfig::openGLToString(OpenGL p_option) { + switch (p_option) { + case OpenGL::Desktop: + return QStringLiteral("desktop"); - case OpenGL::Angle: - return QStringLiteral("angle"); + case OpenGL::Angle: + return QStringLiteral("angle"); - case OpenGL::Software: - return QStringLiteral("software"); + case OpenGL::Software: + return QStringLiteral("software"); - default: - return QStringLiteral("none"); - } + default: + return QStringLiteral("none"); + } } -SessionConfig::OpenGL SessionConfig::stringToOpenGL(const QString &p_str) -{ - auto option = p_str.toLower(); - if (option == QStringLiteral("software")) { - return OpenGL::Software; - } else if (option == QStringLiteral("desktop")) { - return OpenGL::Desktop; - } else if (option == QStringLiteral("angle")) { - return OpenGL::Angle; - } else { - return OpenGL::None; - } +SessionConfig::OpenGL SessionConfig::stringToOpenGL(const QString &p_str) { + auto option = p_str.toLower(); + if (option == QStringLiteral("software")) { + return OpenGL::Software; + } else if (option == QStringLiteral("desktop")) { + return OpenGL::Desktop; + } else if (option == QStringLiteral("angle")) { + return OpenGL::Angle; + } else { + return OpenGL::None; + } } -bool SessionConfig::getSystemTitleBarEnabled() const -{ - return m_systemTitleBarEnabled; -} +bool SessionConfig::getSystemTitleBarEnabled() const { return m_systemTitleBarEnabled; } -void SessionConfig::setSystemTitleBarEnabled(bool p_enabled) -{ - updateConfig(m_systemTitleBarEnabled, p_enabled, this); +void SessionConfig::setSystemTitleBarEnabled(bool p_enabled) { + updateConfig(m_systemTitleBarEnabled, p_enabled, this); } -int SessionConfig::getMinimizeToSystemTray() const -{ - return m_minimizeToSystemTray; -} +int SessionConfig::getMinimizeToSystemTray() const { return m_minimizeToSystemTray; } -void SessionConfig::setMinimizeToSystemTray(bool p_enabled) -{ - updateConfig(m_minimizeToSystemTray, p_enabled ? 1 : 0, this); +void SessionConfig::setMinimizeToSystemTray(bool p_enabled) { + updateConfig(m_minimizeToSystemTray, p_enabled ? 1 : 0, this); } -void SessionConfig::doVersionSpecificOverride() -{ - // In a new version, we may want to change one value by force. - // SHOULD set the in memory variable only, or will override the notebook list. +void SessionConfig::doVersionSpecificOverride() { + // In a new version, we may want to change one value by force. + // SHOULD set the in memory variable only, or will override the notebook list. } -const ExportOption &SessionConfig::getExportOption() const -{ - return m_exportOption; -} +const ExportOption &SessionConfig::getExportOption() const { return m_exportOption; } -void SessionConfig::setExportOption(const ExportOption &p_option) -{ - updateConfig(m_exportOption, p_option, this); +void SessionConfig::setExportOption(const ExportOption &p_option) { + updateConfig(m_exportOption, p_option, this); } -const QVector &SessionConfig::getCustomExportOptions() const -{ - return m_customExportOptions; +const QVector &SessionConfig::getCustomExportOptions() const { + return m_customExportOptions; } -void SessionConfig::setCustomExportOptions(const QVector &p_options) -{ - updateConfig(m_customExportOptions, p_options, this); +void SessionConfig::setCustomExportOptions(const QVector &p_options) { + updateConfig(m_customExportOptions, p_options, this); } -const SearchOption &SessionConfig::getSearchOption() const -{ - return m_searchOption; -} +const SearchOption &SessionConfig::getSearchOption() const { return m_searchOption; } -void SessionConfig::setSearchOption(const SearchOption &p_option) -{ - updateConfig(m_searchOption, p_option, this); +void SessionConfig::setSearchOption(const SearchOption &p_option) { + updateConfig(m_searchOption, p_option, this); } -void SessionConfig::loadStateAndGeometry(const QJsonObject &p_session) -{ - const auto obj = p_session.value(QStringLiteral("state_geometry")).toObject(); - m_mainWindowStateGeometry.m_mainState = readByteArray(obj, QStringLiteral("main_window_state")); - m_mainWindowStateGeometry.m_mainGeometry = readByteArray(obj, QStringLiteral("main_window_geometry")); - m_mainWindowStateGeometry.m_visibleDocksBeforeExpand = readStringList(obj, QStringLiteral("visible_docks_before_expand")); - m_mainWindowStateGeometry.m_tagExplorerState = readByteArray(obj, QStringLiteral("tag_explorer_state")); - m_mainWindowStateGeometry.m_notebookExplorerState = readByteArray(obj, QStringLiteral("notebook_explorer_state")); - m_mainWindowStateGeometry.m_locationListState = readByteArray(obj, QStringLiteral("location_list_state")); +void SessionConfig::loadStateAndGeometry(const QJsonObject &p_session) { + const auto obj = p_session.value(QStringLiteral("state_geometry")).toObject(); + m_mainWindowStateGeometry.m_mainState = readByteArray(obj, QStringLiteral("main_window_state")); + m_mainWindowStateGeometry.m_mainGeometry = + readByteArray(obj, QStringLiteral("main_window_geometry")); + m_mainWindowStateGeometry.m_visibleDocksBeforeExpand = + readStringList(obj, QStringLiteral("visible_docks_before_expand")); + m_mainWindowStateGeometry.m_tagExplorerState = + readByteArray(obj, QStringLiteral("tag_explorer_state")); + m_mainWindowStateGeometry.m_notebookExplorerState = + readByteArray(obj, QStringLiteral("notebook_explorer_state")); + m_mainWindowStateGeometry.m_locationListState = + readByteArray(obj, QStringLiteral("location_list_state")); } -QByteArray SessionConfig::getViewAreaSessionAndClear() -{ - QByteArray bytes; - m_viewAreaSession.swap(bytes); - return bytes; +QByteArray SessionConfig::getViewAreaSessionAndClear() { + QByteArray bytes; + m_viewAreaSession.swap(bytes); + return bytes; } -void SessionConfig::setViewAreaSession(const QByteArray &p_bytes) -{ - updateConfigWithoutCheck(m_viewAreaSession, p_bytes, this); +void SessionConfig::setViewAreaSession(const QByteArray &p_bytes) { + updateConfigWithoutCheck(m_viewAreaSession, p_bytes, this); } -QByteArray SessionConfig::getNotebookExplorerSessionAndClear() -{ - QByteArray bytes; - m_notebookExplorerSession.swap(bytes); - return bytes; +QByteArray SessionConfig::getNotebookExplorerSessionAndClear() { + QByteArray bytes; + m_notebookExplorerSession.swap(bytes); + return bytes; } -void SessionConfig::setNotebookExplorerSession(const QByteArray &p_bytes) -{ - updateConfigWithoutCheck(m_notebookExplorerSession, p_bytes, this); +void SessionConfig::setNotebookExplorerSession(const QByteArray &p_bytes) { + updateConfigWithoutCheck(m_notebookExplorerSession, p_bytes, this); } -const QString &SessionConfig::getFlashPage() const -{ - return m_flashPage; -} +const QString &SessionConfig::getFlashPage() const { return m_flashPage; } -void SessionConfig::setFlashPage(const QString &p_file) -{ - updateConfig(m_flashPage, p_file, this); -} +void SessionConfig::setFlashPage(const QString &p_file) { updateConfig(m_flashPage, p_file, this); } -const QStringList &SessionConfig::getQuickAccessFiles() const -{ - return m_quickAccessFiles; -} +const QStringList &SessionConfig::getQuickAccessFiles() const { return m_quickAccessFiles; } -void SessionConfig::setQuickAccessFiles(const QStringList &p_files) -{ - QStringList files; - for (const auto &file : p_files) { - auto fi = file.trimmed(); - if (!fi.isEmpty()) { - files << fi; - } - } - updateConfig(m_quickAccessFiles, files, this); - if(tryCorrectQuickAccessFiles()) - { - update(); +void SessionConfig::setQuickAccessFiles(const QStringList &p_files) { + QStringList files; + for (const auto &file : p_files) { + auto fi = file.trimmed(); + if (!fi.isEmpty()) { + files << fi; } + } + updateConfig(m_quickAccessFiles, files, this); + if (tryCorrectQuickAccessFiles()) { + update(); + } } -void SessionConfig::removeQuickAccessFile(const QString &p_file) -{ - if (m_quickAccessFiles.removeOne(p_file)) { - tryCorrectQuickAccessFiles(); - update(); - } +void SessionConfig::removeQuickAccessFile(const QString &p_file) { + if (m_quickAccessFiles.removeOne(p_file)) { + tryCorrectQuickAccessFiles(); + update(); + } } -bool SessionConfig::tryCorrectQuickAccessFiles(void) -{ - auto notebook = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); - if (!notebook) { - return false; +bool SessionConfig::tryCorrectQuickAccessFiles(void) { + auto notebook = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); + if (!notebook) { + return false; + } + + QStringList oldResult = m_quickAccessFiles; + QStringList newResult; + for (const auto &file : m_quickAccessFiles) { + auto fi = file.trimmed(); + if (fi.isEmpty()) { + continue; + } + // check absolute path + if (!file.startsWith("#")) { + if (QFileInfo(file).exists()) { + newResult << file; + } + continue; } - QStringList oldResult = m_quickAccessFiles; - QStringList newResult; - for (const auto &file : m_quickAccessFiles) { - auto fi = file.trimmed(); - if (fi.isEmpty()) { - continue; - } - // check absolute path - if (!file.startsWith("#")) { - if (QFileInfo(file).exists()) { - newResult << file; - } - continue; - } - - // update VxURL if file path is changed - const QString rootPath = notebook->getRootFolderAbsolutePath(); - QString signature = VxUrlUtils::getSignatureFromVxURL(file); - QString oldFilePath = VxUrlUtils::getFilePathFromVxURL(file); - - // Start searching for the file from oldFilePath until reaching rootPath - QString newFilePath; - QString currentDir = PathUtils::parentDirPath(oldFilePath); - while (true) { - // make sure currentDir is under rootPath - if (!currentDir.startsWith(rootPath)) { - break; - } - - newFilePath = VxUrlUtils::getFilePathFromSignature(currentDir, signature); - if (!newFilePath.isEmpty()) { - break; - } - // invalid path - if (currentDir.isEmpty() || QDir(currentDir).isRoot()) { - break; - } - - currentDir = PathUtils::parentDirPath(currentDir); - } - - // file deleted - if (newFilePath.isEmpty()) { - continue; - } - // file path not changed - if (oldFilePath == newFilePath) { - newResult << file; - continue; - } - // file path changed, but not exists - if (!QFileInfo(newFilePath).exists()) { - continue; - } - QString newVxURL = VxUrlUtils::generateVxURL(signature, newFilePath); - newResult << newVxURL; + // update VxURL if file path is changed + const QString rootPath = notebook->getRootFolderAbsolutePath(); + QString signature = VxUrlUtils::getSignatureFromVxURL(file); + QString oldFilePath = VxUrlUtils::getFilePathFromVxURL(file); + + // Start searching for the file from oldFilePath until reaching rootPath + QString newFilePath; + QString currentDir = PathUtils::parentDirPath(oldFilePath); + while (true) { + // make sure currentDir is under rootPath + if (!currentDir.startsWith(rootPath)) { + break; + } + + newFilePath = VxUrlUtils::getFilePathFromSignature(currentDir, signature); + if (!newFilePath.isEmpty()) { + break; + } + // invalid path + if (currentDir.isEmpty() || QDir(currentDir).isRoot()) { + break; + } + + currentDir = PathUtils::parentDirPath(currentDir); } - newResult.removeDuplicates(); - m_quickAccessFiles = newResult; - if (oldResult != newResult) { - return true; + // file deleted + if (newFilePath.isEmpty()) { + continue; } - return false; + // file path not changed + if (oldFilePath == newFilePath) { + newResult << file; + continue; + } + // file path changed, but not exists + if (!QFileInfo(newFilePath).exists()) { + continue; + } + QString newVxURL = VxUrlUtils::generateVxURL(signature, newFilePath); + newResult << newVxURL; + } + newResult.removeDuplicates(); + m_quickAccessFiles = newResult; + + if (oldResult != newResult) { + return true; + } + return false; } -void SessionConfig::loadExternalPrograms(const QJsonObject &p_session) -{ - const auto arr = p_session.value(QStringLiteral("external_programs")).toArray(); - m_externalPrograms.resize(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - m_externalPrograms[i].fromJson(arr[i].toObject()); - } +void SessionConfig::loadExternalPrograms(const QJsonObject &p_session) { + const auto arr = p_session.value(QStringLiteral("external_programs")).toArray(); + m_externalPrograms.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_externalPrograms[i].fromJson(arr[i].toObject()); + } } -QJsonArray SessionConfig::saveExternalPrograms() const -{ - QJsonArray arr; - for (const auto &pro : m_externalPrograms) { - arr.append(pro.toJson()); - } - return arr; +QJsonArray SessionConfig::saveExternalPrograms() const { + QJsonArray arr; + for (const auto &pro : m_externalPrograms) { + arr.append(pro.toJson()); + } + return arr; } -void SessionConfig::loadQuickNoteSchemes(const QJsonObject &p_session) -{ - const auto arr = p_session.value(QStringLiteral("quick_note_schemes")).toArray(); - m_quickNoteSchemes.resize(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - m_quickNoteSchemes[i].fromJson(arr[i].toObject()); - } +void SessionConfig::loadQuickNoteSchemes(const QJsonObject &p_session) { + const auto arr = p_session.value(QStringLiteral("quick_note_schemes")).toArray(); + m_quickNoteSchemes.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_quickNoteSchemes[i].fromJson(arr[i].toObject()); + } } -QJsonArray SessionConfig::saveQuickNoteSchemes() const -{ - QJsonArray arr; - for (const auto &scheme : m_quickNoteSchemes) { - arr.append(scheme.toJson()); - } - return arr; +QJsonArray SessionConfig::saveQuickNoteSchemes() const { + QJsonArray arr; + for (const auto &scheme : m_quickNoteSchemes) { + arr.append(scheme.toJson()); + } + return arr; } -const QVector &SessionConfig::getExternalPrograms() const -{ - return m_externalPrograms; +const QVector &SessionConfig::getExternalPrograms() const { + return m_externalPrograms; } -const SessionConfig::ExternalProgram *SessionConfig::findExternalProgram(const QString &p_name) const -{ - for (const auto &pro : m_externalPrograms) { - if (pro.m_name == p_name) { - return &pro; - } +const SessionConfig::ExternalProgram * +SessionConfig::findExternalProgram(const QString &p_name) const { + for (const auto &pro : m_externalPrograms) { + if (pro.m_name == p_name) { + return &pro; } - return nullptr; + } + return nullptr; } -const QVector &SessionConfig::getHistory() const -{ - return m_history; -} +const QVector &SessionConfig::getHistory() const { return m_history; } -void SessionConfig::addHistory(const HistoryItem &p_item) -{ - HistoryMgr::insertHistoryItem(m_history, p_item); - update(); +void SessionConfig::addHistory(const HistoryItem &p_item) { + HistoryMgr::insertHistoryItem(m_history, p_item); + update(); } -void SessionConfig::removeHistory(const QString &p_itemPath) -{ - HistoryMgr::removeHistoryItem(m_history, p_itemPath); - update(); +void SessionConfig::removeHistory(const QString &p_itemPath) { + HistoryMgr::removeHistoryItem(m_history, p_itemPath); + update(); } -void SessionConfig::clearHistory() -{ - m_history.clear(); - update(); +void SessionConfig::clearHistory() { + m_history.clear(); + update(); } -void SessionConfig::loadHistory(const QJsonObject &p_session) -{ - auto arr = p_session[QStringLiteral("history")].toArray(); - m_history.resize(arr.size()); - for (int i = 0; i < arr.size(); ++i) { - m_history[i].fromJson(arr[i].toObject()); - } +void SessionConfig::loadHistory(const QJsonObject &p_session) { + auto arr = p_session[QStringLiteral("history")].toArray(); + m_history.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_history[i].fromJson(arr[i].toObject()); + } } -QJsonArray SessionConfig::saveHistory() const -{ - QJsonArray arr; - for (const auto &item : m_history) { - arr.append(item.toJson()); - } - return arr; +QJsonArray SessionConfig::saveHistory() const { + QJsonArray arr; + for (const auto &item : m_history) { + arr.append(item.toJson()); + } + return arr; } -void SessionConfig::loadExportOption(const QJsonObject &p_session) -{ - auto exportObj = p_session[QStringLiteral("export")].toObject(); +void SessionConfig::loadExportOption(const QJsonObject &p_session) { + auto exportObj = p_session[QStringLiteral("export")].toObject(); - m_exportOption.fromJson(exportObj[QStringLiteral("export_option")].toObject()); + m_exportOption.fromJson(exportObj[QStringLiteral("export_option")].toObject()); - auto customArr = exportObj[QStringLiteral("custom_options")].toArray(); - m_customExportOptions.resize(customArr.size()); - for (int i = 0; i < customArr.size(); ++i) { - m_customExportOptions[i].fromJson(customArr[i].toObject()); - } + auto customArr = exportObj[QStringLiteral("custom_options")].toArray(); + m_customExportOptions.resize(customArr.size()); + for (int i = 0; i < customArr.size(); ++i) { + m_customExportOptions[i].fromJson(customArr[i].toObject()); + } } -QJsonObject SessionConfig::saveExportOption() const -{ - QJsonObject obj; +QJsonObject SessionConfig::saveExportOption() const { + QJsonObject obj; - obj[QStringLiteral("export_option")] = m_exportOption.toJson(); + obj[QStringLiteral("export_option")] = m_exportOption.toJson(); - QJsonArray customArr; - for (int i = 0; i < m_customExportOptions.size(); ++i) { - customArr.push_back(m_customExportOptions[i].toJson()); - } - obj[QStringLiteral("custom_options")] = customArr; + QJsonArray customArr; + for (int i = 0; i < m_customExportOptions.size(); ++i) { + customArr.push_back(m_customExportOptions[i].toJson()); + } + obj[QStringLiteral("custom_options")] = customArr; - return obj; + return obj; } -const QVector &SessionConfig::getQuickNoteSchemes() const -{ - return m_quickNoteSchemes; +const QVector &SessionConfig::getQuickNoteSchemes() const { + return m_quickNoteSchemes; } -void SessionConfig::setQuickNoteSchemes(const QVector& p_schemes) -{ - updateConfig(m_quickNoteSchemes, p_schemes, this); +void SessionConfig::setQuickNoteSchemes(const QVector &p_schemes) { + updateConfig(m_quickNoteSchemes, p_schemes, this); } diff --git a/src/core/sessionconfig.h b/src/core/sessionconfig.h index a23596b7f7..f72f78756d 100644 --- a/src/core/sessionconfig.h +++ b/src/core/sessionconfig.h @@ -6,246 +6,232 @@ #include #include +#include "historyitem.h" #include #include -#include "historyitem.h" -namespace vnotex -{ - class SessionConfig : public IConfig - { - public: - struct NotebookItem - { - NotebookItem() = default; +namespace vnotex { +class SessionConfig : public IConfig { +public: + struct NotebookItem { + NotebookItem() = default; - bool operator==(const NotebookItem &p_other) const; + bool operator==(const NotebookItem &p_other) const; - void fromJson(const QJsonObject &p_jobj); + void fromJson(const QJsonObject &p_jobj); - QJsonObject toJson() const; + QJsonObject toJson() const; - QString m_type; - QString m_rootFolderPath; - QString m_backend; - }; + QString m_type; + QString m_rootFolderPath; + QString m_backend; + }; - struct MainWindowStateGeometry - { - bool operator==(const MainWindowStateGeometry &p_other) const - { - return m_mainState == p_other.m_mainState - && m_mainGeometry == p_other.m_mainGeometry - && m_visibleDocksBeforeExpand == p_other.m_visibleDocksBeforeExpand - && m_tagExplorerState == p_other.m_tagExplorerState - && m_notebookExplorerState == p_other.m_notebookExplorerState - && m_locationListState == p_other.m_locationListState; - } + struct MainWindowStateGeometry { + bool operator==(const MainWindowStateGeometry &p_other) const { + return m_mainState == p_other.m_mainState && m_mainGeometry == p_other.m_mainGeometry && + m_visibleDocksBeforeExpand == p_other.m_visibleDocksBeforeExpand && + m_tagExplorerState == p_other.m_tagExplorerState && + m_notebookExplorerState == p_other.m_notebookExplorerState && + m_locationListState == p_other.m_locationListState; + } - QByteArray m_mainState; + QByteArray m_mainState; - QByteArray m_mainGeometry; + QByteArray m_mainGeometry; - QStringList m_visibleDocksBeforeExpand; + QStringList m_visibleDocksBeforeExpand; - QByteArray m_tagExplorerState; + QByteArray m_tagExplorerState; - QByteArray m_notebookExplorerState; + QByteArray m_notebookExplorerState; - QByteArray m_locationListState; - }; + QByteArray m_locationListState; + }; - struct QuickNoteScheme - { - bool operator==(const QuickNoteScheme &p_other) const; + struct QuickNoteScheme { + bool operator==(const QuickNoteScheme &p_other) const; - void fromJson(const QJsonObject &p_jobj); + void fromJson(const QJsonObject &p_jobj); - QJsonObject toJson() const; + QJsonObject toJson() const; - QString m_name; + QString m_name; - // Where to create the quick note. - QString m_folderPath; + // Where to create the quick note. + QString m_folderPath; - // Name of the quick note. Snippet is supported. - QString m_noteName; + // Name of the quick note. Snippet is supported. + QString m_noteName; - QString m_template; - }; + QString m_template; + }; - enum OpenGL - { - None, - Desktop, - Angle, - Software - }; + enum OpenGL { None, Desktop, Angle, Software }; - struct ExternalProgram - { - void fromJson(const QJsonObject &p_jobj); + struct ExternalProgram { + void fromJson(const QJsonObject &p_jobj); - QJsonObject toJson() const; + QJsonObject toJson() const; - QString fetchCommand(const QString &p_file) const; + QString fetchCommand(const QString &p_file) const; - QString m_name; + QString m_name; - // %1: the file paths to open. - QString m_command; + // %1: the file paths to open. + QString m_command; - QString m_shortcut; - }; + QString m_shortcut; + }; - explicit SessionConfig(ConfigMgr *p_mgr); + explicit SessionConfig(ConfigMgr *p_mgr); - ~SessionConfig(); + ~SessionConfig(); - void init() Q_DECL_OVERRIDE; + void init() Q_DECL_OVERRIDE; - const QString &getNewNotebookDefaultRootFolderPath() const; - void setNewNotebookDefaultRootFolderPath(const QString &p_path); + const QString &getNewNotebookDefaultRootFolderPath() const; + void setNewNotebookDefaultRootFolderPath(const QString &p_path); - const QString &getExternalMediaDefaultPath() const; - void setExternalMediaDefaultPath(const QString &p_path); + const QString &getExternalMediaDefaultPath() const; + void setExternalMediaDefaultPath(const QString &p_path); - const QString &getCurrentNotebookRootFolderPath() const; - void setCurrentNotebookRootFolderPath(const QString &p_path); + const QString &getCurrentNotebookRootFolderPath() const; + void setCurrentNotebookRootFolderPath(const QString &p_path); - const QVector &getNotebooks() const; - void setNotebooks(const QVector &p_notebooks); + const QVector &getNotebooks() const; + void setNotebooks(const QVector &p_notebooks); - void writeToSettings() const Q_DECL_OVERRIDE; + void writeToSettings() const Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - SessionConfig::MainWindowStateGeometry getMainWindowStateGeometry() const; - void setMainWindowStateGeometry(const SessionConfig::MainWindowStateGeometry &p_state); + SessionConfig::MainWindowStateGeometry getMainWindowStateGeometry() const; + void setMainWindowStateGeometry(const SessionConfig::MainWindowStateGeometry &p_state); - OpenGL getOpenGL() const; - void setOpenGL(OpenGL p_option); + OpenGL getOpenGL() const; + void setOpenGL(OpenGL p_option); - bool getSystemTitleBarEnabled() const; - void setSystemTitleBarEnabled(bool p_enabled); + bool getSystemTitleBarEnabled() const; + void setSystemTitleBarEnabled(bool p_enabled); - static OpenGL getOpenGLAtBootstrap(); + static OpenGL getOpenGLAtBootstrap(); - static QString openGLToString(OpenGL p_option); - static OpenGL stringToOpenGL(const QString &p_str); + static QString openGLToString(OpenGL p_option); + static OpenGL stringToOpenGL(const QString &p_str); - int getMinimizeToSystemTray() const; - void setMinimizeToSystemTray(bool p_enabled); + int getMinimizeToSystemTray() const; + void setMinimizeToSystemTray(bool p_enabled); - const ExportOption &getExportOption() const; - void setExportOption(const ExportOption &p_option); + const ExportOption &getExportOption() const; + void setExportOption(const ExportOption &p_option); - const QVector &getCustomExportOptions() const; - void setCustomExportOptions(const QVector &p_options); + const QVector &getCustomExportOptions() const; + void setCustomExportOptions(const QVector &p_options); - const SearchOption &getSearchOption() const; - void setSearchOption(const SearchOption &p_option); + const SearchOption &getSearchOption() const; + void setSearchOption(const SearchOption &p_option); - QByteArray getViewAreaSessionAndClear(); - void setViewAreaSession(const QByteArray &p_bytes); + QByteArray getViewAreaSessionAndClear(); + void setViewAreaSession(const QByteArray &p_bytes); - QByteArray getNotebookExplorerSessionAndClear(); - void setNotebookExplorerSession(const QByteArray &p_bytes); + QByteArray getNotebookExplorerSessionAndClear(); + void setNotebookExplorerSession(const QByteArray &p_bytes); - const QString &getFlashPage() const; - void setFlashPage(const QString &p_file); + const QString &getFlashPage() const; + void setFlashPage(const QString &p_file); - const QStringList &getQuickAccessFiles() const; - void setQuickAccessFiles(const QStringList &p_files); + const QStringList &getQuickAccessFiles() const; + void setQuickAccessFiles(const QStringList &p_files); - void removeQuickAccessFile(const QString &p_file); - bool tryCorrectQuickAccessFiles(void); + void removeQuickAccessFile(const QString &p_file); + bool tryCorrectQuickAccessFiles(void); - const QVector &getExternalPrograms() const; - const ExternalProgram *findExternalProgram(const QString &p_name) const; + const QVector &getExternalPrograms() const; + const ExternalProgram *findExternalProgram(const QString &p_name) const; - const QVector &getHistory() const; - void addHistory(const HistoryItem &p_item); - void removeHistory(const QString &p_itemPath); - void clearHistory(); + const QVector &getHistory() const; + void addHistory(const HistoryItem &p_item); + void removeHistory(const QString &p_itemPath); + void clearHistory(); - const QVector &getQuickNoteSchemes() const; - void setQuickNoteSchemes(const QVector& p_schemes); + const QVector &getQuickNoteSchemes() const; + void setQuickNoteSchemes(const QVector &p_schemes); - private: - void loadCore(const QJsonObject &p_session); +private: + void loadCore(const QJsonObject &p_session); - QJsonObject saveCore() const; + QJsonObject saveCore() const; - void loadNotebooks(const QJsonObject &p_session); + void loadNotebooks(const QJsonObject &p_session); - QJsonArray saveNotebooks() const; + QJsonArray saveNotebooks() const; - void loadStateAndGeometry(const QJsonObject &p_session); + void loadStateAndGeometry(const QJsonObject &p_session); - QJsonObject saveStateAndGeometry() const; + QJsonObject saveStateAndGeometry() const; - void loadExternalPrograms(const QJsonObject &p_session); + void loadExternalPrograms(const QJsonObject &p_session); - QJsonArray saveExternalPrograms() const; + QJsonArray saveExternalPrograms() const; - void loadQuickNoteSchemes(const QJsonObject &p_session); + void loadQuickNoteSchemes(const QJsonObject &p_session); - QJsonArray saveQuickNoteSchemes() const; + QJsonArray saveQuickNoteSchemes() const; - void doVersionSpecificOverride(); + void doVersionSpecificOverride(); - void loadHistory(const QJsonObject &p_session); + void loadHistory(const QJsonObject &p_session); - QJsonArray saveHistory() const; + QJsonArray saveHistory() const; - void loadExportOption(const QJsonObject &p_session); + void loadExportOption(const QJsonObject &p_session); - QJsonObject saveExportOption() const; + QJsonObject saveExportOption() const; - QString m_newNotebookDefaultRootFolderPath; + QString m_newNotebookDefaultRootFolderPath; - // Use root folder to identify a notebook uniquely. - QString m_currentNotebookRootFolderPath; + // Use root folder to identify a notebook uniquely. + QString m_currentNotebookRootFolderPath; - QVector m_notebooks; + QVector m_notebooks; - MainWindowStateGeometry m_mainWindowStateGeometry; + MainWindowStateGeometry m_mainWindowStateGeometry; - OpenGL m_openGL = OpenGL::None; + OpenGL m_openGL = OpenGL::None; - // Whether use system's title bar or not. - bool m_systemTitleBarEnabled = true; + // Whether use system's title bar or not. + bool m_systemTitleBarEnabled = true; - // Whether to minimize to tray. - // -1 for prompting for user; - // 0 for disabling minimizing to system tray; - // 1 for enabling minimizing to system tray. - int m_minimizeToSystemTray = -1; + // Whether to minimize to tray. + // -1 for prompting for user; + // 0 for disabling minimizing to system tray; + // 1 for enabling minimizing to system tray. + int m_minimizeToSystemTray = -1; - ExportOption m_exportOption; + ExportOption m_exportOption; - QVector m_customExportOptions; + QVector m_customExportOptions; - SearchOption m_searchOption; + SearchOption m_searchOption; - QByteArray m_viewAreaSession; + QByteArray m_viewAreaSession; - QByteArray m_notebookExplorerSession; + QByteArray m_notebookExplorerSession; - QString m_flashPage; + QString m_flashPage; - QStringList m_quickAccessFiles; + QStringList m_quickAccessFiles; - QVector m_externalPrograms; + QVector m_externalPrograms; - QVector m_history; + QVector m_history; - // Default folder path to open for external media like images and files. - QString m_externalMediaDefaultPath; + // Default folder path to open for external media like images and files. + QString m_externalMediaDefaultPath; - QVector m_quickNoteSchemes; - }; -} // ns vnotex + QVector m_quickNoteSchemes; +}; +} // namespace vnotex #endif // SESSIONCONFIG_H diff --git a/src/core/singleinstanceguard.cpp b/src/core/singleinstanceguard.cpp index 05d8bc4184..2af264d77a 100644 --- a/src/core/singleinstanceguard.cpp +++ b/src/core/singleinstanceguard.cpp @@ -1,10 +1,10 @@ #include "singleinstanceguard.h" +#include +#include #include #include #include -#include -#include #include @@ -14,213 +14,196 @@ const QString SingleInstanceGuard::c_serverName = "vnote"; const QChar SingleInstanceGuard::c_stringListSeparator = '>'; -SingleInstanceGuard::~SingleInstanceGuard() -{ - exit(); -} +SingleInstanceGuard::~SingleInstanceGuard() { exit(); } -bool SingleInstanceGuard::tryRun() -{ - Q_ASSERT(!m_online); +bool SingleInstanceGuard::tryRun() { + Q_ASSERT(!m_online); - // On Windows, multiple servers on the same name are allowed. - m_client = tryConnect(); - if (m_client) { - // There is one server running and we are now connected, so we could not continue. - return false; - } + // On Windows, multiple servers on the same name are allowed. + m_client = tryConnect(); + if (m_client) { + // There is one server running and we are now connected, so we could not continue. + return false; + } - m_server = tryListen(); - if (m_server) { - // We are the lucky one. - qInfo() << "guard succeeds to run"; - } else { - // We still allow the guard to run. There maybe a bug need to fix. - qWarning() << "failed to connect to an existing instance or establish a new local server"; - } + m_server = tryListen(); + if (m_server) { + // We are the lucky one. + qInfo() << "guard succeeds to run"; + } else { + // We still allow the guard to run. There maybe a bug need to fix. + qWarning() << "failed to connect to an existing instance or establish a new local server"; + } - setupServer(); + setupServer(); - m_online = true; - return true; + m_online = true; + return true; } -void SingleInstanceGuard::requestOpenFiles(const QStringList &p_files) -{ - if (p_files.isEmpty()) { - return; - } +void SingleInstanceGuard::requestOpenFiles(const QStringList &p_files) { + if (p_files.isEmpty()) { + return; + } - Q_ASSERT(!m_online); - if (!m_client || m_client->state() != QLocalSocket::ConnectedState) { - qWarning() << "failed to request open files" << m_client->errorString(); - return ; - } + Q_ASSERT(!m_online); + if (!m_client || m_client->state() != QLocalSocket::ConnectedState) { + qWarning() << "failed to request open files" << m_client->errorString(); + return; + } - sendRequest(m_client.data(), OpCode::OpenFiles, p_files.join(c_stringListSeparator)); + sendRequest(m_client.data(), OpCode::OpenFiles, p_files.join(c_stringListSeparator)); } -void SingleInstanceGuard::requestShow() -{ - Q_ASSERT(!m_online); - if (!m_client || m_client->state() != QLocalSocket::ConnectedState) { - qWarning() << "failed to request show" << m_client->errorString(); - return ; - } +void SingleInstanceGuard::requestShow() { + Q_ASSERT(!m_online); + if (!m_client || m_client->state() != QLocalSocket::ConnectedState) { + qWarning() << "failed to request show" << m_client->errorString(); + return; + } - sendRequest(m_client.data(), OpCode::Show, QString()); + sendRequest(m_client.data(), OpCode::Show, QString()); } -void SingleInstanceGuard::exit() -{ - m_online = false; +void SingleInstanceGuard::exit() { + m_online = false; - if (m_client) { - m_client->disconnectFromServer(); - m_client.clear(); - } + if (m_client) { + m_client->disconnectFromServer(); + m_client.clear(); + } - if (m_server) { - m_server->close(); - m_server.clear(); - } + if (m_server) { + m_server->close(); + m_server.clear(); + } } -QSharedPointer SingleInstanceGuard::tryConnect() -{ - auto socket = QSharedPointer::create(); - socket->connectToServer(c_serverName); - if (socket->waitForConnected(200)) { - // Connected. - qDebug() << "socket connected to server" << c_serverName; - return socket; - } else { - qDebug() << "socket connect timeout"; - return nullptr; - } +QSharedPointer SingleInstanceGuard::tryConnect() { + auto socket = QSharedPointer::create(); + socket->connectToServer(c_serverName); + if (socket->waitForConnected(200)) { + // Connected. + qDebug() << "socket connected to server" << c_serverName; + return socket; + } else { + qDebug() << "socket connect timeout"; + return nullptr; + } } -QSharedPointer SingleInstanceGuard::tryListen() -{ - auto server = QSharedPointer::create(); - bool ret = server->listen(c_serverName); - if (!ret && server->serverError() == QAbstractSocket::AddressInUseError) { - // On Unix, a previous crash may leave a server running. - // Clean up and try again. - QLocalServer::removeServer(c_serverName); - ret = server->listen(c_serverName); - } +QSharedPointer SingleInstanceGuard::tryListen() { + auto server = QSharedPointer::create(); + bool ret = server->listen(c_serverName); + if (!ret && server->serverError() == QAbstractSocket::AddressInUseError) { + // On Unix, a previous crash may leave a server running. + // Clean up and try again. + QLocalServer::removeServer(c_serverName); + ret = server->listen(c_serverName); + } + + if (ret) { + qDebug() << "local server listening on" << c_serverName; + return server; + } else { + qDebug() << "failed to start local server"; + return nullptr; + } +} + +void SingleInstanceGuard::setupServer() { + if (!m_server) { + return; + } + + connect(m_server.data(), &QLocalServer::newConnection, this, [this]() { + auto socket = m_server->nextPendingConnection(); + if (socket) { + qInfo() << "local server receives new connect" << socket; + if (m_ongoingConnect) { + qWarning() << "drop the connection since there is one ongoing connect"; + socket->disconnectFromServer(); + socket->deleteLater(); + return; + } - if (ret) { - qDebug() << "local server listening on" << c_serverName; - return server; - } else { - qDebug() << "failed to start local server"; - return nullptr; + m_ongoingConnect = true; + m_command.clear(); + + connect(socket, &QLocalSocket::disconnected, this, [this, socket]() { + Q_ASSERT(m_ongoingConnect); + socket->deleteLater(); + m_ongoingConnect = false; + }); + connect(socket, &QLocalSocket::readyRead, this, [this, socket]() { receiveCommand(socket); }); } + }); } -void SingleInstanceGuard::setupServer() -{ - if (!m_server) { +void SingleInstanceGuard::receiveCommand(QLocalSocket *p_socket) { + QDataStream inStream; + inStream.setDevice(p_socket); + inStream.setVersion(QDataStream::Qt_5_12); + + while (p_socket->bytesAvailable() > 0) { + if (m_command.m_opCode == OpCode::Null) { + // Relies on the fact that QDataStream serializes a quint32 into + // sizeof(quint32) bytes. + if (p_socket->bytesAvailable() < (int)sizeof(quint32) * 2) { return; - } + } - connect(m_server.data(), &QLocalServer::newConnection, - this, [this]() { - auto socket = m_server->nextPendingConnection(); - if (socket) { - qInfo() << "local server receives new connect" << socket; - if (m_ongoingConnect) { - qWarning() << "drop the connection since there is one ongoing connect"; - socket->disconnectFromServer(); - socket->deleteLater(); - return; - } - - m_ongoingConnect = true; - m_command.clear(); - - connect(socket, &QLocalSocket::disconnected, - this, [this, socket]() { - Q_ASSERT(m_ongoingConnect); - socket->deleteLater(); - m_ongoingConnect = false; - }); - connect(socket, &QLocalSocket::readyRead, - this, [this, socket]() { - receiveCommand(socket); - }); - } - }); -} + quint32 opCode = 0; + inStream >> opCode; + m_command.m_opCode = static_cast(opCode); + inStream >> m_command.m_size; + } -void SingleInstanceGuard::receiveCommand(QLocalSocket *p_socket) -{ - QDataStream inStream; - inStream.setDevice(p_socket); - inStream.setVersion(QDataStream::Qt_5_12); - - while (p_socket->bytesAvailable() > 0) { - if (m_command.m_opCode == OpCode::Null) { - // Relies on the fact that QDataStream serializes a quint32 into - // sizeof(quint32) bytes. - if (p_socket->bytesAvailable() < (int)sizeof(quint32) * 2) { - return; - } - - quint32 opCode = 0; - inStream >> opCode; - m_command.m_opCode = static_cast(opCode); - inStream >> m_command.m_size; - } - - if (p_socket->bytesAvailable() < m_command.m_size) { - return; - } - - qDebug() << "op code" << m_command.m_opCode << m_command.m_size << p_socket->bytesAvailable(); - - switch (m_command.m_opCode) { - case OpCode::Show: - Q_ASSERT(m_command.m_size == 0); - emit showRequested(); - break; - - case OpCode::OpenFiles: - { - Q_ASSERT(m_command.m_size != 0); - QString payload; - inStream >> payload; - const auto files = payload.split(c_stringListSeparator); - emit openFilesRequested(files); - break; - } - - default: - qWarning() << "unknown op code" << m_command.m_opCode; - m_command.clear(); - return; - } - - m_command.clear(); + if (p_socket->bytesAvailable() < m_command.m_size) { + return; } -} -void SingleInstanceGuard::sendRequest(QLocalSocket *p_socket, OpCode p_code, const QString &p_payload) -{ - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_5_12); - out << static_cast(p_code); - out << static_cast(p_payload.size()); - if (p_payload.size() > 0) { - out << p_payload; + qDebug() << "op code" << m_command.m_opCode << m_command.m_size << p_socket->bytesAvailable(); + + switch (m_command.m_opCode) { + case OpCode::Show: + Q_ASSERT(m_command.m_size == 0); + emit showRequested(); + break; + + case OpCode::OpenFiles: { + Q_ASSERT(m_command.m_size != 0); + QString payload; + inStream >> payload; + const auto files = payload.split(c_stringListSeparator); + emit openFilesRequested(files); + break; } - p_socket->write(block); - if (p_socket->waitForBytesWritten(3000)) { - qDebug() << "request sent" << p_code << p_payload.size(); - } else { - qWarning() << "failed to send request" << p_code; + + default: + qWarning() << "unknown op code" << m_command.m_opCode; + m_command.clear(); + return; } + + m_command.clear(); + } +} + +void SingleInstanceGuard::sendRequest(QLocalSocket *p_socket, OpCode p_code, + const QString &p_payload) { + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_5_12); + out << static_cast(p_code); + out << static_cast(p_payload.size()); + if (p_payload.size() > 0) { + out << p_payload; + } + p_socket->write(block); + if (p_socket->waitForBytesWritten(3000)) { + qDebug() << "request sent" << p_code << p_payload.size(); + } else { + qWarning() << "failed to send request" << p_code; + } } diff --git a/src/core/singleinstanceguard.h b/src/core/singleinstanceguard.h index deccb116c1..8c2011ffac 100644 --- a/src/core/singleinstanceguard.h +++ b/src/core/singleinstanceguard.h @@ -2,86 +2,77 @@ #define SINGLEINSTANCEGUARD_H #include -#include #include +#include class QLocalServer; class QLocalSocket; -namespace vnotex -{ - class SingleInstanceGuard : public QObject - { - Q_OBJECT - public: - SingleInstanceGuard() = default; +namespace vnotex { +class SingleInstanceGuard : public QObject { + Q_OBJECT +public: + SingleInstanceGuard() = default; - ~SingleInstanceGuard(); + ~SingleInstanceGuard(); - // Try to run. Return true on success. - bool tryRun(); + // Try to run. Return true on success. + bool tryRun(); - // Server API. - public: - // A running instance requests to exit. - void exit(); + // Server API. +public: + // A running instance requests to exit. + void exit(); - // Clients API. - public: - void requestOpenFiles(const QStringList &p_files); + // Clients API. +public: + void requestOpenFiles(const QStringList &p_files); - void requestShow(); + void requestShow(); - signals: - void openFilesRequested(const QStringList &p_files); +signals: + void openFilesRequested(const QStringList &p_files); - void showRequested(); + void showRequested(); - private: - enum OpCode - { - Null = 0, - Show, - OpenFiles - }; +private: + enum OpCode { Null = 0, Show, OpenFiles }; - struct Command - { - void clear() - { - m_opCode = OpCode::Null; - m_size = 0; - } + struct Command { + void clear() { + m_opCode = OpCode::Null; + m_size = 0; + } - OpCode m_opCode = OpCode::Null; - int m_size = 0; - }; + OpCode m_opCode = OpCode::Null; + int m_size = 0; + }; - QSharedPointer tryConnect(); + QSharedPointer tryConnect(); - QSharedPointer tryListen(); + QSharedPointer tryListen(); - void setupServer(); + void setupServer(); - void receiveCommand(QLocalSocket *p_socket); + void receiveCommand(QLocalSocket *p_socket); - void sendRequest(QLocalSocket *p_socket, OpCode p_code, const QString &p_payload); + void sendRequest(QLocalSocket *p_socket, OpCode p_code, const QString &p_payload); - // Whether succeeded to run. - bool m_online = false; + // Whether succeeded to run. + bool m_online = false; - QSharedPointer m_client; + QSharedPointer m_client; - QSharedPointer m_server; + QSharedPointer m_server; - bool m_ongoingConnect = false; + bool m_ongoingConnect = false; - Command m_command; + Command m_command; - static const QString c_serverName; + static const QString c_serverName; - static const QChar c_stringListSeparator; - }; -} // ns vnotex + static const QChar c_stringListSeparator; +}; +} // namespace vnotex #endif // SINGLEINSTANCEGUARD_H diff --git a/src/core/templatemgr.cpp b/src/core/templatemgr.cpp index 0ddc082a86..1567cde71e 100644 --- a/src/core/templatemgr.cpp +++ b/src/core/templatemgr.cpp @@ -8,31 +8,27 @@ using namespace vnotex; -QString TemplateMgr::getTemplateFolder() const -{ - return ConfigMgr::getInst().getUserTemplateFolder(); +QString TemplateMgr::getTemplateFolder() const { + return ConfigMgr::getInst().getUserTemplateFolder(); } -QStringList TemplateMgr::getTemplates() const -{ - QDir dir(getTemplateFolder()); - dir.setFilter(QDir::Files | QDir::NoSymLinks); - return dir.entryList(); +QStringList TemplateMgr::getTemplates() const { + QDir dir(getTemplateFolder()); + dir.setFilter(QDir::Files | QDir::NoSymLinks); + return dir.entryList(); } -QString TemplateMgr::getTemplateFilePath(const QString &p_name) const -{ - if (p_name.isEmpty()) { - return QString(); - } - return QDir(getTemplateFolder()).filePath(p_name); +QString TemplateMgr::getTemplateFilePath(const QString &p_name) const { + if (p_name.isEmpty()) { + return QString(); + } + return QDir(getTemplateFolder()).filePath(p_name); } -QString TemplateMgr::getTemplateContent(const QString &p_name) const -{ - const auto filePath = getTemplateFilePath(p_name); - if (filePath.isEmpty()) { - return QString(); - } - return FileUtils::readTextFile(filePath); +QString TemplateMgr::getTemplateContent(const QString &p_name) const { + const auto filePath = getTemplateFilePath(p_name); + if (filePath.isEmpty()) { + return QString(); + } + return FileUtils::readTextFile(filePath); } diff --git a/src/core/templatemgr.h b/src/core/templatemgr.h index 9707dc1f33..c3396642aa 100644 --- a/src/core/templatemgr.h +++ b/src/core/templatemgr.h @@ -6,29 +6,26 @@ #include "noncopyable.h" -namespace vnotex -{ - class TemplateMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - static TemplateMgr &getInst() - { - static TemplateMgr inst; - return inst; - } - - QString getTemplateFolder() const; - - QStringList getTemplates() const; - - QString getTemplateFilePath(const QString &p_name) const; - - QString getTemplateContent(const QString &p_name) const; - - private: - TemplateMgr() = default; - }; -} +namespace vnotex { +class TemplateMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + static TemplateMgr &getInst() { + static TemplateMgr inst; + return inst; + } + + QString getTemplateFolder() const; + + QStringList getTemplates() const; + + QString getTemplateFilePath(const QString &p_name) const; + + QString getTemplateContent(const QString &p_name) const; + +private: + TemplateMgr() = default; +}; +} // namespace vnotex #endif // TEMPLATEMGR_H diff --git a/src/core/texteditorconfig.cpp b/src/core/texteditorconfig.cpp index 03d16c5516..f845e3c387 100644 --- a/src/core/texteditorconfig.cpp +++ b/src/core/texteditorconfig.cpp @@ -7,271 +7,218 @@ using namespace vnotex; #define READINT(key) readInt(appObj, userObj, (key)) TextEditorConfig::TextEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig) -{ - m_sessionName = QStringLiteral("text_editor"); + : IConfig(p_mgr, p_topConfig) { + m_sessionName = QStringLiteral("text_editor"); } -void TextEditorConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void TextEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - { - auto lineNumber = READSTR(QStringLiteral("line_number")); - m_lineNumberType = stringToLineNumberType(lineNumber); - } + { + auto lineNumber = READSTR(QStringLiteral("line_number")); + m_lineNumberType = stringToLineNumberType(lineNumber); + } - m_textFoldingEnabled = READBOOL(QStringLiteral("text_folding")); + m_textFoldingEnabled = READBOOL(QStringLiteral("text_folding")); - { - auto inputMode = READSTR(QStringLiteral("input_mode")); - m_inputMode = stringToInputMode(inputMode); - } + { + auto inputMode = READSTR(QStringLiteral("input_mode")); + m_inputMode = stringToInputMode(inputMode); + } - { - auto centerCursor = READSTR(QStringLiteral("center_cursor")); - m_centerCursor = stringToCenterCursor(centerCursor); - } + { + auto centerCursor = READSTR(QStringLiteral("center_cursor")); + m_centerCursor = stringToCenterCursor(centerCursor); + } - { - auto wrapMode = READSTR(QStringLiteral("wrap_mode")); - m_wrapMode = stringToWrapMode(wrapMode); - } + { + auto wrapMode = READSTR(QStringLiteral("wrap_mode")); + m_wrapMode = stringToWrapMode(wrapMode); + } - m_expandTab = READBOOL(QStringLiteral("expand_tab")); + m_expandTab = READBOOL(QStringLiteral("expand_tab")); - m_tabStopWidth = READINT(QStringLiteral("tab_stop_width")); + m_tabStopWidth = READINT(QStringLiteral("tab_stop_width")); - m_highlightWhitespace = READBOOL(QStringLiteral("highlight_whitespace")); + m_highlightWhitespace = READBOOL(QStringLiteral("highlight_whitespace")); - m_zoomDelta = READINT(QStringLiteral("zoom_delta")); + m_zoomDelta = READINT(QStringLiteral("zoom_delta")); - m_spellCheckEnabled = READBOOL(QStringLiteral("spell_check")); + m_spellCheckEnabled = READBOOL(QStringLiteral("spell_check")); } -QJsonObject TextEditorConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("line_number")] = lineNumberTypeToString(m_lineNumberType); - obj[QStringLiteral("text_folding")] = m_textFoldingEnabled; - obj[QStringLiteral("input_mode")] = inputModeToString(m_inputMode); - obj[QStringLiteral("center_cursor")] = centerCursorToString(m_centerCursor); - obj[QStringLiteral("wrap_mode")] = wrapModeToString(m_wrapMode); - obj[QStringLiteral("expand_tab")] = m_expandTab; - obj[QStringLiteral("tab_stop_width")] = m_tabStopWidth; - obj[QStringLiteral("highlight_whitespace")] = m_highlightWhitespace; - obj[QStringLiteral("zoom_delta")] = m_zoomDelta; - obj[QStringLiteral("spell_check")] = m_spellCheckEnabled; - return obj; +QJsonObject TextEditorConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("line_number")] = lineNumberTypeToString(m_lineNumberType); + obj[QStringLiteral("text_folding")] = m_textFoldingEnabled; + obj[QStringLiteral("input_mode")] = inputModeToString(m_inputMode); + obj[QStringLiteral("center_cursor")] = centerCursorToString(m_centerCursor); + obj[QStringLiteral("wrap_mode")] = wrapModeToString(m_wrapMode); + obj[QStringLiteral("expand_tab")] = m_expandTab; + obj[QStringLiteral("tab_stop_width")] = m_tabStopWidth; + obj[QStringLiteral("highlight_whitespace")] = m_highlightWhitespace; + obj[QStringLiteral("zoom_delta")] = m_zoomDelta; + obj[QStringLiteral("spell_check")] = m_spellCheckEnabled; + return obj; } -QString TextEditorConfig::lineNumberTypeToString(LineNumberType p_type) const -{ - switch (p_type) { - case LineNumberType::None: - return QStringLiteral("none"); +QString TextEditorConfig::lineNumberTypeToString(LineNumberType p_type) const { + switch (p_type) { + case LineNumberType::None: + return QStringLiteral("none"); - case LineNumberType::Relative: - return QStringLiteral("relative"); + case LineNumberType::Relative: + return QStringLiteral("relative"); - default: - return QStringLiteral("absolute"); - } + default: + return QStringLiteral("absolute"); + } } -TextEditorConfig::LineNumberType TextEditorConfig::stringToLineNumberType(const QString &p_str) const -{ - auto lineNumber = p_str.toLower(); - if (lineNumber == QStringLiteral("none")) { - return LineNumberType::None; - } else if (lineNumber == QStringLiteral("relative")) { - return LineNumberType::Relative; - } else { - return LineNumberType::Absolute; - } +TextEditorConfig::LineNumberType +TextEditorConfig::stringToLineNumberType(const QString &p_str) const { + auto lineNumber = p_str.toLower(); + if (lineNumber == QStringLiteral("none")) { + return LineNumberType::None; + } else if (lineNumber == QStringLiteral("relative")) { + return LineNumberType::Relative; + } else { + return LineNumberType::Absolute; + } } -QString TextEditorConfig::inputModeToString(InputMode p_mode) const -{ - switch (p_mode) { - case InputMode::ViMode: - return QStringLiteral("vi"); +QString TextEditorConfig::inputModeToString(InputMode p_mode) const { + switch (p_mode) { + case InputMode::ViMode: + return QStringLiteral("vi"); - case InputMode::VscodeMode: - return QStringLiteral("vscode"); + case InputMode::VscodeMode: + return QStringLiteral("vscode"); - default: - return QStringLiteral("normal"); - } + default: + return QStringLiteral("normal"); + } } -TextEditorConfig::InputMode TextEditorConfig::stringToInputMode(const QString &p_str) const -{ - auto inputMode = p_str.toLower(); - if (inputMode == QStringLiteral("vi")) { - return InputMode::ViMode; - } else if (inputMode == QStringLiteral("vscode")) { - return InputMode::VscodeMode; - } else { - return InputMode::NormalMode; - } +TextEditorConfig::InputMode TextEditorConfig::stringToInputMode(const QString &p_str) const { + auto inputMode = p_str.toLower(); + if (inputMode == QStringLiteral("vi")) { + return InputMode::ViMode; + } else if (inputMode == QStringLiteral("vscode")) { + return InputMode::VscodeMode; + } else { + return InputMode::NormalMode; + } } -QString TextEditorConfig::centerCursorToString(CenterCursor p_cursor) const -{ - switch (p_cursor) { - case CenterCursor::AlwaysCenter: - return QStringLiteral("always"); +QString TextEditorConfig::centerCursorToString(CenterCursor p_cursor) const { + switch (p_cursor) { + case CenterCursor::AlwaysCenter: + return QStringLiteral("always"); - case CenterCursor::CenterOnBottom: - return QStringLiteral("bottom"); + case CenterCursor::CenterOnBottom: + return QStringLiteral("bottom"); - default: - return QStringLiteral("never"); - } + default: + return QStringLiteral("never"); + } } -TextEditorConfig::CenterCursor TextEditorConfig::stringToCenterCursor(const QString &p_str) const -{ - auto centerCursor = p_str.toLower(); - if (centerCursor == QStringLiteral("always")) { - return CenterCursor::AlwaysCenter; - } else if (centerCursor == QStringLiteral("bottom")) { - return CenterCursor::CenterOnBottom; - } else { - return CenterCursor::NeverCenter; - } +TextEditorConfig::CenterCursor TextEditorConfig::stringToCenterCursor(const QString &p_str) const { + auto centerCursor = p_str.toLower(); + if (centerCursor == QStringLiteral("always")) { + return CenterCursor::AlwaysCenter; + } else if (centerCursor == QStringLiteral("bottom")) { + return CenterCursor::CenterOnBottom; + } else { + return CenterCursor::NeverCenter; + } } -QString TextEditorConfig::wrapModeToString(WrapMode p_mode) const -{ - switch (p_mode) { - case WrapMode::NoWrap: - return QStringLiteral("none"); +QString TextEditorConfig::wrapModeToString(WrapMode p_mode) const { + switch (p_mode) { + case WrapMode::NoWrap: + return QStringLiteral("none"); - case WrapMode::WrapAnywhere: - return QStringLiteral("anywhere"); + case WrapMode::WrapAnywhere: + return QStringLiteral("anywhere"); - case WrapMode::WordWrapOrAnywhere: - return QStringLiteral("word_anywhere"); + case WrapMode::WordWrapOrAnywhere: + return QStringLiteral("word_anywhere"); - default: - return QStringLiteral("word"); - } + default: + return QStringLiteral("word"); + } } -TextEditorConfig::WrapMode TextEditorConfig::stringToWrapMode(const QString &p_str) const -{ - auto centerCursor = p_str.toLower(); - if (centerCursor == QStringLiteral("none")) { - return WrapMode::NoWrap; - } else if (centerCursor == QStringLiteral("anywhere")) { - return WrapMode::WrapAnywhere; - } else if (centerCursor == QStringLiteral("word_anywhere")) { - return WrapMode::WordWrapOrAnywhere; - } else { - return WrapMode::WordWrap; - } +TextEditorConfig::WrapMode TextEditorConfig::stringToWrapMode(const QString &p_str) const { + auto centerCursor = p_str.toLower(); + if (centerCursor == QStringLiteral("none")) { + return WrapMode::NoWrap; + } else if (centerCursor == QStringLiteral("anywhere")) { + return WrapMode::WrapAnywhere; + } else if (centerCursor == QStringLiteral("word_anywhere")) { + return WrapMode::WordWrapOrAnywhere; + } else { + return WrapMode::WordWrap; + } } -TextEditorConfig::LineNumberType TextEditorConfig::getLineNumberType() const -{ - return m_lineNumberType; +TextEditorConfig::LineNumberType TextEditorConfig::getLineNumberType() const { + return m_lineNumberType; } -void TextEditorConfig::setLineNumberType(TextEditorConfig::LineNumberType p_type) -{ - updateConfig(m_lineNumberType, p_type, this); +void TextEditorConfig::setLineNumberType(TextEditorConfig::LineNumberType p_type) { + updateConfig(m_lineNumberType, p_type, this); } -bool TextEditorConfig::getTextFoldingEnabled() const -{ - return m_textFoldingEnabled; -} +bool TextEditorConfig::getTextFoldingEnabled() const { return m_textFoldingEnabled; } -void TextEditorConfig::setTextFoldingEnabled(bool p_enabled) -{ - updateConfig(m_textFoldingEnabled, p_enabled, this); +void TextEditorConfig::setTextFoldingEnabled(bool p_enabled) { + updateConfig(m_textFoldingEnabled, p_enabled, this); } -TextEditorConfig::InputMode TextEditorConfig::getInputMode() const -{ - return m_inputMode; -} +TextEditorConfig::InputMode TextEditorConfig::getInputMode() const { return m_inputMode; } -void TextEditorConfig::setInputMode(TextEditorConfig::InputMode p_mode) -{ - updateConfig(m_inputMode, p_mode, this); +void TextEditorConfig::setInputMode(TextEditorConfig::InputMode p_mode) { + updateConfig(m_inputMode, p_mode, this); } -TextEditorConfig::CenterCursor TextEditorConfig::getCenterCursor() const -{ - return m_centerCursor; -} +TextEditorConfig::CenterCursor TextEditorConfig::getCenterCursor() const { return m_centerCursor; } -void TextEditorConfig::setCenterCursor(TextEditorConfig::CenterCursor p_centerCursor) -{ - updateConfig(m_centerCursor, p_centerCursor, this); +void TextEditorConfig::setCenterCursor(TextEditorConfig::CenterCursor p_centerCursor) { + updateConfig(m_centerCursor, p_centerCursor, this); } -TextEditorConfig::WrapMode TextEditorConfig::getWrapMode() const -{ - return m_wrapMode; -} +TextEditorConfig::WrapMode TextEditorConfig::getWrapMode() const { return m_wrapMode; } -void TextEditorConfig::setWrapMode(TextEditorConfig::WrapMode p_mode) -{ - updateConfig(m_wrapMode, p_mode, this); +void TextEditorConfig::setWrapMode(TextEditorConfig::WrapMode p_mode) { + updateConfig(m_wrapMode, p_mode, this); } -bool TextEditorConfig::getExpandTabEnabled() const -{ - return m_expandTab; -} +bool TextEditorConfig::getExpandTabEnabled() const { return m_expandTab; } -void TextEditorConfig::setExpandTabEnabled(bool p_enabled) -{ - updateConfig(m_expandTab, p_enabled, this); +void TextEditorConfig::setExpandTabEnabled(bool p_enabled) { + updateConfig(m_expandTab, p_enabled, this); } -bool TextEditorConfig::getHighlightWhitespaceEnabled() const -{ - return m_highlightWhitespace; -} +bool TextEditorConfig::getHighlightWhitespaceEnabled() const { return m_highlightWhitespace; } -void TextEditorConfig::setHighlightWhitespaceEnabled(bool p_enabled) -{ - updateConfig(m_highlightWhitespace, p_enabled, this); +void TextEditorConfig::setHighlightWhitespaceEnabled(bool p_enabled) { + updateConfig(m_highlightWhitespace, p_enabled, this); } -int TextEditorConfig::getTabStopWidth() const -{ - return m_tabStopWidth; -} +int TextEditorConfig::getTabStopWidth() const { return m_tabStopWidth; } -void TextEditorConfig::setTabStopWidth(int p_width) -{ - updateConfig(m_tabStopWidth, p_width, this); -} +void TextEditorConfig::setTabStopWidth(int p_width) { updateConfig(m_tabStopWidth, p_width, this); } -int TextEditorConfig::getZoomDelta() const -{ - return m_zoomDelta; -} +int TextEditorConfig::getZoomDelta() const { return m_zoomDelta; } -void TextEditorConfig::setZoomDelta(int p_delta) -{ - updateConfig(m_zoomDelta, p_delta, this); -} +void TextEditorConfig::setZoomDelta(int p_delta) { updateConfig(m_zoomDelta, p_delta, this); } -bool TextEditorConfig::isSpellCheckEnabled() const -{ - return m_spellCheckEnabled; -} +bool TextEditorConfig::isSpellCheckEnabled() const { return m_spellCheckEnabled; } -void TextEditorConfig::setSpellCheckEnabled(bool p_enabled) -{ - updateConfig(m_spellCheckEnabled, p_enabled, this); +void TextEditorConfig::setSpellCheckEnabled(bool p_enabled) { + updateConfig(m_spellCheckEnabled, p_enabled, this); } diff --git a/src/core/texteditorconfig.h b/src/core/texteditorconfig.h index 7abc9f6f43..441abe1dec 100644 --- a/src/core/texteditorconfig.h +++ b/src/core/texteditorconfig.h @@ -3,113 +3,90 @@ #include "iconfig.h" -namespace vnotex -{ - class MainConfig; +namespace vnotex { +class MainConfig; - class TextEditorConfig : public IConfig - { - public: - enum class LineNumberType - { - None, - Absolute, - Relative - }; +class TextEditorConfig : public IConfig { +public: + enum class LineNumberType { None, Absolute, Relative }; - enum class InputMode - { - NormalMode, - ViMode, - VscodeMode - }; + enum class InputMode { NormalMode, ViMode, VscodeMode }; - enum class CenterCursor - { - NeverCenter, - AlwaysCenter, - CenterOnBottom - }; + enum class CenterCursor { NeverCenter, AlwaysCenter, CenterOnBottom }; - enum class WrapMode - { - NoWrap, - WordWrap, - WrapAnywhere, - WordWrapOrAnywhere - }; + enum class WrapMode { NoWrap, WordWrap, WrapAnywhere, WordWrapOrAnywhere }; - TextEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); + TextEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - TextEditorConfig::LineNumberType getLineNumberType() const; - void setLineNumberType(TextEditorConfig::LineNumberType p_type); + TextEditorConfig::LineNumberType getLineNumberType() const; + void setLineNumberType(TextEditorConfig::LineNumberType p_type); - bool getTextFoldingEnabled() const; - void setTextFoldingEnabled(bool p_enabled); + bool getTextFoldingEnabled() const; + void setTextFoldingEnabled(bool p_enabled); - TextEditorConfig::InputMode getInputMode() const; - void setInputMode(TextEditorConfig::InputMode p_mode); + TextEditorConfig::InputMode getInputMode() const; + void setInputMode(TextEditorConfig::InputMode p_mode); - TextEditorConfig::CenterCursor getCenterCursor() const; - void setCenterCursor(TextEditorConfig::CenterCursor p_centerCursor); + TextEditorConfig::CenterCursor getCenterCursor() const; + void setCenterCursor(TextEditorConfig::CenterCursor p_centerCursor); - TextEditorConfig::WrapMode getWrapMode() const; - void setWrapMode(TextEditorConfig::WrapMode p_mode); + TextEditorConfig::WrapMode getWrapMode() const; + void setWrapMode(TextEditorConfig::WrapMode p_mode); - bool getExpandTabEnabled() const; - void setExpandTabEnabled(bool p_enabled); + bool getExpandTabEnabled() const; + void setExpandTabEnabled(bool p_enabled); - int getTabStopWidth() const; - void setTabStopWidth(int p_width); + int getTabStopWidth() const; + void setTabStopWidth(int p_width); - bool getHighlightWhitespaceEnabled() const; - void setHighlightWhitespaceEnabled(bool p_enabled); + bool getHighlightWhitespaceEnabled() const; + void setHighlightWhitespaceEnabled(bool p_enabled); - int getZoomDelta() const; - void setZoomDelta(int p_delta); + int getZoomDelta() const; + void setZoomDelta(int p_delta); - bool isSpellCheckEnabled() const; - void setSpellCheckEnabled(bool p_enabled); + bool isSpellCheckEnabled() const; + void setSpellCheckEnabled(bool p_enabled); - private: - friend class MainConfig; +private: + friend class MainConfig; - QString lineNumberTypeToString(LineNumberType p_type) const; - LineNumberType stringToLineNumberType(const QString &p_str) const; + QString lineNumberTypeToString(LineNumberType p_type) const; + LineNumberType stringToLineNumberType(const QString &p_str) const; - QString inputModeToString(InputMode p_mode) const; - InputMode stringToInputMode(const QString &p_str) const; + QString inputModeToString(InputMode p_mode) const; + InputMode stringToInputMode(const QString &p_str) const; - QString centerCursorToString(CenterCursor p_cursor) const; - CenterCursor stringToCenterCursor(const QString &p_str) const; + QString centerCursorToString(CenterCursor p_cursor) const; + CenterCursor stringToCenterCursor(const QString &p_str) const; - QString wrapModeToString(WrapMode p_mode) const; - WrapMode stringToWrapMode(const QString &p_str) const; + QString wrapModeToString(WrapMode p_mode) const; + WrapMode stringToWrapMode(const QString &p_str) const; - LineNumberType m_lineNumberType = LineNumberType::Absolute; + LineNumberType m_lineNumberType = LineNumberType::Absolute; - bool m_textFoldingEnabled = true; + bool m_textFoldingEnabled = true; - InputMode m_inputMode = InputMode::NormalMode; + InputMode m_inputMode = InputMode::NormalMode; - CenterCursor m_centerCursor = CenterCursor::NeverCenter; + CenterCursor m_centerCursor = CenterCursor::NeverCenter; - WrapMode m_wrapMode = WrapMode::WordWrapOrAnywhere; + WrapMode m_wrapMode = WrapMode::WordWrapOrAnywhere; - bool m_expandTab = true; + bool m_expandTab = true; - int m_tabStopWidth = 4; + int m_tabStopWidth = 4; - bool m_highlightWhitespace = false; + bool m_highlightWhitespace = false; - int m_zoomDelta = 0; + int m_zoomDelta = 0; - bool m_spellCheckEnabled = false; - }; -} + bool m_spellCheckEnabled = false; +}; +} // namespace vnotex #endif // TEXTEDITORCONFIG_H diff --git a/src/core/theme.cpp b/src/core/theme.cpp index c149e5f09a..ec33a6963d 100644 --- a/src/core/theme.cpp +++ b/src/core/theme.cpp @@ -1,11 +1,11 @@ #include "theme.h" +#include #include -#include -#include #include #include -#include +#include +#include #include "exception.h" #include @@ -15,476 +15,433 @@ using namespace vnotex; -Theme::Theme(const QString &p_themeFolderPath, - const Metadata &p_metadata, - const Palette &p_palette) - : m_themeFolderPath(p_themeFolderPath), - m_metadata(p_metadata), - m_palette(p_palette) -{ -} +Theme::Theme(const QString &p_themeFolderPath, const Metadata &p_metadata, const Palette &p_palette) + : m_themeFolderPath(p_themeFolderPath), m_metadata(p_metadata), m_palette(p_palette) {} -QString vnotex::Theme::getThemeFolder() const -{ - return m_themeFolderPath; -} +QString vnotex::Theme::getThemeFolder() const { return m_themeFolderPath; } -bool Theme::isValidThemeFolder(const QString &p_folder) -{ - QDir dir(p_folder); - if (!dir.exists()) { - qWarning() << "theme folder does not exist" << p_folder; - return false; - } +bool Theme::isValidThemeFolder(const QString &p_folder) { + QDir dir(p_folder); + if (!dir.exists()) { + qWarning() << "theme folder does not exist" << p_folder; + return false; + } - // The Palette file must exist. - auto file = getFileName(File::Palette); - if (!dir.exists(file)) { - qWarning() << "Not a valid theme folder" << p_folder; - return false; - } + // The Palette file must exist. + auto file = getFileName(File::Palette); + if (!dir.exists(file)) { + qWarning() << "Not a valid theme folder" << p_folder; + return false; + } - return true; + return true; } -QString Theme::getDisplayName(const QString &p_folder, const QString &p_locale) -{ - auto obj = readPaletteFile(p_folder); - const auto metaObj = obj[QStringLiteral("metadata")].toObject(); - QString prefix("display_name"); - - if (!p_locale.isEmpty()) { - // Check full locale. - auto fullLocale = QStringLiteral("%1_%2").arg(prefix, p_locale); - if (metaObj.contains(fullLocale)) { - return metaObj.value(fullLocale).toString(); - } +QString Theme::getDisplayName(const QString &p_folder, const QString &p_locale) { + auto obj = readPaletteFile(p_folder); + const auto metaObj = obj[QStringLiteral("metadata")].toObject(); + QString prefix("display_name"); - auto shortLocale = QStringLiteral("%1_%2").arg(prefix, p_locale.split('_')[0]); - if (metaObj.contains(shortLocale)) { - return metaObj.value(shortLocale).toString(); - } + if (!p_locale.isEmpty()) { + // Check full locale. + auto fullLocale = QStringLiteral("%1_%2").arg(prefix, p_locale); + if (metaObj.contains(fullLocale)) { + return metaObj.value(fullLocale).toString(); } - if (metaObj.contains(prefix)) { - return metaObj.value(prefix).toString(); + auto shortLocale = QStringLiteral("%1_%2").arg(prefix, p_locale.split('_')[0]); + if (metaObj.contains(shortLocale)) { + return metaObj.value(shortLocale).toString(); } - return PathUtils::dirName(p_folder); + } + + if (metaObj.contains(prefix)) { + return metaObj.value(prefix).toString(); + } + return PathUtils::dirName(p_folder); } -Theme *Theme::fromFolder(const QString &p_folder) -{ - Q_ASSERT(!p_folder.isEmpty()); - auto obj = readPaletteFile(p_folder); - auto metadata = readMetadata(obj); - auto paletteObj = translatePalette(obj, metadata.m_backfillSystemPalette); - return new Theme(p_folder, - metadata, - paletteObj); +Theme *Theme::fromFolder(const QString &p_folder) { + Q_ASSERT(!p_folder.isEmpty()); + auto obj = readPaletteFile(p_folder); + auto metadata = readMetadata(obj); + auto paletteObj = translatePalette(obj, metadata.m_backfillSystemPalette); + return new Theme(p_folder, metadata, paletteObj); } -Theme::Metadata Theme::readMetadata(const Palette &p_obj) -{ - Metadata data; +Theme::Metadata Theme::readMetadata(const Palette &p_obj) { + Metadata data; - const auto metaObj = p_obj[QStringLiteral("metadata")].toObject(); + const auto metaObj = p_obj[QStringLiteral("metadata")].toObject(); - data.m_revision = metaObj[QStringLiteral("revision")].toInt(); - data.m_editorHighlightTheme = metaObj[QStringLiteral("editor-highlight-theme")].toString(); - data.m_markdownEditorHighlightTheme = metaObj[QStringLiteral("markdown-editor-highlight-theme")].toString(); - data.m_backfillSystemPalette = metaObj[QStringLiteral("backfill-system-palette")].toBool(false); + data.m_revision = metaObj[QStringLiteral("revision")].toInt(); + data.m_editorHighlightTheme = metaObj[QStringLiteral("editor-highlight-theme")].toString(); + data.m_markdownEditorHighlightTheme = + metaObj[QStringLiteral("markdown-editor-highlight-theme")].toString(); + data.m_backfillSystemPalette = metaObj[QStringLiteral("backfill-system-palette")].toBool(false); - return data; + return data; } -QJsonObject Theme::backfillSystemPalette(QJsonObject p_obj) -{ - const auto qpalette = QApplication::palette(); - // Active. - { - QJsonObject obj; - obj["window"] = qpalette.color(QPalette::Active, QPalette::Window).name(); - obj["window_text"] = qpalette.color(QPalette::Active, QPalette::WindowText).name(); - obj["base"] = qpalette.color(QPalette::Active, QPalette::Base).name(); - obj["alternate_base"] = qpalette.color(QPalette::Active, QPalette::AlternateBase).name(); - obj["text"] = qpalette.color(QPalette::Active, QPalette::Text).name(); - obj["button"] = qpalette.color(QPalette::Active, QPalette::Button).name(); - obj["button_text"] = qpalette.color(QPalette::Active, QPalette::ButtonText).name(); - obj["bright_text"] = qpalette.color(QPalette::Active, QPalette::BrightText).name(); - obj["light"] = qpalette.color(QPalette::Active, QPalette::Light).name(); - obj["midlight"] = qpalette.color(QPalette::Active, QPalette::Midlight).name(); - obj["dark"] = qpalette.color(QPalette::Active, QPalette::Dark).name(); - obj["highlight"] = qpalette.color(QPalette::Active, QPalette::Highlight).name(); - obj["highlighted_text"] = qpalette.color(QPalette::Active, QPalette::HighlightedText).name(); - obj["link"] = qpalette.color(QPalette::Active, QPalette::Link).name(); - obj["link_visited"] = qpalette.color(QPalette::Active, QPalette::LinkVisited).name(); - - p_obj["active"] = obj; - } - - // Inactive. - { - QJsonObject obj; - p_obj["inactive"] = obj; - } - - // Disabled. - { - QJsonObject obj; - obj["window"] = qpalette.color(QPalette::Disabled, QPalette::Window).name(); - obj["window_text"] = qpalette.color(QPalette::Disabled, QPalette::WindowText).name(); - obj["base"] = qpalette.color(QPalette::Disabled, QPalette::Base).name(); - obj["alternate_base"] = qpalette.color(QPalette::Disabled, QPalette::AlternateBase).name(); - obj["text"] = qpalette.color(QPalette::Disabled, QPalette::Text).name(); - obj["button"] = qpalette.color(QPalette::Disabled, QPalette::Button).name(); - obj["button_text"] = qpalette.color(QPalette::Disabled, QPalette::ButtonText).name(); - obj["bright_text"] = qpalette.color(QPalette::Disabled, QPalette::BrightText).name(); - obj["light"] = qpalette.color(QPalette::Disabled, QPalette::Light).name(); - obj["midlight"] = qpalette.color(QPalette::Disabled, QPalette::Midlight).name(); - obj["dark"] = qpalette.color(QPalette::Disabled, QPalette::Dark).name(); - obj["highlight"] = qpalette.color(QPalette::Disabled, QPalette::Highlight).name(); - obj["highlighted_text"] = qpalette.color(QPalette::Disabled, QPalette::HighlightedText).name(); - obj["link"] = qpalette.color(QPalette::Disabled, QPalette::Link).name(); - obj["link_visited"] = qpalette.color(QPalette::Disabled, QPalette::LinkVisited).name(); - - p_obj["disabled"] = obj; - } - - return p_obj; +QJsonObject Theme::backfillSystemPalette(QJsonObject p_obj) { + const auto qpalette = QApplication::palette(); + // Active. + { + QJsonObject obj; + obj["window"] = qpalette.color(QPalette::Active, QPalette::Window).name(); + obj["window_text"] = qpalette.color(QPalette::Active, QPalette::WindowText).name(); + obj["base"] = qpalette.color(QPalette::Active, QPalette::Base).name(); + obj["alternate_base"] = qpalette.color(QPalette::Active, QPalette::AlternateBase).name(); + obj["text"] = qpalette.color(QPalette::Active, QPalette::Text).name(); + obj["button"] = qpalette.color(QPalette::Active, QPalette::Button).name(); + obj["button_text"] = qpalette.color(QPalette::Active, QPalette::ButtonText).name(); + obj["bright_text"] = qpalette.color(QPalette::Active, QPalette::BrightText).name(); + obj["light"] = qpalette.color(QPalette::Active, QPalette::Light).name(); + obj["midlight"] = qpalette.color(QPalette::Active, QPalette::Midlight).name(); + obj["dark"] = qpalette.color(QPalette::Active, QPalette::Dark).name(); + obj["highlight"] = qpalette.color(QPalette::Active, QPalette::Highlight).name(); + obj["highlighted_text"] = qpalette.color(QPalette::Active, QPalette::HighlightedText).name(); + obj["link"] = qpalette.color(QPalette::Active, QPalette::Link).name(); + obj["link_visited"] = qpalette.color(QPalette::Active, QPalette::LinkVisited).name(); + + p_obj["active"] = obj; + } + + // Inactive. + { + QJsonObject obj; + p_obj["inactive"] = obj; + } + + // Disabled. + { + QJsonObject obj; + obj["window"] = qpalette.color(QPalette::Disabled, QPalette::Window).name(); + obj["window_text"] = qpalette.color(QPalette::Disabled, QPalette::WindowText).name(); + obj["base"] = qpalette.color(QPalette::Disabled, QPalette::Base).name(); + obj["alternate_base"] = qpalette.color(QPalette::Disabled, QPalette::AlternateBase).name(); + obj["text"] = qpalette.color(QPalette::Disabled, QPalette::Text).name(); + obj["button"] = qpalette.color(QPalette::Disabled, QPalette::Button).name(); + obj["button_text"] = qpalette.color(QPalette::Disabled, QPalette::ButtonText).name(); + obj["bright_text"] = qpalette.color(QPalette::Disabled, QPalette::BrightText).name(); + obj["light"] = qpalette.color(QPalette::Disabled, QPalette::Light).name(); + obj["midlight"] = qpalette.color(QPalette::Disabled, QPalette::Midlight).name(); + obj["dark"] = qpalette.color(QPalette::Disabled, QPalette::Dark).name(); + obj["highlight"] = qpalette.color(QPalette::Disabled, QPalette::Highlight).name(); + obj["highlighted_text"] = qpalette.color(QPalette::Disabled, QPalette::HighlightedText).name(); + obj["link"] = qpalette.color(QPalette::Disabled, QPalette::Link).name(); + obj["link_visited"] = qpalette.color(QPalette::Disabled, QPalette::LinkVisited).name(); + + p_obj["disabled"] = obj; + } + + return p_obj; } -Theme::Palette Theme::translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette) -{ - const QString paletteSection("palette"); - const QString baseSection("base"); - const QString widgetsSection("widgets"); +Theme::Palette Theme::translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette) { + const QString paletteSection("palette"); + const QString baseSection("base"); + const QString widgetsSection("widgets"); - // @p_palette may contain referenced definitons: derived=@base#sub#sub2. - Palette palette; + // @p_palette may contain referenced definitons: derived=@base#sub#sub2. + Palette palette; - if (p_backfillSystemPalette) { - palette[paletteSection] = backfillSystemPalette(p_obj[paletteSection].toObject()); - } else { - palette[paletteSection] = p_obj[paletteSection]; - } + if (p_backfillSystemPalette) { + palette[paletteSection] = backfillSystemPalette(p_obj[paletteSection].toObject()); + } else { + palette[paletteSection] = p_obj[paletteSection]; + } - palette[baseSection] = p_obj[baseSection]; - palette[widgetsSection] = p_obj[widgetsSection]; + palette[baseSection] = p_obj[baseSection]; + palette[widgetsSection] = p_obj[widgetsSection]; - // Skip paletteSection since it will not contain any reference. + // Skip paletteSection since it will not contain any reference. - translatePaletteObject(palette, palette, baseSection); + translatePaletteObject(palette, palette, baseSection); - translatePaletteObject(palette, palette, widgetsSection); + translatePaletteObject(palette, palette, widgetsSection); - return palette; + return palette; } -void Theme::translatePaletteObject(const Palette &p_palette, - QJsonObject &p_obj, - const QString &p_key) -{ - int lastUnresolvedRefs = 0; - while (true) - { - auto ret = translatePaletteObjectOnce(p_palette, p_obj, p_key); - if (!ret.first) { - break; - } +void Theme::translatePaletteObject(const Palette &p_palette, QJsonObject &p_obj, + const QString &p_key) { + int lastUnresolvedRefs = 0; + while (true) { + auto ret = translatePaletteObjectOnce(p_palette, p_obj, p_key); + if (!ret.first) { + break; + } - if (ret.second > 0 && ret.second == lastUnresolvedRefs) { - qWarning() << "found cyclic references in palette definitions" << p_obj[p_key]; - break; - } - lastUnresolvedRefs = ret.second; + if (ret.second > 0 && ret.second == lastUnresolvedRefs) { + qWarning() << "found cyclic references in palette definitions" << p_obj[p_key]; + break; } + lastUnresolvedRefs = ret.second; + } } -QPair Theme::translatePaletteObjectOnce(const Palette &p_palette, - QJsonObject &p_obj, - const QString &p_key) -{ - bool changed = false; - int unresolvedRefs = 0; - - // May contain referenced definitions: derived=@base#sub#sub2. - QRegularExpression refRe("\\A@(\\w+(?:#\\w+)*)\\z"); - const int baseCapturedIdx = 1; - - auto obj = p_obj[p_key].toObject(); - for (auto it = obj.begin(); it != obj.end(); ++it) { - auto val = it.value(); - if (val.isString()) { - // Check if it references to another key. - auto match = refRe.match(val.toString()); - if (match.hasMatch()) { - auto refVal = findValueByKeyPath(p_palette, match.captured(baseCapturedIdx)); - if (refVal.isUndefined()) { - ++unresolvedRefs; - qWarning() << "failed to find palette key" << match.captured(baseCapturedIdx); - break; - } else if (val.toString() == refVal.toString()) { - ++unresolvedRefs; - qWarning() << "found cyclic references in palette definitions" << it.key() << val.toString(); - break; - } - - Q_ASSERT_X(refVal.isString(), "translatePaletteObjectOnce", val.toString().toStdString().c_str()); - const auto refValStr = refVal.toString(); - it.value() = refValStr; - if (isRef(refValStr)) { - // It is another ref again. - ++unresolvedRefs; - } - changed = true; - } - } else if (val.isObject()) { - auto ret = translatePaletteObjectOnce(p_palette, obj, it.key()); - changed = changed || ret.first; - unresolvedRefs += ret.second; - } else { - Q_ASSERT(false); +QPair Theme::translatePaletteObjectOnce(const Palette &p_palette, QJsonObject &p_obj, + const QString &p_key) { + bool changed = false; + int unresolvedRefs = 0; + + // May contain referenced definitions: derived=@base#sub#sub2. + QRegularExpression refRe("\\A@(\\w+(?:#\\w+)*)\\z"); + const int baseCapturedIdx = 1; + + auto obj = p_obj[p_key].toObject(); + for (auto it = obj.begin(); it != obj.end(); ++it) { + auto val = it.value(); + if (val.isString()) { + // Check if it references to another key. + auto match = refRe.match(val.toString()); + if (match.hasMatch()) { + auto refVal = findValueByKeyPath(p_palette, match.captured(baseCapturedIdx)); + if (refVal.isUndefined()) { + ++unresolvedRefs; + qWarning() << "failed to find palette key" << match.captured(baseCapturedIdx); + break; + } else if (val.toString() == refVal.toString()) { + ++unresolvedRefs; + qWarning() << "found cyclic references in palette definitions" << it.key() + << val.toString(); + break; } - } - if (changed) { - p_obj[p_key] = obj; + Q_ASSERT_X(refVal.isString(), "translatePaletteObjectOnce", + val.toString().toStdString().c_str()); + const auto refValStr = refVal.toString(); + it.value() = refValStr; + if (isRef(refValStr)) { + // It is another ref again. + ++unresolvedRefs; + } + changed = true; + } + } else if (val.isObject()) { + auto ret = translatePaletteObjectOnce(p_palette, obj, it.key()); + changed = changed || ret.first; + unresolvedRefs += ret.second; + } else { + Q_ASSERT(false); } - return qMakePair(changed, unresolvedRefs); + } + + if (changed) { + p_obj[p_key] = obj; + } + return qMakePair(changed, unresolvedRefs); } -QString Theme::fetchQtStyleSheet() const -{ - const auto qtStyleFile = getFile(File::QtStyleSheet); - if (qtStyleFile.isEmpty()) { - return ""; - } - auto style = FileUtils::readTextFile(qtStyleFile); - translateStyleByPalette(m_palette, style); - translateUrlToAbsolute(m_themeFolderPath, style); - translateFontFamilyList(style); - return style; +QString Theme::fetchQtStyleSheet() const { + const auto qtStyleFile = getFile(File::QtStyleSheet); + if (qtStyleFile.isEmpty()) { + return ""; + } + auto style = FileUtils::readTextFile(qtStyleFile); + translateStyleByPalette(m_palette, style); + translateUrlToAbsolute(m_themeFolderPath, style); + translateFontFamilyList(style); + return style; } -void Theme::translateStyleByPalette(const Palette &p_palette, QString &p_style) -{ - QRegularExpression refRe("(\\s|:)@(\\w+(?:#\\w+)*)"); - const int prefixCapturedIdx = 1; - const int refCapturedIdx = 2; - - int pos = 0; - QRegularExpressionMatch match; - while (pos < p_style.size()) { - int idx = p_style.indexOf(refRe, pos, &match); - if (idx == -1) { - break; - } +void Theme::translateStyleByPalette(const Palette &p_palette, QString &p_style) { + QRegularExpression refRe("(\\s|:)@(\\w+(?:#\\w+)*)"); + const int prefixCapturedIdx = 1; + const int refCapturedIdx = 2; + + int pos = 0; + QRegularExpressionMatch match; + while (pos < p_style.size()) { + int idx = p_style.indexOf(refRe, pos, &match); + if (idx == -1) { + break; + } - auto name = match.captured(refCapturedIdx); - auto val = findValueByKeyPath(p_palette, name).toString(); - if (val.isEmpty() || isRef(val)) { - qWarning() << "failed to translate style" << name << val; - pos = idx + match.capturedLength(); - } else { - pos = idx + match.capturedLength() + val.size() - (name.size() + 1); - p_style.replace(idx + match.captured(prefixCapturedIdx).size(), - name.size() + 1, - val); - } + auto name = match.captured(refCapturedIdx); + auto val = findValueByKeyPath(p_palette, name).toString(); + if (val.isEmpty() || isRef(val)) { + qWarning() << "failed to translate style" << name << val; + pos = idx + match.capturedLength(); + } else { + pos = idx + match.capturedLength() + val.size() - (name.size() + 1); + p_style.replace(idx + match.captured(prefixCapturedIdx).size(), name.size() + 1, val); } + } } -void Theme::translateUrlToAbsolute(const QString &p_basePath, QString &p_style) -{ - QRegularExpression urlRe("(\\s|:)url\\(([^\\(\\)]+)\\)"); - const int prefixCapturedIdx = 1; - const int urlCapturedIdx = 2; - - QDir dir(p_basePath); - const int literalSize = QStringLiteral("url(").size(); - int pos = 0; - QRegularExpressionMatch match; - while (pos < p_style.size()) { - int idx = p_style.indexOf(urlRe, pos, &match); - if (idx == -1) { - break; - } +void Theme::translateUrlToAbsolute(const QString &p_basePath, QString &p_style) { + QRegularExpression urlRe("(\\s|:)url\\(([^\\(\\)]+)\\)"); + const int prefixCapturedIdx = 1; + const int urlCapturedIdx = 2; + + QDir dir(p_basePath); + const int literalSize = QStringLiteral("url(").size(); + int pos = 0; + QRegularExpressionMatch match; + while (pos < p_style.size()) { + int idx = p_style.indexOf(urlRe, pos, &match); + if (idx == -1) { + break; + } - auto url = match.captured(urlCapturedIdx); - if (QFileInfo(url).isRelative()) { - auto absoluteUrl = dir.filePath(url); - pos = idx + match.capturedLength() + absoluteUrl.size() - url.size(); - p_style.replace(idx + match.captured(prefixCapturedIdx).size() + literalSize, - url.size(), - absoluteUrl); - } else { - pos = idx + match.capturedLength(); - } + auto url = match.captured(urlCapturedIdx); + if (QFileInfo(url).isRelative()) { + auto absoluteUrl = dir.filePath(url); + pos = idx + match.capturedLength() + absoluteUrl.size() - url.size(); + p_style.replace(idx + match.captured(prefixCapturedIdx).size() + literalSize, url.size(), + absoluteUrl); + } else { + pos = idx + match.capturedLength(); } + } } -void Theme::translateFontFamilyList(QString &p_style) -{ - QRegularExpression fontRe("(\\s|^)font-family:([^;]+);"); - const int prefixCapturedIdx = 1; - const int fontCapturedIdx = 2; - - int pos = 0; - QRegularExpressionMatch match; - while (pos < p_style.size()) { - int idx = p_style.indexOf(fontRe, pos, &match); - if (idx == -1) { - break; - } +void Theme::translateFontFamilyList(QString &p_style) { + QRegularExpression fontRe("(\\s|^)font-family:([^;]+);"); + const int prefixCapturedIdx = 1; + const int fontCapturedIdx = 2; + + int pos = 0; + QRegularExpressionMatch match; + while (pos < p_style.size()) { + int idx = p_style.indexOf(fontRe, pos, &match); + if (idx == -1) { + break; + } - auto familyList = match.captured(fontCapturedIdx).trimmed(); - familyList.remove('"'); - auto family = Utils::pickAvailableFontFamily(familyList.split(',')); - if (family.isEmpty()) { - // Could not find available font. Remove it. - auto newStr = match.captured(prefixCapturedIdx); - p_style.replace(idx, match.capturedLength(), newStr); - pos = idx + newStr.size(); - } else if (family != familyList) { - if (family.contains(' ')) { - family = "\"" + family + "\""; - } - - auto newStr = QStringLiteral("%1font-family: %2;").arg(match.captured(prefixCapturedIdx), family); - p_style.replace(idx, match.capturedLength(), newStr); - pos = idx + newStr.size(); - } else { - pos = idx + match.capturedLength(); - } + auto familyList = match.captured(fontCapturedIdx).trimmed(); + familyList.remove('"'); + auto family = Utils::pickAvailableFontFamily(familyList.split(',')); + if (family.isEmpty()) { + // Could not find available font. Remove it. + auto newStr = match.captured(prefixCapturedIdx); + p_style.replace(idx, match.capturedLength(), newStr); + pos = idx + newStr.size(); + } else if (family != familyList) { + if (family.contains(' ')) { + family = "\"" + family + "\""; + } + + auto newStr = + QStringLiteral("%1font-family: %2;").arg(match.captured(prefixCapturedIdx), family); + p_style.replace(idx, match.capturedLength(), newStr); + pos = idx + newStr.size(); + } else { + pos = idx + match.capturedLength(); } + } } -QString Theme::paletteColor(const QString &p_name) const -{ - auto val = findValueByKeyPath(m_palette, p_name).toString(); - if (!val.isEmpty() && !isRef(val)) { - return val; - } - qWarning() << "undefined or invalid palette color" << p_name; - return QString(); +QString Theme::paletteColor(const QString &p_name) const { + auto val = findValueByKeyPath(m_palette, p_name).toString(); + if (!val.isEmpty() && !isRef(val)) { + return val; + } + qWarning() << "undefined or invalid palette color" << p_name; + return QString(); } -QJsonObject Theme::readJsonFile(const QString &p_filePath) -{ - auto bytes = FileUtils::readFile(p_filePath); - return QJsonDocument::fromJson(bytes).object(); +QJsonObject Theme::readJsonFile(const QString &p_filePath) { + auto bytes = FileUtils::readFile(p_filePath); + return QJsonDocument::fromJson(bytes).object(); } -QJsonObject Theme::readPaletteFile(const QString &p_folder) -{ - auto obj = readJsonFile(QDir(p_folder).filePath(getFileName(File::Palette))); - return obj; +QJsonObject Theme::readPaletteFile(const QString &p_folder) { + auto obj = readJsonFile(QDir(p_folder).filePath(getFileName(File::Palette))); + return obj; } -QJsonValue Theme::findValueByKeyPath(const Palette &p_palette, const QString &p_keyPath) -{ - auto keys = p_keyPath.split('#'); - Q_ASSERT(!keys.isEmpty()); - if (keys.size() == 1) { - return p_palette[keys.first()]; - } +QJsonValue Theme::findValueByKeyPath(const Palette &p_palette, const QString &p_keyPath) { + auto keys = p_keyPath.split('#'); + Q_ASSERT(!keys.isEmpty()); + if (keys.size() == 1) { + return p_palette[keys.first()]; + } - auto obj = p_palette; - for (int i = 0; i < keys.size() - 1; ++i) { - obj = obj[keys[i]].toObject(); - } + auto obj = p_palette; + for (int i = 0; i < keys.size() - 1; ++i) { + obj = obj[keys[i]].toObject(); + } - return obj[keys.last()]; + return obj[keys.last()]; } -bool Theme::isRef(const QString &p_str) -{ - return p_str.startsWith('@'); -} +bool Theme::isRef(const QString &p_str) { return p_str.startsWith('@'); } -QString Theme::getFile(File p_fileType) const -{ - return getFile(m_themeFolderPath, p_fileType); -} +QString Theme::getFile(File p_fileType) const { return getFile(m_themeFolderPath, p_fileType); } -QString Theme::getFile(const QString &p_themeFolder, File p_fileType) -{ - QDir dir(p_themeFolder); - if (dir.exists(getFileName(p_fileType))) { - return dir.filePath(getFileName(p_fileType)); - } else if (p_fileType == File::MarkdownEditorStyle) { - // Fallback to text editor style. - if (dir.exists(getFileName(File::TextEditorStyle))) { - return dir.filePath(getFileName(File::TextEditorStyle)); - } +QString Theme::getFile(const QString &p_themeFolder, File p_fileType) { + QDir dir(p_themeFolder); + if (dir.exists(getFileName(p_fileType))) { + return dir.filePath(getFileName(p_fileType)); + } else if (p_fileType == File::MarkdownEditorStyle) { + // Fallback to text editor style. + if (dir.exists(getFileName(File::TextEditorStyle))) { + return dir.filePath(getFileName(File::TextEditorStyle)); } - return ""; + } + return ""; } -QString Theme::getFileName(File p_fileType) -{ - switch (p_fileType) { - case File::Palette: - return QStringLiteral("palette.json"); - case File::QtStyleSheet: - return QStringLiteral("interface.qss"); - case File::WebStyleSheet: - return QStringLiteral("web.css"); - case File::HighlightStyleSheet: - return QStringLiteral("highlight.css"); - case File::TextEditorStyle: - return QStringLiteral("text-editor.theme"); - case File::MarkdownEditorStyle: - return QStringLiteral("markdown-text-editor.theme"); - case File::EditorHighlightStyle: - return QStringLiteral("editor-highlight.theme"); - case File::MarkdownEditorHighlightStyle: - return QStringLiteral("markdown-editor-highlight.theme"); - case File::Cover: - return QStringLiteral("cover.png"); - case File::Icon: - return QStringLiteral("icons"); - default: - Q_ASSERT(false); - return ""; - } +QString Theme::getFileName(File p_fileType) { + switch (p_fileType) { + case File::Palette: + return QStringLiteral("palette.json"); + case File::QtStyleSheet: + return QStringLiteral("interface.qss"); + case File::WebStyleSheet: + return QStringLiteral("web.css"); + case File::HighlightStyleSheet: + return QStringLiteral("highlight.css"); + case File::TextEditorStyle: + return QStringLiteral("text-editor.theme"); + case File::MarkdownEditorStyle: + return QStringLiteral("markdown-text-editor.theme"); + case File::EditorHighlightStyle: + return QStringLiteral("editor-highlight.theme"); + case File::MarkdownEditorHighlightStyle: + return QStringLiteral("markdown-editor-highlight.theme"); + case File::Cover: + return QStringLiteral("cover.png"); + case File::Icon: + return QStringLiteral("icons"); + default: + Q_ASSERT(false); + return ""; + } } -QString Theme::getEditorHighlightTheme() const -{ - auto file = getFile(File::EditorHighlightStyle); - if (file.isEmpty()) { - return m_metadata.m_editorHighlightTheme; - } else { - return file; - } +QString Theme::getEditorHighlightTheme() const { + auto file = getFile(File::EditorHighlightStyle); + if (file.isEmpty()) { + return m_metadata.m_editorHighlightTheme; + } else { + return file; + } } -QString Theme::getMarkdownEditorHighlightTheme() const -{ - auto file = getFile(File::MarkdownEditorHighlightStyle); - if (!file.isEmpty()) { - return file; - } +QString Theme::getMarkdownEditorHighlightTheme() const { + auto file = getFile(File::MarkdownEditorHighlightStyle); + if (!file.isEmpty()) { + return file; + } - if (!m_metadata.m_markdownEditorHighlightTheme.isEmpty()) { - return m_metadata.m_markdownEditorHighlightTheme; - } + if (!m_metadata.m_markdownEditorHighlightTheme.isEmpty()) { + return m_metadata.m_markdownEditorHighlightTheme; + } - return getEditorHighlightTheme(); + return getEditorHighlightTheme(); } -QString Theme::name() const -{ - return PathUtils::dirName(m_themeFolderPath); -} +QString Theme::name() const { return PathUtils::dirName(m_themeFolderPath); } -QPixmap Theme::getCover(const QString &p_folder) -{ - QDir dir(p_folder); - if (dir.exists(getFileName(File::Cover))) { - const auto coverFile = dir.filePath(getFileName(File::Cover)); - return QPixmap(coverFile); - } - return QPixmap(); +QPixmap Theme::getCover(const QString &p_folder) { + QDir dir(p_folder); + if (dir.exists(getFileName(File::Cover))) { + const auto coverFile = dir.filePath(getFileName(File::Cover)); + return QPixmap(coverFile); + } + return QPixmap(); } diff --git a/src/core/theme.h b/src/core/theme.h index 42d2588c08..52798a5074 100644 --- a/src/core/theme.h +++ b/src/core/theme.h @@ -1,131 +1,122 @@ #ifndef THEME_H #define THEME_H -#include #include #include #include #include +#include -namespace tests -{ - class TestTheme; +namespace tests { +class TestTheme; } -namespace vnotex -{ - class Theme - { - public: - enum class File - { - Palette = 0, - QtStyleSheet, - WebStyleSheet, - HighlightStyleSheet, - TextEditorStyle, - MarkdownEditorStyle, - EditorHighlightStyle, - MarkdownEditorHighlightStyle, - Cover, - Icon, - Max - }; +namespace vnotex { +class Theme { +public: + enum class File { + Palette = 0, + QtStyleSheet, + WebStyleSheet, + HighlightStyleSheet, + TextEditorStyle, + MarkdownEditorStyle, + EditorHighlightStyle, + MarkdownEditorHighlightStyle, + Cover, + Icon, + Max + }; - QString fetchQtStyleSheet() const; + QString fetchQtStyleSheet() const; - QString paletteColor(const QString &p_name) const; + QString paletteColor(const QString &p_name) const; - // Get the file path of @p_fileType if exists. - QString getFile(File p_fileType) const; + // Get the file path of @p_fileType if exists. + QString getFile(File p_fileType) const; - // Return the file path of the theme or just the theme name. - QString getEditorHighlightTheme() const; + // Return the file path of the theme or just the theme name. + QString getEditorHighlightTheme() const; - // Return the file path of the theme or just the theme name. - QString getMarkdownEditorHighlightTheme() const; + // Return the file path of the theme or just the theme name. + QString getMarkdownEditorHighlightTheme() const; - QString name() const; + QString name() const; - QString getThemeFolder() const; + QString getThemeFolder() const; - static bool isValidThemeFolder(const QString &p_folder); + static bool isValidThemeFolder(const QString &p_folder); - static Theme *fromFolder(const QString &p_folder); + static Theme *fromFolder(const QString &p_folder); - static QString getDisplayName(const QString &p_folder, const QString &p_locale); + static QString getDisplayName(const QString &p_folder, const QString &p_locale); - static QPixmap getCover(const QString &p_folder); + static QPixmap getCover(const QString &p_folder); - static QString getFile(const QString &p_themeFolder, File p_fileType); + static QString getFile(const QString &p_themeFolder, File p_fileType); - private: - struct Metadata - { - int m_revision = 0; +private: + struct Metadata { + int m_revision = 0; - // Name of the theme for editor syntax highlight. - // Will be ignored if EditorHighlightStyle file exists within the theme. - QString m_editorHighlightTheme; + // Name of the theme for editor syntax highlight. + // Will be ignored if EditorHighlightStyle file exists within the theme. + QString m_editorHighlightTheme; - // Use for MarkdownEditor code block highlight. - // If not specified, will use m_editorHighlightTheme. - // Valid only when KSyntaxCodeBlockHighlighter is used. - QString m_markdownEditorHighlightTheme; + // Use for MarkdownEditor code block highlight. + // If not specified, will use m_editorHighlightTheme. + // Valid only when KSyntaxCodeBlockHighlighter is used. + QString m_markdownEditorHighlightTheme; - // Whether this theme needs to backfill current standard palette to the theme palette. - bool m_backfillSystemPalette = false; - }; + // Whether this theme needs to backfill current standard palette to the theme palette. + bool m_backfillSystemPalette = false; + }; - typedef QJsonObject Palette; + typedef QJsonObject Palette; - Theme(const QString &p_themeFolderPath, - const Metadata &p_metadata, - const QJsonObject &p_palette); + Theme(const QString &p_themeFolderPath, const Metadata &p_metadata, const QJsonObject &p_palette); - QString m_themeFolderPath; + QString m_themeFolderPath; - Theme::Metadata m_metadata; + Theme::Metadata m_metadata; - Palette m_palette; + Palette m_palette; - static Metadata readMetadata(const QJsonObject &p_obj); + static Metadata readMetadata(const QJsonObject &p_obj); - static Theme::Palette translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette); + static Theme::Palette translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette); - static QJsonObject backfillSystemPalette(QJsonObject p_obj); + static QJsonObject backfillSystemPalette(QJsonObject p_obj); - static void translatePaletteObject(const Palette &p_palette, - QJsonObject &p_obj, - const QString &p_key); + static void translatePaletteObject(const Palette &p_palette, QJsonObject &p_obj, + const QString &p_key); - // Translate p_obj[p_key] by looking up @p_palette. - // Return . - static QPair translatePaletteObjectOnce(const Palette &p_palette, - QJsonObject &p_obj, - const QString &p_key); + // Translate p_obj[p_key] by looking up @p_palette. + // Return . + static QPair translatePaletteObjectOnce(const Palette &p_palette, QJsonObject &p_obj, + const QString &p_key); - static QJsonValue findValueByKeyPath(const Palette &p_palette, const QString &p_keyPath); + static QJsonValue findValueByKeyPath(const Palette &p_palette, const QString &p_keyPath); - static void translateStyleByPalette(const Palette &p_palette, QString &p_style); + static void translateStyleByPalette(const Palette &p_palette, QString &p_style); - static void translateUrlToAbsolute(const QString &p_basePath, QString &p_style); + static void translateUrlToAbsolute(const QString &p_basePath, QString &p_style); - // Font-family in QSS only supports specifying one font, not a list. - // Thus we need to choose one available font from the list. - static void translateFontFamilyList(QString &p_style); + // Font-family in QSS only supports specifying one font, not a list. + // Thus we need to choose one available font from the list. + static void translateFontFamilyList(QString &p_style); - static QJsonObject readJsonFile(const QString &p_filePath); + static QJsonObject readJsonFile(const QString &p_filePath); - static QJsonObject readPaletteFile(const QString &p_folder); + static QJsonObject readPaletteFile(const QString &p_folder); - // Whether @p_str is a reference definition like "@xxxx". - static bool isRef(const QString &p_str); + // Whether @p_str is a reference definition like "@xxxx". + static bool isRef(const QString &p_str); - static QString getFileName(File p_fileType); + static QString getFileName(File p_fileType); - friend class tests::TestTheme; - }; -} // ns vnotex + friend class tests::TestTheme; +}; +} // namespace vnotex #endif // THEME_H diff --git a/src/core/thememgr.cpp b/src/core/thememgr.cpp index 705227cc1b..293cf22c0f 100644 --- a/src/core/thememgr.cpp +++ b/src/core/thememgr.cpp @@ -1,16 +1,16 @@ #include "thememgr.h" -#include -#include #include +#include +#include -#include -#include "exception.h" -#include -#include #include "configmgr.h" #include "coreconfig.h" +#include "exception.h" #include "theme.h" +#include +#include +#include using namespace vnotex; @@ -18,242 +18,205 @@ QStringList ThemeMgr::s_searchPaths; QStringList ThemeMgr::s_webStylesSearchPaths; -ThemeMgr::ThemeMgr(const QString &p_currentThemeName, QObject *p_parent) - : QObject(p_parent) -{ - loadAvailableThemes(); +ThemeMgr::ThemeMgr(const QString &p_currentThemeName, QObject *p_parent) : QObject(p_parent) { + loadAvailableThemes(); - loadCurrentTheme(p_currentThemeName); + loadCurrentTheme(p_currentThemeName); } -QString ThemeMgr::getIconFile(const QString &p_icon) const -{ - Q_ASSERT(!p_icon.isEmpty()); +QString ThemeMgr::getIconFile(const QString &p_icon) const { + Q_ASSERT(!p_icon.isEmpty()); - QRegularExpression sep("[/\\\\]"); - if (p_icon.indexOf(sep) != -1) { - return p_icon; - } + QRegularExpression sep("[/\\\\]"); + if (p_icon.indexOf(sep) != -1) { + return p_icon; + } - // If there is an ICONS folder in the theme configuration, use the custom ICONS from it. - QString customIcon = getFile(Theme::File::Icon) + "/" + p_icon; - if (QFile::exists(customIcon)) { - return customIcon; - } else { - return ":/vnotex/data/core/icons/" + p_icon; - } + // If there is an ICONS folder in the theme configuration, use the custom ICONS from it. + QString customIcon = getFile(Theme::File::Icon) + "/" + p_icon; + if (QFile::exists(customIcon)) { + return customIcon; + } else { + return ":/vnotex/data/core/icons/" + p_icon; + } } -void ThemeMgr::loadAvailableThemes() -{ - m_themes.clear(); +void ThemeMgr::loadAvailableThemes() { + m_themes.clear(); - for (const auto &pa : s_searchPaths) { - loadThemes(pa); - } + for (const auto &pa : s_searchPaths) { + loadThemes(pa); + } - if (m_themes.isEmpty()) { - Exception::throwOne(Exception::Type::EssentialFileMissing, - QStringLiteral("no available themes found in paths: %1").arg(s_searchPaths.join(QLatin1Char(';')))); - } + if (m_themes.isEmpty()) { + Exception::throwOne(Exception::Type::EssentialFileMissing, + QStringLiteral("no available themes found in paths: %1") + .arg(s_searchPaths.join(QLatin1Char(';')))); + } } -void ThemeMgr::loadThemes(const QString &p_path) -{ - qDebug() << "search for themes in" << p_path; - QDir dir(p_path); - dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); - auto themeFolders = dir.entryList(); - const auto localeStr = ConfigMgr::getInst().getCoreConfig().getLocaleToUse(); - for (auto &folder : themeFolders) { - checkAndAddThemeFolder(PathUtils::concatenateFilePath(p_path, folder), localeStr); - } +void ThemeMgr::loadThemes(const QString &p_path) { + qDebug() << "search for themes in" << p_path; + QDir dir(p_path); + dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + auto themeFolders = dir.entryList(); + const auto localeStr = ConfigMgr::getInst().getCoreConfig().getLocaleToUse(); + for (auto &folder : themeFolders) { + checkAndAddThemeFolder(PathUtils::concatenateFilePath(p_path, folder), localeStr); + } } -void ThemeMgr::checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale) -{ - if (Theme::isValidThemeFolder(p_folder)) { - ThemeInfo info; - info.m_name = PathUtils::dirName(p_folder); - info.m_displayName = Theme::getDisplayName(p_folder, p_locale); - info.m_folderPath = p_folder; - m_themes.push_back(info); - qDebug() << "add theme" << info.m_name << info.m_displayName << info.m_folderPath; - } +void ThemeMgr::checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale) { + if (Theme::isValidThemeFolder(p_folder)) { + ThemeInfo info; + info.m_name = PathUtils::dirName(p_folder); + info.m_displayName = Theme::getDisplayName(p_folder, p_locale); + info.m_folderPath = p_folder; + m_themes.push_back(info); + qDebug() << "add theme" << info.m_name << info.m_displayName << info.m_folderPath; + } } -const Theme &ThemeMgr::getCurrentTheme() const -{ - return *m_currentTheme; -} +const Theme &ThemeMgr::getCurrentTheme() const { return *m_currentTheme; } -void ThemeMgr::loadCurrentTheme(const QString &p_themeName) -{ - m_currentTheme.reset(); - auto themeFolder = findThemeFolder(p_themeName); - if (themeFolder.isNull()) { - qWarning() << "failed to locate theme" << p_themeName; - } else { - qInfo() << "using theme" << p_themeName; - m_currentTheme.reset(loadTheme(themeFolder)); - } +void ThemeMgr::loadCurrentTheme(const QString &p_themeName) { + m_currentTheme.reset(); + auto themeFolder = findThemeFolder(p_themeName); + if (themeFolder.isNull()) { + qWarning() << "failed to locate theme" << p_themeName; + } else { + qInfo() << "using theme" << p_themeName; + m_currentTheme.reset(loadTheme(themeFolder)); + } - if (!m_currentTheme) { - const QString defaultTheme("pure"); - qWarning() << "fall back to default theme" << defaultTheme; - m_currentTheme.reset(loadTheme(findThemeFolder(defaultTheme))); - } + if (!m_currentTheme) { + const QString defaultTheme("pure"); + qWarning() << "fall back to default theme" << defaultTheme; + m_currentTheme.reset(loadTheme(findThemeFolder(defaultTheme))); + } - IconUtils::setDefaultIconForeground(paletteColor("base#icon#fg"), paletteColor("base#icon#disabled#fg")); + IconUtils::setDefaultIconForeground(paletteColor("base#icon#fg"), + paletteColor("base#icon#disabled#fg")); } -Theme *ThemeMgr::loadTheme(const QString &p_themeFolder) -{ - if (p_themeFolder.isEmpty()) { - qWarning("failed to load theme from empty folder"); - return nullptr; - } +Theme *ThemeMgr::loadTheme(const QString &p_themeFolder) { + if (p_themeFolder.isEmpty()) { + qWarning("failed to load theme from empty folder"); + return nullptr; + } - try { - return Theme::fromFolder(p_themeFolder); - } catch (Exception &p_e) { - qWarning("failed to load theme from folder %s (%s)", - p_themeFolder.toStdString().c_str(), - p_e.what()); - return nullptr; - } + try { + return Theme::fromFolder(p_themeFolder); + } catch (Exception &p_e) { + qWarning("failed to load theme from folder %s (%s)", p_themeFolder.toStdString().c_str(), + p_e.what()); + return nullptr; + } } -QString ThemeMgr::findThemeFolder(const QString &p_name) const -{ - auto theme = findTheme(p_name); - if (theme) { - return theme->m_folderPath; - } - return QString(); +QString ThemeMgr::findThemeFolder(const QString &p_name) const { + auto theme = findTheme(p_name); + if (theme) { + return theme->m_folderPath; + } + return QString(); } -const ThemeMgr::ThemeInfo *ThemeMgr::findTheme(const QString &p_name) const -{ - for (const auto &info : m_themes) { - if (info.m_name == p_name) { - return &info; - } +const ThemeMgr::ThemeInfo *ThemeMgr::findTheme(const QString &p_name) const { + for (const auto &info : m_themes) { + if (info.m_name == p_name) { + return &info; } + } - return nullptr; + return nullptr; } -QString ThemeMgr::fetchQtStyleSheet() const -{ - Q_ASSERT(m_currentTheme); - if (!m_currentTheme) { - return QString(); - } +QString ThemeMgr::fetchQtStyleSheet() const { + Q_ASSERT(m_currentTheme); + if (!m_currentTheme) { + return QString(); + } - return m_currentTheme->fetchQtStyleSheet(); + return m_currentTheme->fetchQtStyleSheet(); } -QString ThemeMgr::paletteColor(const QString &p_name) const -{ - Q_ASSERT(m_currentTheme); - return m_currentTheme->paletteColor(p_name); +QString ThemeMgr::paletteColor(const QString &p_name) const { + Q_ASSERT(m_currentTheme); + return m_currentTheme->paletteColor(p_name); } -void ThemeMgr::addSearchPath(const QString &p_path) -{ - s_searchPaths << p_path; -} +void ThemeMgr::addSearchPath(const QString &p_path) { s_searchPaths << p_path; } -QString ThemeMgr::getFile(Theme::File p_fileType) const -{ - return m_currentTheme->getFile(p_fileType); +QString ThemeMgr::getFile(Theme::File p_fileType) const { + return m_currentTheme->getFile(p_fileType); } -QString ThemeMgr::getEditorHighlightTheme() const -{ - return m_currentTheme->getEditorHighlightTheme(); +QString ThemeMgr::getEditorHighlightTheme() const { + return m_currentTheme->getEditorHighlightTheme(); } -QString ThemeMgr::getMarkdownEditorHighlightTheme() const -{ - return m_currentTheme->getMarkdownEditorHighlightTheme(); +QString ThemeMgr::getMarkdownEditorHighlightTheme() const { + return m_currentTheme->getMarkdownEditorHighlightTheme(); } -void ThemeMgr::addSyntaxHighlightingSearchPaths(const QStringList &p_paths) -{ - vte::VTextEditor::addSyntaxCustomSearchPaths(p_paths); +void ThemeMgr::addSyntaxHighlightingSearchPaths(const QStringList &p_paths) { + vte::VTextEditor::addSyntaxCustomSearchPaths(p_paths); } -const QColor &ThemeMgr::getBaseBackground() const -{ - return m_baseBackground; -} +const QColor &ThemeMgr::getBaseBackground() const { return m_baseBackground; } -void ThemeMgr::setBaseBackground(const QColor &p_bg) -{ - m_baseBackground = p_bg; -} +void ThemeMgr::setBaseBackground(const QColor &p_bg) { m_baseBackground = p_bg; } -const QVector &ThemeMgr::getAllThemes() const -{ - return m_themes; -} +const QVector &ThemeMgr::getAllThemes() const { return m_themes; } -QPixmap ThemeMgr::getThemePreview(const QString &p_name) const -{ - auto theme = findTheme(p_name); - if (theme) { - return Theme::getCover(theme->m_folderPath); - } - return QPixmap(); +QPixmap ThemeMgr::getThemePreview(const QString &p_name) const { + auto theme = findTheme(p_name); + if (theme) { + return Theme::getCover(theme->m_folderPath); + } + return QPixmap(); } -void ThemeMgr::refresh() -{ - loadAvailableThemes(); - refreshCurrentTheme(); +void ThemeMgr::refresh() { + loadAvailableThemes(); + refreshCurrentTheme(); } -void vnotex::ThemeMgr::refreshCurrentTheme() -{ - if (m_currentTheme) { - loadCurrentTheme(m_currentTheme->name()); - } +void vnotex::ThemeMgr::refreshCurrentTheme() { + if (m_currentTheme) { + loadCurrentTheme(m_currentTheme->name()); + } } -void ThemeMgr::addWebStylesSearchPath(const QString &p_path) -{ - s_webStylesSearchPaths << p_path; -} +void ThemeMgr::addWebStylesSearchPath(const QString &p_path) { s_webStylesSearchPaths << p_path; } + +QVector> ThemeMgr::getWebStyles() const { + QVector> styles; + + // From themes. + for (const auto &th : m_themes) { + auto filePath = Theme::getFile(th.m_folderPath, Theme::File::WebStyleSheet); + if (!filePath.isEmpty()) { + styles.push_back(qMakePair( + tr("[Theme] %1 %2").arg(th.m_displayName, PathUtils::fileName(filePath)), filePath)); + } -QVector> ThemeMgr::getWebStyles() const -{ - QVector> styles; - - // From themes. - for (const auto &th : m_themes) { - auto filePath = Theme::getFile(th.m_folderPath, Theme::File::WebStyleSheet); - if (!filePath.isEmpty()) { - styles.push_back(qMakePair(tr("[Theme] %1 %2").arg(th.m_displayName, PathUtils::fileName(filePath)), - filePath)); - } - - filePath = Theme::getFile(th.m_folderPath, Theme::File::HighlightStyleSheet); - if (!filePath.isEmpty()) { - styles.push_back(qMakePair(tr("[Theme] %1 %2").arg(th.m_displayName, PathUtils::fileName(filePath)), - filePath)); - } + filePath = Theme::getFile(th.m_folderPath, Theme::File::HighlightStyleSheet); + if (!filePath.isEmpty()) { + styles.push_back(qMakePair( + tr("[Theme] %1 %2").arg(th.m_displayName, PathUtils::fileName(filePath)), filePath)); } + } - // From search paths. - for (const auto &pa : s_webStylesSearchPaths) { - QDir dir(pa); - auto styleFiles = dir.entryList({"*.css"}, QDir::Files); - for (const auto &file : styleFiles) { - styles.push_back(qMakePair(file, dir.filePath(file))); - } + // From search paths. + for (const auto &pa : s_webStylesSearchPaths) { + QDir dir(pa); + auto styleFiles = dir.entryList({"*.css"}, QDir::Files); + for (const auto &file : styleFiles) { + styles.push_back(qMakePair(file, dir.filePath(file))); } + } - return styles; + return styles; } diff --git a/src/core/thememgr.h b/src/core/thememgr.h index 399fde4355..5c11ebfd22 100644 --- a/src/core/thememgr.h +++ b/src/core/thememgr.h @@ -3,105 +3,102 @@ #include -#include +#include +#include #include +#include #include #include -#include -#include #include "theme.h" -namespace vnotex -{ - class ThemeMgr : public QObject - { - Q_OBJECT - public: - struct ThemeInfo - { - // Id. - QString m_name; +namespace vnotex { +class ThemeMgr : public QObject { + Q_OBJECT +public: + struct ThemeInfo { + // Id. + QString m_name; - // Locale supported. - QString m_displayName; + // Locale supported. + QString m_displayName; - QString m_folderPath; - }; + QString m_folderPath; + }; - ThemeMgr(const QString &p_currentThemeName, QObject *p_parent = nullptr); + ThemeMgr(const QString &p_currentThemeName, QObject *p_parent = nullptr); - // @p_icon: file path or file name of the icon. - // If @p_icon is a path, just return it. - // Otherwise, first try to find it in current theme, and if not found, - // find it in resource file. - // Return the path of the icon to use. - QString getIconFile(const QString &p_icon) const; + // @p_icon: file path or file name of the icon. + // If @p_icon is a path, just return it. + // Otherwise, first try to find it in current theme, and if not found, + // find it in resource file. + // Return the path of the icon to use. + QString getIconFile(const QString &p_icon) const; - QString fetchQtStyleSheet() const; + QString fetchQtStyleSheet() const; - QString paletteColor(const QString &p_name) const; + QString paletteColor(const QString &p_name) const; - QString getFile(Theme::File p_fileType) const; + QString getFile(Theme::File p_fileType) const; - // Return the file path of the theme or just the theme name. - QString getEditorHighlightTheme() const; + // Return the file path of the theme or just the theme name. + QString getEditorHighlightTheme() const; - QString getMarkdownEditorHighlightTheme() const; + QString getMarkdownEditorHighlightTheme() const; - const QColor &getBaseBackground() const; - void setBaseBackground(const QColor &p_bg); + const QColor &getBaseBackground() const; + void setBaseBackground(const QColor &p_bg); - const QVector &getAllThemes() const; + const QVector &getAllThemes() const; - const Theme &getCurrentTheme() const; + const Theme &getCurrentTheme() const; - QPixmap getThemePreview(const QString &p_name) const; + QPixmap getThemePreview(const QString &p_name) const; - const ThemeInfo *findTheme(const QString &p_name) const; + const ThemeInfo *findTheme(const QString &p_name) const; - // Refresh the themes list and reload current theme. - void refresh(); + // Refresh the themes list and reload current theme. + void refresh(); - void refreshCurrentTheme(); + void refreshCurrentTheme(); - // Return all web stylesheets available, including those from themes and web styles search paths. - // . - QVector> getWebStyles() const; + // Return all web stylesheets available, including those from themes and web styles search paths. + // . + QVector> getWebStyles() const; - static void addSearchPath(const QString &p_path); + static void addSearchPath(const QString &p_path); - static void addSyntaxHighlightingSearchPaths(const QStringList &p_paths); + static void addSyntaxHighlightingSearchPaths(const QStringList &p_paths); - static void addWebStylesSearchPath(const QString &p_path); + static void addWebStylesSearchPath(const QString &p_path); - private: - void loadAvailableThemes(); +private: + void loadAvailableThemes(); - void loadThemes(const QString &p_path); + void loadThemes(const QString &p_path); - void checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale); + void checkAndAddThemeFolder(const QString &p_folder, const QString &p_locale); - void loadCurrentTheme(const QString &p_themeName); + void loadCurrentTheme(const QString &p_themeName); - Theme *loadTheme(const QString &p_themeFolder); + Theme *loadTheme(const QString &p_themeFolder); - QString findThemeFolder(const QString &p_name) const; + QString findThemeFolder(const QString &p_name) const; - QVector m_themes; + QVector m_themes; - QScopedPointer m_currentTheme; + QScopedPointer m_currentTheme; - // Background of the main window. - // Set at runtime, not from the theme config. - QColor m_baseBackground; + // Background of the main window. + // Set at runtime, not from the theme config. + QColor m_baseBackground; - // List of paths to search for themes. - static QStringList s_searchPaths; + // List of paths to search for themes. + static QStringList s_searchPaths; - // List of paths to search for CSS styles, including CSS syntax highlighting styles. - static QStringList s_webStylesSearchPaths; - }; -} // ns vnotex + // List of paths to search for CSS styles, including CSS syntax highlighting styles. + static QStringList s_webStylesSearchPaths; +}; +} // namespace vnotex #endif // THEMEMGR_H diff --git a/src/core/versioncontroller/dummyversioncontroller.cpp b/src/core/versioncontroller/dummyversioncontroller.cpp index fd4f14129d..6e5e316152 100644 --- a/src/core/versioncontroller/dummyversioncontroller.cpp +++ b/src/core/versioncontroller/dummyversioncontroller.cpp @@ -2,27 +2,12 @@ using namespace vnotex; +DummyVersionController::DummyVersionController(const QString &p_name, const QString &p_displayName, + const QString &p_description, QObject *p_parent) + : IVersionController(p_parent), m_info(p_name, p_displayName, p_description) {} -DummyVersionController::DummyVersionController(const QString &p_name, - const QString &p_displayName, - const QString &p_description, - QObject *p_parent) - : IVersionController(p_parent), - m_info(p_name, p_displayName, p_description) -{ -} +QString DummyVersionController::getName() const { return m_info.m_name; } -QString DummyVersionController::getName() const -{ - return m_info.m_name; -} +QString DummyVersionController::getDisplayName() const { return m_info.m_displayName; } -QString DummyVersionController::getDisplayName() const -{ - return m_info.m_displayName; -} - -QString DummyVersionController::getDescription() const -{ - return m_info.m_description; -} +QString DummyVersionController::getDescription() const { return m_info.m_description; } diff --git a/src/core/versioncontroller/dummyversioncontroller.h b/src/core/versioncontroller/dummyversioncontroller.h index c2bcb10005..fa122d37c9 100644 --- a/src/core/versioncontroller/dummyversioncontroller.h +++ b/src/core/versioncontroller/dummyversioncontroller.h @@ -5,26 +5,22 @@ #include -namespace vnotex -{ - class DummyVersionController : public IVersionController - { - Q_OBJECT - public: - explicit DummyVersionController(const QString &p_name, - const QString &p_displayName, - const QString &p_description, - QObject *p_parent = nullptr); - - QString getName() const Q_DECL_OVERRIDE; - - QString getDisplayName() const Q_DECL_OVERRIDE; - - QString getDescription() const Q_DECL_OVERRIDE; - - private: - Info m_info; - }; -} // ns vnotex +namespace vnotex { +class DummyVersionController : public IVersionController { + Q_OBJECT +public: + explicit DummyVersionController(const QString &p_name, const QString &p_displayName, + const QString &p_description, QObject *p_parent = nullptr); + + QString getName() const Q_DECL_OVERRIDE; + + QString getDisplayName() const Q_DECL_OVERRIDE; + + QString getDescription() const Q_DECL_OVERRIDE; + +private: + Info m_info; +}; +} // namespace vnotex #endif // DUMMYVERSIONCONTROLLER_H diff --git a/src/core/versioncontroller/dummyversioncontrollerfactory.cpp b/src/core/versioncontroller/dummyversioncontrollerfactory.cpp index 1de741c984..f979448880 100644 --- a/src/core/versioncontroller/dummyversioncontrollerfactory.cpp +++ b/src/core/versioncontroller/dummyversioncontrollerfactory.cpp @@ -6,28 +6,19 @@ using namespace vnotex; #include "dummyversioncontroller.h" -DummyVersionControllerFactory::DummyVersionControllerFactory() -{ -} +DummyVersionControllerFactory::DummyVersionControllerFactory() {} -QString DummyVersionControllerFactory::getName() const -{ - return QStringLiteral("dummy.vnotex"); -} +QString DummyVersionControllerFactory::getName() const { return QStringLiteral("dummy.vnotex"); } -QString DummyVersionControllerFactory::getDisplayName() const -{ - return QObject::tr("No Version Control"); +QString DummyVersionControllerFactory::getDisplayName() const { + return QObject::tr("No Version Control"); } -QString DummyVersionControllerFactory::getDescription() const -{ - return QObject::tr("Disable version control"); +QString DummyVersionControllerFactory::getDescription() const { + return QObject::tr("Disable version control"); } -QSharedPointer DummyVersionControllerFactory::createVersionController() -{ - return QSharedPointer::create(getName(), - getDisplayName(), - getDescription()); +QSharedPointer DummyVersionControllerFactory::createVersionController() { + return QSharedPointer::create(getName(), getDisplayName(), + getDescription()); } diff --git a/src/core/versioncontroller/dummyversioncontrollerfactory.h b/src/core/versioncontroller/dummyversioncontrollerfactory.h index 481f35bf4a..94f66988d0 100644 --- a/src/core/versioncontroller/dummyversioncontrollerfactory.h +++ b/src/core/versioncontroller/dummyversioncontrollerfactory.h @@ -3,22 +3,19 @@ #include "iversioncontrollerfactory.h" +namespace vnotex { +class DummyVersionControllerFactory : public IVersionControllerFactory { +public: + DummyVersionControllerFactory(); -namespace vnotex -{ - class DummyVersionControllerFactory : public IVersionControllerFactory - { - public: - DummyVersionControllerFactory(); + QString getName() const Q_DECL_OVERRIDE; - QString getName() const Q_DECL_OVERRIDE; + QString getDisplayName() const Q_DECL_OVERRIDE; - QString getDisplayName() const Q_DECL_OVERRIDE; + QString getDescription() const Q_DECL_OVERRIDE; - QString getDescription()const Q_DECL_OVERRIDE; - - QSharedPointer createVersionController() Q_DECL_OVERRIDE; - }; -} // ns vnotex + QSharedPointer createVersionController() Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // DUMMYVERSIONCONTROLLERFACTORY_H diff --git a/src/core/versioncontroller/iversioncontroller.h b/src/core/versioncontroller/iversioncontroller.h index 768e4518c4..8047a6120b 100644 --- a/src/core/versioncontroller/iversioncontroller.h +++ b/src/core/versioncontroller/iversioncontroller.h @@ -3,28 +3,21 @@ #include -namespace vnotex -{ - // Abstract class for version control. - class IVersionController : public QObject - { - Q_OBJECT - public: - explicit IVersionController(QObject *p_parent = nullptr) - : QObject(p_parent) - { - } +namespace vnotex { +// Abstract class for version control. +class IVersionController : public QObject { + Q_OBJECT +public: + explicit IVersionController(QObject *p_parent = nullptr) : QObject(p_parent) {} - virtual ~IVersionController() - { - } + virtual ~IVersionController() {} - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; - }; -} // ns vnotex + virtual QString getDescription() const = 0; +}; +} // namespace vnotex #endif // IVERSIONCONTROLLER_H diff --git a/src/core/versioncontroller/iversioncontrollerfactory.h b/src/core/versioncontroller/iversioncontrollerfactory.h index f2c8f135f1..a16ccd1527 100644 --- a/src/core/versioncontroller/iversioncontrollerfactory.h +++ b/src/core/versioncontroller/iversioncontrollerfactory.h @@ -3,29 +3,23 @@ #include -namespace vnotex -{ - class IVersionController; +namespace vnotex { +class IVersionController; - class IVersionControllerFactory - { - public: - IVersionControllerFactory() - { - } +class IVersionControllerFactory { +public: + IVersionControllerFactory() {} - virtual ~IVersionControllerFactory() - { - } + virtual ~IVersionControllerFactory() {} - virtual QString getName() const = 0; + virtual QString getName() const = 0; - virtual QString getDisplayName() const = 0; + virtual QString getDisplayName() const = 0; - virtual QString getDescription() const = 0; + virtual QString getDescription() const = 0; - virtual QSharedPointer createVersionController() = 0; - }; -} // ns vnotex + virtual QSharedPointer createVersionController() = 0; +}; +} // namespace vnotex #endif // IVERSIONCONTROLLERFACTORY_H diff --git a/src/core/versioncontroller/versioncontrollerserver.cpp b/src/core/versioncontroller/versioncontrollerserver.cpp index 356b1d261e..20f7bc52af 100644 --- a/src/core/versioncontroller/versioncontrollerserver.cpp +++ b/src/core/versioncontroller/versioncontrollerserver.cpp @@ -7,32 +7,29 @@ using namespace vnotex; -VersionControllerServer::VersionControllerServer() -{ +VersionControllerServer::VersionControllerServer() {} + +bool VersionControllerServer::registerFactory( + const QSharedPointer &p_factory) { + Q_ASSERT(p_factory); + if (m_factories.contains(p_factory->getName())) { + qWarning() << "VersionControllerFactory to register already exists" << p_factory->getName() + << p_factory->getDisplayName(); + return false; + } + + qDebug() << "VersionControllerFactory" << p_factory->getName() << "registered"; + m_factories.insert(p_factory->getName(), p_factory); + return true; } -bool VersionControllerServer::registerFactory(const QSharedPointer &p_factory) -{ - Q_ASSERT(p_factory); - if (m_factories.contains(p_factory->getName())) { - qWarning() << "VersionControllerFactory to register already exists" - << p_factory->getName() - << p_factory->getDisplayName(); - return false; - } - - qDebug() << "VersionControllerFactory" << p_factory->getName() << "registered"; - m_factories.insert(p_factory->getName(), p_factory); - return true; -} - -QSharedPointer VersionControllerServer::createVersionController(const QString &p_name) -{ - auto it = m_factories.find(p_name); - if (it != m_factories.end()) { - auto &factory = it.value(); - return factory->createVersionController(); - } +QSharedPointer +VersionControllerServer::createVersionController(const QString &p_name) { + auto it = m_factories.find(p_name); + if (it != m_factories.end()) { + auto &factory = it.value(); + return factory->createVersionController(); + } - return nullptr; + return nullptr; } diff --git a/src/core/versioncontroller/versioncontrollerserver.h b/src/core/versioncontroller/versioncontrollerserver.h index d8e27c3b87..320813508a 100644 --- a/src/core/versioncontroller/versioncontrollerserver.h +++ b/src/core/versioncontroller/versioncontrollerserver.h @@ -4,26 +4,24 @@ #include #include -namespace vnotex -{ - class IVersionController; - class IVersionControllerFactory; +namespace vnotex { +class IVersionController; +class IVersionControllerFactory; - class VersionControllerServer - { - public: - VersionControllerServer(); +class VersionControllerServer { +public: + VersionControllerServer(); - // Register a factory. - bool registerFactory(const QSharedPointer &p_factory); + // Register a factory. + bool registerFactory(const QSharedPointer &p_factory); - // @p_name: Name of the version controller to create. - QSharedPointer createVersionController(const QString &p_name); + // @p_name: Name of the version controller to create. + QSharedPointer createVersionController(const QString &p_name); - private: - // Name to factory mapping. - QHash> m_factories; - }; -} // ns vnotex +private: + // Name to factory mapping. + QHash> m_factories; +}; +} // namespace vnotex #endif // VERSIONCONTROLLERSERVER_H diff --git a/src/core/vnotex.cpp b/src/core/vnotex.cpp index ee6c4c62e5..65a96ea498 100644 --- a/src/core/vnotex.cpp +++ b/src/core/vnotex.cpp @@ -3,155 +3,124 @@ #include #include -#include -#include "notebookmgr.h" #include "buffermgr.h" #include "configmgr.h" #include "coreconfig.h" #include "location.h" +#include "notebookmgr.h" +#include #include "fileopenparameters.h" #include "quickaccesshelper.h" -#include #include - +#include using namespace vnotex; -VNoteX::VNoteX(QObject *p_parent) - : QObject(p_parent) -{ - m_instanceId = QRandomGenerator::global()->generate64(); +VNoteX::VNoteX(QObject *p_parent) : QObject(p_parent) { + m_instanceId = QRandomGenerator::global()->generate64(); - initThemeMgr(); + initThemeMgr(); - initTaskMgr(); + initTaskMgr(); - initNotebookMgr(); + initNotebookMgr(); - initBufferMgr(); + initBufferMgr(); - initDocsUtils(); + initDocsUtils(); - initQuickAccess(); + initQuickAccess(); } -void VNoteX::initLoad() -{ - qDebug() << "start init which may take a while"; - m_notebookMgr->loadNotebooks(); - m_taskMgr->init(); +void VNoteX::initLoad() { + qDebug() << "start init which may take a while"; + m_notebookMgr->loadNotebooks(); + m_taskMgr->init(); } -void VNoteX::initThemeMgr() -{ - Q_ASSERT(!m_themeMgr); - auto &configMgr = ConfigMgr::getInst(); - ThemeMgr::addSearchPath(configMgr.getAppThemeFolder()); - ThemeMgr::addSearchPath(configMgr.getUserThemeFolder()); - ThemeMgr::addSyntaxHighlightingSearchPaths( - QStringList() << configMgr.getUserSyntaxHighlightingFolder() - << configMgr.getAppSyntaxHighlightingFolder()); - ThemeMgr::addWebStylesSearchPath(configMgr.getAppWebStylesFolder()); - ThemeMgr::addWebStylesSearchPath(configMgr.getUserWebStylesFolder()); - m_themeMgr = new ThemeMgr(configMgr.getCoreConfig().getTheme(), this); +void VNoteX::initThemeMgr() { + Q_ASSERT(!m_themeMgr); + auto &configMgr = ConfigMgr::getInst(); + ThemeMgr::addSearchPath(configMgr.getAppThemeFolder()); + ThemeMgr::addSearchPath(configMgr.getUserThemeFolder()); + ThemeMgr::addSyntaxHighlightingSearchPaths(QStringList() + << configMgr.getUserSyntaxHighlightingFolder() + << configMgr.getAppSyntaxHighlightingFolder()); + ThemeMgr::addWebStylesSearchPath(configMgr.getAppWebStylesFolder()); + ThemeMgr::addWebStylesSearchPath(configMgr.getUserWebStylesFolder()); + m_themeMgr = new ThemeMgr(configMgr.getCoreConfig().getTheme(), this); } -void VNoteX::initTaskMgr() -{ - Q_ASSERT(!m_taskMgr); - m_taskMgr = new TaskMgr(this); - connect(m_taskMgr, &TaskMgr::taskOutputRequested, - this, &VNoteX::showOutputRequested); +void VNoteX::initTaskMgr() { + Q_ASSERT(!m_taskMgr); + m_taskMgr = new TaskMgr(this); + connect(m_taskMgr, &TaskMgr::taskOutputRequested, this, &VNoteX::showOutputRequested); } -ThemeMgr &VNoteX::getThemeMgr() const -{ - return *m_themeMgr; -} +ThemeMgr &VNoteX::getThemeMgr() const { return *m_themeMgr; } -TaskMgr &VNoteX::getTaskMgr() const -{ - return *m_taskMgr; -} +TaskMgr &VNoteX::getTaskMgr() const { return *m_taskMgr; } -void VNoteX::setMainWindow(MainWindow *p_mainWindow) -{ - Q_ASSERT(!m_mainWindow); - m_mainWindow = p_mainWindow; +void VNoteX::setMainWindow(MainWindow *p_mainWindow) { + Q_ASSERT(!m_mainWindow); + m_mainWindow = p_mainWindow; } -MainWindow *VNoteX::getMainWindow() const -{ - Q_ASSERT(m_mainWindow); - return m_mainWindow; +MainWindow *VNoteX::getMainWindow() const { + Q_ASSERT(m_mainWindow); + return m_mainWindow; } -void VNoteX::initNotebookMgr() -{ - Q_ASSERT(!m_notebookMgr); - m_notebookMgr = new NotebookMgr(this); - m_notebookMgr->init(); +void VNoteX::initNotebookMgr() { + Q_ASSERT(!m_notebookMgr); + m_notebookMgr = new NotebookMgr(this); + m_notebookMgr->init(); } -void VNoteX::initBufferMgr() -{ - BufferMgr::updateSuffixToFileType(ConfigMgr::getInst().getCoreConfig().getFileTypeSuffixes()); +void VNoteX::initBufferMgr() { + BufferMgr::updateSuffixToFileType(ConfigMgr::getInst().getCoreConfig().getFileTypeSuffixes()); - Q_ASSERT(!m_bufferMgr); - m_bufferMgr = new BufferMgr(this); - m_bufferMgr->init(); + Q_ASSERT(!m_bufferMgr); + m_bufferMgr = new BufferMgr(this); + m_bufferMgr->init(); - connect(this, &VNoteX::openNodeRequested, - m_bufferMgr, QOverload &>::of(&BufferMgr::open)); + connect(this, &VNoteX::openNodeRequested, m_bufferMgr, + QOverload &>::of(&BufferMgr::open)); - connect(this, &VNoteX::openFileRequested, - m_bufferMgr, QOverload &>::of(&BufferMgr::open)); + connect( + this, &VNoteX::openFileRequested, m_bufferMgr, + QOverload &>::of(&BufferMgr::open)); } -NotebookMgr &VNoteX::getNotebookMgr() const -{ - return *m_notebookMgr; -} +NotebookMgr &VNoteX::getNotebookMgr() const { return *m_notebookMgr; } -BufferMgr &VNoteX::getBufferMgr() const -{ - return *m_bufferMgr; -} +BufferMgr &VNoteX::getBufferMgr() const { return *m_bufferMgr; } -void VNoteX::showStatusMessage(const QString &p_message, int p_timeoutMilliseconds) -{ - emit statusMessageRequested(p_message, p_timeoutMilliseconds); +void VNoteX::showStatusMessage(const QString &p_message, int p_timeoutMilliseconds) { + emit statusMessageRequested(p_message, p_timeoutMilliseconds); } -void VNoteX::showStatusMessageShort(const QString &p_message) -{ - showStatusMessage(p_message, 3000); +void VNoteX::showStatusMessageShort(const QString &p_message) { + showStatusMessage(p_message, 3000); } -void VNoteX::showTips(const QString &p_message, int p_timeoutMilliseconds) -{ - emit tipsRequested(p_message, p_timeoutMilliseconds); +void VNoteX::showTips(const QString &p_message, int p_timeoutMilliseconds) { + emit tipsRequested(p_message, p_timeoutMilliseconds); } -ID VNoteX::getInstanceId() const -{ - return m_instanceId; -} +ID VNoteX::getInstanceId() const { return m_instanceId; } -void VNoteX::initDocsUtils() -{ - auto &configMgr = ConfigMgr::getInst(); - // If we got a match in user folder, stop the search. - DocsUtils::addSearchPath(configMgr.getUserDocsFolder()); - DocsUtils::addSearchPath(configMgr.getAppDocsFolder()); +void VNoteX::initDocsUtils() { + auto &configMgr = ConfigMgr::getInst(); + // If we got a match in user folder, stop the search. + DocsUtils::addSearchPath(configMgr.getUserDocsFolder()); + DocsUtils::addSearchPath(configMgr.getAppDocsFolder()); - DocsUtils::setLocale(configMgr.getCoreConfig().getLocaleToUse()); + DocsUtils::setLocale(configMgr.getCoreConfig().getLocaleToUse()); } -void VNoteX::initQuickAccess() -{ - connect(this, &VNoteX::pinToQuickAccessRequested, - this, &QuickAccessHelper::pinToQuickAccess); +void VNoteX::initQuickAccess() { + connect(this, &VNoteX::pinToQuickAccessRequested, this, &QuickAccessHelper::pinToQuickAccess); } diff --git a/src/core/vnotex.h b/src/core/vnotex.h index fa3a4977d3..4d1b32207f 100644 --- a/src/core/vnotex.h +++ b/src/core/vnotex.h @@ -4,154 +4,152 @@ #include #include +#include "global.h" #include "noncopyable.h" #include "thememgr.h" -#include "global.h" -namespace vnotex -{ - class MainWindow; - class NotebookMgr; - class BufferMgr; - class Node; - struct FileOpenParameters; - class Event; - class Notebook; - struct ComplexLocation; - class TaskMgr; +namespace vnotex { +class MainWindow; +class NotebookMgr; +class BufferMgr; +class Node; +struct FileOpenParameters; +class Event; +class Notebook; +struct ComplexLocation; +class TaskMgr; - class VNoteX : public QObject, private Noncopyable - { - Q_OBJECT - public: - static VNoteX &getInst() - { - static VNoteX inst; - return inst; - } +class VNoteX : public QObject, private Noncopyable { + Q_OBJECT +public: + static VNoteX &getInst() { + static VNoteX inst; + return inst; + } - // MUST be called to load some heavy data. - // It is good to call it after MainWindow is shown. - void initLoad(); + // MUST be called to load some heavy data. + // It is good to call it after MainWindow is shown. + void initLoad(); - ThemeMgr &getThemeMgr() const; + ThemeMgr &getThemeMgr() const; - TaskMgr &getTaskMgr() const; + TaskMgr &getTaskMgr() const; - void setMainWindow(MainWindow *p_mainWindow); - MainWindow *getMainWindow() const; + void setMainWindow(MainWindow *p_mainWindow); + MainWindow *getMainWindow() const; - NotebookMgr &getNotebookMgr() const; + NotebookMgr &getNotebookMgr() const; - BufferMgr &getBufferMgr() const; + BufferMgr &getBufferMgr() const; - ID getInstanceId() const; + ID getInstanceId() const; - public slots: - void showStatusMessage(const QString &p_message, int p_timeoutMilliseconds = 0); +public slots: + void showStatusMessage(const QString &p_message, int p_timeoutMilliseconds = 0); - void showStatusMessageShort(const QString &p_message); + void showStatusMessageShort(const QString &p_message); - void showTips(const QString &p_message, int p_timeoutMilliseconds = 3000); + void showTips(const QString &p_message, int p_timeoutMilliseconds = 3000); - signals: - // Requested to new a notebook. - void newNotebookRequested(); +signals: + // Requested to new a notebook. + void newNotebookRequested(); - // Requested to new a notebook from existing folder. - void newNotebookFromFolderRequested(); + // Requested to new a notebook from existing folder. + void newNotebookFromFolderRequested(); - // Requested to import a notebook. - void importNotebookRequested(); + // Requested to import a notebook. + void importNotebookRequested(); - // Requested to import a legacy notebook from VNote 2.0. - void importLegacyNotebookRequested(); + // Requested to import a legacy notebook from VNote 2.0. + void importLegacyNotebookRequested(); - void manageNotebooksRequested(); + void manageNotebooksRequested(); - // Requested to import files. - void importFileRequested(); + // Requested to import files. + void importFileRequested(); - // Requested to import folder. - void importFolderRequested(); + // Requested to import folder. + void importFolderRequested(); - // Requested to new a note in current notebook. - // The handler should determine in which folder this note belongs to. - void newNoteRequested(); + // Requested to new a note in current notebook. + // The handler should determine in which folder this note belongs to. + void newNoteRequested(); - // Requested to new a quick note (maybe in current folder). - void newQuickNoteRequested(); + // Requested to new a quick note (maybe in current folder). + void newQuickNoteRequested(); - // Requested to new a folder in current notebook. - void newFolderRequested(); + // Requested to new a folder in current notebook. + void newFolderRequested(); - // Requested to show output message. - void showOutputRequested(const QString &p_text); + // Requested to show output message. + void showOutputRequested(const QString &p_text); - // Requested to show status message. - void statusMessageRequested(const QString &p_message, int p_timeoutMilliseconds); + // Requested to show status message. + void statusMessageRequested(const QString &p_message, int p_timeoutMilliseconds); - void tipsRequested(const QString &p_message, int p_timeoutMilliseconds); + void tipsRequested(const QString &p_message, int p_timeoutMilliseconds); - // Requested to open @p_node. - void openNodeRequested(Node *p_node, const QSharedPointer &p_paras); + // Requested to open @p_node. + void openNodeRequested(Node *p_node, const QSharedPointer &p_paras); - // @m_response of @p_event: true to continue the move, false to cancel the move. - void nodeAboutToMove(Node *p_node, const QSharedPointer &p_event); + // @m_response of @p_event: true to continue the move, false to cancel the move. + void nodeAboutToMove(Node *p_node, const QSharedPointer &p_event); - // @m_response of @p_event: true to continue the removal, false to cancel the removal. - void nodeAboutToRemove(Node *p_node, const QSharedPointer &p_event); + // @m_response of @p_event: true to continue the removal, false to cancel the removal. + void nodeAboutToRemove(Node *p_node, const QSharedPointer &p_event); - // @m_response of @p_event: true to continue the rename, false to cancel the rename. - void nodeAboutToRename(Node *p_node, const QSharedPointer &p_event); + // @m_response of @p_event: true to continue the rename, false to cancel the rename. + void nodeAboutToRename(Node *p_node, const QSharedPointer &p_event); - // @m_response of @p_event: true to continue the reload, false to cancel the reload. - void nodeAboutToReload(Node *p_node, const QSharedPointer &p_event); + // @m_response of @p_event: true to continue the reload, false to cancel the reload. + void nodeAboutToReload(Node *p_node, const QSharedPointer &p_event); - // Requested to open @p_filePath. - void openFileRequested(const QString &p_filePath, const QSharedPointer &p_paras); + // Requested to open @p_filePath. + void openFileRequested(const QString &p_filePath, + const QSharedPointer &p_paras); - // Requested to locate node in explorer. - void locateNodeRequested(Node *p_node); + // Requested to locate node in explorer. + void locateNodeRequested(Node *p_node); - void exportRequested(); + void exportRequested(); - void pinToQuickAccessRequested(const QStringList &p_files); + void pinToQuickAccessRequested(const QStringList &p_files); - void closeFileRequested(const QString &p_filePath, const QSharedPointer &p_event); + void closeFileRequested(const QString &p_filePath, const QSharedPointer &p_event); - private: - explicit VNoteX(QObject *p_parent = nullptr); +private: + explicit VNoteX(QObject *p_parent = nullptr); - void initThemeMgr(); + void initThemeMgr(); - void initTaskMgr(); + void initTaskMgr(); - void initNotebookMgr(); + void initNotebookMgr(); - void initBufferMgr(); + void initBufferMgr(); - void initDocsUtils(); + void initDocsUtils(); - void initQuickAccess(); + void initQuickAccess(); - MainWindow *m_mainWindow = nullptr; + MainWindow *m_mainWindow = nullptr; - // QObject managed. - ThemeMgr *m_themeMgr = nullptr; + // QObject managed. + ThemeMgr *m_themeMgr = nullptr; - // QObject managed. - TaskMgr *m_taskMgr = nullptr; + // QObject managed. + TaskMgr *m_taskMgr = nullptr; - // QObject managed. - NotebookMgr *m_notebookMgr = nullptr; + // QObject managed. + NotebookMgr *m_notebookMgr = nullptr; - // QObject managed. - BufferMgr *m_bufferMgr = nullptr; + // QObject managed. + BufferMgr *m_bufferMgr = nullptr; - // Used to identify app's instance. - ID m_instanceId = 0; - }; -} // ns vnotex + // Used to identify app's instance. + ID m_instanceId = 0; +}; +} // namespace vnotex #endif // VNOTEX_H diff --git a/src/core/webresource.h b/src/core/webresource.h index 3ca2b28483..03aff038a6 100644 --- a/src/core/webresource.h +++ b/src/core/webresource.h @@ -1,104 +1,94 @@ #ifndef WEBRESOURCE_H #define WEBRESOURCE_H -#include #include +#include #include #include -namespace vnotex -{ - // Resource for Web. - struct WebResource +namespace vnotex { +// Resource for Web. +struct WebResource { + struct Resource { + void init(const QJsonObject &p_obj) { + m_name = p_obj[QStringLiteral("name")].toString(); + m_enabled = p_obj[QStringLiteral("enabled")].toBool(); + + m_styles.clear(); + auto stylesArray = p_obj[QStringLiteral("styles")].toArray(); + for (int i = 0; i < stylesArray.size(); ++i) { + m_styles << stylesArray[i].toString(); + } + + m_scripts.clear(); + auto scriptsArray = p_obj[QStringLiteral("scripts")].toArray(); + for (int i = 0; i < scriptsArray.size(); ++i) { + m_scripts << scriptsArray[i].toString(); + } + } + + QJsonObject toJson() const { + QJsonObject obj; + obj[QStringLiteral("name")] = m_name; + obj[QStringLiteral("enabled")] = m_enabled; + + QJsonArray stylesArray; + for (const auto &ele : m_styles) { + stylesArray.append(ele); + } + obj[QStringLiteral("styles")] = stylesArray; + + QJsonArray scriptsArray; + for (const auto &ele : m_scripts) { + scriptsArray.append(ele); + } + obj[QStringLiteral("scripts")] = scriptsArray; + return obj; + } + + bool isGlobal() const { return m_name == QStringLiteral("global_styles"); } + + QString m_name; + + bool m_enabled = true; + + QStringList m_styles; + + QStringList m_scripts; + }; + + void init(const QJsonObject &p_obj) { + m_template = p_obj[QStringLiteral("template")].toString(); + + auto ary = p_obj[QStringLiteral("resources")].toArray(); + m_resources.resize(ary.size()); + for (int i = 0; i < ary.size(); ++i) { + m_resources[i].init(ary[i].toObject()); + } + } + + QJsonObject toJson() const { + QJsonObject obj; + obj[QStringLiteral("template")] = m_template; + { - struct Resource - { - void init(const QJsonObject &p_obj) - { - m_name = p_obj[QStringLiteral("name")].toString(); - m_enabled = p_obj[QStringLiteral("enabled")].toBool(); - - m_styles.clear(); - auto stylesArray = p_obj[QStringLiteral("styles")].toArray(); - for (int i = 0; i < stylesArray.size(); ++i) { - m_styles << stylesArray[i].toString(); - } - - m_scripts.clear(); - auto scriptsArray = p_obj[QStringLiteral("scripts")].toArray(); - for (int i = 0; i < scriptsArray.size(); ++i) { - m_scripts << scriptsArray[i].toString(); - } - } - - QJsonObject toJson() const - { - QJsonObject obj; - obj[QStringLiteral("name")] = m_name; - obj[QStringLiteral("enabled")] = m_enabled; - - QJsonArray stylesArray; - for (const auto &ele : m_styles) { - stylesArray.append(ele); - } - obj[QStringLiteral("styles")] = stylesArray; - - QJsonArray scriptsArray; - for (const auto &ele : m_scripts) { - scriptsArray.append(ele); - } - obj[QStringLiteral("scripts")] = scriptsArray; - return obj; - } - - bool isGlobal() const - { - return m_name == QStringLiteral("global_styles"); - } - - QString m_name; - - bool m_enabled = true; - - QStringList m_styles; - - QStringList m_scripts; - }; - - void init(const QJsonObject &p_obj) - { - m_template = p_obj[QStringLiteral("template")].toString(); - - auto ary = p_obj[QStringLiteral("resources")].toArray(); - m_resources.resize(ary.size()); - for (int i = 0; i < ary.size(); ++i) { - m_resources[i].init(ary[i].toObject()); - } - } - - QJsonObject toJson() const - { - QJsonObject obj; - obj[QStringLiteral("template")] = m_template; - - { - QJsonArray ary; - for (const auto &ele : m_resources) { - ary.append(ele.toJson()); - } - obj[QStringLiteral("resources")] = ary; - } - - return obj; - } - - // HTML template file. - QString m_template; - - // Resources to fill in the template. - QVector m_resources; - }; - -} + QJsonArray ary; + for (const auto &ele : m_resources) { + ary.append(ele.toJson()); + } + obj[QStringLiteral("resources")] = ary; + } + + return obj; + } + + // HTML template file. + QString m_template; + + // Resources to fill in the template. + QVector m_resources; +}; + +} // namespace vnotex #endif // WEBRESOURCE_H diff --git a/src/core/widgetconfig.cpp b/src/core/widgetconfig.cpp index a0eadff4ab..33d4e7dbf0 100644 --- a/src/core/widgetconfig.cpp +++ b/src/core/widgetconfig.cpp @@ -6,225 +6,184 @@ using namespace vnotex; #define READBOOL(key) readBool(appObj, userObj, (key)) #define READSTRLIST(key) readStringList(appObj, userObj, (key)) -WidgetConfig::WidgetConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) - : IConfig(p_mgr, p_topConfig) -{ - m_sessionName = QStringLiteral("widget"); +WidgetConfig::WidgetConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) : IConfig(p_mgr, p_topConfig) { + m_sessionName = QStringLiteral("widget"); } -void WidgetConfig::init(const QJsonObject &p_app, - const QJsonObject &p_user) -{ - const auto appObj = p_app.value(m_sessionName).toObject(); - const auto userObj = p_user.value(m_sessionName).toObject(); +void WidgetConfig::init(const QJsonObject &p_app, const QJsonObject &p_user) { + const auto appObj = p_app.value(m_sessionName).toObject(); + const auto userObj = p_user.value(m_sessionName).toObject(); - { - m_outlineAutoExpandedLevel = READINT(QStringLiteral("outline_auto_expanded_level")); - if (m_outlineAutoExpandedLevel < 0 || m_outlineAutoExpandedLevel > 6) { - m_outlineAutoExpandedLevel = 6; - } - - m_outlineSectionNumberEnabled = READBOOL(QStringLiteral("outline_section_number_enabled")); + { + m_outlineAutoExpandedLevel = READINT(QStringLiteral("outline_auto_expanded_level")); + if (m_outlineAutoExpandedLevel < 0 || m_outlineAutoExpandedLevel > 6) { + m_outlineAutoExpandedLevel = 6; } - m_findAndReplaceOptions = static_cast(READINT(QStringLiteral("find_and_replace_options"))); + m_outlineSectionNumberEnabled = READBOOL(QStringLiteral("outline_section_number_enabled")); + } - m_notebookSelectorViewOrder = READINT(QStringLiteral("notebook_selector_view_order")); + m_findAndReplaceOptions = + static_cast(READINT(QStringLiteral("find_and_replace_options"))); - { - m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order")); - m_nodeExplorerExploreMode = READINT(QStringLiteral("node_explorer_explore_mode")); - m_nodeExplorerExternalFilesVisible = READBOOL(QStringLiteral("node_explorer_external_files_visible")); - m_nodeExplorerAutoImportExternalFilesEnabled = READBOOL(QStringLiteral("node_explorer_auto_import_external_files_enabled")); - m_nodeExplorerCloseBeforeOpenWithEnabled = READBOOL(QStringLiteral("node_explorer_close_before_open_with_enabled")); - } + m_notebookSelectorViewOrder = READINT(QStringLiteral("notebook_selector_view_order")); + + { + m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order")); + m_nodeExplorerExploreMode = READINT(QStringLiteral("node_explorer_explore_mode")); + m_nodeExplorerExternalFilesVisible = + READBOOL(QStringLiteral("node_explorer_external_files_visible")); + m_nodeExplorerAutoImportExternalFilesEnabled = + READBOOL(QStringLiteral("node_explorer_auto_import_external_files_enabled")); + m_nodeExplorerCloseBeforeOpenWithEnabled = + READBOOL(QStringLiteral("node_explorer_close_before_open_with_enabled")); + } - m_searchPanelAdvancedSettingsVisible = READBOOL(QStringLiteral("search_panel_advanced_settings_visible")); + m_searchPanelAdvancedSettingsVisible = + READBOOL(QStringLiteral("search_panel_advanced_settings_visible")); - m_mainWindowKeepDocksExpandingContentArea = READSTRLIST(QStringLiteral("main_window_keep_docks_expanding_content_area")); + m_mainWindowKeepDocksExpandingContentArea = + READSTRLIST(QStringLiteral("main_window_keep_docks_expanding_content_area")); - m_snippetPanelBuiltInSnippetsVisible = READBOOL(QStringLiteral("snippet_panel_builtin_snippets_visible")); + m_snippetPanelBuiltInSnippetsVisible = + READBOOL(QStringLiteral("snippet_panel_builtin_snippets_visible")); - m_tagExplorerTwoColumnsEnabled = READBOOL(QStringLiteral("tag_explorer_two_columns_enabled")); + m_tagExplorerTwoColumnsEnabled = READBOOL(QStringLiteral("tag_explorer_two_columns_enabled")); - m_newNoteDefaultFileType = READINT(QStringLiteral("new_note_default_file_type")); + m_newNoteDefaultFileType = READINT(QStringLiteral("new_note_default_file_type")); - m_unitedEntryExpandAllEnabled = READBOOL(QStringLiteral("united_entry_expand_all")); + m_unitedEntryExpandAllEnabled = READBOOL(QStringLiteral("united_entry_expand_all")); } -QJsonObject WidgetConfig::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("outline_auto_expanded_level")] = m_outlineAutoExpandedLevel; - obj[QStringLiteral("outline_section_number_enabled")] = m_outlineSectionNumberEnabled; +QJsonObject WidgetConfig::toJson() const { + QJsonObject obj; + obj[QStringLiteral("outline_auto_expanded_level")] = m_outlineAutoExpandedLevel; + obj[QStringLiteral("outline_section_number_enabled")] = m_outlineSectionNumberEnabled; - obj[QStringLiteral("find_and_replace_options")] = static_cast(m_findAndReplaceOptions); + obj[QStringLiteral("find_and_replace_options")] = static_cast(m_findAndReplaceOptions); - obj[QStringLiteral("notebook_selector_view_order")] = m_notebookSelectorViewOrder; + obj[QStringLiteral("notebook_selector_view_order")] = m_notebookSelectorViewOrder; - obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder; - obj[QStringLiteral("node_explorer_explore_mode")] = m_nodeExplorerExploreMode; - obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible; - obj[QStringLiteral("node_explorer_auto_import_external_files_enabled")] = m_nodeExplorerAutoImportExternalFilesEnabled; - obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = m_nodeExplorerCloseBeforeOpenWithEnabled; + obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder; + obj[QStringLiteral("node_explorer_explore_mode")] = m_nodeExplorerExploreMode; + obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible; + obj[QStringLiteral("node_explorer_auto_import_external_files_enabled")] = + m_nodeExplorerAutoImportExternalFilesEnabled; + obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = + m_nodeExplorerCloseBeforeOpenWithEnabled; - obj[QStringLiteral("search_panel_advanced_settings_visible")] = m_searchPanelAdvancedSettingsVisible; - obj[QStringLiteral("snippet_panel_builtin_snippets_visible")] = m_snippetPanelBuiltInSnippetsVisible; - obj[QStringLiteral("tag_explorer_two_columns_enabled")] = m_tagExplorerTwoColumnsEnabled; - writeStringList(obj, - QStringLiteral("main_window_keep_docks_expanding_content_area"), - m_mainWindowKeepDocksExpandingContentArea); - obj[QStringLiteral("new_note_default_file_type")] = m_newNoteDefaultFileType; - obj[QStringLiteral("united_entry_expand_all")] = m_unitedEntryExpandAllEnabled; - return obj; + obj[QStringLiteral("search_panel_advanced_settings_visible")] = + m_searchPanelAdvancedSettingsVisible; + obj[QStringLiteral("snippet_panel_builtin_snippets_visible")] = + m_snippetPanelBuiltInSnippetsVisible; + obj[QStringLiteral("tag_explorer_two_columns_enabled")] = m_tagExplorerTwoColumnsEnabled; + writeStringList(obj, QStringLiteral("main_window_keep_docks_expanding_content_area"), + m_mainWindowKeepDocksExpandingContentArea); + obj[QStringLiteral("new_note_default_file_type")] = m_newNoteDefaultFileType; + obj[QStringLiteral("united_entry_expand_all")] = m_unitedEntryExpandAllEnabled; + return obj; } -int WidgetConfig::getOutlineAutoExpandedLevel() const -{ - return m_outlineAutoExpandedLevel; -} +int WidgetConfig::getOutlineAutoExpandedLevel() const { return m_outlineAutoExpandedLevel; } -void WidgetConfig::setOutlineAutoExpandedLevel(int p_level) -{ - updateConfig(m_outlineAutoExpandedLevel, p_level, this); +void WidgetConfig::setOutlineAutoExpandedLevel(int p_level) { + updateConfig(m_outlineAutoExpandedLevel, p_level, this); } -bool WidgetConfig::getOutlineSectionNumberEnabled() const -{ - return m_outlineSectionNumberEnabled; -} +bool WidgetConfig::getOutlineSectionNumberEnabled() const { return m_outlineSectionNumberEnabled; } -void WidgetConfig::setOutlineSectionNumberEnabled(bool p_enabled) -{ - updateConfig(m_outlineSectionNumberEnabled, p_enabled, this); +void WidgetConfig::setOutlineSectionNumberEnabled(bool p_enabled) { + updateConfig(m_outlineSectionNumberEnabled, p_enabled, this); } -FindOptions WidgetConfig::getFindAndReplaceOptions() const -{ - return m_findAndReplaceOptions; -} +FindOptions WidgetConfig::getFindAndReplaceOptions() const { return m_findAndReplaceOptions; } -void WidgetConfig::setFindAndReplaceOptions(FindOptions p_options) -{ - updateConfig(m_findAndReplaceOptions, p_options, this); +void WidgetConfig::setFindAndReplaceOptions(FindOptions p_options) { + updateConfig(m_findAndReplaceOptions, p_options, this); } -int WidgetConfig::getNodeExplorerViewOrder() const -{ - return m_nodeExplorerViewOrder; -} +int WidgetConfig::getNodeExplorerViewOrder() const { return m_nodeExplorerViewOrder; } -void WidgetConfig::setNodeExplorerViewOrder(int p_viewOrder) -{ - updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this); +void WidgetConfig::setNodeExplorerViewOrder(int p_viewOrder) { + updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this); } -int WidgetConfig::getNotebookSelectorViewOrder() const -{ - return m_notebookSelectorViewOrder; -} +int WidgetConfig::getNotebookSelectorViewOrder() const { return m_notebookSelectorViewOrder; } -void WidgetConfig::setNotebookSelectorViewOrder(int p_viewOrder) -{ - updateConfig(m_notebookSelectorViewOrder, p_viewOrder, this); +void WidgetConfig::setNotebookSelectorViewOrder(int p_viewOrder) { + updateConfig(m_notebookSelectorViewOrder, p_viewOrder, this); } -int WidgetConfig::getNodeExplorerExploreMode() const -{ - return m_nodeExplorerExploreMode; -} +int WidgetConfig::getNodeExplorerExploreMode() const { return m_nodeExplorerExploreMode; } -void WidgetConfig::setNodeExplorerExploreMode(int p_mode) -{ - updateConfig(m_nodeExplorerExploreMode, p_mode, this); +void WidgetConfig::setNodeExplorerExploreMode(int p_mode) { + updateConfig(m_nodeExplorerExploreMode, p_mode, this); } -bool WidgetConfig::isNodeExplorerExternalFilesVisible() const -{ - return m_nodeExplorerExternalFilesVisible; +bool WidgetConfig::isNodeExplorerExternalFilesVisible() const { + return m_nodeExplorerExternalFilesVisible; } -void WidgetConfig::setNodeExplorerExternalFilesVisible(bool p_visible) -{ - updateConfig(m_nodeExplorerExternalFilesVisible, p_visible, this); +void WidgetConfig::setNodeExplorerExternalFilesVisible(bool p_visible) { + updateConfig(m_nodeExplorerExternalFilesVisible, p_visible, this); } -bool WidgetConfig::getNodeExplorerAutoImportExternalFilesEnabled() const -{ - return m_nodeExplorerAutoImportExternalFilesEnabled; +bool WidgetConfig::getNodeExplorerAutoImportExternalFilesEnabled() const { + return m_nodeExplorerAutoImportExternalFilesEnabled; } -void WidgetConfig::setNodeExplorerAutoImportExternalFilesEnabled(bool p_enabled) -{ - updateConfig(m_nodeExplorerAutoImportExternalFilesEnabled, p_enabled, this); +void WidgetConfig::setNodeExplorerAutoImportExternalFilesEnabled(bool p_enabled) { + updateConfig(m_nodeExplorerAutoImportExternalFilesEnabled, p_enabled, this); } -bool WidgetConfig::getNodeExplorerCloseBeforeOpenWithEnabled() const -{ - return m_nodeExplorerCloseBeforeOpenWithEnabled; +bool WidgetConfig::getNodeExplorerCloseBeforeOpenWithEnabled() const { + return m_nodeExplorerCloseBeforeOpenWithEnabled; } -void WidgetConfig::setNodeExplorerCloseBeforeOpenWithEnabled(bool p_enabled) -{ - updateConfig(m_nodeExplorerCloseBeforeOpenWithEnabled, p_enabled, this); +void WidgetConfig::setNodeExplorerCloseBeforeOpenWithEnabled(bool p_enabled) { + updateConfig(m_nodeExplorerCloseBeforeOpenWithEnabled, p_enabled, this); } -bool WidgetConfig::isSearchPanelAdvancedSettingsVisible() const -{ - return m_searchPanelAdvancedSettingsVisible; +bool WidgetConfig::isSearchPanelAdvancedSettingsVisible() const { + return m_searchPanelAdvancedSettingsVisible; } -void WidgetConfig::setSearchPanelAdvancedSettingsVisible(bool p_visible) -{ - updateConfig(m_searchPanelAdvancedSettingsVisible, p_visible, this); +void WidgetConfig::setSearchPanelAdvancedSettingsVisible(bool p_visible) { + updateConfig(m_searchPanelAdvancedSettingsVisible, p_visible, this); } -const QStringList &WidgetConfig::getMainWindowKeepDocksExpandingContentArea() const -{ - return m_mainWindowKeepDocksExpandingContentArea; +const QStringList &WidgetConfig::getMainWindowKeepDocksExpandingContentArea() const { + return m_mainWindowKeepDocksExpandingContentArea; } -void WidgetConfig::setMainWindowKeepDocksExpandingContentArea(const QStringList &p_docks) -{ - updateConfig(m_mainWindowKeepDocksExpandingContentArea, p_docks, this); +void WidgetConfig::setMainWindowKeepDocksExpandingContentArea(const QStringList &p_docks) { + updateConfig(m_mainWindowKeepDocksExpandingContentArea, p_docks, this); } -bool WidgetConfig::isSnippetPanelBuiltInSnippetsVisible() const -{ - return m_snippetPanelBuiltInSnippetsVisible; +bool WidgetConfig::isSnippetPanelBuiltInSnippetsVisible() const { + return m_snippetPanelBuiltInSnippetsVisible; } -void WidgetConfig::setSnippetPanelBuiltInSnippetsVisible(bool p_visible) -{ - updateConfig(m_snippetPanelBuiltInSnippetsVisible, p_visible, this); +void WidgetConfig::setSnippetPanelBuiltInSnippetsVisible(bool p_visible) { + updateConfig(m_snippetPanelBuiltInSnippetsVisible, p_visible, this); } -bool WidgetConfig::getTagExplorerTwoColumnsEnabled() const -{ - return m_tagExplorerTwoColumnsEnabled; +bool WidgetConfig::getTagExplorerTwoColumnsEnabled() const { + return m_tagExplorerTwoColumnsEnabled; } -void WidgetConfig::setTagExplorerTwoColumnsEnabled(bool p_enabled) -{ - updateConfig(m_tagExplorerTwoColumnsEnabled, p_enabled, this); +void WidgetConfig::setTagExplorerTwoColumnsEnabled(bool p_enabled) { + updateConfig(m_tagExplorerTwoColumnsEnabled, p_enabled, this); } -int WidgetConfig::getNewNoteDefaultFileType() const -{ - return m_newNoteDefaultFileType; -} +int WidgetConfig::getNewNoteDefaultFileType() const { return m_newNoteDefaultFileType; } -void WidgetConfig::setNewNoteDefaultFileType(int p_type) -{ - updateConfig(m_newNoteDefaultFileType, p_type, this); +void WidgetConfig::setNewNoteDefaultFileType(int p_type) { + updateConfig(m_newNoteDefaultFileType, p_type, this); } -bool WidgetConfig::getUnitedEntryExpandAllEnabled() const -{ - return m_unitedEntryExpandAllEnabled; -} +bool WidgetConfig::getUnitedEntryExpandAllEnabled() const { return m_unitedEntryExpandAllEnabled; } -void WidgetConfig::setUnitedEntryExpandAllEnabled(bool p_enabled) -{ - updateConfig(m_unitedEntryExpandAllEnabled, p_enabled, this); +void WidgetConfig::setUnitedEntryExpandAllEnabled(bool p_enabled) { + updateConfig(m_unitedEntryExpandAllEnabled, p_enabled, this); } diff --git a/src/core/widgetconfig.h b/src/core/widgetconfig.h index e9fcc47693..df1dca0be5 100644 --- a/src/core/widgetconfig.h +++ b/src/core/widgetconfig.h @@ -7,95 +7,93 @@ #include -namespace vnotex -{ - class WidgetConfig : public IConfig - { - public: - WidgetConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); +namespace vnotex { +class WidgetConfig : public IConfig { +public: + WidgetConfig(ConfigMgr *p_mgr, IConfig *p_topConfig); - void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; + void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; - QJsonObject toJson() const Q_DECL_OVERRIDE; + QJsonObject toJson() const Q_DECL_OVERRIDE; - int getOutlineAutoExpandedLevel() const; - void setOutlineAutoExpandedLevel(int p_level); + int getOutlineAutoExpandedLevel() const; + void setOutlineAutoExpandedLevel(int p_level); - bool getOutlineSectionNumberEnabled() const; - void setOutlineSectionNumberEnabled(bool p_enabled); + bool getOutlineSectionNumberEnabled() const; + void setOutlineSectionNumberEnabled(bool p_enabled); - FindOptions getFindAndReplaceOptions() const; - void setFindAndReplaceOptions(FindOptions p_options); + FindOptions getFindAndReplaceOptions() const; + void setFindAndReplaceOptions(FindOptions p_options); - int getNotebookSelectorViewOrder() const; - void setNotebookSelectorViewOrder(int p_viewOrder); + int getNotebookSelectorViewOrder() const; + void setNotebookSelectorViewOrder(int p_viewOrder); - int getNodeExplorerViewOrder() const; - void setNodeExplorerViewOrder(int p_viewOrder); + int getNodeExplorerViewOrder() const; + void setNodeExplorerViewOrder(int p_viewOrder); - int getNodeExplorerExploreMode() const; - void setNodeExplorerExploreMode(int p_mode); + int getNodeExplorerExploreMode() const; + void setNodeExplorerExploreMode(int p_mode); - bool isNodeExplorerExternalFilesVisible() const; - void setNodeExplorerExternalFilesVisible(bool p_visible); + bool isNodeExplorerExternalFilesVisible() const; + void setNodeExplorerExternalFilesVisible(bool p_visible); - bool getNodeExplorerAutoImportExternalFilesEnabled() const; - void setNodeExplorerAutoImportExternalFilesEnabled(bool p_enabled); + bool getNodeExplorerAutoImportExternalFilesEnabled() const; + void setNodeExplorerAutoImportExternalFilesEnabled(bool p_enabled); - bool getNodeExplorerCloseBeforeOpenWithEnabled() const; - void setNodeExplorerCloseBeforeOpenWithEnabled(bool p_enabled); + bool getNodeExplorerCloseBeforeOpenWithEnabled() const; + void setNodeExplorerCloseBeforeOpenWithEnabled(bool p_enabled); - bool isSearchPanelAdvancedSettingsVisible() const; - void setSearchPanelAdvancedSettingsVisible(bool p_visible); + bool isSearchPanelAdvancedSettingsVisible() const; + void setSearchPanelAdvancedSettingsVisible(bool p_visible); - const QStringList &getMainWindowKeepDocksExpandingContentArea() const; - void setMainWindowKeepDocksExpandingContentArea(const QStringList &p_docks); + const QStringList &getMainWindowKeepDocksExpandingContentArea() const; + void setMainWindowKeepDocksExpandingContentArea(const QStringList &p_docks); - bool isSnippetPanelBuiltInSnippetsVisible() const; - void setSnippetPanelBuiltInSnippetsVisible(bool p_visible); + bool isSnippetPanelBuiltInSnippetsVisible() const; + void setSnippetPanelBuiltInSnippetsVisible(bool p_visible); - bool getTagExplorerTwoColumnsEnabled() const; - void setTagExplorerTwoColumnsEnabled(bool p_enabled); + bool getTagExplorerTwoColumnsEnabled() const; + void setTagExplorerTwoColumnsEnabled(bool p_enabled); - int getNewNoteDefaultFileType() const; - void setNewNoteDefaultFileType(int p_type); + int getNewNoteDefaultFileType() const; + void setNewNoteDefaultFileType(int p_type); - bool getUnitedEntryExpandAllEnabled() const; - void setUnitedEntryExpandAllEnabled(bool p_enabled); + bool getUnitedEntryExpandAllEnabled() const; + void setUnitedEntryExpandAllEnabled(bool p_enabled); - private: - int m_outlineAutoExpandedLevel = 6; +private: + int m_outlineAutoExpandedLevel = 6; - bool m_outlineSectionNumberEnabled = false; + bool m_outlineSectionNumberEnabled = false; - FindOptions m_findAndReplaceOptions = FindOption::FindNone; + FindOptions m_findAndReplaceOptions = FindOption::FindNone; - int m_notebookSelectorViewOrder = 0; + int m_notebookSelectorViewOrder = 0; - int m_nodeExplorerViewOrder = 0; + int m_nodeExplorerViewOrder = 0; - int m_nodeExplorerExploreMode = 1; + int m_nodeExplorerExploreMode = 1; - bool m_nodeExplorerExternalFilesVisible = true; + bool m_nodeExplorerExternalFilesVisible = true; - bool m_nodeExplorerAutoImportExternalFilesEnabled = true; + bool m_nodeExplorerAutoImportExternalFilesEnabled = true; - bool m_nodeExplorerCloseBeforeOpenWithEnabled = true; + bool m_nodeExplorerCloseBeforeOpenWithEnabled = true; - bool m_searchPanelAdvancedSettingsVisible = true; + bool m_searchPanelAdvancedSettingsVisible = true; - // Object name of those docks that should be kept when expanding content area. - QStringList m_mainWindowKeepDocksExpandingContentArea; + // Object name of those docks that should be kept when expanding content area. + QStringList m_mainWindowKeepDocksExpandingContentArea; - bool m_snippetPanelBuiltInSnippetsVisible = true; + bool m_snippetPanelBuiltInSnippetsVisible = true; - // Whether enable two columns for tag explorer. - bool m_tagExplorerTwoColumnsEnabled = false; + // Whether enable two columns for tag explorer. + bool m_tagExplorerTwoColumnsEnabled = false; - int m_newNoteDefaultFileType = 0; + int m_newNoteDefaultFileType = 0; - bool m_unitedEntryExpandAllEnabled = false; - }; -} + bool m_unitedEntryExpandAllEnabled = false; +}; +} // namespace vnotex #endif // WIDGETCONFIG_H diff --git a/src/export/exportdata.cpp b/src/export/exportdata.cpp index 3b4f1032cb..393f2b2939 100644 --- a/src/export/exportdata.cpp +++ b/src/export/exportdata.cpp @@ -1,238 +1,212 @@ #include "exportdata.h" -#include -#include #include +#include +#include using namespace vnotex; -QJsonObject ExportHtmlOption::toJson() const -{ - QJsonObject obj; - obj["embed_styles"] = m_embedStyles; - obj["complete_page"] = m_completePage; - obj["embed_images"] = m_embedImages; - obj["use_mime_html_format"] = m_useMimeHtmlFormat; - obj["add_outline_panel"] = m_addOutlinePanel; - obj["scrollable"] = m_scrollable; - return obj; +QJsonObject ExportHtmlOption::toJson() const { + QJsonObject obj; + obj["embed_styles"] = m_embedStyles; + obj["complete_page"] = m_completePage; + obj["embed_images"] = m_embedImages; + obj["use_mime_html_format"] = m_useMimeHtmlFormat; + obj["add_outline_panel"] = m_addOutlinePanel; + obj["scrollable"] = m_scrollable; + return obj; } -void ExportHtmlOption::fromJson(const QJsonObject &p_obj) -{ - if (p_obj.isEmpty()) { - return; - } - - m_embedStyles = p_obj["embed_styles"].toBool(); - m_completePage = p_obj["complete_page"].toBool(); - m_embedImages = p_obj["embed_images"].toBool(); - m_useMimeHtmlFormat = p_obj["use_mime_html_format"].toBool(); - m_addOutlinePanel = p_obj["add_outline_panel"].toBool(); - m_scrollable = p_obj["scrollable"].toBool(true); +void ExportHtmlOption::fromJson(const QJsonObject &p_obj) { + if (p_obj.isEmpty()) { + return; + } + + m_embedStyles = p_obj["embed_styles"].toBool(); + m_completePage = p_obj["complete_page"].toBool(); + m_embedImages = p_obj["embed_images"].toBool(); + m_useMimeHtmlFormat = p_obj["use_mime_html_format"].toBool(); + m_addOutlinePanel = p_obj["add_outline_panel"].toBool(); + m_scrollable = p_obj["scrollable"].toBool(true); } -bool ExportHtmlOption::operator==(const ExportHtmlOption &p_other) const -{ - return m_embedStyles == p_other.m_embedStyles - && m_completePage == p_other.m_completePage - && m_embedImages == p_other.m_embedImages - && m_useMimeHtmlFormat == p_other.m_useMimeHtmlFormat - && m_addOutlinePanel == p_other.m_addOutlinePanel - && m_scrollable == p_other.m_scrollable; +bool ExportHtmlOption::operator==(const ExportHtmlOption &p_other) const { + return m_embedStyles == p_other.m_embedStyles && m_completePage == p_other.m_completePage && + m_embedImages == p_other.m_embedImages && + m_useMimeHtmlFormat == p_other.m_useMimeHtmlFormat && + m_addOutlinePanel == p_other.m_addOutlinePanel && m_scrollable == p_other.m_scrollable; } -static QJsonObject pageLayoutToJsonObject(const QPageLayout &p_layout) -{ - QJsonObject obj; - obj["page_size"] = static_cast(p_layout.pageSize().id()); - obj["orientation"] = static_cast(p_layout.orientation()); - obj["units"] = static_cast(p_layout.units()); - { - QStringList marginsStr; - const auto margins = p_layout.margins(); - marginsStr << QString::number(margins.left()); - marginsStr << QString::number(margins.top()); - marginsStr << QString::number(margins.right()); - marginsStr << QString::number(margins.bottom()); - obj["margins"] = marginsStr.join(QLatin1Char(',')); - } - return obj; +static QJsonObject pageLayoutToJsonObject(const QPageLayout &p_layout) { + QJsonObject obj; + obj["page_size"] = static_cast(p_layout.pageSize().id()); + obj["orientation"] = static_cast(p_layout.orientation()); + obj["units"] = static_cast(p_layout.units()); + { + QStringList marginsStr; + const auto margins = p_layout.margins(); + marginsStr << QString::number(margins.left()); + marginsStr << QString::number(margins.top()); + marginsStr << QString::number(margins.right()); + marginsStr << QString::number(margins.bottom()); + obj["margins"] = marginsStr.join(QLatin1Char(',')); + } + return obj; } -static void jsonObjectToPageLayout(const QJsonObject &p_obj, QPageLayout &p_layout) -{ - const int pageSize = p_obj["page_size"].toInt(static_cast(QPageSize::A4)); - p_layout.setPageSize(QPageSize(static_cast(pageSize))); +static void jsonObjectToPageLayout(const QJsonObject &p_obj, QPageLayout &p_layout) { + const int pageSize = p_obj["page_size"].toInt(static_cast(QPageSize::A4)); + p_layout.setPageSize(QPageSize(static_cast(pageSize))); - const int orientation = p_obj["orientation"].toInt(static_cast(QPageLayout::Portrait)); - p_layout.setOrientation(static_cast(orientation)); + const int orientation = p_obj["orientation"].toInt(static_cast(QPageLayout::Portrait)); + p_layout.setOrientation(static_cast(orientation)); - const int units = p_obj["units"].toInt(static_cast(QPageLayout::Millimeter)); - p_layout.setUnits(static_cast(units)); + const int units = p_obj["units"].toInt(static_cast(QPageLayout::Millimeter)); + p_layout.setUnits(static_cast(units)); - auto marginsStr = p_obj["margins"].toString().split(QLatin1Char(',')); - if (marginsStr.size() == 4) { - p_layout.setMargins(QMarginsF(marginsStr[0].toDouble(), - marginsStr[1].toDouble(), - marginsStr[2].toDouble(), - marginsStr[3].toDouble())); - } + auto marginsStr = p_obj["margins"].toString().split(QLatin1Char(',')); + if (marginsStr.size() == 4) { + p_layout.setMargins(QMarginsF(marginsStr[0].toDouble(), marginsStr[1].toDouble(), + marginsStr[2].toDouble(), marginsStr[3].toDouble())); + } } ExportPdfOption::ExportPdfOption() - : m_layout(new QPageLayout(QPageSize(QPageSize::A4), - QPageLayout::Portrait, - QMarginsF(10, 16, 10, 10), - QPageLayout::Millimeter)) -{ -} - -QJsonObject ExportPdfOption::toJson() const -{ - QJsonObject obj; - obj["add_table_of_contents"] = m_addTableOfContents; - obj["use_wkhtmltopdf"] = m_useWkhtmltopdf; - obj["all_in_one"] = m_allInOne; - obj["wkhtmltopdf_exe_path"] = m_wkhtmltopdfExePath; - obj["wkhtmltopdf_args"] = m_wkhtmltopdfArgs; - obj["layout"] = pageLayoutToJsonObject(*m_layout); - return obj; + : m_layout(new QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, + QMarginsF(10, 16, 10, 10), QPageLayout::Millimeter)) {} + +QJsonObject ExportPdfOption::toJson() const { + QJsonObject obj; + obj["add_table_of_contents"] = m_addTableOfContents; + obj["use_wkhtmltopdf"] = m_useWkhtmltopdf; + obj["all_in_one"] = m_allInOne; + obj["wkhtmltopdf_exe_path"] = m_wkhtmltopdfExePath; + obj["wkhtmltopdf_args"] = m_wkhtmltopdfArgs; + obj["layout"] = pageLayoutToJsonObject(*m_layout); + return obj; } -void ExportPdfOption::fromJson(const QJsonObject &p_obj) -{ - if (p_obj.isEmpty()) { - return; - } - - m_addTableOfContents = p_obj["add_table_of_contents"].toBool(); - m_useWkhtmltopdf = p_obj["use_wkhtmltopdf"].toBool(); - m_allInOne = p_obj["all_in_one"].toBool(); - m_wkhtmltopdfExePath = p_obj["wkhtmltopdf_exe_path"].toString(); - m_wkhtmltopdfArgs = p_obj["wkhtmltopdf_args"].toString(); - jsonObjectToPageLayout(p_obj["layout"].toObject(), *m_layout); +void ExportPdfOption::fromJson(const QJsonObject &p_obj) { + if (p_obj.isEmpty()) { + return; + } + + m_addTableOfContents = p_obj["add_table_of_contents"].toBool(); + m_useWkhtmltopdf = p_obj["use_wkhtmltopdf"].toBool(); + m_allInOne = p_obj["all_in_one"].toBool(); + m_wkhtmltopdfExePath = p_obj["wkhtmltopdf_exe_path"].toString(); + m_wkhtmltopdfArgs = p_obj["wkhtmltopdf_args"].toString(); + jsonObjectToPageLayout(p_obj["layout"].toObject(), *m_layout); } -bool ExportPdfOption::operator==(const ExportPdfOption &p_other) const -{ - return m_addTableOfContents == p_other.m_addTableOfContents - && m_useWkhtmltopdf == p_other.m_useWkhtmltopdf - && m_allInOne == p_other.m_allInOne - && m_wkhtmltopdfExePath == p_other.m_wkhtmltopdfExePath - && m_wkhtmltopdfArgs == p_other.m_wkhtmltopdfArgs; +bool ExportPdfOption::operator==(const ExportPdfOption &p_other) const { + return m_addTableOfContents == p_other.m_addTableOfContents && + m_useWkhtmltopdf == p_other.m_useWkhtmltopdf && m_allInOne == p_other.m_allInOne && + m_wkhtmltopdfExePath == p_other.m_wkhtmltopdfExePath && + m_wkhtmltopdfArgs == p_other.m_wkhtmltopdfArgs; } -QJsonObject ExportCustomOption::toJson() const -{ - QJsonObject obj; - obj["name"] = m_name; - obj["target_suffix"] = m_targetSuffix; - obj["command"] = m_command; - obj["use_html_input"] = m_useHtmlInput; - obj["all_in_one"] = m_allInOne; - obj["target_page_scrollable"] = m_targetPageScrollable; - obj["resource_path_separator"] = m_resourcePathSeparator; - return obj; +QJsonObject ExportCustomOption::toJson() const { + QJsonObject obj; + obj["name"] = m_name; + obj["target_suffix"] = m_targetSuffix; + obj["command"] = m_command; + obj["use_html_input"] = m_useHtmlInput; + obj["all_in_one"] = m_allInOne; + obj["target_page_scrollable"] = m_targetPageScrollable; + obj["resource_path_separator"] = m_resourcePathSeparator; + return obj; } -void ExportCustomOption::fromJson(const QJsonObject &p_obj) -{ - if (p_obj.isEmpty()) { - return; - } - - m_name = p_obj["name"].toString(); - m_targetSuffix = p_obj["target_suffix"].toString(); - m_command = p_obj["command"].toString(); - m_useHtmlInput = p_obj["use_html_input"].toBool(); - m_allInOne = p_obj["all_in_one"].toBool(); - m_targetPageScrollable = p_obj["target_page_scrollable"].toBool(); - m_resourcePathSeparator = p_obj["resource_path_separator"].toString(); +void ExportCustomOption::fromJson(const QJsonObject &p_obj) { + if (p_obj.isEmpty()) { + return; + } + + m_name = p_obj["name"].toString(); + m_targetSuffix = p_obj["target_suffix"].toString(); + m_command = p_obj["command"].toString(); + m_useHtmlInput = p_obj["use_html_input"].toBool(); + m_allInOne = p_obj["all_in_one"].toBool(); + m_targetPageScrollable = p_obj["target_page_scrollable"].toBool(); + m_resourcePathSeparator = p_obj["resource_path_separator"].toString(); } -bool ExportCustomOption::operator==(const ExportCustomOption &p_other) const -{ - return m_name == p_other.m_name - && m_useHtmlInput == p_other.m_useHtmlInput - && m_targetSuffix == p_other.m_targetSuffix - && m_command == p_other.m_command - && m_allInOne == p_other.m_allInOne - && m_targetPageScrollable == p_other.m_targetPageScrollable - && m_resourcePathSeparator == p_other.m_resourcePathSeparator; +bool ExportCustomOption::operator==(const ExportCustomOption &p_other) const { + return m_name == p_other.m_name && m_useHtmlInput == p_other.m_useHtmlInput && + m_targetSuffix == p_other.m_targetSuffix && m_command == p_other.m_command && + m_allInOne == p_other.m_allInOne && + m_targetPageScrollable == p_other.m_targetPageScrollable && + m_resourcePathSeparator == p_other.m_resourcePathSeparator; } -QJsonObject ExportOption::toJson() const -{ - QJsonObject obj; - obj["target_format"] = static_cast(m_targetFormat); - obj["use_transparent_bg"] = m_useTransparentBg; - obj["output_dir"] = m_outputDir; - obj["recursive"] = m_recursive; - obj["export_attachments"] = m_exportAttachments; - obj["html_option"] = m_htmlOption.toJson(); - obj["pdf_option"] = m_pdfOption.toJson(); - obj["custom_export"] = m_customExport; - return obj; +QJsonObject ExportOption::toJson() const { + QJsonObject obj; + obj["target_format"] = static_cast(m_targetFormat); + obj["use_transparent_bg"] = m_useTransparentBg; + obj["output_dir"] = m_outputDir; + obj["recursive"] = m_recursive; + obj["export_attachments"] = m_exportAttachments; + obj["html_option"] = m_htmlOption.toJson(); + obj["pdf_option"] = m_pdfOption.toJson(); + obj["custom_export"] = m_customExport; + return obj; } -void ExportOption::fromJson(const QJsonObject &p_obj) -{ - if (p_obj.isEmpty()) { - return; - } - - { - int fmt = p_obj["target_format"].toInt(); - switch (fmt) { - case static_cast(ExportFormat::Markdown): - m_targetFormat = ExportFormat::Markdown; - break; - - case static_cast(ExportFormat::PDF): - m_targetFormat = ExportFormat::PDF; - break; - - case static_cast(ExportFormat::Custom): - m_targetFormat = ExportFormat::Custom; - break; - - case static_cast(ExportFormat::HTML): - Q_FALLTHROUGH(); - default: - m_targetFormat = ExportFormat::HTML; - break; - } +void ExportOption::fromJson(const QJsonObject &p_obj) { + if (p_obj.isEmpty()) { + return; + } + + { + int fmt = p_obj["target_format"].toInt(); + switch (fmt) { + case static_cast(ExportFormat::Markdown): + m_targetFormat = ExportFormat::Markdown; + break; + + case static_cast(ExportFormat::PDF): + m_targetFormat = ExportFormat::PDF; + break; + + case static_cast(ExportFormat::Custom): + m_targetFormat = ExportFormat::Custom; + break; + + case static_cast(ExportFormat::HTML): + Q_FALLTHROUGH(); + default: + m_targetFormat = ExportFormat::HTML; + break; } - - m_useTransparentBg = p_obj["use_transparent_bg"].toBool(); - m_outputDir = p_obj["output_dir"].toString(); - m_recursive = p_obj["recursive"].toBool(); - m_exportAttachments = p_obj["export_attachments"].toBool(); - m_htmlOption.fromJson(p_obj["html_option"].toObject()); - m_pdfOption.fromJson(p_obj["pdf_option"].toObject()); - m_customExport = p_obj["custom_export"].toString(); + } + + m_useTransparentBg = p_obj["use_transparent_bg"].toBool(); + m_outputDir = p_obj["output_dir"].toString(); + m_recursive = p_obj["recursive"].toBool(); + m_exportAttachments = p_obj["export_attachments"].toBool(); + m_htmlOption.fromJson(p_obj["html_option"].toObject()); + m_pdfOption.fromJson(p_obj["pdf_option"].toObject()); + m_customExport = p_obj["custom_export"].toString(); } -bool ExportOption::operator==(const ExportOption &p_other) const -{ - bool ret = m_targetFormat == p_other.m_targetFormat - && m_useTransparentBg == p_other.m_useTransparentBg - && m_outputDir == p_other.m_outputDir - && m_recursive == p_other.m_recursive - && m_exportAttachments == p_other.m_exportAttachments; +bool ExportOption::operator==(const ExportOption &p_other) const { + bool ret = m_targetFormat == p_other.m_targetFormat && + m_useTransparentBg == p_other.m_useTransparentBg && + m_outputDir == p_other.m_outputDir && m_recursive == p_other.m_recursive && + m_exportAttachments == p_other.m_exportAttachments; - if (!ret) { - return false; - } + if (!ret) { + return false; + } - if (!(m_htmlOption == p_other.m_htmlOption)) { - return false; - } + if (!(m_htmlOption == p_other.m_htmlOption)) { + return false; + } - if (!(m_pdfOption == p_other.m_pdfOption)) { - return false; - } + if (!(m_pdfOption == p_other.m_pdfOption)) { + return false; + } - return true; + return true; } diff --git a/src/export/exportdata.h b/src/export/exportdata.h index 7f26dbfc1b..3f65d2fb9d 100644 --- a/src/export/exportdata.h +++ b/src/export/exportdata.h @@ -5,154 +5,135 @@ class QPageLayout; -namespace vnotex -{ - enum class ExportSource - { - CurrentBuffer = 0, - CurrentNote, - CurrentFolder, - CurrentNotebook - }; +namespace vnotex { +enum class ExportSource { CurrentBuffer = 0, CurrentNote, CurrentFolder, CurrentNotebook }; - enum class ExportFormat - { - Markdown = 0, - HTML, - PDF, - Custom - }; +enum class ExportFormat { Markdown = 0, HTML, PDF, Custom }; - struct ExportHtmlOption - { - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_obj); +struct ExportHtmlOption { + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_obj); - bool operator==(const ExportHtmlOption &p_other) const; + bool operator==(const ExportHtmlOption &p_other) const; - bool m_embedStyles = true; + bool m_embedStyles = true; - bool m_completePage = true; + bool m_completePage = true; - bool m_embedImages = true; + bool m_embedImages = true; - bool m_useMimeHtmlFormat = false; + bool m_useMimeHtmlFormat = false; - // Whether add outline panel. - bool m_addOutlinePanel = true; + // Whether add outline panel. + bool m_addOutlinePanel = true; - // When exporting to PDF or custom format, we may need to export to HTML first without scrollable. - bool m_scrollable = true; - }; + // When exporting to PDF or custom format, we may need to export to HTML first without scrollable. + bool m_scrollable = true; +}; - struct ExportPdfOption - { - ExportPdfOption(); +struct ExportPdfOption { + ExportPdfOption(); - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_obj); + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_obj); - bool operator==(const ExportPdfOption &p_other) const; + bool operator==(const ExportPdfOption &p_other) const; - QSharedPointer m_layout; + QSharedPointer m_layout; - // Add TOC at the front. - bool m_addTableOfContents = false; + // Add TOC at the front. + bool m_addTableOfContents = false; - bool m_useWkhtmltopdf = false; + bool m_useWkhtmltopdf = false; - // Valid only when wkhtmltopdf is used. - bool m_allInOne = false; + // Valid only when wkhtmltopdf is used. + bool m_allInOne = false; - QString m_wkhtmltopdfExePath; + QString m_wkhtmltopdfExePath; - QString m_wkhtmltopdfArgs; - }; + QString m_wkhtmltopdfArgs; +}; - struct ExportCustomOption - { - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_obj); +struct ExportCustomOption { + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_obj); - bool operator==(const ExportCustomOption &p_other) const; + bool operator==(const ExportCustomOption &p_other) const; - QString m_name; + QString m_name; - QString m_targetSuffix; + QString m_targetSuffix; - QString m_command; + QString m_command; - bool m_useHtmlInput = true; + bool m_useHtmlInput = true; - bool m_allInOne = false; + bool m_allInOne = false; - // Whether the page of target format is scrollable. - bool m_targetPageScrollable = false; + // Whether the page of target format is scrollable. + bool m_targetPageScrollable = false; - // The default value here follows the rules of Pandoc. + // The default value here follows the rules of Pandoc. #if defined(Q_OS_WIN) - QString m_resourcePathSeparator = ";"; + QString m_resourcePathSeparator = ";"; #else - QString m_resourcePathSeparator = ":"; + QString m_resourcePathSeparator = ":"; #endif - }; +}; - struct ExportOption - { - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_obj); +struct ExportOption { + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_obj); - bool operator==(const ExportOption &p_other) const; + bool operator==(const ExportOption &p_other) const; - ExportSource m_source = ExportSource::CurrentBuffer; + ExportSource m_source = ExportSource::CurrentBuffer; - ExportFormat m_targetFormat = ExportFormat::HTML; + ExportFormat m_targetFormat = ExportFormat::HTML; - bool m_useTransparentBg = true; + bool m_useTransparentBg = true; - QString m_renderingStyleFile; + QString m_renderingStyleFile; - QString m_syntaxHighlightStyleFile; + QString m_syntaxHighlightStyleFile; - QString m_outputDir; + QString m_outputDir; - bool m_recursive = true; + bool m_recursive = true; - bool m_exportAttachments = true; + bool m_exportAttachments = true; - ExportHtmlOption m_htmlOption; + ExportHtmlOption m_htmlOption; - ExportPdfOption m_pdfOption; + ExportPdfOption m_pdfOption; - QString m_customExport; + QString m_customExport; - // Following fields are used in runtime only. - ExportCustomOption *m_customOption = nullptr; + // Following fields are used in runtime only. + ExportCustomOption *m_customOption = nullptr; - bool m_transformSvgToPngEnabled = false; + bool m_transformSvgToPngEnabled = false; - bool m_removeCodeToolBarEnabled = true; - }; + bool m_removeCodeToolBarEnabled = true; +}; - inline QString exportFormatString(ExportFormat p_format) - { - switch (p_format) - { - case ExportFormat::Markdown: - return QStringLiteral("Markdown"); +inline QString exportFormatString(ExportFormat p_format) { + switch (p_format) { + case ExportFormat::Markdown: + return QStringLiteral("Markdown"); - case ExportFormat::HTML: - return QStringLiteral("HTML"); + case ExportFormat::HTML: + return QStringLiteral("HTML"); - case ExportFormat::PDF: - return QStringLiteral("PDF"); + case ExportFormat::PDF: + return QStringLiteral("PDF"); - case ExportFormat::Custom: - return QStringLiteral("Custom"); - } + case ExportFormat::Custom: + return QStringLiteral("Custom"); + } - return QStringLiteral("Unknown"); - } + return QStringLiteral("Unknown"); } +} // namespace vnotex #endif // EXPORTDATA_H diff --git a/src/export/exporter.cpp b/src/export/exporter.cpp index e4b1ed3d23..b6a4ace973 100644 --- a/src/export/exporter.cpp +++ b/src/export/exporter.cpp @@ -1,689 +1,653 @@ #include "exporter.h" -#include #include +#include -#include -#include +#include "webviewexporter.h" #include +#include #include +#include +#include +#include #include -#include #include #include -#include -#include "webviewexporter.h" -#include +#include using namespace vnotex; -Exporter::Exporter(QWidget *p_parent) - : QObject(p_parent) -{ -} +Exporter::Exporter(QWidget *p_parent) : QObject(p_parent) {} -QString Exporter::doExport(const ExportOption &p_option, Buffer *p_buffer) -{ - m_askedToStop = false; +QString Exporter::doExport(const ExportOption &p_option, Buffer *p_buffer) { + m_askedToStop = false; - QString outputFile; - auto file = p_buffer->getFile(); - if (!file) { - emit logRequested(tr("Skipped buffer (%1) without file base.").arg(p_buffer->getName())); - return outputFile; - } + QString outputFile; + auto file = p_buffer->getFile(); + if (!file) { + emit logRequested(tr("Skipped buffer (%1) without file base.").arg(p_buffer->getName())); + return outputFile; + } - // Make sure output folder exists. - if (!QDir().mkpath(p_option.m_outputDir)) { - emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir)); - return outputFile; - } + // Make sure output folder exists. + if (!QDir().mkpath(p_option.m_outputDir)) { + emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir)); + return outputFile; + } - outputFile = doExport(p_option, p_option.m_outputDir, file.data()); + outputFile = doExport(p_option, p_option.m_outputDir, file.data()); - cleanUp(); + cleanUp(); - return outputFile; + return outputFile; } -static QString makeOutputFolder(const QString &p_outputDir, const QString &p_folderName) -{ - const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_folderName); - const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name); - if (!QDir().mkpath(outputFolder)) { - return QString(); - } +static QString makeOutputFolder(const QString &p_outputDir, const QString &p_folderName) { + const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_folderName); + const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name); + if (!QDir().mkpath(outputFolder)) { + return QString(); + } - return outputFolder; + return outputFolder; } -QString Exporter::doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, const File *p_file) -{ - QString outputFile; - if (!p_file->getContentType().isMarkdown()) { - emit logRequested(tr("Format %1 is not supported to export as Markdown.").arg(p_file->getContentType().m_displayName)); - return outputFile; - } +QString Exporter::doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file) { + QString outputFile; + if (!p_file->getContentType().isMarkdown()) { + emit logRequested(tr("Format %1 is not supported to export as Markdown.") + .arg(p_file->getContentType().m_displayName)); + return outputFile; + } + + // Export it to a folder with the same name. + const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_file->getName(), ""); + const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name); + QDir outDir(outputFolder); + if (!outDir.mkpath(outputFolder)) { + emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); + return outputFile; + } - // Export it to a folder with the same name. - const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_file->getName(), ""); - const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name); - QDir outDir(outputFolder); - if (!outDir.mkpath(outputFolder)) { - emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); - return outputFile; - } + // Copy source file itself. + const auto srcFilePath = p_file->getFilePath(); + auto destFilePath = outDir.filePath(p_file->getName()); + FileUtils::copyFile(srcFilePath, destFilePath, false); + outputFile = destFilePath; - // Copy source file itself. - const auto srcFilePath = p_file->getFilePath(); - auto destFilePath = outDir.filePath(p_file->getName()); - FileUtils::copyFile(srcFilePath, destFilePath, false); - outputFile = destFilePath; + ContentMediaUtils::copyMediaFiles(p_file, destFilePath); - ContentMediaUtils::copyMediaFiles(p_file, destFilePath); + // Copy attachments if available. + if (p_option.m_exportAttachments) { + exportAttachments(p_file->getNode(), srcFilePath, outputFolder, destFilePath); + } - // Copy attachments if available. - if (p_option.m_exportAttachments) { - exportAttachments(p_file->getNode(), srcFilePath, outputFolder, destFilePath); - } + return outputFile; +} - return outputFile; +void Exporter::exportAttachments(Node *p_node, const QString &p_srcFilePath, + const QString &p_outputFolder, const QString &p_destFilePath) { + if (!p_node) { + return; + } + const auto &attachmentFolder = p_node->getAttachmentFolder(); + if (!attachmentFolder.isEmpty()) { + auto relativePath = PathUtils::relativePath(PathUtils::parentDirPath(p_srcFilePath), + p_node->fetchAttachmentFolderPath()); + auto destAttachmentFolderPath = QDir(p_outputFolder).filePath(relativePath); + destAttachmentFolderPath = FileUtils::renameIfExistsCaseInsensitive(destAttachmentFolderPath); + ContentMediaUtils::copyAttachment(p_node, nullptr, p_destFilePath, destAttachmentFolderPath); + } } -void Exporter::exportAttachments(Node *p_node, - const QString &p_srcFilePath, - const QString &p_outputFolder, - const QString &p_destFilePath) -{ - if (!p_node) { - return; - } - const auto &attachmentFolder = p_node->getAttachmentFolder(); - if (!attachmentFolder.isEmpty()) { - auto relativePath = PathUtils::relativePath(PathUtils::parentDirPath(p_srcFilePath), - p_node->fetchAttachmentFolderPath()); - auto destAttachmentFolderPath = QDir(p_outputFolder).filePath(relativePath); - destAttachmentFolderPath = FileUtils::renameIfExistsCaseInsensitive(destAttachmentFolderPath); - ContentMediaUtils::copyAttachment(p_node, nullptr, p_destFilePath, destAttachmentFolderPath); - } +QString Exporter::doExport(const ExportOption &p_option, Node *p_note) { + m_askedToStop = false; + + QString outputFile; + auto file = p_note->getContentFile(); + + // Make sure output folder exists. + if (!QDir().mkpath(p_option.m_outputDir)) { + emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir)); + return outputFile; + } + + outputFile = doExport(p_option, p_option.m_outputDir, file.data()); + + cleanUp(); + + return outputFile; } -QString Exporter::doExport(const ExportOption &p_option, Node *p_note) -{ - m_askedToStop = false; +QString Exporter::doExportPdfAllInOne(const ExportOption &p_option, Notebook *p_notebook, + Node *p_folder) { + Q_ASSERT((p_notebook || p_folder) && !(p_notebook && p_folder)); - QString outputFile; - auto file = p_note->getContentFile(); + // Make path. + const auto name = p_notebook ? tr("notebook_%1").arg(p_notebook->getName()) : p_folder->getName(); + const auto outputFolder = makeOutputFolder(p_option.m_outputDir, name); + if (outputFolder.isEmpty()) { + emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir)); + return QString(); + } - // Make sure output folder exists. - if (!QDir().mkpath(p_option.m_outputDir)) { - emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir)); - return outputFile; - } + // Export to HTML to a tmp dir first. + QTemporaryDir tmpDir; + if (!tmpDir.isValid()) { + emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); + return QString(); + } - outputFile = doExport(p_option, p_option.m_outputDir, file.data()); + auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path())); - cleanUp(); + QStringList htmlFiles; + if (p_notebook) { + htmlFiles = doExportNotebook(tmpOption, tmpDir.path(), p_notebook); + } else { + htmlFiles = doExport(tmpOption, tmpDir.path(), p_folder); + } - return outputFile; + cleanUpWebViewExporter(); + + if (htmlFiles.isEmpty()) { + return QString(); + } + + if (checkAskedToStop()) { + return QString(); + } + + auto fileName = + FileUtils::generateFileNameWithSequence(outputFolder, tr("all_in_one_export"), "pdf"); + auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName); + if (getWebViewExporter(p_option)->htmlToPdfViaWkhtmltopdf(p_option.m_pdfOption, htmlFiles, + destFilePath)) { + emit logRequested(tr("Exported to (%1).").arg(destFilePath)); + return destFilePath; + } + + return QString(); } -QString Exporter::doExportPdfAllInOne(const ExportOption &p_option, Notebook *p_notebook, Node *p_folder) -{ - Q_ASSERT((p_notebook || p_folder) && !(p_notebook && p_folder)); +QString Exporter::doExportCustomAllInOne(const ExportOption &p_option, Notebook *p_notebook, + Node *p_folder) { + Q_ASSERT((p_notebook || p_folder) && !(p_notebook && p_folder)); - // Make path. - const auto name = p_notebook ? tr("notebook_%1").arg(p_notebook->getName()) : p_folder->getName(); - const auto outputFolder = makeOutputFolder(p_option.m_outputDir, name); - if (outputFolder.isEmpty()) { - emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir)); - return QString(); - } + // Make path. + const auto name = p_notebook ? tr("notebook_%1").arg(p_notebook->getName()) : p_folder->getName(); + const auto outputFolder = makeOutputFolder(p_option.m_outputDir, name); + if (outputFolder.isEmpty()) { + emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir)); + return QString(); + } + QStringList inputFiles; + QStringList resourcePaths; + + QTemporaryDir tmpDir; + if (p_option.m_customOption->m_useHtmlInput) { // Export to HTML to a tmp dir first. - QTemporaryDir tmpDir; if (!tmpDir.isValid()) { - emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); - return QString(); + emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); + return QString(); } auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path())); QStringList htmlFiles; if (p_notebook) { - htmlFiles = doExportNotebook(tmpOption, tmpDir.path(), p_notebook); + htmlFiles = doExportNotebook(tmpOption, tmpDir.path(), p_notebook); } else { - htmlFiles = doExport(tmpOption, tmpDir.path(), p_folder); + htmlFiles = doExport(tmpOption, tmpDir.path(), p_folder); } cleanUpWebViewExporter(); if (htmlFiles.isEmpty()) { - return QString(); + return QString(); } if (checkAskedToStop()) { - return QString(); + return QString(); + } + + inputFiles = htmlFiles; + for (const auto &file : htmlFiles) { + resourcePaths << PathUtils::parentDirPath(file); + } + } else { + // Collect source files. + if (p_notebook) { + collectFiles(p_notebook->collectFiles(), inputFiles, resourcePaths); + } else { + collectFiles(p_folder->collectFiles(), inputFiles, resourcePaths); } - auto fileName = FileUtils::generateFileNameWithSequence(outputFolder, - tr("all_in_one_export"), - "pdf"); - auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName); - if (getWebViewExporter(p_option)->htmlToPdfViaWkhtmltopdf(p_option.m_pdfOption, htmlFiles, destFilePath)) { - emit logRequested(tr("Exported to (%1).").arg(destFilePath)); - return destFilePath; + if (checkAskedToStop()) { + return QString(); } + } + if (inputFiles.isEmpty()) { return QString(); + } + + auto fileName = FileUtils::generateFileNameWithSequence(outputFolder, tr("all_in_one_export"), + p_option.m_customOption->m_targetSuffix); + auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName); + bool success = doExportCustom(p_option, inputFiles, resourcePaths, destFilePath); + if (success) { + emit logRequested(tr("Exported to (%1).").arg(destFilePath)); + return destFilePath; + } + + return QString(); } -QString Exporter::doExportCustomAllInOne(const ExportOption &p_option, Notebook *p_notebook, Node *p_folder) -{ - Q_ASSERT((p_notebook || p_folder) && !(p_notebook && p_folder)); - - // Make path. - const auto name = p_notebook ? tr("notebook_%1").arg(p_notebook->getName()) : p_folder->getName(); - const auto outputFolder = makeOutputFolder(p_option.m_outputDir, name); - if (outputFolder.isEmpty()) { - emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir)); - return QString(); - } +QStringList Exporter::doExportFolder(const ExportOption &p_option, Node *p_folder) { + m_askedToStop = false; - QStringList inputFiles; - QStringList resourcePaths; + QStringList outputFiles; - QTemporaryDir tmpDir; - if (p_option.m_customOption->m_useHtmlInput) { - // Export to HTML to a tmp dir first. - if (!tmpDir.isValid()) { - emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); - return QString(); - } + if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf && + p_option.m_pdfOption.m_allInOne) { + auto file = doExportPdfAllInOne(p_option, nullptr, p_folder); + if (!file.isEmpty()) { + outputFiles << file; + } + } else if (p_option.m_targetFormat == ExportFormat::Custom && + p_option.m_customOption->m_allInOne) { + auto file = doExportCustomAllInOne(p_option, nullptr, p_folder); + if (!file.isEmpty()) { + outputFiles << file; + } + } else { + outputFiles = doExport(p_option, p_option.m_outputDir, p_folder); + } - auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path())); + cleanUp(); - QStringList htmlFiles; - if (p_notebook) { - htmlFiles = doExportNotebook(tmpOption, tmpDir.path(), p_notebook); - } else { - htmlFiles = doExport(tmpOption, tmpDir.path(), p_folder); - } + return outputFiles; +} - cleanUpWebViewExporter(); +QStringList Exporter::doExport(const ExportOption &p_option, const QString &p_outputDir, + Node *p_folder) { + Q_ASSERT(p_folder->isContainer()); - if (htmlFiles.isEmpty()) { - return QString(); - } + QStringList outputFiles; - if (checkAskedToStop()) { - return QString(); - } + // Make path. + const auto outputFolder = makeOutputFolder(p_outputDir, p_folder->getName()); + if (outputFolder.isEmpty()) { + emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); + return outputFiles; + } + + try { + p_folder->load(); + } catch (Exception &p_e) { + QString msg = tr("Failed to load node (%1) (%2).").arg(p_folder->fetchPath(), p_e.what()); + qWarning() << msg; + emit logRequested(msg); + return outputFiles; + } - inputFiles = htmlFiles; - for (const auto &file : htmlFiles) { - resourcePaths << PathUtils::parentDirPath(file); - } - } else { - // Collect source files. - if (p_notebook) { - collectFiles(p_notebook->collectFiles(), inputFiles, resourcePaths); - } else { - collectFiles(p_folder->collectFiles(), inputFiles, resourcePaths); - } - - if (checkAskedToStop()) { - return QString(); - } + const auto &children = p_folder->getChildrenRef(); + emit progressUpdated(0, children.size()); + for (int i = 0; i < children.size(); ++i) { + if (checkAskedToStop()) { + break; } - if (inputFiles.isEmpty()) { - return QString(); + const auto &child = children[i]; + if (child->hasContent()) { + auto outputFile = doExport(p_option, outputFolder, child->getContentFile().data()); + if (!outputFile.isEmpty()) { + outputFiles << outputFile; + } } - - auto fileName = FileUtils::generateFileNameWithSequence(outputFolder, - tr("all_in_one_export"), - p_option.m_customOption->m_targetSuffix); - auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName); - bool success = doExportCustom(p_option, - inputFiles, - resourcePaths, - destFilePath); - if (success) { - emit logRequested(tr("Exported to (%1).").arg(destFilePath)); - return destFilePath; + if (p_option.m_recursive && child->isContainer() && child->getUse() == Node::Use::Normal) { + outputFiles.append(doExport(p_option, outputFolder, child.data())); } - return QString(); + emit progressUpdated(i + 1, children.size()); + } + + return outputFiles; } -QStringList Exporter::doExportFolder(const ExportOption &p_option, Node *p_folder) -{ - m_askedToStop = false; - - QStringList outputFiles; - - if (p_option.m_targetFormat == ExportFormat::PDF - && p_option.m_pdfOption.m_useWkhtmltopdf - && p_option.m_pdfOption.m_allInOne) { - auto file = doExportPdfAllInOne(p_option, nullptr, p_folder); - if (!file.isEmpty()) { - outputFiles << file; - } - } else if (p_option.m_targetFormat == ExportFormat::Custom - && p_option.m_customOption->m_allInOne) { - auto file = doExportCustomAllInOne(p_option, nullptr, p_folder); - if (!file.isEmpty()) { - outputFiles << file; - } - } else { - outputFiles = doExport(p_option, p_option.m_outputDir, p_folder); - } +QString Exporter::doExport(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file) { + QString outputFile; - cleanUp(); + switch (p_option.m_targetFormat) { + case ExportFormat::Markdown: + outputFile = doExportMarkdown(p_option, p_outputDir, p_file); + break; - return outputFiles; + case ExportFormat::HTML: + outputFile = doExportHtml(p_option, p_outputDir, p_file); + break; + + case ExportFormat::PDF: + outputFile = doExportPdf(p_option, p_outputDir, p_file); + break; + + case ExportFormat::Custom: + outputFile = doExportCustom(p_option, p_outputDir, p_file); + break; + + default: + emit logRequested( + tr("Unknown target format %1.").arg(exportFormatString(p_option.m_targetFormat))); + break; + } + + if (!outputFile.isEmpty()) { + emit logRequested(tr("File (%1) exported to (%2)").arg(p_file->getFilePath(), outputFile)); + } else { + emit logRequested(tr("Failed to export file (%1)").arg(p_file->getFilePath())); + } + + return outputFile; } -QStringList Exporter::doExport(const ExportOption &p_option, const QString &p_outputDir, Node *p_folder) -{ - Q_ASSERT(p_folder->isContainer()); +QStringList Exporter::doExport(const ExportOption &p_option, Notebook *p_notebook) { + m_askedToStop = false; - QStringList outputFiles; + QStringList outputFiles; - // Make path. - const auto outputFolder = makeOutputFolder(p_outputDir, p_folder->getName()); - if (outputFolder.isEmpty()) { - emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); - return outputFiles; + if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf && + p_option.m_pdfOption.m_allInOne) { + auto file = doExportPdfAllInOne(p_option, p_notebook, nullptr); + if (!file.isEmpty()) { + outputFiles << file; } - - try { - p_folder->load(); - } catch (Exception &p_e) { - QString msg = tr("Failed to load node (%1) (%2).").arg(p_folder->fetchPath(), p_e.what()); - qWarning() << msg; - emit logRequested(msg); - return outputFiles; + } else if (p_option.m_targetFormat == ExportFormat::Custom && + p_option.m_customOption->m_allInOne) { + auto file = doExportCustomAllInOne(p_option, p_notebook, nullptr); + if (!file.isEmpty()) { + outputFiles << file; } + } else { + outputFiles = doExportNotebook(p_option, p_option.m_outputDir, p_notebook); + } - const auto &children = p_folder->getChildrenRef(); - emit progressUpdated(0, children.size()); - for (int i = 0; i < children.size(); ++i) { - if (checkAskedToStop()) { - break; - } - - const auto &child = children[i]; - if (child->hasContent()) { - auto outputFile = doExport(p_option, outputFolder, child->getContentFile().data()); - if (!outputFile.isEmpty()) { - outputFiles << outputFile; - } - } - if (p_option.m_recursive && child->isContainer() && child->getUse() == Node::Use::Normal) { - outputFiles.append(doExport(p_option, outputFolder, child.data())); - } - - emit progressUpdated(i + 1, children.size()); - } + cleanUp(); - return outputFiles; + return outputFiles; } -QString Exporter::doExport(const ExportOption &p_option, const QString &p_outputDir, const File *p_file) -{ - QString outputFile; - - switch (p_option.m_targetFormat) { - case ExportFormat::Markdown: - outputFile = doExportMarkdown(p_option, p_outputDir, p_file); - break; +QStringList Exporter::doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, + Notebook *p_notebook) { + m_askedToStop = false; - case ExportFormat::HTML: - outputFile = doExportHtml(p_option, p_outputDir, p_file); - break; + QStringList outputFiles; - case ExportFormat::PDF: - outputFile = doExportPdf(p_option, p_outputDir, p_file); - break; + // Make path. + const auto outputFolder = + makeOutputFolder(p_outputDir, tr("notebook_%1").arg(p_notebook->getName())); + if (outputFolder.isEmpty()) { + emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); + return outputFiles; + } - case ExportFormat::Custom: - outputFile = doExportCustom(p_option, p_outputDir, p_file); - break; + auto rootNode = p_notebook->getRootNode(); + Q_ASSERT(rootNode->isLoaded()); - default: - emit logRequested(tr("Unknown target format %1.").arg(exportFormatString(p_option.m_targetFormat))); - break; + const auto &children = rootNode->getChildrenRef(); + emit progressUpdated(0, children.size()); + for (int i = 0; i < children.size(); ++i) { + if (checkAskedToStop()) { + break; } - if (!outputFile.isEmpty()) { - emit logRequested(tr("File (%1) exported to (%2)").arg(p_file->getFilePath(), outputFile)); - } else { - emit logRequested(tr("Failed to export file (%1)").arg(p_file->getFilePath())); + const auto &child = children[i]; + if (child->hasContent()) { + auto outputFile = doExport(p_option, outputFolder, child->getContentFile().data()); + if (!outputFile.isEmpty()) { + outputFiles << outputFile; + } } - - return outputFile; -} - -QStringList Exporter::doExport(const ExportOption &p_option, Notebook *p_notebook) -{ - m_askedToStop = false; - - QStringList outputFiles; - - if (p_option.m_targetFormat == ExportFormat::PDF - && p_option.m_pdfOption.m_useWkhtmltopdf - && p_option.m_pdfOption.m_allInOne) { - auto file = doExportPdfAllInOne(p_option, p_notebook, nullptr); - if (!file.isEmpty()) { - outputFiles << file; - } - } else if (p_option.m_targetFormat == ExportFormat::Custom - && p_option.m_customOption->m_allInOne) { - auto file = doExportCustomAllInOne(p_option, p_notebook, nullptr); - if (!file.isEmpty()) { - outputFiles << file; - } - } else { - outputFiles = doExportNotebook(p_option, p_option.m_outputDir, p_notebook); + if (child->isContainer() && child->getUse() == Node::Use::Normal) { + outputFiles.append(doExport(p_option, outputFolder, child.data())); } - cleanUp(); + emit progressUpdated(i + 1, children.size()); + } - return outputFiles; + cleanUp(); + + return outputFiles; } -QStringList Exporter::doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, Notebook *p_notebook) -{ - m_askedToStop = false; +QString Exporter::doExportHtml(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file) { + QString outputFile; + if (!p_file->getContentType().isMarkdown()) { + emit logRequested(tr("Format %1 is not supported to export as HTML.") + .arg(p_file->getContentType().m_displayName)); + return outputFile; + } - QStringList outputFiles; + QString suffix = + p_option.m_htmlOption.m_useMimeHtmlFormat ? QStringLiteral("mht") : QStringLiteral("html"); + auto fileName = FileUtils::generateFileNameWithSequence( + p_outputDir, QFileInfo(p_file->getName()).completeBaseName(), suffix); + auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); - // Make path. - const auto outputFolder = makeOutputFolder(p_outputDir, tr("notebook_%1").arg(p_notebook->getName())); - if (outputFolder.isEmpty()) { - emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir)); - return outputFiles; - } + bool success = getWebViewExporter(p_option)->doExport(p_option, p_file, destFilePath); + if (success) { + outputFile = destFilePath; - auto rootNode = p_notebook->getRootNode(); - Q_ASSERT(rootNode->isLoaded()); - - const auto &children = rootNode->getChildrenRef(); - emit progressUpdated(0, children.size()); - for (int i = 0; i < children.size(); ++i) { - if (checkAskedToStop()) { - break; - } - - const auto &child = children[i]; - if (child->hasContent()) { - auto outputFile = doExport(p_option, outputFolder, child->getContentFile().data()); - if (!outputFile.isEmpty()) { - outputFiles << outputFile; - } - } - if (child->isContainer() && child->getUse() == Node::Use::Normal) { - outputFiles.append(doExport(p_option, outputFolder, child.data())); - } - - emit progressUpdated(i + 1, children.size()); + // Copy attachments if available. + if (p_option.m_exportAttachments) { + exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); } + } + return outputFile; +} - cleanUp(); +WebViewExporter *Exporter::getWebViewExporter(const ExportOption &p_option) { + if (!m_webViewExporter) { + m_webViewExporter = new WebViewExporter(static_cast(parent())); + connect(m_webViewExporter, &WebViewExporter::logRequested, this, &Exporter::logRequested); + m_webViewExporter->prepare(p_option); + } - return outputFiles; + return m_webViewExporter; } -QString Exporter::doExportHtml(const ExportOption &p_option, const QString &p_outputDir, const File *p_file) -{ - QString outputFile; - if (!p_file->getContentType().isMarkdown()) { - emit logRequested(tr("Format %1 is not supported to export as HTML.").arg(p_file->getContentType().m_displayName)); - return outputFile; - } +void Exporter::cleanUpWebViewExporter() { + if (m_webViewExporter) { + m_webViewExporter->clear(); + delete m_webViewExporter; + m_webViewExporter = nullptr; + } +} - QString suffix = p_option.m_htmlOption.m_useMimeHtmlFormat ? QStringLiteral("mht") : QStringLiteral("html"); - auto fileName = FileUtils::generateFileNameWithSequence(p_outputDir, - QFileInfo(p_file->getName()).completeBaseName(), - suffix); - auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); +void Exporter::cleanUp() { cleanUpWebViewExporter(); } - bool success = getWebViewExporter(p_option)->doExport(p_option, p_file, destFilePath); - if (success) { - outputFile = destFilePath; +void Exporter::stop() { + m_askedToStop = true; - // Copy attachments if available. - if (p_option.m_exportAttachments) { - exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); - } - } - return outputFile; + if (m_webViewExporter) { + m_webViewExporter->stop(); + } } -WebViewExporter *Exporter::getWebViewExporter(const ExportOption &p_option) -{ - if (!m_webViewExporter) { - m_webViewExporter = new WebViewExporter(static_cast(parent())); - connect(m_webViewExporter, &WebViewExporter::logRequested, - this, &Exporter::logRequested); - m_webViewExporter->prepare(p_option); - } +bool Exporter::checkAskedToStop() const { + if (m_askedToStop) { + emit const_cast(this)->logRequested(tr("Asked to stop. Aborting.")); + return true; + } - return m_webViewExporter; + return false; } -void Exporter::cleanUpWebViewExporter() -{ - if (m_webViewExporter) { - m_webViewExporter->clear(); - delete m_webViewExporter; - m_webViewExporter = nullptr; - } -} +QString Exporter::doExportPdf(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file) { + QString outputFile; + if (!p_file->getContentType().isMarkdown()) { + emit logRequested(tr("Format %1 is not supported to export as PDF.") + .arg(p_file->getContentType().m_displayName)); + return outputFile; + } -void Exporter::cleanUp() -{ - cleanUpWebViewExporter(); -} + auto fileName = FileUtils::generateFileNameWithSequence( + p_outputDir, QFileInfo(p_file->getName()).completeBaseName(), "pdf"); + auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); -void Exporter::stop() -{ - m_askedToStop = true; + bool success = getWebViewExporter(p_option)->doExport(p_option, p_file, destFilePath); + if (success) { + outputFile = destFilePath; - if (m_webViewExporter) { - m_webViewExporter->stop(); + // Copy attachments if available. + if (p_option.m_exportAttachments) { + exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); } + } + return outputFile; } -bool Exporter::checkAskedToStop() const -{ - if (m_askedToStop) { - emit const_cast(this)->logRequested(tr("Asked to stop. Aborting.")); - return true; +QString Exporter::doExportCustom(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file) { + Q_ASSERT(p_option.m_customOption); + QStringList inputFiles; + QStringList resourcePaths; + + QTemporaryDir tmpDir; + if (p_option.m_customOption->m_useHtmlInput) { + // Export to HTML to a tmp dir first. + if (!tmpDir.isValid()) { + emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); + return QString(); } - return false; -} + auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path())); + auto htmlFile = doExport(tmpOption, tmpDir.path(), p_file); + if (htmlFile.isEmpty()) { + return QString(); + } -QString Exporter::doExportPdf(const ExportOption &p_option, const QString &p_outputDir, const File *p_file) -{ - QString outputFile; - if (!p_file->getContentType().isMarkdown()) { - emit logRequested(tr("Format %1 is not supported to export as PDF.").arg(p_file->getContentType().m_displayName)); - return outputFile; + if (checkAskedToStop()) { + return QString(); } - auto fileName = FileUtils::generateFileNameWithSequence(p_outputDir, - QFileInfo(p_file->getName()).completeBaseName(), - "pdf"); - auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); + cleanUpWebViewExporter(); - bool success = getWebViewExporter(p_option)->doExport(p_option, p_file, destFilePath); - if (success) { - outputFile = destFilePath; + inputFiles << htmlFile; + resourcePaths << PathUtils::parentDirPath(htmlFile); + } else { + inputFiles << p_file->getContentPath(); + resourcePaths << p_file->getResourcePath(); + } - // Copy attachments if available. - if (p_option.m_exportAttachments) { - exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); - } - } - return outputFile; -} + auto fileName = FileUtils::generateFileNameWithSequence( + p_outputDir, QFileInfo(p_file->getName()).completeBaseName(), + p_option.m_customOption->m_targetSuffix); + auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); -QString Exporter::doExportCustom(const ExportOption &p_option, const QString &p_outputDir, const File *p_file) -{ - Q_ASSERT(p_option.m_customOption); - QStringList inputFiles; - QStringList resourcePaths; - - QTemporaryDir tmpDir; - if (p_option.m_customOption->m_useHtmlInput) { - // Export to HTML to a tmp dir first. - if (!tmpDir.isValid()) { - emit logRequested(tr("Failed to create temporary directory to hold HTML files.")); - return QString(); - } - - auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path())); - auto htmlFile = doExport(tmpOption, tmpDir.path(), p_file); - if (htmlFile.isEmpty()) { - return QString(); - } - - if (checkAskedToStop()) { - return QString(); - } - - cleanUpWebViewExporter(); - - inputFiles << htmlFile; - resourcePaths << PathUtils::parentDirPath(htmlFile); - } else { - inputFiles << p_file->getContentPath(); - resourcePaths << p_file->getResourcePath(); + bool success = doExportCustom(p_option, inputFiles, resourcePaths, destFilePath); + if (success) { + // Copy attachments if available. + if (p_option.m_exportAttachments) { + exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); } - auto fileName = FileUtils::generateFileNameWithSequence(p_outputDir, - QFileInfo(p_file->getName()).completeBaseName(), - p_option.m_customOption->m_targetSuffix); - auto destFilePath = PathUtils::concatenateFilePath(p_outputDir, fileName); - - bool success = doExportCustom(p_option, - inputFiles, - resourcePaths, - destFilePath); - if (success) { - // Copy attachments if available. - if (p_option.m_exportAttachments) { - exportAttachments(p_file->getNode(), p_file->getFilePath(), p_outputDir, destFilePath); - } - - return destFilePath; - } + return destFilePath; + } - return QString(); + return QString(); } -ExportOption Exporter::getExportOptionForIntermediateHtml(const ExportOption &p_option, const QString &p_outputDir) -{ - ExportOption tmpOption(p_option); - tmpOption.m_exportAttachments = false; - tmpOption.m_targetFormat = ExportFormat::HTML; - tmpOption.m_transformSvgToPngEnabled = true; - tmpOption.m_removeCodeToolBarEnabled = true; - - tmpOption.m_htmlOption.m_embedStyles = true; - tmpOption.m_htmlOption.m_completePage = true; - tmpOption.m_htmlOption.m_embedImages = false; - tmpOption.m_htmlOption.m_useMimeHtmlFormat = false; - tmpOption.m_htmlOption.m_addOutlinePanel = false; - tmpOption.m_htmlOption.m_scrollable = false; - if (p_option.m_targetFormat == ExportFormat::Custom && p_option.m_customOption->m_targetPageScrollable) { - tmpOption.m_htmlOption.m_scrollable = true; - } - tmpOption.m_outputDir = p_outputDir; - return tmpOption; +ExportOption Exporter::getExportOptionForIntermediateHtml(const ExportOption &p_option, + const QString &p_outputDir) { + ExportOption tmpOption(p_option); + tmpOption.m_exportAttachments = false; + tmpOption.m_targetFormat = ExportFormat::HTML; + tmpOption.m_transformSvgToPngEnabled = true; + tmpOption.m_removeCodeToolBarEnabled = true; + + tmpOption.m_htmlOption.m_embedStyles = true; + tmpOption.m_htmlOption.m_completePage = true; + tmpOption.m_htmlOption.m_embedImages = false; + tmpOption.m_htmlOption.m_useMimeHtmlFormat = false; + tmpOption.m_htmlOption.m_addOutlinePanel = false; + tmpOption.m_htmlOption.m_scrollable = false; + if (p_option.m_targetFormat == ExportFormat::Custom && + p_option.m_customOption->m_targetPageScrollable) { + tmpOption.m_htmlOption.m_scrollable = true; + } + tmpOption.m_outputDir = p_outputDir; + return tmpOption; } -bool Exporter::doExportCustom(const ExportOption &p_option, - const QStringList &p_files, - const QStringList &p_resourcePaths, - const QString &p_filePath) -{ - const auto cmd = evaluateCommand(p_option, - p_files, - p_resourcePaths, - p_filePath); - - emit logRequested(tr("Custom command: %1").arg(cmd)); - qDebug() << "custom export" << cmd; - - auto state = ProcessUtils::start(cmd, - [this](const QString &msg) { - emit logRequested(msg); - }, - m_askedToStop); - - return state == ProcessUtils::Succeeded; +bool Exporter::doExportCustom(const ExportOption &p_option, const QStringList &p_files, + const QStringList &p_resourcePaths, const QString &p_filePath) { + const auto cmd = evaluateCommand(p_option, p_files, p_resourcePaths, p_filePath); + + emit logRequested(tr("Custom command: %1").arg(cmd)); + qDebug() << "custom export" << cmd; + + auto state = ProcessUtils::start( + cmd, [this](const QString &msg) { emit logRequested(msg); }, m_askedToStop); + + return state == ProcessUtils::Succeeded; } -QString Exporter::evaluateCommand(const ExportOption &p_option, - const QStringList &p_files, - const QStringList &p_resourcePaths, - const QString &p_filePath) -{ - auto cmd(p_option.m_customOption->m_command); +QString Exporter::evaluateCommand(const ExportOption &p_option, const QStringList &p_files, + const QStringList &p_resourcePaths, const QString &p_filePath) { + auto cmd(p_option.m_customOption->m_command); + + QString inputs; + for (int i = 0; i < p_files.size(); ++i) { + if (i > 0) { + inputs += " "; + } + + inputs += getQuotedPath(p_files[i]); + } - QString inputs; - for (int i = 0; i < p_files.size(); ++i) { - if (i > 0) { - inputs += " "; - } + QString resourcePath; + for (int i = 0; i < p_resourcePaths.size(); ++i) { + bool duplicated = false; + for (int j = 0; j < i; ++j) { + if (p_resourcePaths[j] == p_resourcePaths[i]) { + // Deduplicate. + duplicated = true; + break; + } + } - inputs += getQuotedPath(p_files[i]); + if (duplicated) { + continue; } - QString resourcePath; - for (int i = 0; i < p_resourcePaths.size(); ++i) { - bool duplicated = false; - for (int j = 0; j < i; ++j) { - if (p_resourcePaths[j] == p_resourcePaths[i]) { - // Deduplicate. - duplicated = true; - break; - } - } - - if (duplicated) { - continue; - } - - if (i > 0) { - resourcePath += p_option.m_customOption->m_resourcePathSeparator; - } - - resourcePath += getQuotedPath(p_resourcePaths[i]); + if (i > 0) { + resourcePath += p_option.m_customOption->m_resourcePathSeparator; } - cmd.replace("%1", inputs); - cmd.replace("%2", resourcePath); - cmd.replace("%3", getQuotedPath(p_option.m_renderingStyleFile)); - cmd.replace("%4", getQuotedPath(p_option.m_syntaxHighlightStyleFile)); - cmd.replace("%5", getQuotedPath(p_filePath)); - return cmd; + resourcePath += getQuotedPath(p_resourcePaths[i]); + } + + cmd.replace("%1", inputs); + cmd.replace("%2", resourcePath); + cmd.replace("%3", getQuotedPath(p_option.m_renderingStyleFile)); + cmd.replace("%4", getQuotedPath(p_option.m_syntaxHighlightStyleFile)); + cmd.replace("%5", getQuotedPath(p_filePath)); + return cmd; } -QString Exporter::getQuotedPath(const QString &p_path) -{ - return QStringLiteral("\"%1\"").arg(QDir::toNativeSeparators(p_path)); +QString Exporter::getQuotedPath(const QString &p_path) { + return QStringLiteral("\"%1\"").arg(QDir::toNativeSeparators(p_path)); } -void Exporter::collectFiles(const QList> &p_files, QStringList &p_inputFiles, QStringList &p_resourcePaths) -{ - for (const auto &file : p_files) { - p_inputFiles << file->getContentPath(); - p_resourcePaths << file->getResourcePath(); - } +void Exporter::collectFiles(const QList> &p_files, QStringList &p_inputFiles, + QStringList &p_resourcePaths) { + for (const auto &file : p_files) { + p_inputFiles << file->getContentPath(); + p_resourcePaths << file->getResourcePath(); + } } diff --git a/src/export/exporter.h b/src/export/exporter.h index 3027e095c1..5c5b8d8c31 100644 --- a/src/export/exporter.h +++ b/src/export/exporter.h @@ -6,93 +6,92 @@ #include "exportdata.h" -namespace vnotex -{ - class Notebook; - class Node; - class Buffer; - class File; - class WebViewExporter; +namespace vnotex { +class Notebook; +class Node; +class Buffer; +class File; +class WebViewExporter; - class Exporter : public QObject - { - Q_OBJECT - public: - // We need the QWidget as parent. - explicit Exporter(QWidget *p_parent); +class Exporter : public QObject { + Q_OBJECT +public: + // We need the QWidget as parent. + explicit Exporter(QWidget *p_parent); - // Return exported output file. - QString doExport(const ExportOption &p_option, Buffer *p_buffer); + // Return exported output file. + QString doExport(const ExportOption &p_option, Buffer *p_buffer); - // Return exported output file. - QString doExport(const ExportOption &p_option, Node *p_note); + // Return exported output file. + QString doExport(const ExportOption &p_option, Node *p_note); - // Return exported output files. - QStringList doExportFolder(const ExportOption &p_option, Node *p_folder); + // Return exported output files. + QStringList doExportFolder(const ExportOption &p_option, Node *p_folder); - QStringList doExport(const ExportOption &p_option, Notebook *p_notebook); + QStringList doExport(const ExportOption &p_option, Notebook *p_notebook); - void stop(); + void stop(); - signals: - void progressUpdated(int p_val, int p_maximum); +signals: + void progressUpdated(int p_val, int p_maximum); - void logRequested(const QString &p_log); + void logRequested(const QString &p_log); - private: - QStringList doExport(const ExportOption &p_option, const QString &p_outputDir, Node *p_folder); +private: + QStringList doExport(const ExportOption &p_option, const QString &p_outputDir, Node *p_folder); - QString doExport(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); + QString doExport(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); - QString doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); + QString doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file); - QString doExportHtml(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); + QString doExportHtml(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file); - QString doExportPdf(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); + QString doExportPdf(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); - QString doExportCustom(const ExportOption &p_option, const QString &p_outputDir, const File *p_file); + QString doExportCustom(const ExportOption &p_option, const QString &p_outputDir, + const File *p_file); - bool doExportCustom(const ExportOption &p_option, - const QStringList &p_files, - const QStringList &p_resourcePaths, - const QString &p_filePath); + bool doExportCustom(const ExportOption &p_option, const QStringList &p_files, + const QStringList &p_resourcePaths, const QString &p_filePath); - // Export @p_notebook or @p_folder. @p_folder will be considered only when @p_notebook is null. - QString doExportPdfAllInOne(const ExportOption &p_option, Notebook *p_notebook, Node *p_folder); + // Export @p_notebook or @p_folder. @p_folder will be considered only when @p_notebook is null. + QString doExportPdfAllInOne(const ExportOption &p_option, Notebook *p_notebook, Node *p_folder); - QString doExportCustomAllInOne(const ExportOption &p_option, Notebook *p_notebook, Node *p_folder); + QString doExportCustomAllInOne(const ExportOption &p_option, Notebook *p_notebook, + Node *p_folder); - void exportAttachments(Node *p_node, - const QString &p_srcFilePath, - const QString &p_outputFolder, - const QString &p_destFilePath); + void exportAttachments(Node *p_node, const QString &p_srcFilePath, const QString &p_outputFolder, + const QString &p_destFilePath); - WebViewExporter *getWebViewExporter(const ExportOption &p_option); + WebViewExporter *getWebViewExporter(const ExportOption &p_option); - void cleanUpWebViewExporter(); + void cleanUpWebViewExporter(); - void cleanUp(); + void cleanUp(); - bool checkAskedToStop() const; + bool checkAskedToStop() const; - QStringList doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, Notebook *p_notebook); + QStringList doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, + Notebook *p_notebook); - static ExportOption getExportOptionForIntermediateHtml(const ExportOption &p_option, const QString &p_outputDir); + static ExportOption getExportOptionForIntermediateHtml(const ExportOption &p_option, + const QString &p_outputDir); - static QString evaluateCommand(const ExportOption &p_option, - const QStringList &p_files, - const QStringList &p_resourcePaths, - const QString &p_filePath); + static QString evaluateCommand(const ExportOption &p_option, const QStringList &p_files, + const QStringList &p_resourcePaths, const QString &p_filePath); - static QString getQuotedPath(const QString &p_path); + static QString getQuotedPath(const QString &p_path); - static void collectFiles(const QList> &p_files, QStringList &p_inputFiles, QStringList &p_resourcePaths); + static void collectFiles(const QList> &p_files, QStringList &p_inputFiles, + QStringList &p_resourcePaths); - // Managed by QObject. - WebViewExporter *m_webViewExporter = nullptr; + // Managed by QObject. + WebViewExporter *m_webViewExporter = nullptr; - bool m_askedToStop = false; - }; -} + bool m_askedToStop = false; +}; +} // namespace vnotex #endif // EXPORTER_H diff --git a/src/export/webviewexporter.cpp b/src/export/webviewexporter.cpp index 617fe2c365..b04e8ea648 100644 --- a/src/export/webviewexporter.cpp +++ b/src/export/webviewexporter.cpp @@ -1,484 +1,445 @@ #include "webviewexporter.h" -#include -#include #include -#include #include #include +#include +#include +#include -#include -#include -#include -#include #include +#include +#include #include -#include -#include +#include #include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include using namespace vnotex; static const QString c_imgRegExp = "]*)src=\"(?!data:)([^\"]+)\"([^>]*)>"; -WebViewExporter::WebViewExporter(QWidget *p_parent) - : QObject(p_parent) -{ -} +WebViewExporter::WebViewExporter(QWidget *p_parent) : QObject(p_parent) {} -WebViewExporter::~WebViewExporter() -{ - clear(); -} +WebViewExporter::~WebViewExporter() { clear(); } -void WebViewExporter::clear() -{ - m_askedToStop = false; +void WebViewExporter::clear() { + m_askedToStop = false; - delete m_viewer; - m_viewer = nullptr; + delete m_viewer; + m_viewer = nullptr; - m_htmlTemplate.clear(); - m_exportHtmlTemplate.clear(); + m_htmlTemplate.clear(); + m_exportHtmlTemplate.clear(); - m_exportOngoing = false; + m_exportOngoing = false; } -bool WebViewExporter::doExport(const ExportOption &p_option, - const File *p_file, - const QString &p_outputFile) -{ - bool ret = false; - m_askedToStop = false; - - Q_ASSERT(p_file->getContentType().isMarkdown()); +bool WebViewExporter::doExport(const ExportOption &p_option, const File *p_file, + const QString &p_outputFile) { + bool ret = false; + m_askedToStop = false; - Q_ASSERT(!m_exportOngoing); - m_exportOngoing = true; + Q_ASSERT(p_file->getContentType().isMarkdown()); - m_webViewStates = WebViewState::Started; + Q_ASSERT(!m_exportOngoing); + m_exportOngoing = true; - auto baseUrl = PathUtils::pathToUrl(p_file->getContentPath()); - m_viewer->adapter()->reset(); - m_viewer->setHtml(m_htmlTemplate, baseUrl); + m_webViewStates = WebViewState::Started; - auto textContent = p_file->read(); - if (p_option.m_targetFormat == ExportFormat::PDF - && p_option.m_pdfOption.m_addTableOfContents - && !p_option.m_pdfOption.m_useWkhtmltopdf) { - // Add `[TOC]` at the beginning. - m_viewer->adapter()->setText("[TOC]\n\n" + textContent); - } else { - m_viewer->adapter()->setText(textContent); - } + auto baseUrl = PathUtils::pathToUrl(p_file->getContentPath()); + m_viewer->adapter()->reset(); + m_viewer->setHtml(m_htmlTemplate, baseUrl); - while (!isWebViewReady()) { - Utils::sleepWait(100); + auto textContent = p_file->read(); + if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_addTableOfContents && + !p_option.m_pdfOption.m_useWkhtmltopdf) { + // Add `[TOC]` at the beginning. + m_viewer->adapter()->setText("[TOC]\n\n" + textContent); + } else { + m_viewer->adapter()->setText(textContent); + } - if (m_askedToStop) { - goto exit_export; - } + while (!isWebViewReady()) { + Utils::sleepWait(100); - if (isWebViewFailed()) { - qWarning() << "WebView failed when exporting" << p_file->getFilePath(); - goto exit_export; - } + if (m_askedToStop) { + goto exit_export; } - qDebug() << "WebView is ready"; + if (isWebViewFailed()) { + qWarning() << "WebView failed when exporting" << p_file->getFilePath(); + goto exit_export; + } + } - // Add extra wait to make sure Web side is really ready. - Utils::sleepWait(200); + qDebug() << "WebView is ready"; - switch (p_option.m_targetFormat) { - case ExportFormat::HTML: - // TODO: MIME HTML format is not supported yet. - Q_ASSERT(!p_option.m_htmlOption.m_useMimeHtmlFormat); - ret = doExportHtml(p_option.m_htmlOption, p_outputFile, baseUrl); - break; + // Add extra wait to make sure Web side is really ready. + Utils::sleepWait(200); - case ExportFormat::PDF: - if (p_option.m_pdfOption.m_useWkhtmltopdf) { - ret = doExportWkhtmltopdf(p_option.m_pdfOption, p_outputFile, baseUrl); - } else { - ret = doExportPdf(p_option.m_pdfOption, p_outputFile); - } - break; + switch (p_option.m_targetFormat) { + case ExportFormat::HTML: + // TODO: MIME HTML format is not supported yet. + Q_ASSERT(!p_option.m_htmlOption.m_useMimeHtmlFormat); + ret = doExportHtml(p_option.m_htmlOption, p_outputFile, baseUrl); + break; - default: - break; + case ExportFormat::PDF: + if (p_option.m_pdfOption.m_useWkhtmltopdf) { + ret = doExportWkhtmltopdf(p_option.m_pdfOption, p_outputFile, baseUrl); + } else { + ret = doExportPdf(p_option.m_pdfOption, p_outputFile); } + break; + + default: + break; + } exit_export: - m_exportOngoing = false; - return ret; + m_exportOngoing = false; + return ret; } -void WebViewExporter::stop() -{ - m_askedToStop = true; -} +void WebViewExporter::stop() { m_askedToStop = true; } -bool WebViewExporter::isWebViewReady() const -{ - return m_webViewStates == (WebViewState::LoadFinished | WebViewState::WorkFinished); +bool WebViewExporter::isWebViewReady() const { + return m_webViewStates == (WebViewState::LoadFinished | WebViewState::WorkFinished); } -bool WebViewExporter::isWebViewFailed() const -{ - return m_webViewStates & WebViewState::Failed; -} +bool WebViewExporter::isWebViewFailed() const { return m_webViewStates & WebViewState::Failed; } bool WebViewExporter::doExportHtml(const ExportHtmlOption &p_htmlOption, - const QString &p_outputFile, - const QUrl &p_baseUrl) -{ - ExportState state = ExportState::Busy; - - connect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, - this, [&, this](const QString &p_headContent, - const QString &p_styleContent, - const QString &p_content, - const QString &p_bodyClassList) { - qDebug() << "doExportHtml contentReady"; - // Maybe unnecessary. Just to avoid duplicated signal connections. - disconnect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, 0); - - if (p_content.isEmpty() || m_askedToStop) { - state = ExportState::Failed; - return; - } - - if (!writeHtmlFile(p_outputFile, - p_baseUrl, - p_headContent, - p_styleContent, - p_content, - p_bodyClassList, - p_htmlOption.m_embedStyles, - p_htmlOption.m_completePage, - p_htmlOption.m_embedImages)) { - state = ExportState::Failed; - return; - } - - state = ExportState::Finished; - }); - - m_viewer->adapter()->saveContent(); - - while (state == ExportState::Busy) { - Utils::sleepWait(100); - - if (m_askedToStop) { - break; - } + const QString &p_outputFile, const QUrl &p_baseUrl) { + ExportState state = ExportState::Busy; + + connect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, + [&, this](const QString &p_headContent, const QString &p_styleContent, + const QString &p_content, const QString &p_bodyClassList) { + qDebug() << "doExportHtml contentReady"; + // Maybe unnecessary. Just to avoid duplicated signal connections. + disconnect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, 0); + + if (p_content.isEmpty() || m_askedToStop) { + state = ExportState::Failed; + return; + } + + if (!writeHtmlFile(p_outputFile, p_baseUrl, p_headContent, p_styleContent, p_content, + p_bodyClassList, p_htmlOption.m_embedStyles, + p_htmlOption.m_completePage, p_htmlOption.m_embedImages)) { + state = ExportState::Failed; + return; + } + + state = ExportState::Finished; + }); + + m_viewer->adapter()->saveContent(); + + while (state == ExportState::Busy) { + Utils::sleepWait(100); + + if (m_askedToStop) { + break; } + } - return state == ExportState::Finished; + return state == ExportState::Finished; } -bool WebViewExporter::writeHtmlFile(const QString &p_file, - const QUrl &p_baseUrl, - const QString &p_headContent, - QString p_styleContent, - const QString &p_content, - const QString &p_bodyClassList, - bool p_embedStyles, - bool p_completePage, - bool p_embedImages) -{ - const auto baseName = QFileInfo(p_file).completeBaseName(); - - const QString resourceFolderName = baseName + "_files"; - auto resourceFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_file), resourceFolderName); +bool WebViewExporter::writeHtmlFile(const QString &p_file, const QUrl &p_baseUrl, + const QString &p_headContent, QString p_styleContent, + const QString &p_content, const QString &p_bodyClassList, + bool p_embedStyles, bool p_completePage, bool p_embedImages) { + const auto baseName = QFileInfo(p_file).completeBaseName(); - qDebug() << "HTML files folder" << resourceFolder; + const QString resourceFolderName = baseName + "_files"; + auto resourceFolder = + PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_file), resourceFolderName); - auto htmlContent = m_exportHtmlTemplate; + qDebug() << "HTML files folder" << resourceFolder; - const auto title = QStringLiteral("%1").arg(baseName); - HtmlTemplateHelper::fillTitle(htmlContent, title); + auto htmlContent = m_exportHtmlTemplate; - if (!p_styleContent.isEmpty() && p_embedStyles) { - embedStyleResources(p_styleContent); - HtmlTemplateHelper::fillStyleContent(htmlContent, p_styleContent); - } + const auto title = QStringLiteral("%1").arg(baseName); + HtmlTemplateHelper::fillTitle(htmlContent, title); - if (!p_headContent.isEmpty()) { - HtmlTemplateHelper::fillHeadContent(htmlContent, p_headContent); - } + if (!p_styleContent.isEmpty() && p_embedStyles) { + embedStyleResources(p_styleContent); + HtmlTemplateHelper::fillStyleContent(htmlContent, p_styleContent); + } - if (p_completePage) { - QString content(p_content); - if (p_embedImages) { - embedBodyResources(p_baseUrl, content); - } else { - fixBodyResources(p_baseUrl, resourceFolder, content); - } + if (!p_headContent.isEmpty()) { + HtmlTemplateHelper::fillHeadContent(htmlContent, p_headContent); + } - HtmlTemplateHelper::fillContent(htmlContent, content); + if (p_completePage) { + QString content(p_content); + if (p_embedImages) { + embedBodyResources(p_baseUrl, content); } else { - HtmlTemplateHelper::fillContent(htmlContent, p_content); + fixBodyResources(p_baseUrl, resourceFolder, content); } - if (!p_bodyClassList.isEmpty()) { - HtmlTemplateHelper::fillBodyClassList(htmlContent, p_bodyClassList); - } + HtmlTemplateHelper::fillContent(htmlContent, content); + } else { + HtmlTemplateHelper::fillContent(htmlContent, p_content); + } - FileUtils::writeFile(p_file, htmlContent); + if (!p_bodyClassList.isEmpty()) { + HtmlTemplateHelper::fillBodyClassList(htmlContent, p_bodyClassList); + } - // Delete empty resource folder. - QDir dir(resourceFolder); - if (dir.exists() && dir.isEmpty()) { - dir.cdUp(); - dir.rmdir(resourceFolderName); - } + FileUtils::writeFile(p_file, htmlContent); - return true; -} + // Delete empty resource folder. + QDir dir(resourceFolder); + if (dir.exists() && dir.isEmpty()) { + dir.cdUp(); + dir.rmdir(resourceFolderName); + } -QSize WebViewExporter::pageLayoutSize(const QPageLayout &p_layout) const -{ - Q_ASSERT(m_viewer); - auto rect = p_layout.paintRect(QPageLayout::Inch); - return QSize(rect.width() * m_viewer->logicalDpiX(), rect.height() * m_viewer->logicalDpiY()); + return true; } -void WebViewExporter::prepare(const ExportOption &p_option) -{ - Q_ASSERT(!m_viewer && !m_exportOngoing); - Q_ASSERT(p_option.m_targetFormat == ExportFormat::PDF || p_option.m_targetFormat == ExportFormat::HTML); - - { - // Adapter will be managed by MarkdownViewer. - auto adapter = new MarkdownViewerAdapter(this); - m_viewer = new MarkdownViewer(adapter, QColor(), 1, static_cast(parent())); - m_viewer->hide(); - connect(m_viewer->page(), &QWebEnginePage::loadFinished, - this, [this]() { - m_webViewStates |= WebViewState::LoadFinished; - }); - connect(adapter, &MarkdownViewerAdapter::workFinished, - this, [this]() { - m_webViewStates |= WebViewState::WorkFinished; - }); - } - - bool scrollable = true; - if (p_option.m_targetFormat == ExportFormat::PDF - || (p_option.m_targetFormat == ExportFormat::HTML && !p_option.m_htmlOption.m_scrollable) - || (p_option.m_targetFormat == ExportFormat::Custom && !p_option.m_customOption->m_targetPageScrollable)) { - scrollable = false; - } +QSize WebViewExporter::pageLayoutSize(const QPageLayout &p_layout) const { + Q_ASSERT(m_viewer); + auto rect = p_layout.paintRect(QPageLayout::Inch); + return QSize(rect.width() * m_viewer->logicalDpiX(), rect.height() * m_viewer->logicalDpiY()); +} - const auto &config = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - bool useWkhtmltopdf = false; - QSize pageBodySize(1024, 768); - if (p_option.m_targetFormat == ExportFormat::PDF) { - useWkhtmltopdf = p_option.m_pdfOption.m_useWkhtmltopdf; - pageBodySize = pageLayoutSize(*(p_option.m_pdfOption.m_layout)); - } +void WebViewExporter::prepare(const ExportOption &p_option) { + Q_ASSERT(!m_viewer && !m_exportOngoing); + Q_ASSERT(p_option.m_targetFormat == ExportFormat::PDF || + p_option.m_targetFormat == ExportFormat::HTML); + + { + // Adapter will be managed by MarkdownViewer. + auto adapter = new MarkdownViewerAdapter(this); + m_viewer = new MarkdownViewer(adapter, QColor(), 1, static_cast(parent())); + m_viewer->hide(); + connect(m_viewer->page(), &QWebEnginePage::loadFinished, this, + [this]() { m_webViewStates |= WebViewState::LoadFinished; }); + connect(adapter, &MarkdownViewerAdapter::workFinished, this, + [this]() { m_webViewStates |= WebViewState::WorkFinished; }); + } + + bool scrollable = true; + if (p_option.m_targetFormat == ExportFormat::PDF || + (p_option.m_targetFormat == ExportFormat::HTML && !p_option.m_htmlOption.m_scrollable) || + (p_option.m_targetFormat == ExportFormat::Custom && + !p_option.m_customOption->m_targetPageScrollable)) { + scrollable = false; + } + + const auto &config = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); + bool useWkhtmltopdf = false; + QSize pageBodySize(1024, 768); + if (p_option.m_targetFormat == ExportFormat::PDF) { + useWkhtmltopdf = p_option.m_pdfOption.m_useWkhtmltopdf; + pageBodySize = pageLayoutSize(*(p_option.m_pdfOption.m_layout)); + } + + qDebug() << "export page body size" << pageBodySize; + + HtmlTemplateHelper::MarkdownParas paras; + paras.m_webStyleSheetFile = p_option.m_renderingStyleFile; + paras.m_highlightStyleSheetFile = p_option.m_syntaxHighlightStyleFile; + paras.m_transparentBackgroundEnabled = p_option.m_useTransparentBg; + paras.m_scrollable = scrollable; + paras.m_bodyWidth = pageBodySize.width(); + paras.m_bodyHeight = pageBodySize.height(); + paras.m_transformSvgToPngEnabled = p_option.m_transformSvgToPngEnabled; + paras.m_mathJaxScale = useWkhtmltopdf ? 2.5 : -1; + paras.m_removeCodeToolBarEnabled = p_option.m_removeCodeToolBarEnabled; + + m_htmlTemplate = HtmlTemplateHelper::generateMarkdownViewerTemplate(config, paras); + + { + const bool addOutlinePanel = + p_option.m_targetFormat == ExportFormat::HTML && p_option.m_htmlOption.m_addOutlinePanel; + m_exportHtmlTemplate = + HtmlTemplateHelper::generateMarkdownExportTemplate(config, addOutlinePanel); + } + + if (useWkhtmltopdf) { + prepareWkhtmltopdfArguments(p_option.m_pdfOption); + } +} - qDebug() << "export page body size" << pageBodySize; +static QString marginToStrMM(qreal p_margin) { return QStringLiteral("%1mm").arg(p_margin); } - HtmlTemplateHelper::MarkdownParas paras; - paras.m_webStyleSheetFile = p_option.m_renderingStyleFile; - paras.m_highlightStyleSheetFile = p_option.m_syntaxHighlightStyleFile; - paras.m_transparentBackgroundEnabled = p_option.m_useTransparentBg; - paras.m_scrollable = scrollable; - paras.m_bodyWidth = pageBodySize.width(); - paras.m_bodyHeight = pageBodySize.height(); - paras.m_transformSvgToPngEnabled = p_option.m_transformSvgToPngEnabled; - paras.m_mathJaxScale = useWkhtmltopdf ? 2.5 : -1; - paras.m_removeCodeToolBarEnabled = p_option.m_removeCodeToolBarEnabled; +void WebViewExporter::prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption) { + m_wkhtmltopdfArgs.clear(); - m_htmlTemplate = HtmlTemplateHelper::generateMarkdownViewerTemplate(config, paras); + // Page layout. + { + const auto &layout = p_pdfOption.m_layout; + m_wkhtmltopdfArgs << "--page-size" << layout->pageSize().key(); + m_wkhtmltopdfArgs << "--orientation" + << (layout->orientation() == QPageLayout::Portrait ? "Portrait" + : "Landscape"); - { - const bool addOutlinePanel = p_option.m_targetFormat == ExportFormat::HTML && p_option.m_htmlOption.m_addOutlinePanel; - m_exportHtmlTemplate = HtmlTemplateHelper::generateMarkdownExportTemplate(config, addOutlinePanel); - } + const auto marginsMM = layout->margins(QPageLayout::Millimeter); + m_wkhtmltopdfArgs << "--margin-bottom" << marginToStrMM(marginsMM.bottom()); + m_wkhtmltopdfArgs << "--margin-left" << marginToStrMM(marginsMM.left()); + m_wkhtmltopdfArgs << "--margin-right" << marginToStrMM(marginsMM.right()); + m_wkhtmltopdfArgs << "--margin-top" << marginToStrMM(marginsMM.top()); - if (useWkhtmltopdf) { - prepareWkhtmltopdfArguments(p_option.m_pdfOption); - } -} + // Footer. + m_wkhtmltopdfArgs << "--footer-right" << "[page]" + << "--footer-spacing" << QString::number(marginsMM.bottom() / 3, 'f', 2); + } -static QString marginToStrMM(qreal p_margin) -{ - return QStringLiteral("%1mm").arg(p_margin); -} + m_wkhtmltopdfArgs << "--encoding" << "utf-8"; -void WebViewExporter::prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption) -{ - m_wkhtmltopdfArgs.clear(); - - // Page layout. - { - const auto &layout = p_pdfOption.m_layout; - m_wkhtmltopdfArgs << "--page-size" << layout->pageSize().key(); - m_wkhtmltopdfArgs << "--orientation" - << (layout->orientation() == QPageLayout::Portrait ? "Portrait" : "Landscape"); - - const auto marginsMM = layout->margins(QPageLayout::Millimeter); - m_wkhtmltopdfArgs << "--margin-bottom" << marginToStrMM(marginsMM.bottom()); - m_wkhtmltopdfArgs << "--margin-left" << marginToStrMM(marginsMM.left()); - m_wkhtmltopdfArgs << "--margin-right" << marginToStrMM(marginsMM.right()); - m_wkhtmltopdfArgs << "--margin-top" << marginToStrMM(marginsMM.top()); - - // Footer. - m_wkhtmltopdfArgs << "--footer-right" << "[page]" - << "--footer-spacing" << QString::number(marginsMM.bottom() / 3, 'f', 2); - } + // Delay 10 seconds for MathJax. + m_wkhtmltopdfArgs << "--javascript-delay" << "5000"; - m_wkhtmltopdfArgs << "--encoding" << "utf-8"; + m_wkhtmltopdfArgs << "--enable-local-file-access"; - // Delay 10 seconds for MathJax. - m_wkhtmltopdfArgs << "--javascript-delay" << "5000"; + // Append additional global option. + if (!p_pdfOption.m_wkhtmltopdfArgs.isEmpty()) { + m_wkhtmltopdfArgs.append(ProcessUtils::parseCombinedArgString(p_pdfOption.m_wkhtmltopdfArgs)); + } - m_wkhtmltopdfArgs << "--enable-local-file-access"; + // Must be put after the global object options. + if (p_pdfOption.m_addTableOfContents) { + m_wkhtmltopdfArgs << "toc"; + m_wkhtmltopdfArgs << "--toc-text-size-shrink" << "1.0"; + m_wkhtmltopdfArgs << "--toc-header-text" << HtmlUtils::unicodeEncode(tr("Table of Contents")); + } +} - // Append additional global option. - if (!p_pdfOption.m_wkhtmltopdfArgs.isEmpty()) { - m_wkhtmltopdfArgs.append(ProcessUtils::parseCombinedArgString(p_pdfOption.m_wkhtmltopdfArgs)); - } +bool WebViewExporter::embedStyleResources(QString &p_html) const { + bool altered = false; + QRegularExpression reg("\\burl\\(\"((file|qrc):[^\"\\)]+)\"\\);"); - // Must be put after the global object options. - if (p_pdfOption.m_addTableOfContents) { - m_wkhtmltopdfArgs << "toc"; - m_wkhtmltopdfArgs << "--toc-text-size-shrink" << "1.0"; - m_wkhtmltopdfArgs << "--toc-header-text" << HtmlUtils::unicodeEncode(tr("Table of Contents")); + int pos = 0; + while (pos < p_html.size()) { + QRegularExpressionMatch match; + int idx = p_html.indexOf(reg, pos, &match); + if (idx == -1) { + break; } -} - -bool WebViewExporter::embedStyleResources(QString &p_html) const -{ - bool altered = false; - QRegularExpression reg("\\burl\\(\"((file|qrc):[^\"\\)]+)\"\\);"); - - int pos = 0; - while (pos < p_html.size()) { - QRegularExpressionMatch match; - int idx = p_html.indexOf(reg, pos, &match); - if (idx == -1) { - break; - } - QString dataURI = WebUtils::toDataUri(QUrl(match.captured(1)), false); - if (dataURI.isEmpty()) { - pos = idx + match.capturedLength(); - } else { - // Replace the url string in html. - QString newUrl = QStringLiteral("url('%1');").arg(dataURI); - p_html.replace(idx, match.capturedLength(), newUrl); - pos = idx + newUrl.size(); - altered = true; - } + QString dataURI = WebUtils::toDataUri(QUrl(match.captured(1)), false); + if (dataURI.isEmpty()) { + pos = idx + match.capturedLength(); + } else { + // Replace the url string in html. + QString newUrl = QStringLiteral("url('%1');").arg(dataURI); + p_html.replace(idx, match.capturedLength(), newUrl); + pos = idx + newUrl.size(); + altered = true; } + } - return altered; + return altered; } -bool WebViewExporter::embedBodyResources(const QUrl &p_baseUrl, QString &p_html) -{ - bool altered = false; - if (p_baseUrl.isEmpty()) { - return altered; - } +bool WebViewExporter::embedBodyResources(const QUrl &p_baseUrl, QString &p_html) { + bool altered = false; + if (p_baseUrl.isEmpty()) { + return altered; + } - QRegularExpression reg(c_imgRegExp); + QRegularExpression reg(c_imgRegExp); - int pos = 0; - while (pos < p_html.size()) { - QRegularExpressionMatch match; - int idx = p_html.indexOf(reg, pos, &match); - if (idx == -1) { - break; - } + int pos = 0; + while (pos < p_html.size()) { + QRegularExpressionMatch match; + int idx = p_html.indexOf(reg, pos, &match); + if (idx == -1) { + break; + } - if (match.captured(2).isEmpty()) { - pos = idx + match.capturedLength(); - continue; - } + if (match.captured(2).isEmpty()) { + pos = idx + match.capturedLength(); + continue; + } - QUrl srcUrl(p_baseUrl.resolved(match.captured(2))); - const auto dataURI = WebUtils::toDataUri(srcUrl, true); - if (dataURI.isEmpty()) { - pos = idx + match.capturedLength(); - } else { - // Replace the url string in html. - QString newUrl = QStringLiteral("").arg(match.captured(1), dataURI, match.captured(3)); - p_html.replace(idx, match.capturedLength(), newUrl); - pos = idx + newUrl.size(); - altered = true; - } + QUrl srcUrl(p_baseUrl.resolved(match.captured(2))); + const auto dataURI = WebUtils::toDataUri(srcUrl, true); + if (dataURI.isEmpty()) { + pos = idx + match.capturedLength(); + } else { + // Replace the url string in html. + QString newUrl = + QStringLiteral("").arg(match.captured(1), dataURI, match.captured(3)); + p_html.replace(idx, match.capturedLength(), newUrl); + pos = idx + newUrl.size(); + altered = true; } + } - return altered; + return altered; } -static QString getResourceRelativePath(const QString &p_file) -{ - int idx = p_file.lastIndexOf('/'); - int idx2 = p_file.lastIndexOf('/', idx - 1); - Q_ASSERT(idx > 0 && idx2 < idx); - return "." + p_file.mid(idx2); +static QString getResourceRelativePath(const QString &p_file) { + int idx = p_file.lastIndexOf('/'); + int idx2 = p_file.lastIndexOf('/', idx - 1); + Q_ASSERT(idx > 0 && idx2 < idx); + return "." + p_file.mid(idx2); } -bool WebViewExporter::fixBodyResources(const QUrl &p_baseUrl, - const QString &p_folder, - QString &p_html) -{ - bool altered = false; - if (p_baseUrl.isEmpty()) { - return altered; - } +bool WebViewExporter::fixBodyResources(const QUrl &p_baseUrl, const QString &p_folder, + QString &p_html) { + bool altered = false; + if (p_baseUrl.isEmpty()) { + return altered; + } - QRegularExpression reg(c_imgRegExp); + QRegularExpression reg(c_imgRegExp); - int pos = 0; - while (pos < p_html.size()) { - QRegularExpressionMatch match; - int idx = p_html.indexOf(reg, pos, &match); - if (idx == -1) { - break; - } + int pos = 0; + while (pos < p_html.size()) { + QRegularExpressionMatch match; + int idx = p_html.indexOf(reg, pos, &match); + if (idx == -1) { + break; + } - if (match.captured(2).isEmpty()) { - pos = idx + match.capturedLength(); - continue; - } + if (match.captured(2).isEmpty()) { + pos = idx + match.capturedLength(); + continue; + } - QUrl srcUrl(p_baseUrl.resolved(match.captured(2))); - QString targetFile = WebUtils::copyResource(srcUrl, p_folder); - if (targetFile.isEmpty()) { - pos = idx + match.capturedLength(); - } else { - // Replace the url string in html. - QString newUrl = QStringLiteral("").arg(match.captured(1), getResourceRelativePath(targetFile), match.captured(3)); - p_html.replace(idx, match.capturedLength(), newUrl); - pos = idx + newUrl.size(); - altered = true; - } + QUrl srcUrl(p_baseUrl.resolved(match.captured(2))); + QString targetFile = WebUtils::copyResource(srcUrl, p_folder); + if (targetFile.isEmpty()) { + pos = idx + match.capturedLength(); + } else { + // Replace the url string in html. + QString newUrl = + QStringLiteral("") + .arg(match.captured(1), getResourceRelativePath(targetFile), match.captured(3)); + p_html.replace(idx, match.capturedLength(), newUrl); + pos = idx + newUrl.size(); + altered = true; } + } - return altered; + return altered; } -bool WebViewExporter::doExportPdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile) -{ - ExportState state = ExportState::Busy; +bool WebViewExporter::doExportPdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile) { + ExportState state = ExportState::Busy; - m_viewer->page()->printToPdf([&, this](const QByteArray &p_result) { + m_viewer->page()->printToPdf( + [&, this](const QByteArray &p_result) { qDebug() << "doExportPdf printToPdf ready"; if (p_result.isEmpty() || m_askedToStop) { - state = ExportState::Failed; - return; + state = ExportState::Failed; + return; } Q_ASSERT(!p_outputFile.isEmpty()); @@ -486,123 +447,112 @@ bool WebViewExporter::doExportPdf(const ExportPdfOption &p_pdfOption, const QStr FileUtils::writeFile(p_outputFile, p_result); state = ExportState::Finished; - }, *p_pdfOption.m_layout); + }, + *p_pdfOption.m_layout); - while (state == ExportState::Busy) { - Utils::sleepWait(100); + while (state == ExportState::Busy) { + Utils::sleepWait(100); - if (m_askedToStop) { - break; - } + if (m_askedToStop) { + break; } + } - return state == ExportState::Finished; + return state == ExportState::Finished; } -bool WebViewExporter::doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile, const QUrl &p_baseUrl) -{ - if (p_pdfOption.m_wkhtmltopdfExePath.isEmpty()) { - qWarning() << "invalid wkhtmltopdf executable path"; - return false; +bool WebViewExporter::doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, + const QString &p_outputFile, const QUrl &p_baseUrl) { + if (p_pdfOption.m_wkhtmltopdfExePath.isEmpty()) { + qWarning() << "invalid wkhtmltopdf executable path"; + return false; + } + + ExportState state = ExportState::Busy; + + connect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, + [&, this](const QString &p_headContent, const QString &p_styleContent, + const QString &p_content, const QString &p_bodyClassList) { + qDebug() << "doExportWkhtmltopdf contentReady"; + // Maybe unnecessary. Just to avoid duplicated signal connections. + disconnect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, 0); + + if (p_content.isEmpty() || m_askedToStop) { + state = ExportState::Failed; + return; + } + + // Save HTML to a temp dir. + QTemporaryDir tmpDir; + if (!tmpDir.isValid()) { + state = ExportState::Failed; + return; + } + + auto tmpHtmlFile = tmpDir.filePath("vnote_export_tmp.html"); + if (!writeHtmlFile(tmpHtmlFile, p_baseUrl, p_headContent, p_styleContent, p_content, + p_bodyClassList, true, true, false)) { + state = ExportState::Failed; + return; + } + + // Convert HTML to PDF via wkhtmltopdf. + if (htmlToPdfViaWkhtmltopdf(p_pdfOption, QStringList() << tmpHtmlFile, p_outputFile)) { + state = ExportState::Finished; + } else { + state = ExportState::Failed; + } + }); + + m_viewer->adapter()->saveContent(); + + while (state == ExportState::Busy) { + Utils::sleepWait(100); + + if (m_askedToStop) { + break; } + } - ExportState state = ExportState::Busy; - - connect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, - this, [&, this](const QString &p_headContent, - const QString &p_styleContent, - const QString &p_content, - const QString &p_bodyClassList) { - qDebug() << "doExportWkhtmltopdf contentReady"; - // Maybe unnecessary. Just to avoid duplicated signal connections. - disconnect(m_viewer->adapter(), &MarkdownViewerAdapter::contentReady, this, 0); - - if (p_content.isEmpty() || m_askedToStop) { - state = ExportState::Failed; - return; - } - - // Save HTML to a temp dir. - QTemporaryDir tmpDir; - if (!tmpDir.isValid()) { - state = ExportState::Failed; - return; - } - - auto tmpHtmlFile = tmpDir.filePath("vnote_export_tmp.html"); - if (!writeHtmlFile(tmpHtmlFile, - p_baseUrl, - p_headContent, - p_styleContent, - p_content, - p_bodyClassList, - true, - true, - false)) { - state = ExportState::Failed; - return; - } - - // Convert HTML to PDF via wkhtmltopdf. - if (htmlToPdfViaWkhtmltopdf(p_pdfOption, QStringList() << tmpHtmlFile, p_outputFile)) { - state = ExportState::Finished; - } else { - state = ExportState::Failed; - } - }); - - m_viewer->adapter()->saveContent(); - - while (state == ExportState::Busy) { - Utils::sleepWait(100); - - if (m_askedToStop) { - break; - } - } - - return state == ExportState::Finished; + return state == ExportState::Finished; } -bool WebViewExporter::htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile) -{ - QStringList args(m_wkhtmltopdfArgs); - - // Prepare the args. - for (auto const &file : p_htmlFiles) { - // Note: system's locale settings (Language for non-Unicode programs) is important to wkhtmltopdf. - // Input file could be encoded via QUrl::fromLocalFile(p_htmlFile).toString(QUrl::EncodeUnicode) to - // handle non-ASCII path. But for the output file, it is useless. - args << QUrl::fromLocalFile(QDir::toNativeSeparators(file)).toString(QUrl::EncodeUnicode); - } - - // To handle non-ASCII path, export it to a temp file and then copy it. - QTemporaryDir tmpDir; - if (!tmpDir.isValid()) { - return false; - } - - const auto tmpFile = tmpDir.filePath("vx_tmp_output.pdf"); - args << QDir::toNativeSeparators(tmpFile); - - bool ret = startProcess(QDir::toNativeSeparators(p_pdfOption.m_wkhtmltopdfExePath), args); - if (ret && QFileInfo::exists(tmpFile)) { - emit logRequested(tr("Copy output file (%1) to (%2).").arg(tmpFile, p_outputFile)); - FileUtils::copyFile(tmpFile, p_outputFile); - } - - return ret; +bool WebViewExporter::htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, + const QStringList &p_htmlFiles, + const QString &p_outputFile) { + QStringList args(m_wkhtmltopdfArgs); + + // Prepare the args. + for (auto const &file : p_htmlFiles) { + // Note: system's locale settings (Language for non-Unicode programs) is important to + // wkhtmltopdf. Input file could be encoded via + // QUrl::fromLocalFile(p_htmlFile).toString(QUrl::EncodeUnicode) to handle non-ASCII path. But + // for the output file, it is useless. + args << QUrl::fromLocalFile(QDir::toNativeSeparators(file)).toString(QUrl::EncodeUnicode); + } + + // To handle non-ASCII path, export it to a temp file and then copy it. + QTemporaryDir tmpDir; + if (!tmpDir.isValid()) { + return false; + } + + const auto tmpFile = tmpDir.filePath("vx_tmp_output.pdf"); + args << QDir::toNativeSeparators(tmpFile); + + bool ret = startProcess(QDir::toNativeSeparators(p_pdfOption.m_wkhtmltopdfExePath), args); + if (ret && QFileInfo::exists(tmpFile)) { + emit logRequested(tr("Copy output file (%1) to (%2).").arg(tmpFile, p_outputFile)); + FileUtils::copyFile(tmpFile, p_outputFile); + } + + return ret; } -bool WebViewExporter::startProcess(const QString &p_program, const QStringList &p_args) -{ - emit logRequested(p_program + " " + ProcessUtils::combineArgString(p_args)); - - auto ret = ProcessUtils::start(p_program, - p_args, - [this](const QString &p_log) { - emit logRequested(p_log); - }, - m_askedToStop); - return ret == ProcessUtils::State::Succeeded; +bool WebViewExporter::startProcess(const QString &p_program, const QStringList &p_args) { + emit logRequested(p_program + " " + ProcessUtils::combineArgString(p_args)); + + auto ret = ProcessUtils::start( + p_program, p_args, [this](const QString &p_log) { emit logRequested(p_log); }, m_askedToStop); + return ret == ProcessUtils::State::Succeeded; } diff --git a/src/export/webviewexporter.h b/src/export/webviewexporter.h index c62d769166..142058bd98 100644 --- a/src/export/webviewexporter.h +++ b/src/export/webviewexporter.h @@ -7,103 +7,84 @@ class QWidget; -namespace vnotex -{ - class File; - class MarkdownViewer; +namespace vnotex { +class File; +class MarkdownViewer; - class WebViewExporter : public QObject - { - Q_OBJECT - public: - enum WebViewState - { - Started = 0, - LoadFinished = 0x1, - WorkFinished = 0x2, - Failed = 0x4 - }; - Q_DECLARE_FLAGS(WebViewStates, WebViewState); +class WebViewExporter : public QObject { + Q_OBJECT +public: + enum WebViewState { Started = 0, LoadFinished = 0x1, WorkFinished = 0x2, Failed = 0x4 }; + Q_DECLARE_FLAGS(WebViewStates, WebViewState); - // We need QWidget as parent. - explicit WebViewExporter(QWidget *p_parent); + // We need QWidget as parent. + explicit WebViewExporter(QWidget *p_parent); - ~WebViewExporter(); + ~WebViewExporter(); - bool doExport(const ExportOption &p_option, - const File *p_file, - const QString &p_outputFile); + bool doExport(const ExportOption &p_option, const File *p_file, const QString &p_outputFile); - void prepare(const ExportOption &p_option); + void prepare(const ExportOption &p_option); - // Release resources after one batch of export. - void clear(); + // Release resources after one batch of export. + void clear(); - void stop(); + void stop(); - bool htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile); + bool htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, + const QString &p_outputFile); - signals: - void logRequested(const QString &p_log); +signals: + void logRequested(const QString &p_log); - private: - enum class ExportState - { - Busy = 0, - Finished, - Failed - }; +private: + enum class ExportState { Busy = 0, Finished, Failed }; - bool isWebViewReady() const; + bool isWebViewReady() const; - bool isWebViewFailed() const; + bool isWebViewFailed() const; - bool doExportHtml(const ExportHtmlOption &p_htmlOption, - const QString &p_outputFile, - const QUrl &p_baseUrl); + bool doExportHtml(const ExportHtmlOption &p_htmlOption, const QString &p_outputFile, + const QUrl &p_baseUrl); - bool writeHtmlFile(const QString &p_file, - const QUrl &p_baseUrl, - const QString &p_headContent, - QString p_styleContent, - const QString &p_content, - const QString &p_bodyClassList, - bool p_embedStyles, - bool p_completePage, - bool p_embedImages); + bool writeHtmlFile(const QString &p_file, const QUrl &p_baseUrl, const QString &p_headContent, + QString p_styleContent, const QString &p_content, + const QString &p_bodyClassList, bool p_embedStyles, bool p_completePage, + bool p_embedImages); - bool embedStyleResources(QString &p_html) const; + bool embedStyleResources(QString &p_html) const; - bool embedBodyResources(const QUrl &p_baseUrl, QString &p_html); + bool embedBodyResources(const QUrl &p_baseUrl, QString &p_html); - bool fixBodyResources(const QUrl &p_baseUrl, const QString &p_folder, QString &p_html); + bool fixBodyResources(const QUrl &p_baseUrl, const QString &p_folder, QString &p_html); - bool doExportPdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile); + bool doExportPdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile); - bool doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile, const QUrl &p_baseUrl); + bool doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QString &p_outputFile, + const QUrl &p_baseUrl); - QSize pageLayoutSize(const QPageLayout &p_layout) const; + QSize pageLayoutSize(const QPageLayout &p_layout) const; - void prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption); + void prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption); - bool startProcess(const QString &p_program, const QStringList &p_args); + bool startProcess(const QString &p_program, const QStringList &p_args); - bool m_askedToStop = false; + bool m_askedToStop = false; - bool m_exportOngoing = false; + bool m_exportOngoing = false; - WebViewStates m_webViewStates = WebViewState::Started; + WebViewStates m_webViewStates = WebViewState::Started; - // Managed by QObject. - MarkdownViewer *m_viewer = nullptr; + // Managed by QObject. + MarkdownViewer *m_viewer = nullptr; - QString m_htmlTemplate; + QString m_htmlTemplate; - QString m_exportHtmlTemplate; + QString m_exportHtmlTemplate; - QStringList m_wkhtmltopdfArgs; - }; -} + QStringList m_wkhtmltopdfArgs; +}; +} // namespace vnotex Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::WebViewExporter::WebViewStates) diff --git a/src/fakeaccessible.cpp b/src/fakeaccessible.cpp index 8aaf30e1d3..6ee7ea0747 100644 --- a/src/fakeaccessible.cpp +++ b/src/fakeaccessible.cpp @@ -5,87 +5,60 @@ using namespace vnotex; -QAccessibleInterface *FakeAccessible::accessibleFactory(const QString &p_className, QObject *p_obj) -{ - // Try to fix non-responsible issue caused by Youdao Dict. - if (p_className.startsWith(QStringLiteral("vnotex::")) - || p_className.startsWith(QStringLiteral("vte::"))) { - // Qt's docs: All interfaces are managed by an internal cache and should not be deleted. - return new FakeAccessibleInterface(p_obj); - } - - return nullptr; +QAccessibleInterface *FakeAccessible::accessibleFactory(const QString &p_className, + QObject *p_obj) { + // Try to fix non-responsible issue caused by Youdao Dict. + if (p_className.startsWith(QStringLiteral("vnotex::")) || + p_className.startsWith(QStringLiteral("vte::"))) { + // Qt's docs: All interfaces are managed by an internal cache and should not be deleted. + return new FakeAccessibleInterface(p_obj); + } + + return nullptr; } -FakeAccessibleInterface::FakeAccessibleInterface(QObject *p_obj) - : m_object(p_obj) -{ -} +FakeAccessibleInterface::FakeAccessibleInterface(QObject *p_obj) : m_object(p_obj) {} -QAccessibleInterface *FakeAccessibleInterface::child(int p_index) const -{ - Q_UNUSED(p_index); - return nullptr; +QAccessibleInterface *FakeAccessibleInterface::child(int p_index) const { + Q_UNUSED(p_index); + return nullptr; } -QAccessibleInterface *FakeAccessibleInterface::childAt(int p_x, int p_y) const -{ - Q_UNUSED(p_x); - Q_UNUSED(p_y); - return nullptr; +QAccessibleInterface *FakeAccessibleInterface::childAt(int p_x, int p_y) const { + Q_UNUSED(p_x); + Q_UNUSED(p_y); + return nullptr; } -int FakeAccessibleInterface::childCount() const -{ - return 0; -} +int FakeAccessibleInterface::childCount() const { return 0; } -int FakeAccessibleInterface::indexOfChild(const QAccessibleInterface *p_child) const -{ - Q_UNUSED(p_child); - return -1; +int FakeAccessibleInterface::indexOfChild(const QAccessibleInterface *p_child) const { + Q_UNUSED(p_child); + return -1; } -bool FakeAccessibleInterface::isValid() const -{ - return false; -} +bool FakeAccessibleInterface::isValid() const { return false; } -QObject *FakeAccessibleInterface::object() const -{ - return m_object; -} +QObject *FakeAccessibleInterface::object() const { return m_object; } -QAccessibleInterface *FakeAccessibleInterface::parent() const -{ - return nullptr; -} +QAccessibleInterface *FakeAccessibleInterface::parent() const { return nullptr; } -QRect FakeAccessibleInterface::rect() const -{ - return QRect(); -} +QRect FakeAccessibleInterface::rect() const { return QRect(); } -QAccessible::Role FakeAccessibleInterface::role() const -{ - return QAccessible::NoRole; -} +QAccessible::Role FakeAccessibleInterface::role() const { return QAccessible::NoRole; } -void FakeAccessibleInterface::setText(QAccessible::Text p_t, const QString &p_text) -{ - Q_UNUSED(p_t); - Q_UNUSED(p_text); +void FakeAccessibleInterface::setText(QAccessible::Text p_t, const QString &p_text) { + Q_UNUSED(p_t); + Q_UNUSED(p_text); } -QAccessible::State FakeAccessibleInterface::state() const -{ - QAccessible::State state; - state.disabled = true; - return state; +QAccessible::State FakeAccessibleInterface::state() const { + QAccessible::State state; + state.disabled = true; + return state; } -QString FakeAccessibleInterface::text(QAccessible::Text p_t) const -{ - Q_UNUSED(p_t); - return QString(); +QString FakeAccessibleInterface::text(QAccessible::Text p_t) const { + Q_UNUSED(p_t); + return QString(); } diff --git a/src/fakeaccessible.h b/src/fakeaccessible.h index d509ef0c44..af48a7bda4 100644 --- a/src/fakeaccessible.h +++ b/src/fakeaccessible.h @@ -6,48 +6,45 @@ class QObject; class QString; -namespace vnotex -{ - class FakeAccessible - { - public: - FakeAccessible() = delete; +namespace vnotex { +class FakeAccessible { +public: + FakeAccessible() = delete; - static QAccessibleInterface *accessibleFactory(const QString &p_className, QObject *p_obj); - }; + static QAccessibleInterface *accessibleFactory(const QString &p_className, QObject *p_obj); +}; - class FakeAccessibleInterface : public QAccessibleInterface - { - public: - FakeAccessibleInterface(QObject *p_obj); +class FakeAccessibleInterface : public QAccessibleInterface { +public: + FakeAccessibleInterface(QObject *p_obj); - QAccessibleInterface *child(int p_index) const Q_DECL_OVERRIDE; + QAccessibleInterface *child(int p_index) const Q_DECL_OVERRIDE; - QAccessibleInterface *childAt(int p_x, int p_y) const Q_DECL_OVERRIDE; + QAccessibleInterface *childAt(int p_x, int p_y) const Q_DECL_OVERRIDE; - int childCount() const Q_DECL_OVERRIDE; + int childCount() const Q_DECL_OVERRIDE; - int indexOfChild(const QAccessibleInterface *p_child) const Q_DECL_OVERRIDE; + int indexOfChild(const QAccessibleInterface *p_child) const Q_DECL_OVERRIDE; - bool isValid() const Q_DECL_OVERRIDE; + bool isValid() const Q_DECL_OVERRIDE; - QObject *object() const Q_DECL_OVERRIDE; + QObject *object() const Q_DECL_OVERRIDE; - QAccessibleInterface *parent() const Q_DECL_OVERRIDE; + QAccessibleInterface *parent() const Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; + QRect rect() const Q_DECL_OVERRIDE; - QAccessible::Role role() const Q_DECL_OVERRIDE; + QAccessible::Role role() const Q_DECL_OVERRIDE; - void setText(QAccessible::Text p_t, const QString &p_text) Q_DECL_OVERRIDE; + void setText(QAccessible::Text p_t, const QString &p_text) Q_DECL_OVERRIDE; - QAccessible::State state() const Q_DECL_OVERRIDE; + QAccessible::State state() const Q_DECL_OVERRIDE; - QString text(QAccessible::Text p_t) const Q_DECL_OVERRIDE; + QString text(QAccessible::Text p_t) const Q_DECL_OVERRIDE; - private: - QObject *m_object = nullptr; - }; -} +private: + QObject *m_object = nullptr; +}; +} // namespace vnotex #endif // FAKEACCESSIBLE_H diff --git a/src/imagehost/giteeimagehost.cpp b/src/imagehost/giteeimagehost.cpp index c059437103..7ef63ef8fe 100644 --- a/src/imagehost/giteeimagehost.cpp +++ b/src/imagehost/giteeimagehost.cpp @@ -1,178 +1,174 @@ #include "giteeimagehost.h" +#include #include #include -#include -#include #include +#include using namespace vnotex; const QString GiteeImageHost::c_apiUrl = "https://gitee.com/api/v5"; -GiteeImageHost::GiteeImageHost(QObject *p_parent) - : RepoImageHost(p_parent) -{ -} +GiteeImageHost::GiteeImageHost(QObject *p_parent) : RepoImageHost(p_parent) {} -bool GiteeImageHost::ready() const -{ - return !m_personalAccessToken.isEmpty() && !m_userName.isEmpty() && !m_repoName.isEmpty(); +bool GiteeImageHost::ready() const { + return !m_personalAccessToken.isEmpty() && !m_userName.isEmpty() && !m_repoName.isEmpty(); } -ImageHost::Type GiteeImageHost::getType() const -{ - return Type::Gitee; -} +ImageHost::Type GiteeImageHost::getType() const { return Type::Gitee; } -QJsonObject GiteeImageHost::getConfig() const -{ - QJsonObject obj; - obj[QStringLiteral("personal_access_token")] = m_personalAccessToken; - obj[QStringLiteral("user_name")] = m_userName; - obj[QStringLiteral("repository_name")] = m_repoName; - return obj; +QJsonObject GiteeImageHost::getConfig() const { + QJsonObject obj; + obj[QStringLiteral("personal_access_token")] = m_personalAccessToken; + obj[QStringLiteral("user_name")] = m_userName; + obj[QStringLiteral("repository_name")] = m_repoName; + return obj; } -void GiteeImageHost::setConfig(const QJsonObject &p_jobj) -{ - parseConfig(p_jobj, m_personalAccessToken, m_userName, m_repoName); +void GiteeImageHost::setConfig(const QJsonObject &p_jobj) { + parseConfig(p_jobj, m_personalAccessToken, m_userName, m_repoName); - // Do not assume the default branch. - m_imageUrlPrefix = QStringLiteral("https://gitee.com/%1/%2/raw/").arg(m_userName, m_repoName); + // Do not assume the default branch. + m_imageUrlPrefix = QStringLiteral("https://gitee.com/%1/%2/raw/").arg(m_userName, m_repoName); } -vte::NetworkAccess::RawHeaderPairs GiteeImageHost::prepareCommonHeaders() -{ - vte::NetworkAccess::RawHeaderPairs rawHeader; - rawHeader.push_back(qMakePair(QByteArray("Content-Type"), QByteArray("application/json;charset=UTF-8"))); - return rawHeader; +vte::NetworkAccess::RawHeaderPairs GiteeImageHost::prepareCommonHeaders() { + vte::NetworkAccess::RawHeaderPairs rawHeader; + rawHeader.push_back( + qMakePair(QByteArray("Content-Type"), QByteArray("application/json;charset=UTF-8"))); + return rawHeader; } -QString GiteeImageHost::addAccessToken(const QString &p_token, QString p_url) -{ - if (p_url.contains(QLatin1Char('?'))) { - p_url += QStringLiteral("&access_token=%1").arg(p_token); - } else { - p_url += QStringLiteral("?access_token=%1").arg(p_token); - } - return p_url; +QString GiteeImageHost::addAccessToken(const QString &p_token, QString p_url) { + if (p_url.contains(QLatin1Char('?'))) { + p_url += QStringLiteral("&access_token=%1").arg(p_token); + } else { + p_url += QStringLiteral("?access_token=%1").arg(p_token); + } + return p_url; } -vte::NetworkReply GiteeImageHost::getRepoInfo(const QString &p_token, const QString &p_userName, const QString &p_repoName) const -{ - auto rawHeader = prepareCommonHeaders(); - auto urlStr = QStringLiteral("%1/repos/%2/%3").arg(c_apiUrl, p_userName, p_repoName); - auto reply = vte::NetworkAccess::request(QUrl(addAccessToken(p_token, urlStr)), rawHeader); - return reply; +vte::NetworkReply GiteeImageHost::getRepoInfo(const QString &p_token, const QString &p_userName, + const QString &p_repoName) const { + auto rawHeader = prepareCommonHeaders(); + auto urlStr = QStringLiteral("%1/repos/%2/%3").arg(c_apiUrl, p_userName, p_repoName); + auto reply = vte::NetworkAccess::request(QUrl(addAccessToken(p_token, urlStr)), rawHeader); + return reply; } -static bool isEmptyResponse(const QByteArray &p_data) -{ - return p_data == QByteArray("[]"); -} +static bool isEmptyResponse(const QByteArray &p_data) { return p_data == QByteArray("[]"); } -QString GiteeImageHost::create(const QByteArray &p_data, const QString &p_path, QString &p_msg) -{ - QString destUrl; +QString GiteeImageHost::create(const QByteArray &p_data, const QString &p_path, QString &p_msg) { + QString destUrl; - if (p_path.isEmpty()) { - p_msg = tr("Failed to create image with empty path."); - return destUrl; - } + if (p_path.isEmpty()) { + p_msg = tr("Failed to create image with empty path."); + return destUrl; + } - if (!ready()) { - p_msg = tr("Invalid Gitee image host configuration."); - return QString(); - } + if (!ready()) { + p_msg = tr("Invalid Gitee image host configuration."); + return QString(); + } - auto rawHeader = prepareCommonHeaders(); - const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, p_path); - - // Check if @p_path already exists. - auto reply = vte::NetworkAccess::request(QUrl(addAccessToken(m_personalAccessToken, urlStr)), rawHeader); - if (reply.m_error == QNetworkReply::NoError) { - if (!isEmptyResponse(reply.m_data)) { - p_msg = tr("The resource already exists at the image host (%1).").arg(p_path); - return QString(); - } - } else if (reply.m_error != QNetworkReply::ContentNotFoundError) { - p_msg = tr("Failed to query the resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - return QString(); - } + auto rawHeader = prepareCommonHeaders(); + const auto urlStr = + QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, p_path); - // Create the content. - QJsonObject requestDataObj; - requestDataObj[QStringLiteral("access_token")] = m_personalAccessToken; - requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_ADD: %1").arg(p_path); - requestDataObj[QStringLiteral("content")] = QString::fromUtf8(p_data.toBase64()); - auto requestData = Utils::toJsonString(requestDataObj); - reply = vte::NetworkAccess::post(QUrl(urlStr), rawHeader, requestData); - if (reply.m_error != QNetworkReply::NoError) { - p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - return QString(); - } else { - auto replyObj = Utils::fromJsonString(reply.m_data); - Q_ASSERT(!replyObj.isEmpty()); - auto targetUrl = replyObj[QStringLiteral("content")].toObject().value(QStringLiteral("download_url")).toString(); - if (targetUrl.isEmpty()) { - p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - } else { - targetUrl = PathUtils::encodeSpacesInPath(targetUrl); - qDebug() << "created resource" << targetUrl; - } - return targetUrl; + // Check if @p_path already exists. + auto reply = + vte::NetworkAccess::request(QUrl(addAccessToken(m_personalAccessToken, urlStr)), rawHeader); + if (reply.m_error == QNetworkReply::NoError) { + if (!isEmptyResponse(reply.m_data)) { + p_msg = tr("The resource already exists at the image host (%1).").arg(p_path); + return QString(); } -} - -bool GiteeImageHost::ownsUrl(const QString &p_url) const -{ - return p_url.startsWith(m_imageUrlPrefix); -} - -bool GiteeImageHost::remove(const QString &p_url, QString &p_msg) -{ - Q_ASSERT(ownsUrl(p_url)); - - if (!ready()) { - p_msg = tr("Invalid Gitee image host configuration."); - return false; - } - - const auto resourcePath = fetchResourcePath(m_imageUrlPrefix, p_url); - - auto rawHeader = prepareCommonHeaders(); - const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, resourcePath); - - // Get the SHA of the resource. - auto reply = vte::NetworkAccess::request(QUrl(addAccessToken(m_personalAccessToken, urlStr)), rawHeader); - if (reply.m_error != QNetworkReply::NoError || isEmptyResponse(reply.m_data)) { - p_msg = tr("Failed to fetch information about the resource (%1).").arg(resourcePath); - return false; - } - + } else if (reply.m_error != QNetworkReply::ContentNotFoundError) { + p_msg = tr("Failed to query the resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); + return QString(); + } + + // Create the content. + QJsonObject requestDataObj; + requestDataObj[QStringLiteral("access_token")] = m_personalAccessToken; + requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_ADD: %1").arg(p_path); + requestDataObj[QStringLiteral("content")] = QString::fromUtf8(p_data.toBase64()); + auto requestData = Utils::toJsonString(requestDataObj); + reply = vte::NetworkAccess::post(QUrl(urlStr), rawHeader, requestData); + if (reply.m_error != QNetworkReply::NoError) { + p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); + return QString(); + } else { auto replyObj = Utils::fromJsonString(reply.m_data); Q_ASSERT(!replyObj.isEmpty()); - const auto sha = replyObj[QStringLiteral("sha")].toString(); - if (sha.isEmpty()) { - p_msg = tr("Failed to fetch SHA about the resource (%1) (%2).").arg(resourcePath, QString::fromUtf8(reply.m_data)); - return false; - } - - // Delete. - QJsonObject requestDataObj; - requestDataObj[QStringLiteral("access_token")] = m_personalAccessToken; - requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_DEL: %1").arg(resourcePath); - requestDataObj[QStringLiteral("sha")] = sha; - auto requestData = Utils::toJsonString(requestDataObj); - reply = vte::NetworkAccess::deleteResource(QUrl(urlStr), rawHeader, requestData); - if (reply.m_error != QNetworkReply::NoError) { - p_msg = tr("Failed to delete resource (%1) (%2).").arg(resourcePath, QString::fromUtf8(reply.m_data)); - return false; + auto targetUrl = replyObj[QStringLiteral("content")] + .toObject() + .value(QStringLiteral("download_url")) + .toString(); + if (targetUrl.isEmpty()) { + p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); + } else { + targetUrl = PathUtils::encodeSpacesInPath(targetUrl); + qDebug() << "created resource" << targetUrl; } + return targetUrl; + } +} - qDebug() << "deleted resource" << resourcePath; +bool GiteeImageHost::ownsUrl(const QString &p_url) const { + return p_url.startsWith(m_imageUrlPrefix); +} - return true; +bool GiteeImageHost::remove(const QString &p_url, QString &p_msg) { + Q_ASSERT(ownsUrl(p_url)); + + if (!ready()) { + p_msg = tr("Invalid Gitee image host configuration."); + return false; + } + + const auto resourcePath = fetchResourcePath(m_imageUrlPrefix, p_url); + + auto rawHeader = prepareCommonHeaders(); + const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4") + .arg(c_apiUrl, m_userName, m_repoName, resourcePath); + + // Get the SHA of the resource. + auto reply = + vte::NetworkAccess::request(QUrl(addAccessToken(m_personalAccessToken, urlStr)), rawHeader); + if (reply.m_error != QNetworkReply::NoError || isEmptyResponse(reply.m_data)) { + p_msg = tr("Failed to fetch information about the resource (%1).").arg(resourcePath); + return false; + } + + auto replyObj = Utils::fromJsonString(reply.m_data); + Q_ASSERT(!replyObj.isEmpty()); + const auto sha = replyObj[QStringLiteral("sha")].toString(); + if (sha.isEmpty()) { + p_msg = tr("Failed to fetch SHA about the resource (%1) (%2).") + .arg(resourcePath, QString::fromUtf8(reply.m_data)); + return false; + } + + // Delete. + QJsonObject requestDataObj; + requestDataObj[QStringLiteral("access_token")] = m_personalAccessToken; + requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_DEL: %1").arg(resourcePath); + requestDataObj[QStringLiteral("sha")] = sha; + auto requestData = Utils::toJsonString(requestDataObj); + reply = vte::NetworkAccess::deleteResource(QUrl(urlStr), rawHeader, requestData); + if (reply.m_error != QNetworkReply::NoError) { + p_msg = tr("Failed to delete resource (%1) (%2).") + .arg(resourcePath, QString::fromUtf8(reply.m_data)); + return false; + } + + qDebug() << "deleted resource" << resourcePath; + + return true; } diff --git a/src/imagehost/giteeimagehost.h b/src/imagehost/giteeimagehost.h index 335d7cd253..df024bdf37 100644 --- a/src/imagehost/giteeimagehost.h +++ b/src/imagehost/giteeimagehost.h @@ -3,45 +3,44 @@ #include "repoimagehost.h" -namespace vnotex -{ - class GiteeImageHost : public RepoImageHost - { - Q_OBJECT - public: - explicit GiteeImageHost(QObject *p_parent); +namespace vnotex { +class GiteeImageHost : public RepoImageHost { + Q_OBJECT +public: + explicit GiteeImageHost(QObject *p_parent); - bool ready() const Q_DECL_OVERRIDE; + bool ready() const Q_DECL_OVERRIDE; - Type getType() const Q_DECL_OVERRIDE; + Type getType() const Q_DECL_OVERRIDE; - QJsonObject getConfig() const Q_DECL_OVERRIDE; + QJsonObject getConfig() const Q_DECL_OVERRIDE; - void setConfig(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; + void setConfig(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; - QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) Q_DECL_OVERRIDE; + QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) Q_DECL_OVERRIDE; - bool remove(const QString &p_url, QString &p_msg) Q_DECL_OVERRIDE; + bool remove(const QString &p_url, QString &p_msg) Q_DECL_OVERRIDE; - bool ownsUrl(const QString &p_url) const Q_DECL_OVERRIDE; + bool ownsUrl(const QString &p_url) const Q_DECL_OVERRIDE; - private: - vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, const QString &p_repoName) const Q_DECL_OVERRIDE; +private: + vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, + const QString &p_repoName) const Q_DECL_OVERRIDE; - static vte::NetworkAccess::RawHeaderPairs prepareCommonHeaders(); + static vte::NetworkAccess::RawHeaderPairs prepareCommonHeaders(); - static QString addAccessToken(const QString &p_token, QString p_url); + static QString addAccessToken(const QString &p_token, QString p_url); - QString m_personalAccessToken; + QString m_personalAccessToken; - QString m_userName; + QString m_userName; - QString m_repoName; + QString m_repoName; - QString m_imageUrlPrefix; + QString m_imageUrlPrefix; - static const QString c_apiUrl; - }; -} + static const QString c_apiUrl; +}; +} // namespace vnotex #endif // GITEEIMAGEHOST_H diff --git a/src/imagehost/githubimagehost.cpp b/src/imagehost/githubimagehost.cpp index 281d6c68cc..a38317561f 100644 --- a/src/imagehost/githubimagehost.cpp +++ b/src/imagehost/githubimagehost.cpp @@ -1,8 +1,8 @@ #include "githubimagehost.h" +#include #include #include -#include #include #include @@ -12,181 +12,177 @@ using namespace vnotex; const QString GitHubImageHost::c_apiUrl = "https://api.github.com"; -GitHubImageHost::GitHubImageHost(QObject *p_parent) - : RepoImageHost(p_parent) -{ -} +GitHubImageHost::GitHubImageHost(QObject *p_parent) : RepoImageHost(p_parent) {} -bool GitHubImageHost::ready() const -{ - return !m_personalAccessToken.isEmpty() && !m_userName.isEmpty() && !m_repoName.isEmpty(); +bool GitHubImageHost::ready() const { + return !m_personalAccessToken.isEmpty() && !m_userName.isEmpty() && !m_repoName.isEmpty(); } -ImageHost::Type GitHubImageHost::getType() const -{ - return Type::GitHub; -} +ImageHost::Type GitHubImageHost::getType() const { return Type::GitHub; } -QJsonObject GitHubImageHost::getConfig() const -{ - QJsonObject obj; - obj[QStringLiteral("personal_access_token")] = m_personalAccessToken; - obj[QStringLiteral("user_name")] = m_userName; - obj[QStringLiteral("repository_name")] = m_repoName; - return obj; +QJsonObject GitHubImageHost::getConfig() const { + QJsonObject obj; + obj[QStringLiteral("personal_access_token")] = m_personalAccessToken; + obj[QStringLiteral("user_name")] = m_userName; + obj[QStringLiteral("repository_name")] = m_repoName; + return obj; } -void GitHubImageHost::setConfig(const QJsonObject &p_jobj) -{ - parseConfig(p_jobj, m_personalAccessToken, m_userName, m_repoName); +void GitHubImageHost::setConfig(const QJsonObject &p_jobj) { + parseConfig(p_jobj, m_personalAccessToken, m_userName, m_repoName); - // Do not assume the default branch. - m_imageUrlPrefix = QStringLiteral("https://raw.githubusercontent.com/%1/%2/").arg(m_userName, m_repoName); + // Do not assume the default branch. + m_imageUrlPrefix = + QStringLiteral("https://raw.githubusercontent.com/%1/%2/").arg(m_userName, m_repoName); } -QPair GitHubImageHost::authorizationHeader(const QString &p_token) -{ - auto token = "token " + p_token; - return qMakePair(QByteArray("Authorization"), token.toUtf8()); +QPair GitHubImageHost::authorizationHeader(const QString &p_token) { + auto token = "token " + p_token; + return qMakePair(QByteArray("Authorization"), token.toUtf8()); } -QPair GitHubImageHost::acceptHeader() -{ - return qMakePair(QByteArray("Accept"), QByteArray("application/vnd.github.v3+json")); +QPair GitHubImageHost::acceptHeader() { + return qMakePair(QByteArray("Accept"), QByteArray("application/vnd.github.v3+json")); } -vte::NetworkAccess::RawHeaderPairs GitHubImageHost::prepareCommonHeaders(const QString &p_token) -{ - vte::NetworkAccess::RawHeaderPairs rawHeader; - rawHeader.push_back(authorizationHeader(p_token)); - rawHeader.push_back(acceptHeader()); - return rawHeader; +vte::NetworkAccess::RawHeaderPairs GitHubImageHost::prepareCommonHeaders(const QString &p_token) { + vte::NetworkAccess::RawHeaderPairs rawHeader; + rawHeader.push_back(authorizationHeader(p_token)); + rawHeader.push_back(acceptHeader()); + return rawHeader; } -vte::NetworkReply GitHubImageHost::getRepoInfo(const QString &p_token, const QString &p_userName, const QString &p_repoName) const -{ - auto rawHeader = prepareCommonHeaders(p_token); - const auto urlStr = QStringLiteral("%1/repos/%2/%3").arg(c_apiUrl, p_userName, p_repoName); - auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); - return reply; +vte::NetworkReply GitHubImageHost::getRepoInfo(const QString &p_token, const QString &p_userName, + const QString &p_repoName) const { + auto rawHeader = prepareCommonHeaders(p_token); + const auto urlStr = QStringLiteral("%1/repos/%2/%3").arg(c_apiUrl, p_userName, p_repoName); + auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); + return reply; } -QString GitHubImageHost::create(const QByteArray &p_data, const QString &p_path, QString &p_msg) -{ - QString destUrl; - - if (p_path.isEmpty()) { - p_msg = tr("Failed to create image with empty path."); - return destUrl; - } - - if (!ready()) { - p_msg = tr("Invalid GitHub image host configuration."); - return QString(); - } - - auto rawHeader = prepareCommonHeaders(m_personalAccessToken); - const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, p_path); - - // Check if @p_path already exists. - auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); - if (reply.m_error == QNetworkReply::NoError) { - p_msg = tr("The resource already exists at the image host (%1).").arg(p_path); - return QString(); - } else if (reply.m_error != QNetworkReply::ContentNotFoundError) { - p_msg = tr("Failed to query the resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - return QString(); - } - - // Create the content. - QJsonObject requestDataObj; - requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_ADD: %1").arg(p_path); - requestDataObj[QStringLiteral("content")] = QString::fromUtf8(p_data.toBase64()); - auto requestData = Utils::toJsonString(requestDataObj); - reply = vte::NetworkAccess::put(QUrl(urlStr), rawHeader, requestData); - if (reply.m_error != QNetworkReply::NoError) { - p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - return QString(); +QString GitHubImageHost::create(const QByteArray &p_data, const QString &p_path, QString &p_msg) { + QString destUrl; + + if (p_path.isEmpty()) { + p_msg = tr("Failed to create image with empty path."); + return destUrl; + } + + if (!ready()) { + p_msg = tr("Invalid GitHub image host configuration."); + return QString(); + } + + auto rawHeader = prepareCommonHeaders(m_personalAccessToken); + const auto urlStr = + QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, p_path); + + // Check if @p_path already exists. + auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); + if (reply.m_error == QNetworkReply::NoError) { + p_msg = tr("The resource already exists at the image host (%1).").arg(p_path); + return QString(); + } else if (reply.m_error != QNetworkReply::ContentNotFoundError) { + p_msg = tr("Failed to query the resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); + return QString(); + } + + // Create the content. + QJsonObject requestDataObj; + requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_ADD: %1").arg(p_path); + requestDataObj[QStringLiteral("content")] = QString::fromUtf8(p_data.toBase64()); + auto requestData = Utils::toJsonString(requestDataObj); + reply = vte::NetworkAccess::put(QUrl(urlStr), rawHeader, requestData); + if (reply.m_error != QNetworkReply::NoError) { + p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); + return QString(); + } else { + auto replyObj = Utils::fromJsonString(reply.m_data); + Q_ASSERT(!replyObj.isEmpty()); + auto targetUrl = replyObj[QStringLiteral("content")] + .toObject() + .value(QStringLiteral("download_url")) + .toString(); + if (targetUrl.isEmpty()) { + p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).") + .arg(urlStr, reply.errorStr(), reply.m_data); } else { - auto replyObj = Utils::fromJsonString(reply.m_data); - Q_ASSERT(!replyObj.isEmpty()); - auto targetUrl = replyObj[QStringLiteral("content")].toObject().value(QStringLiteral("download_url")).toString(); - if (targetUrl.isEmpty()) { - p_msg = tr("Failed to create resource at the image host (%1) (%2) (%3).").arg(urlStr, reply.errorStr(), reply.m_data); - } else { - qDebug() << "created resource" << targetUrl; - } - return targetUrl; + qDebug() << "created resource" << targetUrl; } + return targetUrl; + } } -bool GitHubImageHost::ownsUrl(const QString &p_url) const -{ - return p_url.startsWith(m_imageUrlPrefix); +bool GitHubImageHost::ownsUrl(const QString &p_url) const { + return p_url.startsWith(m_imageUrlPrefix); } -bool GitHubImageHost::remove(const QString &p_url, QString &p_msg) -{ - Q_ASSERT(ownsUrl(p_url)); - - if (!ready()) { - p_msg = tr("Invalid GitHub image host configuration."); - return false; - } - - const auto resourcePath = fetchResourcePath(m_imageUrlPrefix, p_url); - - auto rawHeader = prepareCommonHeaders(m_personalAccessToken); - const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4").arg(c_apiUrl, m_userName, m_repoName, resourcePath); - - // Get the SHA of the resource. - QString sha = ""; - auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); - if (reply.m_error == QNetworkReply::NoError) { - auto replyObj = Utils::fromJsonString(reply.m_data); - Q_ASSERT(!replyObj.isEmpty()); - sha = replyObj[QStringLiteral("sha")].toString(); - } else if (reply.m_error == QNetworkReply::ContentAccessDenied) { // File larger than 1M - - // Get all file information under the warehouse directory - const auto fileInfo = QFileInfo(urlStr); - const auto urlFilePath = QUrl(fileInfo.path()); - const auto fleName = fileInfo.fileName(); - reply = vte::NetworkAccess::request(urlFilePath, rawHeader); - - if (QNetworkReply::NoError == reply.m_error) { - const auto jsonArray = QJsonDocument::fromJson(reply.m_data).array(); - for (auto i = jsonArray.begin(); i < jsonArray.end(); i++) { - if (!i->isObject()) { - continue; - } - const auto jsonObj = i->toObject(); - const auto name = jsonObj[QStringLiteral("name")].toString(); - if (name == fleName) { - sha = jsonObj[QStringLiteral("sha")].toString(); - break; - } - } +bool GitHubImageHost::remove(const QString &p_url, QString &p_msg) { + Q_ASSERT(ownsUrl(p_url)); + + if (!ready()) { + p_msg = tr("Invalid GitHub image host configuration."); + return false; + } + + const auto resourcePath = fetchResourcePath(m_imageUrlPrefix, p_url); + + auto rawHeader = prepareCommonHeaders(m_personalAccessToken); + const auto urlStr = QStringLiteral("%1/repos/%2/%3/contents/%4") + .arg(c_apiUrl, m_userName, m_repoName, resourcePath); + + // Get the SHA of the resource. + QString sha = ""; + auto reply = vte::NetworkAccess::request(QUrl(urlStr), rawHeader); + if (reply.m_error == QNetworkReply::NoError) { + auto replyObj = Utils::fromJsonString(reply.m_data); + Q_ASSERT(!replyObj.isEmpty()); + sha = replyObj[QStringLiteral("sha")].toString(); + } else if (reply.m_error == QNetworkReply::ContentAccessDenied) { // File larger than 1M + + // Get all file information under the warehouse directory + const auto fileInfo = QFileInfo(urlStr); + const auto urlFilePath = QUrl(fileInfo.path()); + const auto fleName = fileInfo.fileName(); + reply = vte::NetworkAccess::request(urlFilePath, rawHeader); + + if (QNetworkReply::NoError == reply.m_error) { + const auto jsonArray = QJsonDocument::fromJson(reply.m_data).array(); + for (auto i = jsonArray.begin(); i < jsonArray.end(); i++) { + if (!i->isObject()) { + continue; } + const auto jsonObj = i->toObject(); + const auto name = jsonObj[QStringLiteral("name")].toString(); + if (name == fleName) { + sha = jsonObj[QStringLiteral("sha")].toString(); + break; + } + } } - - if (sha.isEmpty()) { - p_msg = tr("Failed to fetch SHA about the resource (%1) (%2).").arg(resourcePath, QString::fromUtf8(reply.m_data)); - return false; - } - - // Delete. - QJsonObject requestDataObj; - requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_DEL: %1").arg(resourcePath); - requestDataObj[QStringLiteral("sha")] = sha; - auto requestData = Utils::toJsonString(requestDataObj); - reply = vte::NetworkAccess::deleteResource(QUrl(urlStr), rawHeader, requestData); - if (reply.m_error != QNetworkReply::NoError) { - p_msg = tr("Failed to delete resource (%1) (%2).").arg(resourcePath, QString::fromUtf8(reply.m_data)); - return false; - } - - qDebug() << "deleted resource" << resourcePath; - - return true; + } + + if (sha.isEmpty()) { + p_msg = tr("Failed to fetch SHA about the resource (%1) (%2).") + .arg(resourcePath, QString::fromUtf8(reply.m_data)); + return false; + } + + // Delete. + QJsonObject requestDataObj; + requestDataObj[QStringLiteral("message")] = QStringLiteral("VX_DEL: %1").arg(resourcePath); + requestDataObj[QStringLiteral("sha")] = sha; + auto requestData = Utils::toJsonString(requestDataObj); + reply = vte::NetworkAccess::deleteResource(QUrl(urlStr), rawHeader, requestData); + if (reply.m_error != QNetworkReply::NoError) { + p_msg = tr("Failed to delete resource (%1) (%2).") + .arg(resourcePath, QString::fromUtf8(reply.m_data)); + return false; + } + + qDebug() << "deleted resource" << resourcePath; + + return true; } diff --git a/src/imagehost/githubimagehost.h b/src/imagehost/githubimagehost.h index 96755f2c96..133767f5c0 100644 --- a/src/imagehost/githubimagehost.h +++ b/src/imagehost/githubimagehost.h @@ -3,48 +3,47 @@ #include "repoimagehost.h" -namespace vnotex -{ - class GitHubImageHost : public RepoImageHost - { - Q_OBJECT - public: - explicit GitHubImageHost(QObject *p_parent); +namespace vnotex { +class GitHubImageHost : public RepoImageHost { + Q_OBJECT +public: + explicit GitHubImageHost(QObject *p_parent); - bool ready() const Q_DECL_OVERRIDE; + bool ready() const Q_DECL_OVERRIDE; - Type getType() const Q_DECL_OVERRIDE; + Type getType() const Q_DECL_OVERRIDE; - QJsonObject getConfig() const Q_DECL_OVERRIDE; + QJsonObject getConfig() const Q_DECL_OVERRIDE; - void setConfig(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; + void setConfig(const QJsonObject &p_jobj) Q_DECL_OVERRIDE; - QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) Q_DECL_OVERRIDE; + QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) Q_DECL_OVERRIDE; - bool remove(const QString &p_url, QString &p_msg) Q_DECL_OVERRIDE; + bool remove(const QString &p_url, QString &p_msg) Q_DECL_OVERRIDE; - bool ownsUrl(const QString &p_url) const Q_DECL_OVERRIDE; + bool ownsUrl(const QString &p_url) const Q_DECL_OVERRIDE; - protected: - QString m_personalAccessToken; +protected: + QString m_personalAccessToken; - QString m_userName; + QString m_userName; - QString m_repoName; + QString m_repoName; - QString m_imageUrlPrefix; + QString m_imageUrlPrefix; - private: - vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, const QString &p_repoName) const Q_DECL_OVERRIDE; +private: + vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, + const QString &p_repoName) const Q_DECL_OVERRIDE; - static QPair authorizationHeader(const QString &p_token); + static QPair authorizationHeader(const QString &p_token); - static QPair acceptHeader(); + static QPair acceptHeader(); - static vte::NetworkAccess::RawHeaderPairs prepareCommonHeaders(const QString &p_token); + static vte::NetworkAccess::RawHeaderPairs prepareCommonHeaders(const QString &p_token); - static const QString c_apiUrl; - }; -} + static const QString c_apiUrl; +}; +} // namespace vnotex #endif // GITHUBIMAGEHOST_H diff --git a/src/imagehost/imagehost.cpp b/src/imagehost/imagehost.cpp index 7cf4947113..bc6fdc24f3 100644 --- a/src/imagehost/imagehost.cpp +++ b/src/imagehost/imagehost.cpp @@ -2,32 +2,22 @@ using namespace vnotex; -ImageHost::ImageHost(QObject *p_parent) - : QObject(p_parent) -{ -} +ImageHost::ImageHost(QObject *p_parent) : QObject(p_parent) {} -const QString &ImageHost::getName() const -{ - return m_name; -} +const QString &ImageHost::getName() const { return m_name; } -void ImageHost::setName(const QString &p_name) -{ - m_name = p_name; -} +void ImageHost::setName(const QString &p_name) { m_name = p_name; } -QString ImageHost::typeString(ImageHost::Type p_type) -{ - switch (p_type) { - case Type::GitHub: - return tr("GitHub"); +QString ImageHost::typeString(ImageHost::Type p_type) { + switch (p_type) { + case Type::GitHub: + return tr("GitHub"); - case Type::Gitee: - return tr("Gitee"); + case Type::Gitee: + return tr("Gitee"); - default: - Q_ASSERT(false); - return QStringLiteral("Unknown"); - } + default: + Q_ASSERT(false); + return QStringLiteral("Unknown"); + } } diff --git a/src/imagehost/imagehost.h b/src/imagehost/imagehost.h index 55ace6cd5c..a3b7a603d8 100644 --- a/src/imagehost/imagehost.h +++ b/src/imagehost/imagehost.h @@ -1,58 +1,51 @@ #ifndef IMAGEHOST_H #define IMAGEHOST_H -#include #include +#include #include class QByteArray; -namespace vnotex -{ - // Abstract class for image host. - class ImageHost : public QObject - { - Q_OBJECT - public: - enum Type - { - GitHub = 0, - Gitee, - MaxHost - }; +namespace vnotex { +// Abstract class for image host. +class ImageHost : public QObject { + Q_OBJECT +public: + enum Type { GitHub = 0, Gitee, MaxHost }; - virtual ~ImageHost() = default; + virtual ~ImageHost() = default; - const QString &getName() const; - void setName(const QString &p_name); + const QString &getName() const; + void setName(const QString &p_name); - virtual Type getType() const = 0; + virtual Type getType() const = 0; - // Whether it is ready to serve. - virtual bool ready() const = 0; + // Whether it is ready to serve. + virtual bool ready() const = 0; - virtual QJsonObject getConfig() const = 0; - virtual void setConfig(const QJsonObject &p_jobj) = 0; + virtual QJsonObject getConfig() const = 0; + virtual void setConfig(const QJsonObject &p_jobj) = 0; - virtual bool testConfig(const QJsonObject &p_jobj, QString &p_msg) = 0; + virtual bool testConfig(const QJsonObject &p_jobj, QString &p_msg) = 0; - // Upload @p_data to the host at path @p_path. Return the target Url string on success. - virtual QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) = 0; + // Upload @p_data to the host at path @p_path. Return the target Url string on success. + virtual QString create(const QByteArray &p_data, const QString &p_path, QString &p_msg) = 0; - virtual bool remove(const QString &p_url, QString &p_msg) = 0; + virtual bool remove(const QString &p_url, QString &p_msg) = 0; - // Test if @p_url is owned by this image host. - virtual bool ownsUrl(const QString &p_url) const = 0; + // Test if @p_url is owned by this image host. + virtual bool ownsUrl(const QString &p_url) const = 0; - static QString typeString(Type p_type); + static QString typeString(Type p_type); - protected: - explicit ImageHost(QObject *p_parent = nullptr); +protected: + explicit ImageHost(QObject *p_parent = nullptr); - // Name to identify one image host. One type of image host may have multiple instances. - QString m_name; - }; -} + // Name to identify one image host. One type of image host may have multiple instances. + QString m_name; +}; +} // namespace vnotex #endif // IMAGEHOST_H diff --git a/src/imagehost/imagehostmgr.cpp b/src/imagehost/imagehostmgr.cpp index af73e56377..f9f2eabb63 100644 --- a/src/imagehost/imagehostmgr.cpp +++ b/src/imagehost/imagehostmgr.cpp @@ -5,198 +5,178 @@ #include #include -#include "githubimagehost.h" #include "giteeimagehost.h" +#include "githubimagehost.h" using namespace vnotex; -ImageHostMgr::ImageHostMgr() -{ - loadImageHosts(); -} +ImageHostMgr::ImageHostMgr() { loadImageHosts(); } -void ImageHostMgr::loadImageHosts() -{ - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - for (const auto &host : editorConfig.getImageHosts()) { - if (host.m_type >= ImageHost::Type::MaxHost) { - qWarning() << "skipped unknown type image host" << host.m_type << host.m_name; - continue; - } - - if (find(host.m_name)) { - qWarning() << "sikpped image host with name conflict" << host.m_type << host.m_name; - continue; - } - - auto imageHost = createImageHost(static_cast(host.m_type), this); - if (!imageHost) { - qWarning() << "failed to create image host" << host.m_type << host.m_name; - continue; - } - - imageHost->setName(host.m_name); - imageHost->setConfig(host.m_config); - add(imageHost); +void ImageHostMgr::loadImageHosts() { + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + for (const auto &host : editorConfig.getImageHosts()) { + if (host.m_type >= ImageHost::Type::MaxHost) { + qWarning() << "skipped unknown type image host" << host.m_type << host.m_name; + continue; } - m_defaultHost = find(editorConfig.getDefaultImageHost()); - - qDebug() << "loaded" << m_hosts.size() << "image hosts"; -} + if (find(host.m_name)) { + qWarning() << "sikpped image host with name conflict" << host.m_type << host.m_name; + continue; + } -void ImageHostMgr::saveImageHosts() -{ - QVector items; - items.resize(m_hosts.size()); - for (int i = 0; i < m_hosts.size(); ++i) { - items[i].m_type = static_cast(m_hosts[i]->getType()); - items[i].m_name = m_hosts[i]->getName(); - items[i].m_config = m_hosts[i]->getConfig(); + auto imageHost = createImageHost(static_cast(host.m_type), this); + if (!imageHost) { + qWarning() << "failed to create image host" << host.m_type << host.m_name; + continue; } - auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - editorConfig.setImageHosts(items); + imageHost->setName(host.m_name); + imageHost->setConfig(host.m_config); + add(imageHost); + } + + m_defaultHost = find(editorConfig.getDefaultImageHost()); + + qDebug() << "loaded" << m_hosts.size() << "image hosts"; +} + +void ImageHostMgr::saveImageHosts() { + QVector items; + items.resize(m_hosts.size()); + for (int i = 0; i < m_hosts.size(); ++i) { + items[i].m_type = static_cast(m_hosts[i]->getType()); + items[i].m_name = m_hosts[i]->getName(); + items[i].m_config = m_hosts[i]->getConfig(); + } + + auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + editorConfig.setImageHosts(items); } -ImageHost *ImageHostMgr::createImageHost(ImageHost::Type p_type, QObject *p_parent) -{ - switch (p_type) { - case ImageHost::Type::GitHub: - return new GitHubImageHost(p_parent); +ImageHost *ImageHostMgr::createImageHost(ImageHost::Type p_type, QObject *p_parent) { + switch (p_type) { + case ImageHost::Type::GitHub: + return new GitHubImageHost(p_parent); - case ImageHost::Type::Gitee: - return new GiteeImageHost(p_parent); + case ImageHost::Type::Gitee: + return new GiteeImageHost(p_parent); - default: - return nullptr; - } + default: + return nullptr; + } } -void ImageHostMgr::add(ImageHost *p_host) -{ - p_host->setParent(this); - m_hosts.append(p_host); +void ImageHostMgr::add(ImageHost *p_host) { + p_host->setParent(this); + m_hosts.append(p_host); } -ImageHost *ImageHostMgr::find(const QString &p_name) const -{ - if (p_name.isEmpty()) { - return nullptr; - } +ImageHost *ImageHostMgr::find(const QString &p_name) const { + if (p_name.isEmpty()) { + return nullptr; + } - for (auto host : m_hosts) { - if (host->getName() == p_name) { - return host; - } + for (auto host : m_hosts) { + if (host->getName() == p_name) { + return host; } + } - return nullptr; + return nullptr; } -ImageHost *ImageHostMgr::newImageHost(ImageHost::Type p_type, const QString &p_name) -{ - if (find(p_name)) { - qWarning() << "failed to new image host with existing name" << p_name; - return nullptr; - } +ImageHost *ImageHostMgr::newImageHost(ImageHost::Type p_type, const QString &p_name) { + if (find(p_name)) { + qWarning() << "failed to new image host with existing name" << p_name; + return nullptr; + } - auto host = createImageHost(p_type, this); - if (!host) { - return nullptr; - } + auto host = createImageHost(p_type, this); + if (!host) { + return nullptr; + } - host->setName(p_name); - add(host); + host->setName(p_name); + add(host); - saveImageHosts(); + saveImageHosts(); - emit imageHostChanged(); + emit imageHostChanged(); - return host; + return host; } -const QVector &ImageHostMgr::getImageHosts() const -{ - return m_hosts; -} +const QVector &ImageHostMgr::getImageHosts() const { return m_hosts; } -void ImageHostMgr::removeImageHost(ImageHost *p_host) -{ - m_hosts.removeOne(p_host); +void ImageHostMgr::removeImageHost(ImageHost *p_host) { + m_hosts.removeOne(p_host); - saveImageHosts(); + saveImageHosts(); - if (p_host == m_defaultHost) { - m_defaultHost = nullptr; - saveDefaultImageHost(); - } + if (p_host == m_defaultHost) { + m_defaultHost = nullptr; + saveDefaultImageHost(); + } - emit imageHostChanged(); + emit imageHostChanged(); } -bool ImageHostMgr::renameImageHost(ImageHost *p_host, const QString &p_newName) -{ - if (p_newName.isEmpty()) { - return false; - } +bool ImageHostMgr::renameImageHost(ImageHost *p_host, const QString &p_newName) { + if (p_newName.isEmpty()) { + return false; + } - if (p_newName == p_host->getName()) { - return true; - } + if (p_newName == p_host->getName()) { + return true; + } - if (find(p_newName)) { - return false; - } + if (find(p_newName)) { + return false; + } - p_host->setName(p_newName); + p_host->setName(p_newName); - saveImageHosts(); + saveImageHosts(); - if (m_defaultHost == p_host) { - saveDefaultImageHost(); - } + if (m_defaultHost == p_host) { + saveDefaultImageHost(); + } - emit imageHostChanged(); - return true; + emit imageHostChanged(); + return true; } -ImageHost *ImageHostMgr::getDefaultImageHost() const -{ - return m_defaultHost; -} +ImageHost *ImageHostMgr::getDefaultImageHost() const { return m_defaultHost; } -void ImageHostMgr::setDefaultImageHost(const QString &p_name) -{ - auto host = find(p_name); - if (m_defaultHost == host) { - return; - } +void ImageHostMgr::setDefaultImageHost(const QString &p_name) { + auto host = find(p_name); + if (m_defaultHost == host) { + return; + } - m_defaultHost = host; + m_defaultHost = host; - saveDefaultImageHost(); + saveDefaultImageHost(); - emit imageHostChanged(); + emit imageHostChanged(); } -void ImageHostMgr::saveDefaultImageHost() -{ - auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - editorConfig.setDefaultImageHost(m_defaultHost ? m_defaultHost->getName() : QString()); +void ImageHostMgr::saveDefaultImageHost() { + auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + editorConfig.setDefaultImageHost(m_defaultHost ? m_defaultHost->getName() : QString()); } -ImageHost *ImageHostMgr::findByImageUrl(const QString &p_url) const -{ - if (p_url.isEmpty()) { - return nullptr; - } +ImageHost *ImageHostMgr::findByImageUrl(const QString &p_url) const { + if (p_url.isEmpty()) { + return nullptr; + } - for (auto host : m_hosts) { - if (host->ownsUrl(p_url)) { - return host; - } + for (auto host : m_hosts) { + if (host->ownsUrl(p_url)) { + return host; } + } - return nullptr; + return nullptr; } diff --git a/src/imagehost/imagehostmgr.h b/src/imagehost/imagehostmgr.h index 0a82c620b8..37e8922c35 100644 --- a/src/imagehost/imagehostmgr.h +++ b/src/imagehost/imagehostmgr.h @@ -8,54 +8,51 @@ #include "imagehost.h" -namespace vnotex -{ - class ImageHostMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - static ImageHostMgr &getInst() - { - static ImageHostMgr inst; - return inst; - } +namespace vnotex { +class ImageHostMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + static ImageHostMgr &getInst() { + static ImageHostMgr inst; + return inst; + } - ImageHost *find(const QString &p_name) const; + ImageHost *find(const QString &p_name) const; - ImageHost *findByImageUrl(const QString &p_url) const; + ImageHost *findByImageUrl(const QString &p_url) const; - ImageHost *newImageHost(ImageHost::Type p_type, const QString &p_name); + ImageHost *newImageHost(ImageHost::Type p_type, const QString &p_name); - const QVector &getImageHosts() const; + const QVector &getImageHosts() const; - void removeImageHost(ImageHost *p_host); + void removeImageHost(ImageHost *p_host); - bool renameImageHost(ImageHost *p_host, const QString &p_newName); + bool renameImageHost(ImageHost *p_host, const QString &p_newName); - void saveImageHosts(); + void saveImageHosts(); - ImageHost *getDefaultImageHost() const; + ImageHost *getDefaultImageHost() const; - void setDefaultImageHost(const QString &p_name); + void setDefaultImageHost(const QString &p_name); - signals: - void imageHostChanged(); +signals: + void imageHostChanged(); - private: - ImageHostMgr(); +private: + ImageHostMgr(); - void loadImageHosts(); + void loadImageHosts(); - void add(ImageHost *p_host); + void add(ImageHost *p_host); - void saveDefaultImageHost(); + void saveDefaultImageHost(); - static ImageHost *createImageHost(ImageHost::Type p_type, QObject *p_parent); + static ImageHost *createImageHost(ImageHost::Type p_type, QObject *p_parent); - QVector m_hosts; + QVector m_hosts; - ImageHost *m_defaultHost = nullptr; - }; -} + ImageHost *m_defaultHost = nullptr; +}; +} // namespace vnotex #endif // IMAGEHOSTMGR_H diff --git a/src/imagehost/imagehostutils.cpp b/src/imagehost/imagehostutils.cpp index 93b04146a6..d2b0ab0b92 100644 --- a/src/imagehost/imagehostutils.cpp +++ b/src/imagehost/imagehostutils.cpp @@ -8,22 +8,21 @@ using namespace vnotex; -QString ImageHostUtils::generateRelativePath(const Buffer *p_buffer) -{ - QString relativePath; +QString ImageHostUtils::generateRelativePath(const Buffer *p_buffer) { + QString relativePath; - // To avoid leaking any private information, for external files, we won't add path to it. - if (auto node = p_buffer->getNode()) { - auto notebook = node->getNotebook(); - auto name = notebook->getName(); - if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { - name = QStringLiteral("vx_notebooks"); - } - - relativePath = name; - relativePath += "/" + notebook->getBackend()->getRelativePath(p_buffer->getPath()); - relativePath = relativePath.toLower(); + // To avoid leaking any private information, for external files, we won't add path to it. + if (auto node = p_buffer->getNode()) { + auto notebook = node->getNotebook(); + auto name = notebook->getName(); + if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { + name = QStringLiteral("vx_notebooks"); } - return relativePath; + relativePath = name; + relativePath += "/" + notebook->getBackend()->getRelativePath(p_buffer->getPath()); + relativePath = relativePath.toLower(); + } + + return relativePath; } diff --git a/src/imagehost/imagehostutils.h b/src/imagehost/imagehostutils.h index 5844b0854c..3c1e73c035 100644 --- a/src/imagehost/imagehostutils.h +++ b/src/imagehost/imagehostutils.h @@ -6,18 +6,16 @@ class QImage; class QWidget; -namespace vnotex -{ - class Buffer; +namespace vnotex { +class Buffer; - class ImageHostUtils - { - public: - ImageHostUtils() = delete; +class ImageHostUtils { +public: + ImageHostUtils() = delete; - // According to @p_buffer, generate the relative path on image host for images. - static QString generateRelativePath(const Buffer *p_buffer); - }; -} + // According to @p_buffer, generate the relative path on image host for images. + static QString generateRelativePath(const Buffer *p_buffer); +}; +} // namespace vnotex #endif // IMAGEHOSTUTILS_H diff --git a/src/imagehost/repoimagehost.cpp b/src/imagehost/repoimagehost.cpp index 5daf08c392..e9fa4fda0b 100644 --- a/src/imagehost/repoimagehost.cpp +++ b/src/imagehost/repoimagehost.cpp @@ -1,62 +1,54 @@ #include "repoimagehost.h" -#include #include +#include using namespace vnotex; -RepoImageHost::RepoImageHost(QObject *p_parent) - : ImageHost(p_parent) -{ -} +RepoImageHost::RepoImageHost(QObject *p_parent) : ImageHost(p_parent) {} -bool RepoImageHost::testConfig(const QJsonObject &p_jobj, QString &p_msg) -{ - p_msg.clear(); +bool RepoImageHost::testConfig(const QJsonObject &p_jobj, QString &p_msg) { + p_msg.clear(); - QString token, userName, repoName; - parseConfig(p_jobj, token, userName, repoName); + QString token, userName, repoName; + parseConfig(p_jobj, token, userName, repoName); - if (token.isEmpty() || userName.isEmpty() || repoName.isEmpty()) { - p_msg = tr("PersonalAccessToken/UserName/RepositoryName should not be empty."); - return false; - } + if (token.isEmpty() || userName.isEmpty() || repoName.isEmpty()) { + p_msg = tr("PersonalAccessToken/UserName/RepositoryName should not be empty."); + return false; + } - auto reply = getRepoInfo(token, userName, repoName); - p_msg = QString::fromUtf8(reply.m_data); + auto reply = getRepoInfo(token, userName, repoName); + p_msg = QString::fromUtf8(reply.m_data); - if (reply.m_error != QNetworkReply::NoError) { - return false; - } + if (reply.m_error != QNetworkReply::NoError) { + return false; + } - auto replyObj = Utils::fromJsonString(reply.m_data); - if (replyObj.isEmpty()) { - return false; - } + auto replyObj = Utils::fromJsonString(reply.m_data); + if (replyObj.isEmpty()) { + return false; + } - if (replyObj[QStringLiteral("private")].toBool()) { - p_msg = tr("Private repository is not supported."); - return false; - } + if (replyObj[QStringLiteral("private")].toBool()) { + p_msg = tr("Private repository is not supported."); + return false; + } - return true; + return true; } -void RepoImageHost::parseConfig(const QJsonObject &p_jobj, - QString &p_token, - QString &p_userName, - QString &p_repoName) -{ - p_token = p_jobj[QStringLiteral("personal_access_token")].toString(); - p_userName = p_jobj[QStringLiteral("user_name")].toString(); - p_repoName = p_jobj[QStringLiteral("repository_name")].toString(); +void RepoImageHost::parseConfig(const QJsonObject &p_jobj, QString &p_token, QString &p_userName, + QString &p_repoName) { + p_token = p_jobj[QStringLiteral("personal_access_token")].toString(); + p_userName = p_jobj[QStringLiteral("user_name")].toString(); + p_repoName = p_jobj[QStringLiteral("repository_name")].toString(); } -QString RepoImageHost::fetchResourcePath(const QString &p_prefix, const QString &p_url) -{ - auto resourcePath = p_url.mid(p_prefix.size()); - // Skip the branch name. - resourcePath = resourcePath.mid(resourcePath.indexOf(QLatin1Char('/')) + 1); - resourcePath = WebUtils::purifyUrl(resourcePath); - return resourcePath; +QString RepoImageHost::fetchResourcePath(const QString &p_prefix, const QString &p_url) { + auto resourcePath = p_url.mid(p_prefix.size()); + // Skip the branch name. + resourcePath = resourcePath.mid(resourcePath.indexOf(QLatin1Char('/')) + 1); + resourcePath = WebUtils::purifyUrl(resourcePath); + return resourcePath; } diff --git a/src/imagehost/repoimagehost.h b/src/imagehost/repoimagehost.h index 91b56c7e05..6196bc7e61 100644 --- a/src/imagehost/repoimagehost.h +++ b/src/imagehost/repoimagehost.h @@ -5,27 +5,24 @@ #include -namespace vnotex -{ - class RepoImageHost : public ImageHost - { - Q_OBJECT - public: - explicit RepoImageHost(QObject *p_parent); - - bool testConfig(const QJsonObject &p_jobj, QString &p_msg) Q_DECL_OVERRIDE; - - protected: - virtual void parseConfig(const QJsonObject &p_jobj, - QString &p_token, - QString &p_userName, - QString &p_repoName); - - // Used to test. - virtual vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, const QString &p_repoName) const = 0; - - static QString fetchResourcePath(const QString &p_prefix, const QString &p_url); - }; -} +namespace vnotex { +class RepoImageHost : public ImageHost { + Q_OBJECT +public: + explicit RepoImageHost(QObject *p_parent); + + bool testConfig(const QJsonObject &p_jobj, QString &p_msg) Q_DECL_OVERRIDE; + +protected: + virtual void parseConfig(const QJsonObject &p_jobj, QString &p_token, QString &p_userName, + QString &p_repoName); + + // Used to test. + virtual vte::NetworkReply getRepoInfo(const QString &p_token, const QString &p_userName, + const QString &p_repoName) const = 0; + + static QString fetchResourcePath(const QString &p_prefix, const QString &p_url); +}; +} // namespace vnotex #endif // REPOIMAGEHOST_H diff --git a/src/main.cpp b/src/main.cpp index 425f0e7372..22e6954517 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,32 +1,32 @@ +#include +#include #include -#include -#include +#include #include -#include -#include #include -#include -#include #include +#include +#include +#include +#include +#include #include #include -#include -#include +#include "application.h" +#include "commandlineoptions.h" +#include "fakeaccessible.h" #include -#include #include +#include +#include +#include #include #include #include -#include -#include -#include #include +#include #include -#include "commandlineoptions.h" -#include "application.h" -#include "fakeaccessible.h" using namespace vnotex; @@ -34,236 +34,232 @@ void loadTranslators(QApplication &p_app); void showMessageOnCommandLineIfAvailable(const QString &p_msg); -int main(int argc, char *argv[]) -{ - QTextCodec *codec = QTextCodec::codecForName("UTF8"); - if (codec) { - QTextCodec::setCodecForLocale(codec); - } +int main(int argc, char *argv[]) { + QTextCodec *codec = QTextCodec::codecForName("UTF8"); + if (codec) { + QTextCodec::setCodecForLocale(codec); + } #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - // This only takes effect on Win, X11 and Android. - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + // This only takes effect on Win, X11 and Android. + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif - // Set OpenGL option on Windows. - // Set environment QT_OPENGL to "angle/desktop/software". + // Set OpenGL option on Windows. + // Set environment QT_OPENGL to "angle/desktop/software". #if defined(Q_OS_WIN) - { - auto option = SessionConfig::getOpenGLAtBootstrap(); - qDebug() << "OpenGL option" << SessionConfig::openGLToString(option); - switch (option) { - case SessionConfig::OpenGL::Desktop: - QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); - break; - - case SessionConfig::OpenGL::Angle: - QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); - break; - - case SessionConfig::OpenGL::Software: - QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); - break; - - default: - break; - } + { + auto option = SessionConfig::getOpenGLAtBootstrap(); + qDebug() << "OpenGL option" << SessionConfig::openGLToString(option); + switch (option) { + case SessionConfig::OpenGL::Desktop: + QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); + break; + + case SessionConfig::OpenGL::Angle: + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); + break; + + case SessionConfig::OpenGL::Software: + QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); + break; + + default: + break; } + } #endif #if defined(Q_OS_LINUX) - // Disable sandbox on Linux. - qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox"); + // Disable sandbox on Linux. + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox"); #endif - Application app(argc, argv); - - ConfigMgr::initAppPrefixPath(); - - QAccessible::installFactory(&FakeAccessible::accessibleFactory); - - { - const QString iconPath = ":/vnotex/data/core/icons/vnote.ico"; - // Make sense only on Windows. - app.setWindowIcon(QIcon(iconPath)); - - app.setApplicationName(ConfigMgr::c_appName); - app.setOrganizationName(ConfigMgr::c_orgName); - - app.setApplicationVersion(ConfigMgr::getApplicationVersion()); - } - - CommandLineOptions cmdOptions; - switch (cmdOptions.parse(app.arguments())) { - case CommandLineOptions::Ok: - break; - - case CommandLineOptions::Error: - fprintf(stderr, "%s\n", qPrintable(cmdOptions.m_errorMsg)); - // Arguments to WebEngineView will be unknown ones. So just let it go. - break; - - case CommandLineOptions::VersionRequested: - { - auto versionStr = QStringLiteral("%1 %2").arg(app.applicationName()).arg(app.applicationVersion()); - showMessageOnCommandLineIfAvailable(versionStr); - return 0; - } - - case CommandLineOptions::HelpRequested: - Q_FALLTHROUGH(); - default: - showMessageOnCommandLineIfAvailable(cmdOptions.m_helpText); - return 0; - } - - // Guarding. - SingleInstanceGuard guard; - bool canRun = guard.tryRun(); - if (!canRun) { - guard.requestOpenFiles(cmdOptions.m_pathsToOpen); - guard.requestShow(); - return 0; - } - - try { - ConfigMgr::getInst(); - } catch (Exception &e) { - MessageBoxHelper::notify(MessageBoxHelper::Critical, - MainWindow::tr("%1 failed to start.").arg(ConfigMgr::c_appName), - MainWindow::tr("Failed to initialize configuration manager. " - "Please check if all the files are intact or reinstall the application."), - e.what()); - return -1; + Application app(argc, argv); + + ConfigMgr::initAppPrefixPath(); + + QAccessible::installFactory(&FakeAccessible::accessibleFactory); + + { + const QString iconPath = ":/vnotex/data/core/icons/vnote.ico"; + // Make sense only on Windows. + app.setWindowIcon(QIcon(iconPath)); + + app.setApplicationName(ConfigMgr::c_appName); + app.setOrganizationName(ConfigMgr::c_orgName); + + app.setApplicationVersion(ConfigMgr::getApplicationVersion()); + } + + CommandLineOptions cmdOptions; + switch (cmdOptions.parse(app.arguments())) { + case CommandLineOptions::Ok: + break; + + case CommandLineOptions::Error: + fprintf(stderr, "%s\n", qPrintable(cmdOptions.m_errorMsg)); + // Arguments to WebEngineView will be unknown ones. So just let it go. + break; + + case CommandLineOptions::VersionRequested: { + auto versionStr = + QStringLiteral("%1 %2").arg(app.applicationName()).arg(app.applicationVersion()); + showMessageOnCommandLineIfAvailable(versionStr); + return 0; + } + + case CommandLineOptions::HelpRequested: + Q_FALLTHROUGH(); + default: + showMessageOnCommandLineIfAvailable(cmdOptions.m_helpText); + return 0; + } + + // Guarding. + SingleInstanceGuard guard; + bool canRun = guard.tryRun(); + if (!canRun) { + guard.requestOpenFiles(cmdOptions.m_pathsToOpen); + guard.requestShow(); + return 0; + } + + try { + ConfigMgr::getInst(); + } catch (Exception &e) { + MessageBoxHelper::notify( + MessageBoxHelper::Critical, MainWindow::tr("%1 failed to start.").arg(ConfigMgr::c_appName), + MainWindow::tr("Failed to initialize configuration manager. " + "Please check if all the files are intact or reinstall the application."), + e.what()); + return -1; + } + + // Init logger after app info is set. + Logger::init(cmdOptions.m_verbose, cmdOptions.m_logToStderr); + + qInfo() << QStringLiteral("%1 (v%2) started at %3 (%4)") + .arg(ConfigMgr::c_appName, app.applicationVersion(), + QDateTime::currentDateTime().toString(), QSysInfo::productType()); + + qInfo() << "OpenSSL build version:" << QSslSocket::sslLibraryBuildVersionString() + << "link version:" << QSslSocket::sslLibraryVersionString(); + + if (QSslSocket::sslLibraryBuildVersionNumber() != QSslSocket::sslLibraryVersionNumber()) { + qWarning() << "versions of the built and linked OpenSSL mismatch, network may not work"; + } + + // Should set the correct locale before VNoteX::getInst(). + loadTranslators(app); + + if (app.styleSheet().isEmpty()) { + auto style = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet(); + if (!style.isEmpty()) { + app.setStyleSheet(style); + // Set up hot-reload for the theme folder if enabled via command line + if (cmdOptions.m_watchThemes) { + const auto themeFolderPath = + VNoteX::getInst().getThemeMgr().getCurrentTheme().getThemeFolder(); + app.watchThemeFolder(themeFolderPath); + } } + } - // Init logger after app info is set. - Logger::init(cmdOptions.m_verbose, cmdOptions.m_logToStderr); - - qInfo() << QStringLiteral("%1 (v%2) started at %3 (%4)").arg(ConfigMgr::c_appName, - app.applicationVersion(), - QDateTime::currentDateTime().toString(), - QSysInfo::productType()); + MainWindow window; + window.show(); - qInfo() << "OpenSSL build version:" << QSslSocket::sslLibraryBuildVersionString() - << "link version:" << QSslSocket::sslLibraryVersionString(); + QObject::connect(&guard, &SingleInstanceGuard::showRequested, &window, + &MainWindow::showMainWindow); + QObject::connect(&guard, &SingleInstanceGuard::openFilesRequested, &window, + &MainWindow::openFiles); - if (QSslSocket::sslLibraryBuildVersionNumber() != QSslSocket::sslLibraryVersionNumber()) { - qWarning() << "versions of the built and linked OpenSSL mismatch, network may not work"; - } - - // Should set the correct locale before VNoteX::getInst(). - loadTranslators(app); - - if (app.styleSheet().isEmpty()) { - auto style = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet(); - if (!style.isEmpty()) { - app.setStyleSheet(style); - // Set up hot-reload for the theme folder if enabled via command line - if (cmdOptions.m_watchThemes) { - const auto themeFolderPath = VNoteX::getInst().getThemeMgr().getCurrentTheme().getThemeFolder(); - app.watchThemeFolder(themeFolderPath); - } - } - } + QObject::connect( + &app, &Application::openFileRequested, &window, + [&window](const QString &p_filePath) { window.openFiles(QStringList() << p_filePath); }); - MainWindow window; - window.show(); + // Let MainWindow show first to decide the screen on which app is running. + WidgetUtils::calculateScaleFactor(window.windowHandle()->screen()); - QObject::connect(&guard, &SingleInstanceGuard::showRequested, - &window, &MainWindow::showMainWindow); - QObject::connect(&guard, &SingleInstanceGuard::openFilesRequested, - &window, &MainWindow::openFiles); + VNoteX::getInst().getThemeMgr().setBaseBackground(window.palette().color(QPalette::Base)); - QObject::connect(&app, &Application::openFileRequested, - &window, [&window](const QString &p_filePath) { - window.openFiles(QStringList() << p_filePath); - }); + window.kickOffOnStart(cmdOptions.m_pathsToOpen); - // Let MainWindow show first to decide the screen on which app is running. - WidgetUtils::calculateScaleFactor(window.windowHandle()->screen()); - - VNoteX::getInst().getThemeMgr().setBaseBackground(window.palette().color(QPalette::Base)); - - window.kickOffOnStart(cmdOptions.m_pathsToOpen); - - int ret = app.exec(); - if (ret == RESTART_EXIT_CODE) { - // Asked to restart VNote. - guard.exit(); - QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList()); - // Must use exit() in Linux to quit the parent process in Qt 5.12. - // Thanks to @ygcaicn. - exit(0); - return 0; - } + int ret = app.exec(); + if (ret == RESTART_EXIT_CODE) { + // Asked to restart VNote. + guard.exit(); + QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList()); + // Must use exit() in Linux to quit the parent process in Qt 5.12. + // Thanks to @ygcaicn. + exit(0); + return 0; + } - return ret; + return ret; } -void loadTranslators(QApplication &p_app) -{ - auto localeName = ConfigMgr::getInst().getCoreConfig().getLocale(); - if (!localeName.isEmpty()) { - QLocale::setDefault(QLocale(localeName)); - } - - QLocale locale; - qInfo() << "locale:" << locale.name(); - - const auto translationsPath = QDir("app:translations").absolutePath(); - qInfo() << "translations dir: " << translationsPath; - if (translationsPath.isEmpty()) { - qWarning() << "failed to locate translations directory"; - return; - } - - // For QTextEdit/QTextBrowser and other basic widgets. - QScopedPointer qtbaseTranslator(new QTranslator(&p_app)); - if (qtbaseTranslator->load(locale, "qtbase", "_", translationsPath)) { - p_app.installTranslator(qtbaseTranslator.take()); - } - - // qt_zh_CN.ts does not cover the real QDialogButtonBox which uses QPlatformTheme. - QScopedPointer dialogButtonBoxTranslator(new QTranslator(&p_app)); - if (dialogButtonBoxTranslator->load(locale, "qdialogbuttonbox", "_", translationsPath)) { - p_app.installTranslator(dialogButtonBoxTranslator.take()); - } - - QScopedPointer webengineTranslator(new QTranslator(&p_app)); - if (webengineTranslator->load(locale, "qwebengine", "_", translationsPath)) { - p_app.installTranslator(webengineTranslator.take()); - } - - QScopedPointer qtTranslator(new QTranslator(&p_app)); - if (qtTranslator->load(locale, "qtv", "_", translationsPath)) { - p_app.installTranslator(qtTranslator.take()); - } - - QScopedPointer qtEnvTranslator(new QTranslator(&p_app)); - if (qtEnvTranslator->load(locale, "qt", "_", translationsPath)) { - p_app.installTranslator(qtEnvTranslator.take()); - } - - QScopedPointer vnoteTranslator(new QTranslator(&p_app)); - if (vnoteTranslator->load(locale, "vnote", "_", translationsPath)) { - p_app.installTranslator(vnoteTranslator.take()); - } - - QScopedPointer vtexteditTranslator(new QTranslator(&p_app)); - if (vtexteditTranslator->load(locale, "vtextedit", "_", translationsPath)) { - p_app.installTranslator(vtexteditTranslator.take()); - } +void loadTranslators(QApplication &p_app) { + auto localeName = ConfigMgr::getInst().getCoreConfig().getLocale(); + if (!localeName.isEmpty()) { + QLocale::setDefault(QLocale(localeName)); + } + + QLocale locale; + qInfo() << "locale:" << locale.name(); + + const auto translationsPath = QDir("app:translations").absolutePath(); + qInfo() << "translations dir: " << translationsPath; + if (translationsPath.isEmpty()) { + qWarning() << "failed to locate translations directory"; + return; + } + + // For QTextEdit/QTextBrowser and other basic widgets. + QScopedPointer qtbaseTranslator(new QTranslator(&p_app)); + if (qtbaseTranslator->load(locale, "qtbase", "_", translationsPath)) { + p_app.installTranslator(qtbaseTranslator.take()); + } + + // qt_zh_CN.ts does not cover the real QDialogButtonBox which uses QPlatformTheme. + QScopedPointer dialogButtonBoxTranslator(new QTranslator(&p_app)); + if (dialogButtonBoxTranslator->load(locale, "qdialogbuttonbox", "_", translationsPath)) { + p_app.installTranslator(dialogButtonBoxTranslator.take()); + } + + QScopedPointer webengineTranslator(new QTranslator(&p_app)); + if (webengineTranslator->load(locale, "qwebengine", "_", translationsPath)) { + p_app.installTranslator(webengineTranslator.take()); + } + + QScopedPointer qtTranslator(new QTranslator(&p_app)); + if (qtTranslator->load(locale, "qtv", "_", translationsPath)) { + p_app.installTranslator(qtTranslator.take()); + } + + QScopedPointer qtEnvTranslator(new QTranslator(&p_app)); + if (qtEnvTranslator->load(locale, "qt", "_", translationsPath)) { + p_app.installTranslator(qtEnvTranslator.take()); + } + + QScopedPointer vnoteTranslator(new QTranslator(&p_app)); + if (vnoteTranslator->load(locale, "vnote", "_", translationsPath)) { + p_app.installTranslator(vnoteTranslator.take()); + } + + QScopedPointer vtexteditTranslator(new QTranslator(&p_app)); + if (vtexteditTranslator->load(locale, "vtextedit", "_", translationsPath)) { + p_app.installTranslator(vtexteditTranslator.take()); + } } -void showMessageOnCommandLineIfAvailable(const QString &p_msg) -{ +void showMessageOnCommandLineIfAvailable(const QString &p_msg) { #if defined(Q_OS_WIN) - MessageBoxHelper::notify(MessageBoxHelper::Information, - QStringLiteral("
%1
").arg(p_msg)); + MessageBoxHelper::notify(MessageBoxHelper::Information, + QStringLiteral("
%1
").arg(p_msg)); #else - fprintf(stderr, "%s\n", qPrintable(p_msg)); + fprintf(stderr, "%s\n", qPrintable(p_msg)); #endif } diff --git a/src/search/filesearchengine.cpp b/src/search/filesearchengine.cpp index 845ddedf8a..1b596e8c3b 100644 --- a/src/search/filesearchengine.cpp +++ b/src/search/filesearchengine.cpp @@ -1,250 +1,225 @@ #include "filesearchengine.h" -#include #include +#include #include using namespace vnotex; -FileSearchEngineWorker::FileSearchEngineWorker(QObject *p_parent) - : AsyncWorker(p_parent) -{ -} +FileSearchEngineWorker::FileSearchEngineWorker(QObject *p_parent) : AsyncWorker(p_parent) {} void FileSearchEngineWorker::setData(const QVector &p_items, const QSharedPointer &p_option, - const SearchToken &p_token) -{ - m_items = p_items; - m_option = p_option; - m_token = p_token; + const SearchToken &p_token) { + m_items = p_items; + m_option = p_option; + m_token = p_token; } -void FileSearchEngineWorker::run() -{ - const int c_batchSize = 100; - - m_state = SearchState::Busy; - - m_results.clear(); - int nr = 0; - for (const auto &item : m_items) { - if (isAskedToStop()) { - m_state = SearchState::Stopped; - break; - } - - if (!FileUtils::isText(item.m_filePath)) { - appendError(tr("Skip binary file (%1)").arg(item.m_filePath)); - continue; - } +void FileSearchEngineWorker::run() { + const int c_batchSize = 100; - searchFile(item.m_filePath, item.m_displayPath); + m_state = SearchState::Busy; - if (++nr >= c_batchSize) { - nr = 0; - processBatchResults(); - } + m_results.clear(); + int nr = 0; + for (const auto &item : m_items) { + if (isAskedToStop()) { + m_state = SearchState::Stopped; + break; } - processBatchResults(); - - if (m_state == SearchState::Busy) { - m_state = SearchState::Finished; + if (!FileUtils::isText(item.m_filePath)) { + appendError(tr("Skip binary file (%1)").arg(item.m_filePath)); + continue; } -} -void FileSearchEngineWorker::appendError(const QString &p_err) -{ - m_errors.append(p_err); -} + searchFile(item.m_filePath, item.m_displayPath); -void FileSearchEngineWorker::searchFile(const QString &p_filePath, const QString &p_displayPath) -{ - QFile file(p_filePath); - if (!file.open(QIODevice::ReadOnly)) { - return; + if (++nr >= c_batchSize) { + nr = 0; + processBatchResults(); } + } - const bool shouldStartBatchMode = m_token.shouldStartBatchMode(); - if (shouldStartBatchMode) { - m_token.startBatchMode(); - } + processBatchResults(); - QSharedPointer resultItem; + if (m_state == SearchState::Busy) { + m_state = SearchState::Finished; + } +} - int lineNum = 0; - QTextStream ins(&file); - while (!ins.atEnd()) { - if (isAskedToStop()) { - m_state = SearchState::Stopped; - break; - } +void FileSearchEngineWorker::appendError(const QString &p_err) { m_errors.append(p_err); } - const auto lineText = ins.readLine(); - bool matched = false; - QList segments; - if (!shouldStartBatchMode) { - matched = m_token.matched(lineText, &segments); - } else { - matched = m_token.matchedInBatchMode(lineText, &segments); - } +void FileSearchEngineWorker::searchFile(const QString &p_filePath, const QString &p_displayPath) { + QFile file(p_filePath); + if (!file.open(QIODevice::ReadOnly)) { + return; + } - if (matched) { - if (resultItem) { - resultItem->addLine(lineNum, lineText, segments); - } else { - resultItem = SearchResultItem::createFileItem(p_filePath, p_displayPath, lineNum, lineText, segments); - } - } + const bool shouldStartBatchMode = m_token.shouldStartBatchMode(); + if (shouldStartBatchMode) { + m_token.startBatchMode(); + } - if (shouldStartBatchMode && m_token.readyToEndBatchMode()) { - break; - } + QSharedPointer resultItem; - ++lineNum; + int lineNum = 0; + QTextStream ins(&file); + while (!ins.atEnd()) { + if (isAskedToStop()) { + m_state = SearchState::Stopped; + break; } - if (shouldStartBatchMode) { - bool allMatched = m_token.readyToEndBatchMode(); - m_token.endBatchMode(); + const auto lineText = ins.readLine(); + bool matched = false; + QList segments; + if (!shouldStartBatchMode) { + matched = m_token.matched(lineText, &segments); + } else { + matched = m_token.matchedInBatchMode(lineText, &segments); + } - if (!allMatched) { - // This file does not meet all the tokens. - resultItem.reset(); - } + if (matched) { + if (resultItem) { + resultItem->addLine(lineNum, lineText, segments); + } else { + resultItem = SearchResultItem::createFileItem(p_filePath, p_displayPath, lineNum, lineText, + segments); + } } - if (resultItem) { - m_results.append(resultItem); + if (shouldStartBatchMode && m_token.readyToEndBatchMode()) { + break; } -} -void FileSearchEngineWorker::processBatchResults() -{ - if (!m_results.isEmpty()) { - emit resultItemsReady(m_results); - m_results.clear(); + ++lineNum; + } + + if (shouldStartBatchMode) { + bool allMatched = m_token.readyToEndBatchMode(); + m_token.endBatchMode(); + + if (!allMatched) { + // This file does not meet all the tokens. + resultItem.reset(); } + } + + if (resultItem) { + m_results.append(resultItem); + } } -FileSearchEngine::FileSearchEngine() -{ +void FileSearchEngineWorker::processBatchResults() { + if (!m_results.isEmpty()) { + emit resultItemsReady(m_results); + m_results.clear(); + } } -FileSearchEngine::~FileSearchEngine() -{ - stopInternal(); - clearInternal(); +FileSearchEngine::FileSearchEngine() {} + +FileSearchEngine::~FileSearchEngine() { + stopInternal(); + clearInternal(); } void FileSearchEngine::search(const QSharedPointer &p_option, const SearchToken &p_token, - const QVector &p_items) -{ - int numThread = QThread::idealThreadCount(); - if (numThread < 1) { - numThread = 1; + const QVector &p_items) { + int numThread = QThread::idealThreadCount(); + if (numThread < 1) { + numThread = 1; + } + + Q_ASSERT(!p_items.isEmpty()); + if (p_items.size() < numThread) { + numThread = 1; + } + + clearWorkers(); + m_workers.reserve(numThread); + const int totalSize = p_items.size(); + const int step = totalSize / numThread; + int remain = totalSize % numThread; + int start = 0; + + qDebug() << "start async file search" << totalSize << numThread; + + for (int i = 0; i < numThread && start < totalSize; ++i) { + int len = step; + if (remain) { + ++len; + --remain; } - Q_ASSERT(!p_items.isEmpty()); - if (p_items.size() < numThread) { - numThread = 1; + if (start + len > totalSize) { + len = totalSize - start; } - clearWorkers(); - m_workers.reserve(numThread); - const int totalSize = p_items.size(); - const int step = totalSize / numThread; - int remain = totalSize % numThread; - int start = 0; - - qDebug() << "start async file search" << totalSize << numThread; - - for (int i = 0; i < numThread && start < totalSize; ++i) { - int len = step; - if (remain) { - ++len; - --remain; - } + auto th = QSharedPointer::create(); + th->setData(p_items.mid(start, len), p_option, p_token); + connect(th.data(), &FileSearchEngineWorker::finished, this, + &FileSearchEngine::handleWorkerFinished); + connect(th.data(), &FileSearchEngineWorker::resultItemsReady, this, + &FileSearchEngine::resultItemsAdded); - if (start + len > totalSize) { - len = totalSize - start; - } + m_workers.append(th); + th->start(); - auto th = QSharedPointer::create(); - th->setData(p_items.mid(start, len), p_option, p_token); - connect(th.data(), &FileSearchEngineWorker::finished, - this, &FileSearchEngine::handleWorkerFinished); - connect(th.data(), &FileSearchEngineWorker::resultItemsReady, - this, &FileSearchEngine::resultItemsAdded); + start += len; + } +} - m_workers.append(th); - th->start(); +void FileSearchEngine::stop() { stopInternal(); } - start += len; - } +void FileSearchEngine::stopInternal() { + for (const auto &th : m_workers) { + th->stop(); + } } -void FileSearchEngine::stop() -{ - stopInternal(); -} +void FileSearchEngine::clear() { clearInternal(); } -void FileSearchEngine::stopInternal() -{ - for (const auto &th : m_workers) { - th->stop(); - } -} +void FileSearchEngine::clearInternal() { clearWorkers(); } -void FileSearchEngine::clear() -{ - clearInternal(); -} +void FileSearchEngine::clearWorkers() { + for (const auto &th : m_workers) { + th->quit(); + th->wait(); + } -void FileSearchEngine::clearInternal() -{ - clearWorkers(); + m_workers.clear(); + m_numOfFinishedWorkers = 0; } -void FileSearchEngine::clearWorkers() -{ +void FileSearchEngine::handleWorkerFinished() { + ++m_numOfFinishedWorkers; + if (m_numOfFinishedWorkers == m_workers.size()) { + SearchState state = SearchState::Finished; + for (const auto &th : m_workers) { - th->quit(); - th->wait(); + if (th->m_state == SearchState::Failed) { + if (state != SearchState::Stopped) { + state = SearchState::Failed; + } + } else if (th->m_state == SearchState::Stopped) { + state = SearchState::Stopped; + } + + for (const auto &err : th->m_errors) { + emit logRequested(err); + } + + Q_ASSERT(th->isFinished()); } m_workers.clear(); m_numOfFinishedWorkers = 0; -} - -void FileSearchEngine::handleWorkerFinished() -{ - ++m_numOfFinishedWorkers; - if (m_numOfFinishedWorkers == m_workers.size()) { - SearchState state = SearchState::Finished; - - for (const auto &th : m_workers) { - if (th->m_state == SearchState::Failed) { - if (state != SearchState::Stopped) { - state = SearchState::Failed; - } - } else if (th->m_state == SearchState::Stopped) { - state = SearchState::Stopped; - } - - for (const auto &err : th->m_errors) { - emit logRequested(err); - } - - Q_ASSERT(th->isFinished()); - } - m_workers.clear(); - m_numOfFinishedWorkers = 0; - - emit finished(state); - } + emit finished(state); + } } diff --git a/src/search/filesearchengine.h b/src/search/filesearchengine.h index 138159a08b..c3e707b783 100644 --- a/src/search/filesearchengine.h +++ b/src/search/filesearchengine.h @@ -3,90 +3,86 @@ #include "isearchengine.h" -#include -#include #include +#include +#include #include #include -#include "searchtoken.h" #include "searchdata.h" #include "searchresultitem.h" +#include "searchtoken.h" + +namespace vnotex { +class FileSearchEngineWorker : public AsyncWorker { + Q_OBJECT + friend class FileSearchEngine; -namespace vnotex -{ - class FileSearchEngineWorker : public AsyncWorker - { - Q_OBJECT - friend class FileSearchEngine; - public: - explicit FileSearchEngineWorker(QObject *p_parent = nullptr); +public: + explicit FileSearchEngineWorker(QObject *p_parent = nullptr); - ~FileSearchEngineWorker() = default; + ~FileSearchEngineWorker() = default; - void setData(const QVector &p_items, - const QSharedPointer &p_option, - const SearchToken &p_token); + void setData(const QVector &p_items, + const QSharedPointer &p_option, const SearchToken &p_token); - signals: - void resultItemsReady(const QVector> &p_items); +signals: + void resultItemsReady(const QVector> &p_items); - protected: - void run() Q_DECL_OVERRIDE; +protected: + void run() Q_DECL_OVERRIDE; - private: - void appendError(const QString &p_err); +private: + void appendError(const QString &p_err); - void searchFile(const QString &p_filePath, const QString &p_displayPath); + void searchFile(const QString &p_filePath, const QString &p_displayPath); - void processBatchResults(); + void processBatchResults(); - QVector m_items; + QVector m_items; - SearchToken m_token; + SearchToken m_token; - QSharedPointer m_option; + QSharedPointer m_option; - SearchState m_state = SearchState::Idle; + SearchState m_state = SearchState::Idle; - QStringList m_errors; + QStringList m_errors; - QVector> m_results; - }; + QVector> m_results; +}; - class FileSearchEngine : public ISearchEngine - { - Q_OBJECT - public: - FileSearchEngine(); +class FileSearchEngine : public ISearchEngine { + Q_OBJECT +public: + FileSearchEngine(); - ~FileSearchEngine(); + ~FileSearchEngine(); - void search(const QSharedPointer &p_option, - const SearchToken &p_token, - const QVector &p_items) Q_DECL_OVERRIDE; + void search(const QSharedPointer &p_option, const SearchToken &p_token, + const QVector &p_items) Q_DECL_OVERRIDE; - void stop() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; - void clear() Q_DECL_OVERRIDE; + void clear() Q_DECL_OVERRIDE; - private slots: - void handleWorkerFinished(); +private slots: + void handleWorkerFinished(); - private: - void clearWorkers(); +private: + void clearWorkers(); - // Need non-virtual version of this. - void stopInternal(); + // Need non-virtual version of this. + void stopInternal(); - // Need non-virtual version of this. - void clearInternal(); + // Need non-virtual version of this. + void clearInternal(); - int m_numOfFinishedWorkers = 0; + int m_numOfFinishedWorkers = 0; - QVector> m_workers; - }; -} + QVector> m_workers; +}; +} // namespace vnotex #endif // SEARCHENGINE_H diff --git a/src/search/isearchengine.h b/src/search/isearchengine.h index 4509e6f738..b2d9fafdfd 100644 --- a/src/search/isearchengine.h +++ b/src/search/isearchengine.h @@ -1,56 +1,49 @@ #ifndef ISEARCHENGINE_H #define ISEARCHENGINE_H -#include -#include #include +#include #include +#include #include "searchdata.h" -namespace vnotex -{ - struct SearchResultItem; +namespace vnotex { +struct SearchResultItem; - class SearchToken; +class SearchToken; - struct SearchSecondPhaseItem - { - SearchSecondPhaseItem() = default; +struct SearchSecondPhaseItem { + SearchSecondPhaseItem() = default; - SearchSecondPhaseItem(const QString &p_filePath, const QString &p_displayPath) - : m_filePath(p_filePath), - m_displayPath(p_displayPath) - { - } + SearchSecondPhaseItem(const QString &p_filePath, const QString &p_displayPath) + : m_filePath(p_filePath), m_displayPath(p_displayPath) {} - QString m_filePath; + QString m_filePath; - QString m_displayPath; - }; + QString m_displayPath; +}; - class ISearchEngine : public QObject - { - Q_OBJECT - public: - ISearchEngine() = default; +class ISearchEngine : public QObject { + Q_OBJECT +public: + ISearchEngine() = default; - virtual ~ISearchEngine() = default; + virtual ~ISearchEngine() = default; - virtual void search(const QSharedPointer &p_option, - const SearchToken &p_token, - const QVector &p_items) = 0; + virtual void search(const QSharedPointer &p_option, const SearchToken &p_token, + const QVector &p_items) = 0; - virtual void stop() = 0; + virtual void stop() = 0; - virtual void clear() = 0; + virtual void clear() = 0; - signals: - void finished(SearchState p_state); +signals: + void finished(SearchState p_state); - void resultItemsAdded(const QVector> &p_items); + void resultItemsAdded(const QVector> &p_items); - void logRequested(const QString &p_log); - }; -} + void logRequested(const QString &p_log); +}; +} // namespace vnotex #endif // ISEARCHENGINE_H diff --git a/src/search/isearchinfoprovider.h b/src/search/isearchinfoprovider.h index 353bf930a2..afe1512699 100644 --- a/src/search/isearchinfoprovider.h +++ b/src/search/isearchinfoprovider.h @@ -4,27 +4,25 @@ #include #include -namespace vnotex -{ - class Node; - class Notebook; - class Buffer; +namespace vnotex { +class Node; +class Notebook; +class Buffer; - class ISearchInfoProvider - { - public: - ISearchInfoProvider() = default; +class ISearchInfoProvider { +public: + ISearchInfoProvider() = default; - virtual ~ISearchInfoProvider() = default; + virtual ~ISearchInfoProvider() = default; - virtual QList getBuffers() const = 0; + virtual QList getBuffers() const = 0; - virtual Node *getCurrentFolder() const = 0; + virtual Node *getCurrentFolder() const = 0; - virtual Notebook *getCurrentNotebook() const = 0; + virtual Notebook *getCurrentNotebook() const = 0; - virtual QVector getNotebooks() const = 0; - }; -} + virtual QVector getNotebooks() const = 0; +}; +} // namespace vnotex #endif // ISEARCHINFOPROVIDER_H diff --git a/src/search/searchdata.cpp b/src/search/searchdata.cpp index 20bfbc1af1..ecaa8022d7 100644 --- a/src/search/searchdata.cpp +++ b/src/search/searchdata.cpp @@ -6,47 +6,38 @@ using namespace vnotex; SearchOption::SearchOption() : m_objects(SearchObject::SearchName | SearchObject::SearchContent), - m_targets(SearchTarget::SearchFile | SearchTarget::SearchFolder) -{ + m_targets(SearchTarget::SearchFile | SearchTarget::SearchFolder) {} + +QJsonObject SearchOption::toJson() const { + QJsonObject obj; + obj["file_pattern"] = m_filePattern; + obj["scope"] = static_cast(m_scope); + obj["objects"] = static_cast(m_objects); + obj["targets"] = static_cast(m_targets); + obj["engine"] = static_cast(m_engine); + obj["find_options"] = static_cast(m_findOptions); + return obj; } -QJsonObject SearchOption::toJson() const -{ - QJsonObject obj; - obj["file_pattern"] = m_filePattern; - obj["scope"] = static_cast(m_scope); - obj["objects"] = static_cast(m_objects); - obj["targets"] = static_cast(m_targets); - obj["engine"] = static_cast(m_engine); - obj["find_options"] = static_cast(m_findOptions); - return obj; +void SearchOption::fromJson(const QJsonObject &p_obj) { + if (p_obj.isEmpty()) { + return; + } + + m_filePattern = p_obj["file_pattern"].toString(); + m_scope = static_cast(p_obj["scope"].toInt()); + m_objects = static_cast(p_obj["objects"].toInt()); + m_targets = static_cast(p_obj["targets"].toInt()); + m_engine = static_cast(p_obj["engine"].toInt()); + m_findOptions = static_cast(p_obj["find_options"].toInt()); } -void SearchOption::fromJson(const QJsonObject &p_obj) -{ - if (p_obj.isEmpty()) { - return; - } - - m_filePattern = p_obj["file_pattern"].toString(); - m_scope = static_cast(p_obj["scope"].toInt()); - m_objects = static_cast(p_obj["objects"].toInt()); - m_targets = static_cast(p_obj["targets"].toInt()); - m_engine = static_cast(p_obj["engine"].toInt()); - m_findOptions = static_cast(p_obj["find_options"].toInt()); +bool SearchOption::operator==(const SearchOption &p_other) const { + return m_filePattern == p_other.m_filePattern && m_scope == p_other.m_scope && + m_objects == p_other.m_objects && m_targets == p_other.m_targets && + m_engine == p_other.m_engine && m_findOptions == p_other.m_findOptions; } -bool SearchOption::operator==(const SearchOption &p_other) const -{ - return m_filePattern == p_other.m_filePattern - && m_scope == p_other.m_scope - && m_objects == p_other.m_objects - && m_targets == p_other.m_targets - && m_engine == p_other.m_engine - && m_findOptions == p_other.m_findOptions; -} - -bool SearchOption::strictEquals(const SearchOption &p_other) const -{ - return (*this == p_other) && m_keyword == p_other.m_keyword; +bool SearchOption::strictEquals(const SearchOption &p_other) const { + return (*this == p_other) && m_keyword == p_other.m_keyword; } diff --git a/src/search/searchdata.h b/src/search/searchdata.h index a1638be07b..9474e02841 100644 --- a/src/search/searchdata.h +++ b/src/search/searchdata.h @@ -6,107 +6,85 @@ #include -namespace vnotex -{ - enum class SearchState - { - Idle = 0, - Busy, - Finished, - Failed, - Stopped - }; - - class SearchTranslate : public QObject - { - Q_OBJECT - }; - - inline QString SearchStateToString(SearchState p_state) - { - switch (p_state) { - case SearchState::Idle: - return SearchTranslate::tr("Idle"); - - case SearchState::Busy: - return SearchTranslate::tr("Busy"); - - case SearchState::Finished: - return SearchTranslate::tr("Finished"); - - case SearchState::Failed: - return SearchTranslate::tr("Failed"); - - case SearchState::Stopped: - return SearchTranslate::tr("Stopped"); - } - - return QString(); - } - - enum class SearchScope - { - Buffers = 0, - CurrentFolder, - CurrentNotebook, - AllNotebooks - }; - - enum SearchObject - { - ObjectNone = 0, - SearchName = 0x1UL, - SearchContent = 0x2UL, - // SearchOutline is not supported yet. - SearchOutline = 0x4UL, - SearchTag = 0x8UL, - SearchPath = 0x10UL - }; - Q_DECLARE_FLAGS(SearchObjects, SearchObject); - - enum SearchTarget - { - TargetNone = 0, - SearchFile = 0x1UL, - SearchFolder = 0x2UL, - SearchNotebook = 0x4UL - }; - Q_DECLARE_FLAGS(SearchTargets, SearchTarget); - - enum class SearchEngine - { - Internal = 0 - }; - - struct SearchOption - { - SearchOption(); - - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_obj); - - bool operator==(const SearchOption &p_other) const; - - bool strictEquals(const SearchOption &p_other) const; - - QString m_keyword; - - QString m_filePattern; - - SearchScope m_scope = SearchScope::CurrentNotebook; - - // *nix requests to init in the constructor. - SearchObjects m_objects; - - // *nix requests to init in the constructor. - SearchTargets m_targets; - - SearchEngine m_engine = SearchEngine::Internal; - - FindOptions m_findOptions = FindOption::FindNone; - }; +namespace vnotex { +enum class SearchState { Idle = 0, Busy, Finished, Failed, Stopped }; + +class SearchTranslate : public QObject { + Q_OBJECT +}; + +inline QString SearchStateToString(SearchState p_state) { + switch (p_state) { + case SearchState::Idle: + return SearchTranslate::tr("Idle"); + + case SearchState::Busy: + return SearchTranslate::tr("Busy"); + + case SearchState::Finished: + return SearchTranslate::tr("Finished"); + + case SearchState::Failed: + return SearchTranslate::tr("Failed"); + + case SearchState::Stopped: + return SearchTranslate::tr("Stopped"); + } + + return QString(); } +enum class SearchScope { Buffers = 0, CurrentFolder, CurrentNotebook, AllNotebooks }; + +enum SearchObject { + ObjectNone = 0, + SearchName = 0x1UL, + SearchContent = 0x2UL, + // SearchOutline is not supported yet. + SearchOutline = 0x4UL, + SearchTag = 0x8UL, + SearchPath = 0x10UL +}; +Q_DECLARE_FLAGS(SearchObjects, SearchObject); + +enum SearchTarget { + TargetNone = 0, + SearchFile = 0x1UL, + SearchFolder = 0x2UL, + SearchNotebook = 0x4UL +}; +Q_DECLARE_FLAGS(SearchTargets, SearchTarget); + +enum class SearchEngine { Internal = 0 }; + +struct SearchOption { + SearchOption(); + + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_obj); + + bool operator==(const SearchOption &p_other) const; + + bool strictEquals(const SearchOption &p_other) const; + + QString m_keyword; + + QString m_filePattern; + + SearchScope m_scope = SearchScope::CurrentNotebook; + + // *nix requests to init in the constructor. + SearchObjects m_objects; + + // *nix requests to init in the constructor. + SearchTargets m_targets; + + SearchEngine m_engine = SearchEngine::Internal; + + FindOptions m_findOptions = FindOption::FindNone; +}; +} // namespace vnotex + Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::SearchObjects); Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::SearchTargets); diff --git a/src/search/searcher.cpp b/src/search/searcher.cpp index e272664d02..94b7c69edb 100644 --- a/src/search/searcher.cpp +++ b/src/search/searcher.cpp @@ -4,553 +4,521 @@ #include #include -#include #include +#include #include #include #include -#include "searchresultitem.h" #include "filesearchengine.h" +#include "searchresultitem.h" using namespace vnotex; -Searcher::Searcher(QObject *p_parent) - : QObject(p_parent) -{ -} +Searcher::Searcher(QObject *p_parent) : QObject(p_parent) {} -void Searcher::clear() -{ - m_option.clear(); +void Searcher::clear() { + m_option.clear(); - if (m_engine) { - m_engine->clear(); - m_engine.reset(); - } + if (m_engine) { + m_engine->clear(); + m_engine.reset(); + } - m_askedToStop = false; + m_askedToStop = false; } -void Searcher::stop() -{ - m_askedToStop = true; +void Searcher::stop() { + m_askedToStop = true; - if (m_engine) { - m_engine->stop(); - } + if (m_engine) { + m_engine->stop(); + } } -SearchState Searcher::search(const QSharedPointer &p_option, const QList &p_buffers) -{ - if (!(p_option->m_targets & SearchTarget::SearchFile)) { - // Only File target is applicable. - return SearchState::Finished; - } - - if (!prepare(p_option)) { - return SearchState::Failed; - } +SearchState Searcher::search(const QSharedPointer &p_option, + const QList &p_buffers) { + if (!(p_option->m_targets & SearchTarget::SearchFile)) { + // Only File target is applicable. + return SearchState::Finished; + } - emit logRequested(tr("Searching %n buffer(s)", "", p_buffers.size())); + if (!prepare(p_option)) { + return SearchState::Failed; + } - m_firstPhaseWorker->doWork([this, p_buffers]() { - emit progressUpdated(0, p_buffers.size()); - for (int i = 0; i < p_buffers.size(); ++i) { - if (!p_buffers[i]) { - continue; - } + emit logRequested(tr("Searching %n buffer(s)", "", p_buffers.size())); - if (isAskedToStop()) { - emit finished(SearchState::Stopped); - return; - } + m_firstPhaseWorker->doWork([this, p_buffers]() { + emit progressUpdated(0, p_buffers.size()); + for (int i = 0; i < p_buffers.size(); ++i) { + if (!p_buffers[i]) { + continue; + } - auto file = p_buffers[i]->getFile(); - if (!firstPhaseSearch(file.data())) { - emit finished(SearchState::Failed); - return; - } - - emit progressUpdated(i + 1, p_buffers.size()); - } - - emit finished(SearchState::Finished); - }); + if (isAskedToStop()) { + emit finished(SearchState::Stopped); + return; + } - return SearchState::Busy; -} + auto file = p_buffers[i]->getFile(); + if (!firstPhaseSearch(file.data())) { + emit finished(SearchState::Failed); + return; + } -SearchState Searcher::search(const QSharedPointer &p_option, Node *p_folder) -{ - Q_ASSERT(p_folder->isContainer()); - if (!(p_option->m_targets & (SearchTarget::SearchFile | SearchTarget::SearchFolder))) { - // Only File/Folder target is applicable. - return SearchState::Finished; + emit progressUpdated(i + 1, p_buffers.size()); } - if (!prepare(p_option)) { - return SearchState::Failed; - } + emit finished(SearchState::Finished); + }); - emit logRequested(tr("Searching folder (%1)").arg(p_folder->getName())); + return SearchState::Busy; +} - m_firstPhaseWorker->doWork([this, p_folder]() { - if (!firstPhaseSearchFolder(p_folder, m_secondPhaseItems)) { - m_secondPhaseItems.clear(); - emit finished(SearchState::Failed); - return; - } +SearchState Searcher::search(const QSharedPointer &p_option, Node *p_folder) { + Q_ASSERT(p_folder->isContainer()); + if (!(p_option->m_targets & (SearchTarget::SearchFile | SearchTarget::SearchFolder))) { + // Only File/Folder target is applicable. + return SearchState::Finished; + } - if (m_secondPhaseItems.isEmpty()) { - emit finished(SearchState::Finished); - } - }); + if (!prepare(p_option)) { + return SearchState::Failed; + } - return SearchState::Busy; -} + emit logRequested(tr("Searching folder (%1)").arg(p_folder->getName())); -SearchState Searcher::search(const QSharedPointer &p_option, const QVector &p_notebooks) -{ - if (!prepare(p_option)) { - return SearchState::Failed; + m_firstPhaseWorker->doWork([this, p_folder]() { + if (!firstPhaseSearchFolder(p_folder, m_secondPhaseItems)) { + m_secondPhaseItems.clear(); + emit finished(SearchState::Failed); + return; } - m_firstPhaseWorker->doWork([this, p_notebooks]() { - emit progressUpdated(0, p_notebooks.size()); - for (int i = 0; i < p_notebooks.size(); ++i) { - if (isAskedToStop()) { - m_secondPhaseItems.clear(); - emit finished(SearchState::Stopped); - return; - } - - emit logRequested(tr("Searching notebook (%1)").arg(p_notebooks[i]->getName())); - - if (!firstPhaseSearch(p_notebooks[i], m_secondPhaseItems)) { - m_secondPhaseItems.clear(); - emit finished(SearchState::Failed); - return; - } + if (m_secondPhaseItems.isEmpty()) { + emit finished(SearchState::Finished); + } + }); - emit progressUpdated(i + 1, p_notebooks.size()); - } + return SearchState::Busy; +} - if (m_secondPhaseItems.isEmpty()) { - emit finished(SearchState::Finished); - } - }); +SearchState Searcher::search(const QSharedPointer &p_option, + const QVector &p_notebooks) { + if (!prepare(p_option)) { + return SearchState::Failed; + } + + m_firstPhaseWorker->doWork([this, p_notebooks]() { + emit progressUpdated(0, p_notebooks.size()); + for (int i = 0; i < p_notebooks.size(); ++i) { + if (isAskedToStop()) { + m_secondPhaseItems.clear(); + emit finished(SearchState::Stopped); + return; + } - return SearchState::Busy; -} + emit logRequested(tr("Searching notebook (%1)").arg(p_notebooks[i]->getName())); -bool Searcher::prepare(const QSharedPointer &p_option) -{ - Q_ASSERT(!m_option); - m_option = p_option; + if (!firstPhaseSearch(p_notebooks[i], m_secondPhaseItems)) { + m_secondPhaseItems.clear(); + emit finished(SearchState::Failed); + return; + } - if (!SearchToken::compile(m_option->m_keyword, m_option->m_findOptions, m_token)) { - emit logRequested(tr("Failed to compile tokens (%1)").arg(m_option->m_keyword)); - return false; + emit progressUpdated(i + 1, p_notebooks.size()); } - if (m_option->m_filePattern.isEmpty()) { - m_filePattern = QRegularExpression(); - } else { - m_filePattern = QRegularExpression(QRegularExpression::wildcardToRegularExpression(m_option->m_filePattern), QRegularExpression::CaseInsensitiveOption); + if (m_secondPhaseItems.isEmpty()) { + emit finished(SearchState::Finished); } + }); - if (!m_firstPhaseWorker) { - m_firstPhaseWorker = new AsyncWorkerWithFunctor(this); - connect(m_firstPhaseWorker, &AsyncWorkerWithFunctor::finished, - this, &Searcher::doSecondPhaseSearch); - } + return SearchState::Busy; +} - if (m_firstPhaseWorker->isRunning()) { - emit logRequested(tr("Failed to search due to worker is busy")); - return false; - } +bool Searcher::prepare(const QSharedPointer &p_option) { + Q_ASSERT(!m_option); + m_option = p_option; + + if (!SearchToken::compile(m_option->m_keyword, m_option->m_findOptions, m_token)) { + emit logRequested(tr("Failed to compile tokens (%1)").arg(m_option->m_keyword)); + return false; + } + + if (m_option->m_filePattern.isEmpty()) { + m_filePattern = QRegularExpression(); + } else { + m_filePattern = + QRegularExpression(QRegularExpression::wildcardToRegularExpression(m_option->m_filePattern), + QRegularExpression::CaseInsensitiveOption); + } + + if (!m_firstPhaseWorker) { + m_firstPhaseWorker = new AsyncWorkerWithFunctor(this); + connect(m_firstPhaseWorker, &AsyncWorkerWithFunctor::finished, this, + &Searcher::doSecondPhaseSearch); + } + + if (m_firstPhaseWorker->isRunning()) { + emit logRequested(tr("Failed to search due to worker is busy")); + return false; + } - m_secondPhaseItems.clear(); + m_secondPhaseItems.clear(); - return true; + return true; } -bool Searcher::isAskedToStop() const -{ - return m_askedToStop; -} +bool Searcher::isAskedToStop() const { return m_askedToStop; } -static QString tryGetRelativePath(const File *p_file) -{ - const auto node = p_file->getNode(); - if (node) { - return node->fetchPath(); - } - return p_file->getFilePath(); +static QString tryGetRelativePath(const File *p_file) { + const auto node = p_file->getNode(); + if (node) { + return node->fetchPath(); + } + return p_file->getFilePath(); } -bool Searcher::firstPhaseSearch(const File *p_file) -{ - if (!p_file) { - return true; - } +bool Searcher::firstPhaseSearch(const File *p_file) { + if (!p_file) { + return true; + } - Q_ASSERT(testTarget(SearchTarget::SearchFile)); + Q_ASSERT(testTarget(SearchTarget::SearchFile)); - const auto name = p_file->getName(); - if (!isFilePatternMatched(name)) { - return true; - } + const auto name = p_file->getName(); + if (!isFilePatternMatched(name)) { + return true; + } - const auto filePath = p_file->getFilePath(); - const auto relativePath = tryGetRelativePath(p_file); + const auto filePath = p_file->getFilePath(); + const auto relativePath = tryGetRelativePath(p_file); - if (testObject(SearchObject::SearchName)) { - if (isTokenMatched(name)) { - emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchName)) { + if (isTokenMatched(name)) { + emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); } + } - if (testObject(SearchObject::SearchPath)) { - if (isTokenMatched(relativePath)) { - emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchPath)) { + if (isTokenMatched(relativePath)) { + emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); } + } - if (testObject(SearchObject::SearchTag)) { - if (searchTag(p_file->getNode())) { - emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchTag)) { + if (searchTag(p_file->getNode())) { + emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); } + } - // Make SearchContent always the last one to check. - if (testObject(SearchObject::SearchContent)) { - if (!searchContent(p_file)) { - return false; - } + // Make SearchContent always the last one to check. + if (testObject(SearchObject::SearchContent)) { + if (!searchContent(p_file)) { + return false; } + } - return true; + return true; } -bool Searcher::isFilePatternMatched(const QString &p_name) const -{ - if (m_option->m_filePattern.isEmpty()) { - return true; - } +bool Searcher::isFilePatternMatched(const QString &p_name) const { + if (m_option->m_filePattern.isEmpty()) { + return true; + } - return m_filePattern.match(p_name).hasMatch(); + return m_filePattern.match(p_name).hasMatch(); } -bool Searcher::testTarget(SearchTarget p_target) const -{ - return m_option->m_targets & p_target; -} +bool Searcher::testTarget(SearchTarget p_target) const { return m_option->m_targets & p_target; } -bool Searcher::testObject(SearchObject p_object) const -{ - return m_option->m_objects & p_object; -} +bool Searcher::testObject(SearchObject p_object) const { return m_option->m_objects & p_object; } -bool Searcher::isTokenMatched(const QString &p_text) const -{ - return m_token.matched(p_text); -} +bool Searcher::isTokenMatched(const QString &p_text) const { return m_token.matched(p_text); } -bool Searcher::searchContent(const File *p_file) -{ - const auto content = p_file->read(); - if (content.isEmpty()) { - return true; - } +bool Searcher::searchContent(const File *p_file) { + const auto content = p_file->read(); + if (content.isEmpty()) { + return true; + } - const bool shouldStartBatchMode = m_token.shouldStartBatchMode(); - if (shouldStartBatchMode) { - m_token.startBatchMode(); - } + const bool shouldStartBatchMode = m_token.shouldStartBatchMode(); + if (shouldStartBatchMode) { + m_token.startBatchMode(); + } - const auto filePath = p_file->getFilePath(); - const auto relativePath = tryGetRelativePath(p_file); + const auto filePath = p_file->getFilePath(); + const auto relativePath = tryGetRelativePath(p_file); - QSharedPointer resultItem; + QSharedPointer resultItem; - int lineNum = 0; - int pos = 0; - int contentSize = content.size(); - QRegularExpression newlineRegExp("\\n|\\r\\n|\\r"); - while (pos < contentSize) { - if (isAskedToStop()) { - break; + int lineNum = 0; + int pos = 0; + int contentSize = content.size(); + QRegularExpression newlineRegExp("\\n|\\r\\n|\\r"); + while (pos < contentSize) { + if (isAskedToStop()) { + break; + } + + QRegularExpressionMatch match; + int idx = content.indexOf(newlineRegExp, pos, &match); + if (idx == -1) { + idx = contentSize; + } + + if (idx > pos) { + QString lineText = content.mid(pos, idx - pos); + bool matched = false; + QList segments; + if (!shouldStartBatchMode) { + matched = m_token.matched(lineText, &segments); + } else { + matched = m_token.matchedInBatchMode(lineText, &segments); + } + + if (matched) { + if (resultItem) { + resultItem->addLine(lineNum, lineText, segments); + } else { + resultItem = SearchResultItem::createBufferItem(filePath, relativePath, lineNum, lineText, + segments); } + } + } - QRegularExpressionMatch match; - int idx = content.indexOf(newlineRegExp, pos, &match); - if (idx == -1) { - idx = contentSize; - } + if (idx == contentSize) { + break; + } - if (idx > pos) { - QString lineText = content.mid(pos, idx - pos); - bool matched = false; - QList segments; - if (!shouldStartBatchMode) { - matched = m_token.matched(lineText, &segments); - } else { - matched = m_token.matchedInBatchMode(lineText, &segments); - } - - if (matched) { - if (resultItem) { - resultItem->addLine(lineNum, lineText, segments); - } else { - resultItem = SearchResultItem::createBufferItem(filePath, relativePath, lineNum, lineText, segments); - } - } - } + if (shouldStartBatchMode && m_token.readyToEndBatchMode()) { + break; + } - if (idx == contentSize) { - break; - } + pos = idx + match.capturedLength(); + ++lineNum; + } - if (shouldStartBatchMode && m_token.readyToEndBatchMode()) { - break; - } + if (shouldStartBatchMode) { + bool allMatched = m_token.readyToEndBatchMode(); + m_token.endBatchMode(); - pos = idx + match.capturedLength(); - ++lineNum; + if (!allMatched) { + // This file does not meet all the tokens. + resultItem.reset(); } + } - if (shouldStartBatchMode) { - bool allMatched = m_token.readyToEndBatchMode(); - m_token.endBatchMode(); + if (resultItem) { + emit resultItemAdded(resultItem); + } - if (!allMatched) { - // This file does not meet all the tokens. - resultItem.reset(); - } - } - - if (resultItem) { - emit resultItemAdded(resultItem); - } + return true; +} +bool Searcher::firstPhaseSearchFolder(Node *p_node, + QVector &p_secondPhaseItems) { + if (!p_node) { return true; -} + } -bool Searcher::firstPhaseSearchFolder(Node *p_node, QVector &p_secondPhaseItems) -{ - if (!p_node) { - return true; - } + Q_ASSERT(p_node->isContainer()); + Q_ASSERT(testTarget(SearchTarget::SearchFile) || testTarget(SearchTarget::SearchFolder)); - Q_ASSERT(p_node->isContainer()); - Q_ASSERT(testTarget(SearchTarget::SearchFile) || testTarget(SearchTarget::SearchFolder)); + try { + p_node->load(); + } catch (Exception &p_e) { + QString msg = tr("Failed to load node to search (%1) (%2).").arg(p_node->getName(), p_e.what()); + qCritical() << msg; + emit logRequested(msg); + return false; + } - try { - p_node->load(); - } catch (Exception &p_e) { - QString msg = tr("Failed to load node to search (%1) (%2).") - .arg(p_node->getName(), p_e.what()); - qCritical() << msg; - emit logRequested(msg); - return false; + if (testTarget(SearchTarget::SearchFolder) && !p_node->isRoot()) { + const auto name = p_node->getName(); + const auto folderPath = p_node->fetchAbsolutePath(); + const auto relativePath = p_node->fetchPath(); + if (testObject(SearchObject::SearchName)) { + if (isTokenMatched(name)) { + emit resultItemAdded(SearchResultItem::createFolderItem(folderPath, relativePath)); + } } - if (testTarget(SearchTarget::SearchFolder) && !p_node->isRoot()) { - const auto name = p_node->getName(); - const auto folderPath = p_node->fetchAbsolutePath(); - const auto relativePath = p_node->fetchPath(); - if (testObject(SearchObject::SearchName)) { - if (isTokenMatched(name)) { - emit resultItemAdded(SearchResultItem::createFolderItem(folderPath, relativePath)); - } - } - - if (testObject(SearchObject::SearchPath)) { - if (isTokenMatched(relativePath)) { - emit resultItemAdded(SearchResultItem::createFolderItem(folderPath, relativePath)); - } - } + if (testObject(SearchObject::SearchPath)) { + if (isTokenMatched(relativePath)) { + emit resultItemAdded(SearchResultItem::createFolderItem(folderPath, relativePath)); + } } + } - // Search children. - const auto &children = p_node->getChildrenRef(); - for (const auto &child : children) { - if (isAskedToStop()) { - return true; - } + // Search children. + const auto &children = p_node->getChildrenRef(); + for (const auto &child : children) { + if (isAskedToStop()) { + return true; + } - if (child->hasContent() && testTarget(SearchTarget::SearchFile)) { - if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) { - return false; - } - } + if (child->hasContent() && testTarget(SearchTarget::SearchFile)) { + if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) { + return false; + } + } - if (child->isContainer()) { - if (!firstPhaseSearchFolder(child.data(), p_secondPhaseItems)) { - return false; - } - } + if (child->isContainer()) { + if (!firstPhaseSearchFolder(child.data(), p_secondPhaseItems)) { + return false; + } } + } - return true; + return true; } -bool Searcher::firstPhaseSearch(Node *p_node, QVector &p_secondPhaseItems) -{ - if (!p_node) { - return true; - } +bool Searcher::firstPhaseSearch(Node *p_node, QVector &p_secondPhaseItems) { + if (!p_node) { + return true; + } - Q_ASSERT(testTarget(SearchTarget::SearchFile)); + Q_ASSERT(testTarget(SearchTarget::SearchFile)); - const auto name = p_node->getName(); - if (!isFilePatternMatched(name)) { - return true; - } + const auto name = p_node->getName(); + if (!isFilePatternMatched(name)) { + return true; + } - const auto filePath = p_node->fetchAbsolutePath(); - const auto relativePath = p_node->fetchPath(); + const auto filePath = p_node->fetchAbsolutePath(); + const auto relativePath = p_node->fetchPath(); - if (testObject(SearchObject::SearchName)) { - if (isTokenMatched(name)) { - emit resultItemAdded(SearchResultItem::createFileItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchName)) { + if (isTokenMatched(name)) { + emit resultItemAdded(SearchResultItem::createFileItem(filePath, relativePath)); } + } - if (testObject(SearchObject::SearchPath)) { - if (isTokenMatched(relativePath)) { - emit resultItemAdded(SearchResultItem::createFileItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchPath)) { + if (isTokenMatched(relativePath)) { + emit resultItemAdded(SearchResultItem::createFileItem(filePath, relativePath)); } + } - if (testObject(SearchObject::SearchTag)) { - if (searchTag(p_node)) { - emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchTag)) { + if (searchTag(p_node)) { + emit resultItemAdded(SearchResultItem::createBufferItem(filePath, relativePath)); } + } - if (testObject(SearchObject::SearchContent)) { - p_secondPhaseItems.push_back(SearchSecondPhaseItem(filePath, relativePath)); - } + if (testObject(SearchObject::SearchContent)) { + p_secondPhaseItems.push_back(SearchSecondPhaseItem(filePath, relativePath)); + } - return true; + return true; } -bool Searcher::firstPhaseSearch(Notebook *p_notebook, QVector &p_secondPhaseItems) -{ - if (!p_notebook) { - return true; - } +bool Searcher::firstPhaseSearch(Notebook *p_notebook, + QVector &p_secondPhaseItems) { + if (!p_notebook) { + return true; + } - if (testTarget(SearchTarget::SearchNotebook)) { - if (testObject(SearchObject::SearchName)) { - const auto name = p_notebook->getName(); - if (isTokenMatched(name)) { - emit resultItemAdded(SearchResultItem::createNotebookItem(p_notebook->getRootFolderAbsolutePath(), - name)); - } - } + if (testTarget(SearchTarget::SearchNotebook)) { + if (testObject(SearchObject::SearchName)) { + const auto name = p_notebook->getName(); + if (isTokenMatched(name)) { + emit resultItemAdded( + SearchResultItem::createNotebookItem(p_notebook->getRootFolderAbsolutePath(), name)); + } } + } - if (!testTarget(SearchTarget::SearchFile) && !testTarget(SearchTarget::SearchFolder)) { - return true; - } + if (!testTarget(SearchTarget::SearchFile) && !testTarget(SearchTarget::SearchFolder)) { + return true; + } - auto rootNode = p_notebook->getRootNode(); - Q_ASSERT(rootNode->isLoaded()); - const auto &children = rootNode->getChildrenRef(); - for (const auto &child : children) { - if (isAskedToStop()) { - return true; - } + auto rootNode = p_notebook->getRootNode(); + Q_ASSERT(rootNode->isLoaded()); + const auto &children = rootNode->getChildrenRef(); + for (const auto &child : children) { + if (isAskedToStop()) { + return true; + } - if (child->hasContent() && testTarget(SearchTarget::SearchFile)) { - if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) { - return false; - } - } + if (child->hasContent() && testTarget(SearchTarget::SearchFile)) { + if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) { + return false; + } + } - if (child->isContainer()) { - if (!firstPhaseSearchFolder(child.data(), p_secondPhaseItems)) { - return false; - } - } + if (child->isContainer()) { + if (!firstPhaseSearchFolder(child.data(), p_secondPhaseItems)) { + return false; + } } + } - return true; + return true; } -bool Searcher::secondPhaseSearch(const QVector &p_secondPhaseItems) -{ - Q_ASSERT(!p_secondPhaseItems.isEmpty()); +bool Searcher::secondPhaseSearch(const QVector &p_secondPhaseItems) { + Q_ASSERT(!p_secondPhaseItems.isEmpty()); - emit logRequested(tr("Start second-phase search: %n files(s)", "", p_secondPhaseItems.size())); - qDebug() << "secondPhaseSearch" << p_secondPhaseItems.size(); + emit logRequested(tr("Start second-phase search: %n files(s)", "", p_secondPhaseItems.size())); + qDebug() << "secondPhaseSearch" << p_secondPhaseItems.size(); - createSearchEngine(); + createSearchEngine(); - connect(m_engine.data(), &ISearchEngine::finished, - this, &Searcher::finished); - connect(m_engine.data(), &ISearchEngine::logRequested, - this, &Searcher::logRequested); - connect(m_engine.data(), &ISearchEngine::resultItemsAdded, - this, &Searcher::resultItemsAdded); + connect(m_engine.data(), &ISearchEngine::finished, this, &Searcher::finished); + connect(m_engine.data(), &ISearchEngine::logRequested, this, &Searcher::logRequested); + connect(m_engine.data(), &ISearchEngine::resultItemsAdded, this, &Searcher::resultItemsAdded); - m_engine->search(m_option, m_token, p_secondPhaseItems); + m_engine->search(m_option, m_token, p_secondPhaseItems); - return true; + return true; } -void Searcher::createSearchEngine() -{ - Q_ASSERT(m_option->m_engine == SearchEngine::Internal); +void Searcher::createSearchEngine() { + Q_ASSERT(m_option->m_engine == SearchEngine::Internal); - m_engine.reset(new FileSearchEngine()); + m_engine.reset(new FileSearchEngine()); } -const SearchToken &Searcher::getToken() const -{ - return m_token; -} - -bool Searcher::searchTag(const Node *p_node) const -{ - if (!p_node) { - return false; - } - - Q_ASSERT(p_node->isLoaded()); - - for (const auto &tag : p_node->getTags()) { - if (isTokenMatched(tag)) { - return true; - } - } +const SearchToken &Searcher::getToken() const { return m_token; } +bool Searcher::searchTag(const Node *p_node) const { + if (!p_node) { return false; -} + } -void Searcher::doSecondPhaseSearch() -{ - if (m_secondPhaseItems.isEmpty()) { - return; - } + Q_ASSERT(p_node->isLoaded()); - if (isAskedToStop()) { - emit finished(SearchState::Stopped); - return; + for (const auto &tag : p_node->getTags()) { + if (isTokenMatched(tag)) { + return true; } + } - // Do second phase search. - if (!secondPhaseSearch(m_secondPhaseItems)) { - emit finished(SearchState::Failed); - return; - } + return false; +} - if (isAskedToStop()) { - emit finished(SearchState::Stopped); - return; - } +void Searcher::doSecondPhaseSearch() { + if (m_secondPhaseItems.isEmpty()) { + return; + } + + if (isAskedToStop()) { + emit finished(SearchState::Stopped); + return; + } + + // Do second phase search. + if (!secondPhaseSearch(m_secondPhaseItems)) { + emit finished(SearchState::Failed); + return; + } + + if (isAskedToStop()) { + emit finished(SearchState::Stopped); + return; + } } diff --git a/src/search/searcher.h b/src/search/searcher.h index 6355c4f4e1..c228e508f9 100644 --- a/src/search/searcher.h +++ b/src/search/searcher.h @@ -2,107 +2,107 @@ #define SEARCHER_H #include -#include -#include #include +#include +#include #include +#include "isearchengine.h" #include "searchdata.h" #include "searchtoken.h" -#include "isearchengine.h" -namespace vnotex -{ - class Buffer; - class File; - struct SearchResultItem; - class Node; - class Notebook; - class AsyncWorkerWithFunctor; +namespace vnotex { +class Buffer; +class File; +struct SearchResultItem; +class Node; +class Notebook; +class AsyncWorkerWithFunctor; - class Searcher : public QObject - { - Q_OBJECT - public: - explicit Searcher(QObject *p_parent = nullptr); +class Searcher : public QObject { + Q_OBJECT +public: + explicit Searcher(QObject *p_parent = nullptr); - void clear(); + void clear(); - void stop(); + void stop(); - SearchState search(const QSharedPointer &p_option, const QList &p_buffers); + SearchState search(const QSharedPointer &p_option, + const QList &p_buffers); - SearchState search(const QSharedPointer &p_option, Node *p_folder); + SearchState search(const QSharedPointer &p_option, Node *p_folder); - SearchState search(const QSharedPointer &p_option, const QVector &p_notebooks); + SearchState search(const QSharedPointer &p_option, + const QVector &p_notebooks); - const SearchToken &getToken() const; + const SearchToken &getToken() const; - signals: - void progressUpdated(int p_val, int p_maximum); +signals: + void progressUpdated(int p_val, int p_maximum); - void logRequested(const QString &p_log); + void logRequested(const QString &p_log); - void resultItemAdded(const QSharedPointer &p_item); + void resultItemAdded(const QSharedPointer &p_item); - void resultItemsAdded(const QVector> &p_items); + void resultItemsAdded(const QVector> &p_items); - void finished(SearchState p_state); + void finished(SearchState p_state); - private: - bool isAskedToStop() const; +private: + bool isAskedToStop() const; - bool prepare(const QSharedPointer &p_option); + bool prepare(const QSharedPointer &p_option); - // Return false if there is failure. - // Always search content at first phase. - bool firstPhaseSearch(const File *p_file); + // Return false if there is failure. + // Always search content at first phase. + bool firstPhaseSearch(const File *p_file); - // Return false if there is failure. - bool firstPhaseSearchFolder(Node *p_node, QVector &p_secondPhaseItems); + // Return false if there is failure. + bool firstPhaseSearchFolder(Node *p_node, QVector &p_secondPhaseItems); - // Return false if there is failure. - bool firstPhaseSearch(Node *p_node, QVector &p_secondPhaseItems); + // Return false if there is failure. + bool firstPhaseSearch(Node *p_node, QVector &p_secondPhaseItems); - // Return false if there is failure. - bool firstPhaseSearch(Notebook *p_notebook, QVector &p_secondPhaseItems); + // Return false if there is failure. + bool firstPhaseSearch(Notebook *p_notebook, QVector &p_secondPhaseItems); - // Return false if there is failure. - bool secondPhaseSearch(const QVector &p_secondPhaseItems); + // Return false if there is failure. + bool secondPhaseSearch(const QVector &p_secondPhaseItems); - bool isFilePatternMatched(const QString &p_name) const; + bool isFilePatternMatched(const QString &p_name) const; - bool testTarget(SearchTarget p_target) const; + bool testTarget(SearchTarget p_target) const; - bool testObject(SearchObject p_object) const; + bool testObject(SearchObject p_object) const; - bool isTokenMatched(const QString &p_text) const; + bool isTokenMatched(const QString &p_text) const; - bool searchContent(const File *p_file); + bool searchContent(const File *p_file); - // Return true if matched. - bool searchTag(const Node *p_node) const; + // Return true if matched. + bool searchTag(const Node *p_node) const; - void createSearchEngine(); + void createSearchEngine(); - // Will be called after m_firstPhaseWorker finished. - void doSecondPhaseSearch(); + // Will be called after m_firstPhaseWorker finished. + void doSecondPhaseSearch(); - QSharedPointer m_option; + QSharedPointer m_option; - SearchToken m_token; + SearchToken m_token; - QRegularExpression m_filePattern; + QRegularExpression m_filePattern; - bool m_askedToStop = false; + bool m_askedToStop = false; - QScopedPointer m_engine; + QScopedPointer m_engine; - AsyncWorkerWithFunctor *m_firstPhaseWorker = nullptr; + AsyncWorkerWithFunctor *m_firstPhaseWorker = nullptr; - // Pending second phase items. - QVector m_secondPhaseItems; - }; -} + // Pending second phase items. + QVector m_secondPhaseItems; +}; +} // namespace vnotex #endif // SEARCHER_H diff --git a/src/search/searchhelper.cpp b/src/search/searchhelper.cpp index d1a114d373..587b071917 100644 --- a/src/search/searchhelper.cpp +++ b/src/search/searchhelper.cpp @@ -4,96 +4,90 @@ using namespace vnotex; -bool SearchHelper::isSearchOptionValid(const SearchOption &p_option, QString &p_msg) -{ - if (p_option.m_keyword.isEmpty()) { - p_msg = Searcher::tr("Invalid keyword"); - return false; - } - - if (p_option.m_objects == SearchObject::ObjectNone) { - p_msg = Searcher::tr("No object specified"); - return false; - } - - if (p_option.m_targets == SearchTarget::TargetNone) { - p_msg = Searcher::tr("No target specified"); - return false; - } - - if (p_option.m_findOptions & FindOption::FuzzySearch - && p_option.m_objects & SearchObject::SearchContent) { - p_msg = Searcher::tr("Fuzzy search is not allowed when searching content"); - return false; - } - - p_msg.clear(); - return true; +bool SearchHelper::isSearchOptionValid(const SearchOption &p_option, QString &p_msg) { + if (p_option.m_keyword.isEmpty()) { + p_msg = Searcher::tr("Invalid keyword"); + return false; + } + + if (p_option.m_objects == SearchObject::ObjectNone) { + p_msg = Searcher::tr("No object specified"); + return false; + } + + if (p_option.m_targets == SearchTarget::TargetNone) { + p_msg = Searcher::tr("No target specified"); + return false; + } + + if (p_option.m_findOptions & FindOption::FuzzySearch && + p_option.m_objects & SearchObject::SearchContent) { + p_msg = Searcher::tr("Fuzzy search is not allowed when searching content"); + return false; + } + + p_msg.clear(); + return true; } SearchState SearchHelper::searchOnProvider(Searcher *p_searcher, const QSharedPointer &p_option, const QSharedPointer &p_provider, - QString &p_msg) -{ - p_msg.clear(); + QString &p_msg) { + p_msg.clear(); - if (!isSearchOptionValid(*p_option, p_msg)) { - return SearchState::Failed; - } + if (!isSearchOptionValid(*p_option, p_msg)) { + return SearchState::Failed; + } - SearchState state = SearchState::Finished; - - switch (p_option->m_scope) { - case SearchScope::Buffers: - { - auto buffers = p_provider->getBuffers(); - if (buffers.isEmpty()) { - break; - } - state = p_searcher->search(p_option, buffers); - break; - } + SearchState state = SearchState::Finished; - case SearchScope::CurrentFolder: - { - auto notebook = p_provider->getCurrentNotebook(); - if (!notebook) { - break; - } - auto folder = p_provider->getCurrentFolder(); - if (!folder) { - break; - } - - state = p_searcher->search(p_option, folder); - break; + switch (p_option->m_scope) { + case SearchScope::Buffers: { + auto buffers = p_provider->getBuffers(); + if (buffers.isEmpty()) { + break; } - - case SearchScope::CurrentNotebook: - { - auto notebook = p_provider->getCurrentNotebook(); - if (!notebook) { - break; - } - - QVector notebooks; - notebooks.push_back(notebook); - state = p_searcher->search(p_option, notebooks); - break; + state = p_searcher->search(p_option, buffers); + break; + } + + case SearchScope::CurrentFolder: { + auto notebook = p_provider->getCurrentNotebook(); + if (!notebook) { + break; + } + auto folder = p_provider->getCurrentFolder(); + if (!folder) { + break; } - case SearchScope::AllNotebooks: - { - auto notebooks = p_provider->getNotebooks(); - if (notebooks.isEmpty()) { - break; - } + state = p_searcher->search(p_option, folder); + break; + } - state = p_searcher->search(p_option, notebooks); - break; + case SearchScope::CurrentNotebook: { + auto notebook = p_provider->getCurrentNotebook(); + if (!notebook) { + break; } + + QVector notebooks; + notebooks.push_back(notebook); + state = p_searcher->search(p_option, notebooks); + break; + } + + case SearchScope::AllNotebooks: { + auto notebooks = p_provider->getNotebooks(); + if (notebooks.isEmpty()) { + break; } - return state; + state = p_searcher->search(p_option, notebooks); + break; + } + } + + return state; } diff --git a/src/search/searchhelper.h b/src/search/searchhelper.h index ad728bf33b..36218d1b25 100644 --- a/src/search/searchhelper.h +++ b/src/search/searchhelper.h @@ -6,23 +6,21 @@ #include "searchdata.h" #include "searcher.h" -namespace vnotex -{ - class ISearchInfoProvider; +namespace vnotex { +class ISearchInfoProvider; - class SearchHelper - { - public: - SearchHelper() = delete; +class SearchHelper { +public: + SearchHelper() = delete; - static SearchState searchOnProvider(Searcher *p_searcher, - const QSharedPointer &p_option, - const QSharedPointer &p_provider, - QString &p_msg); + static SearchState searchOnProvider(Searcher *p_searcher, + const QSharedPointer &p_option, + const QSharedPointer &p_provider, + QString &p_msg); - private: - static bool isSearchOptionValid(const SearchOption &p_option, QString &p_msg); - }; -} +private: + static bool isSearchOptionValid(const SearchOption &p_option, QString &p_msg); +}; +} // namespace vnotex #endif // SEARCHHELPER_H diff --git a/src/search/searchresultitem.cpp b/src/search/searchresultitem.cpp index 1e8c918cb9..f786f3f00a 100644 --- a/src/search/searchresultitem.cpp +++ b/src/search/searchresultitem.cpp @@ -2,69 +2,61 @@ using namespace vnotex; -QSharedPointer SearchResultItem::createBufferItem(const QString &p_targetPath, - const QString &p_displayPath, - int p_lineNumber, - const QString &p_text, - const QList &p_segments) -{ - auto item = createBufferItem(p_targetPath, p_displayPath); - item->m_location.addLine(p_lineNumber, p_text, p_segments); - return item; +QSharedPointer +SearchResultItem::createBufferItem(const QString &p_targetPath, const QString &p_displayPath, + int p_lineNumber, const QString &p_text, + const QList &p_segments) { + auto item = createBufferItem(p_targetPath, p_displayPath); + item->m_location.addLine(p_lineNumber, p_text, p_segments); + return item; } QSharedPointer SearchResultItem::createBufferItem(const QString &p_targetPath, - const QString &p_displayPath) -{ - auto item = QSharedPointer::create(); - item->m_location.m_type = LocationType::Buffer; - item->m_location.m_path = p_targetPath; - item->m_location.m_displayPath = p_displayPath; - return item; + const QString &p_displayPath) { + auto item = QSharedPointer::create(); + item->m_location.m_type = LocationType::Buffer; + item->m_location.m_path = p_targetPath; + item->m_location.m_displayPath = p_displayPath; + return item; } -QSharedPointer SearchResultItem::createFileItem(const QString &p_targetPath, - const QString &p_displayPath, - int p_lineNumber, - const QString &p_text, - const QList &p_segments) -{ - auto item = createFileItem(p_targetPath, p_displayPath); - item->m_location.addLine(p_lineNumber, p_text, p_segments); - return item; +QSharedPointer +SearchResultItem::createFileItem(const QString &p_targetPath, const QString &p_displayPath, + int p_lineNumber, const QString &p_text, + const QList &p_segments) { + auto item = createFileItem(p_targetPath, p_displayPath); + item->m_location.addLine(p_lineNumber, p_text, p_segments); + return item; } QSharedPointer SearchResultItem::createFileItem(const QString &p_targetPath, - const QString &p_displayPath) -{ - auto item = QSharedPointer::create(); - item->m_location.m_type = LocationType::File; - item->m_location.m_path = p_targetPath; - item->m_location.m_displayPath = p_displayPath; - return item; + const QString &p_displayPath) { + auto item = QSharedPointer::create(); + item->m_location.m_type = LocationType::File; + item->m_location.m_path = p_targetPath; + item->m_location.m_displayPath = p_displayPath; + return item; } QSharedPointer SearchResultItem::createFolderItem(const QString &p_targetPath, - const QString &p_displayPath) -{ - auto item = QSharedPointer::create(); - item->m_location.m_type = LocationType::Folder; - item->m_location.m_path = p_targetPath; - item->m_location.m_displayPath = p_displayPath; - return item; + const QString &p_displayPath) { + auto item = QSharedPointer::create(); + item->m_location.m_type = LocationType::Folder; + item->m_location.m_path = p_targetPath; + item->m_location.m_displayPath = p_displayPath; + return item; } -QSharedPointer SearchResultItem::createNotebookItem(const QString &p_targetPath, - const QString &p_displayPath) -{ - auto item = QSharedPointer::create(); - item->m_location.m_type = LocationType::Notebook; - item->m_location.m_path = p_targetPath; - item->m_location.m_displayPath = p_displayPath; - return item; +QSharedPointer +SearchResultItem::createNotebookItem(const QString &p_targetPath, const QString &p_displayPath) { + auto item = QSharedPointer::create(); + item->m_location.m_type = LocationType::Notebook; + item->m_location.m_path = p_targetPath; + item->m_location.m_displayPath = p_displayPath; + return item; } -void SearchResultItem::addLine(int p_lineNumber, const QString &p_text, const QList &p_segments) -{ - m_location.addLine(p_lineNumber, p_text, p_segments); +void SearchResultItem::addLine(int p_lineNumber, const QString &p_text, + const QList &p_segments) { + m_location.addLine(p_lineNumber, p_text, p_segments); } diff --git a/src/search/searchresultitem.h b/src/search/searchresultitem.h index f9a13eced0..f2485404e9 100644 --- a/src/search/searchresultitem.h +++ b/src/search/searchresultitem.h @@ -1,50 +1,45 @@ #ifndef SEARCHRESULTITEM_H #define SEARCHRESULTITEM_H +#include #include #include -#include #include -namespace vnotex -{ - struct SearchResultItem - { - friend QDebug operator<<(QDebug p_dbg, const SearchResultItem &p_item) - { - p_dbg << p_item.m_location; - return p_dbg; - } - - void addLine(int p_lineNumber, const QString &p_text, const QList &p_segments); - - static QSharedPointer createBufferItem(const QString &p_targetPath, - const QString &p_displayPath, - int p_lineNumber, - const QString &p_text, - const QList &p_segments); - - static QSharedPointer createBufferItem(const QString &p_targetPath, - const QString &p_displayPath); - - static QSharedPointer createFileItem(const QString &p_targetPath, - const QString &p_displayPath, - int p_lineNumber, - const QString &p_text, - const QList &p_segments); - - static QSharedPointer createFileItem(const QString &p_targetPath, - const QString &p_displayPath); - - static QSharedPointer createFolderItem(const QString &p_targetPath, - const QString &p_displayPath); - - static QSharedPointer createNotebookItem(const QString &p_targetPath, - const QString &p_displayPath); - - ComplexLocation m_location; - }; -} +namespace vnotex { +struct SearchResultItem { + friend QDebug operator<<(QDebug p_dbg, const SearchResultItem &p_item) { + p_dbg << p_item.m_location; + return p_dbg; + } + + void addLine(int p_lineNumber, const QString &p_text, const QList &p_segments); + + static QSharedPointer createBufferItem(const QString &p_targetPath, + const QString &p_displayPath, + int p_lineNumber, const QString &p_text, + const QList &p_segments); + + static QSharedPointer createBufferItem(const QString &p_targetPath, + const QString &p_displayPath); + + static QSharedPointer createFileItem(const QString &p_targetPath, + const QString &p_displayPath, + int p_lineNumber, const QString &p_text, + const QList &p_segments); + + static QSharedPointer createFileItem(const QString &p_targetPath, + const QString &p_displayPath); + + static QSharedPointer createFolderItem(const QString &p_targetPath, + const QString &p_displayPath); + + static QSharedPointer createNotebookItem(const QString &p_targetPath, + const QString &p_displayPath); + + ComplexLocation m_location; +}; +} // namespace vnotex #endif // SEARCHRESULTITEM_H diff --git a/src/search/searchtoken.cpp b/src/search/searchtoken.cpp index 47879f7f8c..51db8dbfb7 100644 --- a/src/search/searchtoken.cpp +++ b/src/search/searchtoken.cpp @@ -8,291 +8,277 @@ using namespace vnotex; -void SearchToken::clear() -{ - m_type = Type::PlainText; - m_operator = Operator::And; - m_caseSensitivity = Qt::CaseInsensitive; - m_keywords.clear(); - m_regularExpressions.clear(); - m_matchedConstraintsInBatchMode.clear(); - m_matchedConstraintsCountInBatchMode = 0; +void SearchToken::clear() { + m_type = Type::PlainText; + m_operator = Operator::And; + m_caseSensitivity = Qt::CaseInsensitive; + m_keywords.clear(); + m_regularExpressions.clear(); + m_matchedConstraintsInBatchMode.clear(); + m_matchedConstraintsCountInBatchMode = 0; } -void SearchToken::append(const QString &p_text) -{ - m_keywords.append(p_text); -} +void SearchToken::append(const QString &p_text) { m_keywords.append(p_text); } -void SearchToken::append(const QRegularExpression &p_regExp) -{ - m_regularExpressions.append(p_regExp); +void SearchToken::append(const QRegularExpression &p_regExp) { + m_regularExpressions.append(p_regExp); } -bool SearchToken::matched(const QString &p_text, QList *p_segments) const -{ - const int consSize = constraintSize(); - if (consSize == 0) { - return false; - } - - bool isMatched = m_operator == Operator::And ? true : false; - for (int i = 0; i < consSize; ++i) { - bool consMatched = false; - if (m_type == Type::PlainText) { - int idx = p_text.indexOf(m_keywords[i], 0, m_caseSensitivity); - if (idx > -1) { - consMatched = true; - if (p_segments) { - p_segments->push_back(Segment(idx, m_keywords[i].size())); - } - } - } else { - QRegularExpressionMatch match; - int idx = p_text.indexOf(m_regularExpressions[i], 0, &match); - if (idx > -1) { - consMatched = true; - if (p_segments) { - p_segments->push_back(Segment(idx, match.capturedLength())); - } - } +bool SearchToken::matched(const QString &p_text, QList *p_segments) const { + const int consSize = constraintSize(); + if (consSize == 0) { + return false; + } + + bool isMatched = m_operator == Operator::And ? true : false; + for (int i = 0; i < consSize; ++i) { + bool consMatched = false; + if (m_type == Type::PlainText) { + int idx = p_text.indexOf(m_keywords[i], 0, m_caseSensitivity); + if (idx > -1) { + consMatched = true; + if (p_segments) { + p_segments->push_back(Segment(idx, m_keywords[i].size())); } - - if (consMatched) { - if (m_operator == Operator::Or) { - isMatched = true; - break; - } - } else if (m_operator == Operator::And) { - isMatched = false; - break; + } + } else { + QRegularExpressionMatch match; + int idx = p_text.indexOf(m_regularExpressions[i], 0, &match); + if (idx > -1) { + consMatched = true; + if (p_segments) { + p_segments->push_back(Segment(idx, match.capturedLength())); } + } } - return isMatched; -} + if (consMatched) { + if (m_operator == Operator::Or) { + isMatched = true; + break; + } + } else if (m_operator == Operator::And) { + isMatched = false; + break; + } + } -int SearchToken::constraintSize() const -{ - return (m_type == Type::PlainText ? m_keywords.size() : m_regularExpressions.size()); + return isMatched; } -bool SearchToken::shouldStartBatchMode() const -{ - return constraintSize() > 1; +int SearchToken::constraintSize() const { + return (m_type == Type::PlainText ? m_keywords.size() : m_regularExpressions.size()); } -void SearchToken::startBatchMode() -{ - m_matchedConstraintsInBatchMode.fill(false, constraintSize()); - m_matchedConstraintsCountInBatchMode = 0; +bool SearchToken::shouldStartBatchMode() const { return constraintSize() > 1; } + +void SearchToken::startBatchMode() { + m_matchedConstraintsInBatchMode.fill(false, constraintSize()); + m_matchedConstraintsCountInBatchMode = 0; } -bool SearchToken::matchedInBatchMode(const QString &p_text, QList *p_segments) -{ - bool isMatched = false; - const int consSize = m_matchedConstraintsInBatchMode.size(); - for (int i = 0; i < consSize; ++i) { - if (m_matchedConstraintsInBatchMode[i]) { - continue; - } +bool SearchToken::matchedInBatchMode(const QString &p_text, QList *p_segments) { + bool isMatched = false; + const int consSize = m_matchedConstraintsInBatchMode.size(); + for (int i = 0; i < consSize; ++i) { + if (m_matchedConstraintsInBatchMode[i]) { + continue; + } - bool consMatched = false; - if (m_type == Type::PlainText) { - int idx = p_text.indexOf(m_keywords[i], 0, m_caseSensitivity); - if (idx > -1) { - consMatched = true; - if (p_segments) { - p_segments->push_back(Segment(idx, m_keywords[i].size())); - } - } - } else { - QRegularExpressionMatch match; - int idx = p_text.indexOf(m_regularExpressions[i], 0, &match); - if (idx > -1) { - consMatched = true; - if (p_segments) { - p_segments->push_back(Segment(idx, match.capturedLength())); - } - } + bool consMatched = false; + if (m_type == Type::PlainText) { + int idx = p_text.indexOf(m_keywords[i], 0, m_caseSensitivity); + if (idx > -1) { + consMatched = true; + if (p_segments) { + p_segments->push_back(Segment(idx, m_keywords[i].size())); } - - if (consMatched) { - m_matchedConstraintsInBatchMode[i] = true; - ++m_matchedConstraintsCountInBatchMode; - isMatched = true; + } + } else { + QRegularExpressionMatch match; + int idx = p_text.indexOf(m_regularExpressions[i], 0, &match); + if (idx > -1) { + consMatched = true; + if (p_segments) { + p_segments->push_back(Segment(idx, match.capturedLength())); } + } } - return isMatched; + if (consMatched) { + m_matchedConstraintsInBatchMode[i] = true; + ++m_matchedConstraintsCountInBatchMode; + isMatched = true; + } + } + + return isMatched; } -bool SearchToken::readyToEndBatchMode() const -{ - if (m_operator == Operator::And) { - // We need all the tokens matched. - if (m_matchedConstraintsCountInBatchMode == m_matchedConstraintsInBatchMode.size()) { - return true; - } - } else { - // We only need one match. - if (m_matchedConstraintsCountInBatchMode > 0) { - return true; - } +bool SearchToken::readyToEndBatchMode() const { + if (m_operator == Operator::And) { + // We need all the tokens matched. + if (m_matchedConstraintsCountInBatchMode == m_matchedConstraintsInBatchMode.size()) { + return true; + } + } else { + // We only need one match. + if (m_matchedConstraintsCountInBatchMode > 0) { + return true; } + } - return false; + return false; } -void SearchToken::endBatchMode() -{ - m_matchedConstraintsInBatchMode.clear(); - m_matchedConstraintsCountInBatchMode = 0; +void SearchToken::endBatchMode() { + m_matchedConstraintsInBatchMode.clear(); + m_matchedConstraintsCountInBatchMode = 0; } -bool SearchToken::isEmpty() const -{ - return constraintSize() == 0; -} +bool SearchToken::isEmpty() const { return constraintSize() == 0; } -QCommandLineParser *SearchToken::getCommandLineParser() -{ - static QScopedPointer parser; +QCommandLineParser *SearchToken::getCommandLineParser() { + static QScopedPointer parser; - if (parser) { - return parser.data(); - } + if (parser) { + return parser.data(); + } - parser.reset(new QCommandLineParser()); - parser->setApplicationDescription(SearchPanel::tr("Full-text search.")); + parser.reset(new QCommandLineParser()); + parser->setApplicationDescription(SearchPanel::tr("Full-text search.")); - parser->addPositionalArgument("keywords", SearchPanel::tr("Keywords to search for.")); + parser->addPositionalArgument("keywords", SearchPanel::tr("Keywords to search for.")); - addSearchOptionsToCommand(parser.data()); + addSearchOptionsToCommand(parser.data()); - return parser.data(); + return parser.data(); } -void SearchToken::addSearchOptionsToCommand(QCommandLineParser *p_parser) -{ - QCommandLineOption caseSensitiveOpt(QStringList() << "c" << "case-sensitive", SearchPanel::tr("Search in case sensitive.")); - p_parser->addOption(caseSensitiveOpt); +void SearchToken::addSearchOptionsToCommand(QCommandLineParser *p_parser) { + QCommandLineOption caseSensitiveOpt(QStringList() << "c" << "case-sensitive", + SearchPanel::tr("Search in case sensitive.")); + p_parser->addOption(caseSensitiveOpt); - QCommandLineOption regularExpressionOpt(QStringList() << "r" << "regular-expression", SearchPanel::tr("Search by regular expression.")); - p_parser->addOption(regularExpressionOpt); + QCommandLineOption regularExpressionOpt(QStringList() << "r" << "regular-expression", + SearchPanel::tr("Search by regular expression.")); + p_parser->addOption(regularExpressionOpt); - QCommandLineOption wholeWordOnlyOpt(QStringList() << "w" << "whole-word-only", SearchPanel::tr("Search whole word only.")); - p_parser->addOption(wholeWordOnlyOpt); + QCommandLineOption wholeWordOnlyOpt(QStringList() << "w" << "whole-word-only", + SearchPanel::tr("Search whole word only.")); + p_parser->addOption(wholeWordOnlyOpt); - QCommandLineOption fuzzySearchOpt(QStringList() << "f" << "fuzzy-search", SearchPanel::tr("Do a fuzzy search (not applicable to content search).")); - p_parser->addOption(fuzzySearchOpt); + QCommandLineOption fuzzySearchOpt( + QStringList() << "f" << "fuzzy-search", + SearchPanel::tr("Do a fuzzy search (not applicable to content search).")); + p_parser->addOption(fuzzySearchOpt); - QCommandLineOption orOpt(QStringList() << "o" << "or", SearchPanel::tr("Do an OR combination of keywords.")); - p_parser->addOption(orOpt); + QCommandLineOption orOpt(QStringList() << "o" << "or", + SearchPanel::tr("Do an OR combination of keywords.")); + p_parser->addOption(orOpt); } -bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token) -{ +bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token) { - p_token.clear(); + p_token.clear(); - if (p_keyword.isEmpty()) { - return false; - } + if (p_keyword.isEmpty()) { + return false; + } - auto parser = getCommandLineParser(); + auto parser = getCommandLineParser(); - auto caseSensitivity = p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; - bool isRegularExpression = p_options & FindOption::RegularExpression; - bool isWholeWordOnly = p_options & FindOption::WholeWordOnly; - bool isFuzzySearch = p_options & FindOption::FuzzySearch; + auto caseSensitivity = + p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; + bool isRegularExpression = p_options & FindOption::RegularExpression; + bool isWholeWordOnly = p_options & FindOption::WholeWordOnly; + bool isFuzzySearch = p_options & FindOption::FuzzySearch; - auto args = ProcessUtils::parseCombinedArgString(p_keyword); - // The parser needs the first arg to be the application name. - args.prepend("vnotex"); - if (!parser->parse(args)) - { - return false; - } - - if (parser->isSet("c")) { - caseSensitivity = Qt::CaseSensitive; - } - if (parser->isSet("r")) { - isRegularExpression = true; - } - if (parser->isSet("w")) { - isWholeWordOnly = true; - } - if (parser->isSet("f")) { - isFuzzySearch = true; - } - - args = parser->positionalArguments(); - if (args.isEmpty()) { - return false; + auto args = ProcessUtils::parseCombinedArgString(p_keyword); + // The parser needs the first arg to be the application name. + args.prepend("vnotex"); + if (!parser->parse(args)) { + return false; + } + + if (parser->isSet("c")) { + caseSensitivity = Qt::CaseSensitive; + } + if (parser->isSet("r")) { + isRegularExpression = true; + } + if (parser->isSet("w")) { + isWholeWordOnly = true; + } + if (parser->isSet("f")) { + isFuzzySearch = true; + } + + args = parser->positionalArguments(); + if (args.isEmpty()) { + return false; + } + + p_token.m_caseSensitivity = caseSensitivity; + if (isRegularExpression || isWholeWordOnly || isFuzzySearch) { + p_token.m_type = Type::RegularExpression; + } else { + p_token.m_type = Type::PlainText; + } + p_token.m_operator = parser->isSet("o") ? Operator::Or : Operator::And; + + auto patternOptions = caseSensitivity == Qt::CaseInsensitive + ? QRegularExpression::CaseInsensitiveOption + : QRegularExpression::NoPatternOption; + for (const auto &ar : args) { + if (ar.isEmpty()) { + continue; } - p_token.m_caseSensitivity = caseSensitivity; - if (isRegularExpression || isWholeWordOnly || isFuzzySearch) { - p_token.m_type = Type::RegularExpression; + if (isRegularExpression) { + p_token.append(QRegularExpression(ar, patternOptions)); + } else if (isFuzzySearch) { + // ABC -> *A*B*C*. + QString wildcardText(ar.size() * 2 + 1, '*'); + for (int i = 0, j = 1; i < ar.size(); ++i, j += 2) { + wildcardText[j] = ar[i]; + } + + p_token.append(QRegularExpression( + QRegularExpression::wildcardToRegularExpression(wildcardText), patternOptions)); + } else if (isWholeWordOnly) { + auto pattern = QRegularExpression::escape(ar); + pattern = "\\b" + pattern + "\\b"; + p_token.append(QRegularExpression(pattern, patternOptions)); } else { - p_token.m_type = Type::PlainText; - } - p_token.m_operator = parser->isSet("o") ? Operator::Or : Operator::And; - - auto patternOptions = caseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption - : QRegularExpression::NoPatternOption; - for (const auto &ar : args) { - if (ar.isEmpty()) { - continue; - } - - if (isRegularExpression) { - p_token.append(QRegularExpression(ar, patternOptions)); - } else if (isFuzzySearch) { - // ABC -> *A*B*C*. - QString wildcardText(ar.size() * 2 + 1, '*'); - for (int i = 0, j = 1; i < ar.size(); ++i, j += 2) { - wildcardText[j] = ar[i]; - } - - p_token.append(QRegularExpression(QRegularExpression::wildcardToRegularExpression(wildcardText), - patternOptions)); - } else if (isWholeWordOnly) { - auto pattern = QRegularExpression::escape(ar); - pattern = "\\b" + pattern + "\\b"; - p_token.append(QRegularExpression(pattern, patternOptions)); - } else { - p_token.append(ar); - } + p_token.append(ar); } + } - return !p_token.isEmpty(); + return !p_token.isEmpty(); } -QString SearchToken::getHelpText() -{ - auto parser = getCommandLineParser(); - auto text = parser->helpText(); - // Skip the first line containing the application name. - return text.mid(text.indexOf('\n') + 1); +QString SearchToken::getHelpText() { + auto parser = getCommandLineParser(); + auto text = parser->helpText(); + // Skip the first line containing the application name. + return text.mid(text.indexOf('\n') + 1); } -QPair SearchToken::toPatterns() const -{ - QPair ret; +QPair SearchToken::toPatterns() const { + QPair ret; - ret.second = m_caseSensitivity == Qt::CaseSensitive ? FindOption::CaseSensitive : FindOption::FindNone; - if (m_type == Type::RegularExpression) { - ret.second |= FindOption::RegularExpression; + ret.second = + m_caseSensitivity == Qt::CaseSensitive ? FindOption::CaseSensitive : FindOption::FindNone; + if (m_type == Type::RegularExpression) { + ret.second |= FindOption::RegularExpression; - for (const auto ® : m_regularExpressions) { - ret.first << reg.pattern(); - } - } else { - ret.first = m_keywords; + for (const auto ® : m_regularExpressions) { + ret.first << reg.pattern(); } + } else { + ret.first = m_keywords; + } - return ret; + return ret; } diff --git a/src/search/searchtoken.h b/src/search/searchtoken.h index 2d46e18990..fa2b5923bc 100644 --- a/src/search/searchtoken.h +++ b/src/search/searchtoken.h @@ -1,87 +1,77 @@ #ifndef SEARCHTOKEN_H #define SEARCHTOKEN_H -#include -#include -#include #include +#include #include +#include +#include #include class QCommandLineParser; -namespace vnotex -{ - class SearchToken - { - public: - enum class Type - { - PlainText, - RegularExpression - }; +namespace vnotex { +class SearchToken { +public: + enum class Type { PlainText, RegularExpression }; - enum class Operator - { - And, - Or - }; + enum class Operator { And, Or }; - void clear(); + void clear(); - void append(const QString &p_text); + void append(const QString &p_text); - void append(const QRegularExpression &p_regExp); + void append(const QRegularExpression &p_regExp); - // Whether @p_text is matched. - bool matched(const QString &p_text, QList *p_segments = nullptr) const; + // Whether @p_text is matched. + bool matched(const QString &p_text, QList *p_segments = nullptr) const; - int constraintSize() const; + int constraintSize() const; - bool isEmpty() const; + bool isEmpty() const; - bool shouldStartBatchMode() const; + bool shouldStartBatchMode() const; - // Batch Mode: use a list of text string to match the same token. - void startBatchMode(); + // Batch Mode: use a list of text string to match the same token. + void startBatchMode(); - // Match one string in batch mode. - // Return true if @p_text is matched. - bool matchedInBatchMode(const QString &p_text, QList *p_segments = nullptr); + // Match one string in batch mode. + // Return true if @p_text is matched. + bool matchedInBatchMode(const QString &p_text, QList *p_segments = nullptr); - bool readyToEndBatchMode() const; + bool readyToEndBatchMode() const; - void endBatchMode(); + void endBatchMode(); - QPair toPatterns() const; + QPair toPatterns() const; - // Compile tokens from keyword. - // Support some magic switchs in the keyword which will suppress the given options. - static bool compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token); + // Compile tokens from keyword. + // Support some magic switchs in the keyword which will suppress the given options. + static bool compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token); - static QString getHelpText(); + static QString getHelpText(); - static void addSearchOptionsToCommand(QCommandLineParser *p_parser); + static void addSearchOptionsToCommand(QCommandLineParser *p_parser); - private: - static QCommandLineParser *getCommandLineParser(); +private: + static QCommandLineParser *getCommandLineParser(); - Type m_type = Type::PlainText; + Type m_type = Type::PlainText; - Operator m_operator = Operator::And; + Operator m_operator = Operator::And; - Qt::CaseSensitivity m_caseSensitivity = Qt::CaseInsensitive; + Qt::CaseSensitivity m_caseSensitivity = Qt::CaseInsensitive; - QStringList m_keywords; + QStringList m_keywords; - QVector m_regularExpressions; + QVector m_regularExpressions; - // [i] is true only if m_keywords[i] or m_regularExpressions[i] is matched. - QBitArray m_matchedConstraintsInBatchMode; + // [i] is true only if m_keywords[i] or m_regularExpressions[i] is matched. + QBitArray m_matchedConstraintsInBatchMode; - int m_matchedConstraintsCountInBatchMode = 0; - }; -} + int m_matchedConstraintsCountInBatchMode = 0; +}; +} // namespace vnotex #endif // SEARCHTOKEN_H diff --git a/src/snippet/dynamicsnippet.cpp b/src/snippet/dynamicsnippet.cpp index 029fe0fc0f..62092c0958 100644 --- a/src/snippet/dynamicsnippet.cpp +++ b/src/snippet/dynamicsnippet.cpp @@ -4,28 +4,19 @@ using namespace vnotex; -DynamicSnippet::DynamicSnippet(const QString &p_name, - const QString &p_description, +DynamicSnippet::DynamicSnippet(const QString &p_name, const QString &p_description, const Callback &p_callback) - : Snippet(p_name, - p_description, - QString(), - Snippet::InvalidShortcut, - false, - QString(), + : Snippet(p_name, p_description, QString(), Snippet::InvalidShortcut, false, QString(), QString()), - m_callback(p_callback) -{ - setType(Type::Dynamic); - setReadOnly(true); + m_callback(p_callback) { + setType(Type::Dynamic); + setReadOnly(true); } -QString DynamicSnippet::apply(const QString &p_selectedText, - const QString &p_indentationSpaces, - int &p_cursorOffset) -{ - Q_UNUSED(p_indentationSpaces); - auto text = m_callback(p_selectedText); - p_cursorOffset = text.size(); - return text; +QString DynamicSnippet::apply(const QString &p_selectedText, const QString &p_indentationSpaces, + int &p_cursorOffset) { + Q_UNUSED(p_indentationSpaces); + auto text = m_callback(p_selectedText); + p_cursorOffset = text.size(); + return text; } diff --git a/src/snippet/dynamicsnippet.h b/src/snippet/dynamicsnippet.h index 371e598c46..78d72b44b5 100644 --- a/src/snippet/dynamicsnippet.h +++ b/src/snippet/dynamicsnippet.h @@ -5,26 +5,21 @@ #include -namespace vnotex -{ - // Snippet based on function. - // To replace the legacy Magic Word. - class DynamicSnippet : public Snippet - { - public: - typedef std::function Callback; +namespace vnotex { +// Snippet based on function. +// To replace the legacy Magic Word. +class DynamicSnippet : public Snippet { +public: + typedef std::function Callback; - DynamicSnippet(const QString &p_name, - const QString &p_description, - const Callback &p_callback); + DynamicSnippet(const QString &p_name, const QString &p_description, const Callback &p_callback); - QString apply(const QString &p_selectedText, - const QString &p_indentationSpaces, - int &p_cursorOffset) Q_DECL_OVERRIDE; + QString apply(const QString &p_selectedText, const QString &p_indentationSpaces, + int &p_cursorOffset) Q_DECL_OVERRIDE; - private: - Callback m_callback; - }; -} +private: + Callback m_callback; +}; +} // namespace vnotex #endif // DYNAMICSNIPPET_H diff --git a/src/snippet/snippet.cpp b/src/snippet/snippet.cpp index 5c2c3e5eea..711cc78837 100644 --- a/src/snippet/snippet.cpp +++ b/src/snippet/snippet.cpp @@ -10,174 +10,119 @@ const QString Snippet::c_defaultCursorMark = QStringLiteral("@@"); const QString Snippet::c_defaultSelectionMark = QStringLiteral("$$"); -Snippet::Snippet(const QString &p_name) - : m_name(p_name) -{ -} +Snippet::Snippet(const QString &p_name) : m_name(p_name) {} -Snippet::Snippet(const QString &p_name, - const QString &p_description, - const QString &p_content, - int p_shortcut, - bool p_indentAsFirstLine, - const QString &p_cursorMark, +Snippet::Snippet(const QString &p_name, const QString &p_description, const QString &p_content, + int p_shortcut, bool p_indentAsFirstLine, const QString &p_cursorMark, const QString &p_selectionMark) - : m_type(Type::Text), - m_name(p_name), - m_description(p_description), - m_content(p_content), - m_shortcut(p_shortcut), - m_indentAsFirstLine(p_indentAsFirstLine), - m_cursorMark(p_cursorMark), - m_selectionMark(p_selectionMark) -{ -} + : m_type(Type::Text), m_name(p_name), m_description(p_description), m_content(p_content), + m_shortcut(p_shortcut), m_indentAsFirstLine(p_indentAsFirstLine), m_cursorMark(p_cursorMark), + m_selectionMark(p_selectionMark) {} -QJsonObject Snippet::toJson() const -{ - QJsonObject obj; +QJsonObject Snippet::toJson() const { + QJsonObject obj; - obj[QStringLiteral("type")] = static_cast(m_type); - obj[QStringLiteral("description")] = m_description; - obj[QStringLiteral("content")] = m_content; - obj[QStringLiteral("shortcut")] = m_shortcut; - obj[QStringLiteral("indent_as_first_line")] = m_indentAsFirstLine; - obj[QStringLiteral("cursor_mark")] = m_cursorMark; - obj[QStringLiteral("selection_mark")] = m_selectionMark; + obj[QStringLiteral("type")] = static_cast(m_type); + obj[QStringLiteral("description")] = m_description; + obj[QStringLiteral("content")] = m_content; + obj[QStringLiteral("shortcut")] = m_shortcut; + obj[QStringLiteral("indent_as_first_line")] = m_indentAsFirstLine; + obj[QStringLiteral("cursor_mark")] = m_cursorMark; + obj[QStringLiteral("selection_mark")] = m_selectionMark; - return obj; + return obj; } -void Snippet::fromJson(const QJsonObject &p_jobj) -{ - m_type = static_cast(p_jobj[QStringLiteral("type")].toInt()); - m_description = p_jobj[QStringLiteral("description")].toString(); - m_content = p_jobj[QStringLiteral("content")].toString(); - m_shortcut = p_jobj[QStringLiteral("shortcut")].toInt(); - m_indentAsFirstLine = p_jobj[QStringLiteral("indent_as_first_line")].toBool(); - m_cursorMark = p_jobj[QStringLiteral("cursor_mark")].toString(); - m_selectionMark = p_jobj[QStringLiteral("selection_mark")].toString(); +void Snippet::fromJson(const QJsonObject &p_jobj) { + m_type = static_cast(p_jobj[QStringLiteral("type")].toInt()); + m_description = p_jobj[QStringLiteral("description")].toString(); + m_content = p_jobj[QStringLiteral("content")].toString(); + m_shortcut = p_jobj[QStringLiteral("shortcut")].toInt(); + m_indentAsFirstLine = p_jobj[QStringLiteral("indent_as_first_line")].toBool(); + m_cursorMark = p_jobj[QStringLiteral("cursor_mark")].toString(); + m_selectionMark = p_jobj[QStringLiteral("selection_mark")].toString(); } -bool Snippet::isValid() const -{ - return !m_name.isEmpty() && m_type != Type::Invalid; -} +bool Snippet::isValid() const { return !m_name.isEmpty() && m_type != Type::Invalid; } -const QString &Snippet::getName() const -{ - return m_name; -} +const QString &Snippet::getName() const { return m_name; } -int Snippet::getShortcut() const -{ - return m_shortcut; -} +int Snippet::getShortcut() const { return m_shortcut; } -QString Snippet::getShortcutString() const -{ - if (m_shortcut == InvalidShortcut) { - return QString(); - } else { - return Utils::intToString(m_shortcut, 2); - } +QString Snippet::getShortcutString() const { + if (m_shortcut == InvalidShortcut) { + return QString(); + } else { + return Utils::intToString(m_shortcut, 2); + } } -Snippet::Type Snippet::getType() const -{ - return m_type; -} +Snippet::Type Snippet::getType() const { return m_type; } -const QString &Snippet::getCursorMark() const -{ - return m_cursorMark; -} +const QString &Snippet::getCursorMark() const { return m_cursorMark; } -const QString &Snippet::getSelectionMark() const -{ - return m_selectionMark; -} +const QString &Snippet::getSelectionMark() const { return m_selectionMark; } -bool Snippet::isIndentAsFirstLineEnabled() const -{ - return m_indentAsFirstLine; -} +bool Snippet::isIndentAsFirstLineEnabled() const { return m_indentAsFirstLine; } -const QString &Snippet::getContent() const -{ - return m_content; -} +const QString &Snippet::getContent() const { return m_content; } -const QString &Snippet::getDescription() const -{ - return m_description; -} +const QString &Snippet::getDescription() const { return m_description; } -QString Snippet::apply(const QString &p_selectedText, - const QString &p_indentationSpaces, - int &p_cursorOffset) -{ - QString appliedText; - p_cursorOffset = 0; - if (!isValid() || m_content.isEmpty()) { - qWarning() << "failed to apply an invalid snippet" << m_name; - return appliedText; - } +QString Snippet::apply(const QString &p_selectedText, const QString &p_indentationSpaces, + int &p_cursorOffset) { + QString appliedText; + p_cursorOffset = 0; + if (!isValid() || m_content.isEmpty()) { + qWarning() << "failed to apply an invalid snippet" << m_name; + return appliedText; + } - // Indent each line after the first line. - if (m_indentAsFirstLine && !p_indentationSpaces.isEmpty()) { - auto lines = m_content.split(QLatin1Char('\n')); - Q_ASSERT(!lines.isEmpty()); - appliedText = lines[0]; - for (int i = 1; i < lines.size(); ++i) { - appliedText += QLatin1Char('\n') + p_indentationSpaces + lines[i]; - } - } else { - appliedText = m_content; + // Indent each line after the first line. + if (m_indentAsFirstLine && !p_indentationSpaces.isEmpty()) { + auto lines = m_content.split(QLatin1Char('\n')); + Q_ASSERT(!lines.isEmpty()); + appliedText = lines[0]; + for (int i = 1; i < lines.size(); ++i) { + appliedText += QLatin1Char('\n') + p_indentationSpaces + lines[i]; + } + } else { + appliedText = m_content; + } + + // Find the cursor mark and break the content. + QString secondPart; + if (!m_cursorMark.isEmpty()) { + QStringList parts = appliedText.split(m_cursorMark); + Q_ASSERT(!parts.isEmpty()); + if (parts.size() > 2) { + qWarning() << "failed to apply snippet with multiple cursor marks" << m_name; + return QString(); } - // Find the cursor mark and break the content. - QString secondPart; - if (!m_cursorMark.isEmpty()) { - QStringList parts = appliedText.split(m_cursorMark); - Q_ASSERT(!parts.isEmpty()); - if (parts.size() > 2) { - qWarning() << "failed to apply snippet with multiple cursor marks" << m_name; - return QString(); - } - - appliedText = parts[0]; - if (parts.size() == 2) { - secondPart = parts[1]; - } + appliedText = parts[0]; + if (parts.size() == 2) { + secondPart = parts[1]; } + } - // Replace the selection mark. - if (!m_selectionMark.isEmpty()) { - if (!appliedText.isEmpty()) { - appliedText.replace(m_selectionMark, p_selectedText); - } + // Replace the selection mark. + if (!m_selectionMark.isEmpty()) { + if (!appliedText.isEmpty()) { + appliedText.replace(m_selectionMark, p_selectedText); + } - if (!secondPart.isEmpty()) { - secondPart.replace(m_selectionMark, p_selectedText); - } + if (!secondPart.isEmpty()) { + secondPart.replace(m_selectionMark, p_selectedText); } + } - p_cursorOffset = appliedText.size(); - return appliedText + secondPart; + p_cursorOffset = appliedText.size(); + return appliedText + secondPart; } -bool Snippet::isReadOnly() const -{ - return m_readOnly; -} +bool Snippet::isReadOnly() const { return m_readOnly; } -void Snippet::setReadOnly(bool p_readOnly) -{ - m_readOnly = p_readOnly; -} +void Snippet::setReadOnly(bool p_readOnly) { m_readOnly = p_readOnly; } -void Snippet::setType(Type p_type) -{ - m_type = p_type; -} +void Snippet::setType(Type p_type) { m_type = p_type; } diff --git a/src/snippet/snippet.h b/src/snippet/snippet.h index 5310436e6d..aa7b661324 100644 --- a/src/snippet/snippet.h +++ b/src/snippet/snippet.h @@ -1,103 +1,91 @@ #ifndef SNIPPET_H #define SNIPPET_H -#include #include +#include -namespace vnotex -{ - class Snippet - { - public: - enum class Type - { - Invalid, - Text, - Script, - Dynamic - }; +namespace vnotex { +class Snippet { +public: + enum class Type { Invalid, Text, Script, Dynamic }; - enum { InvalidShortcut = -1 }; + enum { InvalidShortcut = -1 }; - Snippet() = default; + Snippet() = default; - explicit Snippet(const QString &p_name); + explicit Snippet(const QString &p_name); - Snippet(const QString &p_name, - const QString &p_description, - const QString &p_content, - int p_shortcut, - bool p_indentAsFirstLine, - const QString &p_cursorMark, - const QString &p_selectionMark); + Snippet(const QString &p_name, const QString &p_description, const QString &p_content, + int p_shortcut, bool p_indentAsFirstLine, const QString &p_cursorMark, + const QString &p_selectionMark); - virtual ~Snippet() = default; + virtual ~Snippet() = default; - QJsonObject toJson() const; - void fromJson(const QJsonObject &p_jobj); + QJsonObject toJson() const; + void fromJson(const QJsonObject &p_jobj); - bool isValid() const; + bool isValid() const; - bool isReadOnly() const; + bool isReadOnly() const; - void setReadOnly(bool p_readOnly); + void setReadOnly(bool p_readOnly); - const QString &getName() const; + const QString &getName() const; - const QString &getDescription() const; + const QString &getDescription() const; - Type getType() const; + Type getType() const; - int getShortcut() const; + int getShortcut() const; - QString getShortcutString() const; + QString getShortcutString() const; - const QString &getCursorMark() const; + const QString &getCursorMark() const; - const QString &getSelectionMark() const; + const QString &getSelectionMark() const; - bool isIndentAsFirstLineEnabled() const; + bool isIndentAsFirstLineEnabled() const; - const QString &getContent() const; + const QString &getContent() const; - // Apply the snippet to generate result text. - virtual QString apply(const QString &p_selectedText, - const QString &p_indentationSpaces, - int &p_cursorOffset); + // Apply the snippet to generate result text. + virtual QString apply(const QString &p_selectedText, const QString &p_indentationSpaces, + int &p_cursorOffset); - static const QString c_defaultCursorMark; + static const QString c_defaultCursorMark; - static const QString c_defaultSelectionMark; + static const QString c_defaultSelectionMark; - protected: - void setType(Type p_type); +protected: + void setType(Type p_type); - private: - bool m_readOnly = false; +private: + bool m_readOnly = false; - Type m_type = Type::Invalid; + Type m_type = Type::Invalid; - // Name (and file name) of the snippet. - // To avoid mixed with shortcut, the name should not contain digits. - QString m_name; + // Name (and file name) of the snippet. + // To avoid mixed with shortcut, the name should not contain digits. + QString m_name; - QString m_description; + QString m_description; - // Content of the snippet if it is Text. - // Embedded snippet is supported. - QString m_content; + // Content of the snippet if it is Text. + // Embedded snippet is supported. + QString m_content; - // Shortcut digits of this snippet. - int m_shortcut = InvalidShortcut; + // Shortcut digits of this snippet. + int m_shortcut = InvalidShortcut; - bool m_indentAsFirstLine = false; + bool m_indentAsFirstLine = false; - // CursorMark is a mark string to indicate the cursor position after applying the snippet. - QString m_cursorMark; + // CursorMark is a mark string to indicate the cursor position after applying the snippet. + QString m_cursorMark; - // SelectionMark is a mark string which will be replaced by the selected text before applying the snippet after a snippet is applied. - QString m_selectionMark; - }; -} + // SelectionMark is a mark string which will be replaced by the selected text before applying the + // snippet after a snippet is applied. + QString m_selectionMark; +}; +} // namespace vnotex #endif // SNIPPET_H diff --git a/src/snippet/snippetmgr.cpp b/src/snippet/snippetmgr.cpp index 4b9cbf6ec3..0452e65b43 100644 --- a/src/snippet/snippetmgr.cpp +++ b/src/snippet/snippetmgr.cpp @@ -1,457 +1,376 @@ #include "snippetmgr.h" -#include -#include +#include #include +#include #include +#include +#include #include #include -#include -#include -#include #include +#include #include -#include #include -#include +#include #include #include +#include using namespace vnotex; const QChar SnippetMgr::c_snippetSymbolGuard = QLatin1Char('%'); -const QString SnippetMgr::c_snippetSymbolRegExp = QStringLiteral("%1([^%]+)%1").arg(c_snippetSymbolGuard); +const QString SnippetMgr::c_snippetSymbolRegExp = + QStringLiteral("%1([^%]+)%1").arg(c_snippetSymbolGuard); -SnippetMgr::SnippetMgr() -{ - loadSnippets(); -} +SnippetMgr::SnippetMgr() { loadSnippets(); } -QString SnippetMgr::getSnippetFolder() const -{ - return ConfigMgr::getInst().getUserSnippetFolder(); -} +QString SnippetMgr::getSnippetFolder() const { return ConfigMgr::getInst().getUserSnippetFolder(); } -const QVector> &SnippetMgr::getSnippets() const -{ - return m_snippets; -} +const QVector> &SnippetMgr::getSnippets() const { return m_snippets; } -void SnippetMgr::loadSnippets() -{ - Q_ASSERT(m_snippets.isEmpty()); +void SnippetMgr::loadSnippets() { + Q_ASSERT(m_snippets.isEmpty()); - auto builtInSnippets = loadBuiltInSnippets(); + auto builtInSnippets = loadBuiltInSnippets(); - QSet names; - for (const auto &snippet : builtInSnippets) { - Q_ASSERT(!names.contains(snippet->getName())); - names.insert(snippet->getName()); - } + QSet names; + for (const auto &snippet : builtInSnippets) { + Q_ASSERT(!names.contains(snippet->getName())); + names.insert(snippet->getName()); + } + + // Look for all the *.json files. + QDir dir(getSnippetFolder()); + dir.setFilter(QDir::Files | QDir::NoSymLinks); + const auto jsonFiles = dir.entryList(QStringList() << "*.json"); + for (const auto &jsonFile : jsonFiles) { + auto snip = loadSnippet(dir.filePath(jsonFile)); + if (snip->isValid()) { + if (names.contains(snip->getName())) { + qWarning() << "skip loading snippet with name conflict" << snip->getName() << jsonFile; + continue; + } - // Look for all the *.json files. - QDir dir(getSnippetFolder()); - dir.setFilter(QDir::Files | QDir::NoSymLinks); - const auto jsonFiles = dir.entryList(QStringList() << "*.json"); - for (const auto &jsonFile : jsonFiles) { - auto snip = loadSnippet(dir.filePath(jsonFile)); - if (snip->isValid()) { - if (names.contains(snip->getName())) { - qWarning() << "skip loading snippet with name conflict" << snip->getName() << jsonFile; - continue; - } - - names.insert(snip->getName()); - - addOneSnippet(snip); - } + names.insert(snip->getName()); + + addOneSnippet(snip); } + } - m_snippets.append(builtInSnippets); + m_snippets.append(builtInSnippets); - qDebug() << "loaded" << m_snippets.size() << "snippets"; + qDebug() << "loaded" << m_snippets.size() << "snippets"; } -QVector SnippetMgr::getAvailableShortcuts(int p_exemption) const -{ - QVector shortcuts; +QVector SnippetMgr::getAvailableShortcuts(int p_exemption) const { + QVector shortcuts; - for (int i = 0; i < 100; ++i) { - if (!m_shortcutToSnippet.contains(i) || i == p_exemption) { - shortcuts.push_back(i); - } + for (int i = 0; i < 100; ++i) { + if (!m_shortcutToSnippet.contains(i) || i == p_exemption) { + shortcuts.push_back(i); } + } - return shortcuts; + return shortcuts; } -QSharedPointer SnippetMgr::find(const QString &p_name, Qt::CaseSensitivity p_cs) const -{ - if (p_cs == Qt::CaseInsensitive) { - const auto lowerName = p_name.toLower(); - for (const auto &snip : m_snippets) { - if (snip->getName().toLower() == lowerName) { - return snip; - } - } - } else { - for (const auto &snip : m_snippets) { - if (snip->getName() == p_name) { - return snip; - } - } +QSharedPointer SnippetMgr::find(const QString &p_name, Qt::CaseSensitivity p_cs) const { + if (p_cs == Qt::CaseInsensitive) { + const auto lowerName = p_name.toLower(); + for (const auto &snip : m_snippets) { + if (snip->getName().toLower() == lowerName) { + return snip; + } + } + } else { + for (const auto &snip : m_snippets) { + if (snip->getName() == p_name) { + return snip; + } } + } - return nullptr; + return nullptr; } -void SnippetMgr::addSnippet(const QSharedPointer &p_snippet) -{ - Q_ASSERT(!find(p_snippet->getName(), Qt::CaseInsensitive)); - saveSnippet(p_snippet); - addOneSnippet(p_snippet); +void SnippetMgr::addSnippet(const QSharedPointer &p_snippet) { + Q_ASSERT(!find(p_snippet->getName(), Qt::CaseInsensitive)); + saveSnippet(p_snippet); + addOneSnippet(p_snippet); } -void SnippetMgr::addOneSnippet(const QSharedPointer &p_snippet) -{ - m_snippets.push_back(p_snippet); - addSnippetToShortcutMap(p_snippet); +void SnippetMgr::addOneSnippet(const QSharedPointer &p_snippet) { + m_snippets.push_back(p_snippet); + addSnippetToShortcutMap(p_snippet); } -QSharedPointer SnippetMgr::loadSnippet(const QString &p_snippetFile) const -{ - const auto obj = FileUtils::readJsonFile(p_snippetFile); - auto snip = QSharedPointer::create(QFileInfo(p_snippetFile).completeBaseName()); - snip->fromJson(obj); - return snip; +QSharedPointer SnippetMgr::loadSnippet(const QString &p_snippetFile) const { + const auto obj = FileUtils::readJsonFile(p_snippetFile); + auto snip = QSharedPointer::create(QFileInfo(p_snippetFile).completeBaseName()); + snip->fromJson(obj); + return snip; } -void SnippetMgr::saveSnippet(const QSharedPointer &p_snippet) -{ - Q_ASSERT(p_snippet->isValid() - && !p_snippet->isReadOnly() - && p_snippet->getType() != Snippet::Type::Dynamic); - FileUtils::writeFile(getSnippetFile(p_snippet), p_snippet->toJson()); +void SnippetMgr::saveSnippet(const QSharedPointer &p_snippet) { + Q_ASSERT(p_snippet->isValid() && !p_snippet->isReadOnly() && + p_snippet->getType() != Snippet::Type::Dynamic); + FileUtils::writeFile(getSnippetFile(p_snippet), p_snippet->toJson()); } -void SnippetMgr::removeSnippet(const QString &p_name) -{ - auto snippet = find(p_name); - if (!snippet || snippet->isReadOnly()) { - return; - } +void SnippetMgr::removeSnippet(const QString &p_name) { + auto snippet = find(p_name); + if (!snippet || snippet->isReadOnly()) { + return; + } - removeSnippetFromShortcutMap(snippet); - m_snippets.removeAll(snippet); - FileUtils::removeFile(getSnippetFile(snippet)); + removeSnippetFromShortcutMap(snippet); + m_snippets.removeAll(snippet); + FileUtils::removeFile(getSnippetFile(snippet)); } -QString SnippetMgr::getSnippetFile(const QSharedPointer &p_snippet) const -{ - return PathUtils::concatenateFilePath(getSnippetFolder(), p_snippet->getName() + QStringLiteral(".json")); +QString SnippetMgr::getSnippetFile(const QSharedPointer &p_snippet) const { + return PathUtils::concatenateFilePath(getSnippetFolder(), + p_snippet->getName() + QStringLiteral(".json")); } -void SnippetMgr::updateSnippet(const QString &p_name, const QSharedPointer &p_snippet) -{ - auto snippet = find(p_name); - Q_ASSERT(snippet); +void SnippetMgr::updateSnippet(const QString &p_name, const QSharedPointer &p_snippet) { + auto snippet = find(p_name); + Q_ASSERT(snippet); - // If renamed, remove the old file first. - if (p_name != p_snippet->getName()) { - FileUtils::removeFile(getSnippetFile(snippet)); - } + // If renamed, remove the old file first. + if (p_name != p_snippet->getName()) { + FileUtils::removeFile(getSnippetFile(snippet)); + } - removeSnippetFromShortcutMap(snippet); + removeSnippetFromShortcutMap(snippet); - *snippet = *p_snippet; - saveSnippet(snippet); + *snippet = *p_snippet; + saveSnippet(snippet); - addSnippetToShortcutMap(snippet); + addSnippetToShortcutMap(snippet); } -void SnippetMgr::removeSnippetFromShortcutMap(const QSharedPointer &p_snippet) -{ - if (p_snippet->getShortcut() != Snippet::InvalidShortcut) { - auto iter = m_shortcutToSnippet.find(p_snippet->getShortcut()); - Q_ASSERT(iter != m_shortcutToSnippet.end()); - if (iter.value() == p_snippet) { - // There may exist conflict in shortcut. - m_shortcutToSnippet.erase(iter); - } +void SnippetMgr::removeSnippetFromShortcutMap(const QSharedPointer &p_snippet) { + if (p_snippet->getShortcut() != Snippet::InvalidShortcut) { + auto iter = m_shortcutToSnippet.find(p_snippet->getShortcut()); + Q_ASSERT(iter != m_shortcutToSnippet.end()); + if (iter.value() == p_snippet) { + // There may exist conflict in shortcut. + m_shortcutToSnippet.erase(iter); } + } } -void SnippetMgr::addSnippetToShortcutMap(const QSharedPointer &p_snippet) -{ - if (p_snippet->getShortcut() != Snippet::InvalidShortcut) { - m_shortcutToSnippet.insert(p_snippet->getShortcut(), p_snippet); - } +void SnippetMgr::addSnippetToShortcutMap(const QSharedPointer &p_snippet) { + if (p_snippet->getShortcut() != Snippet::InvalidShortcut) { + m_shortcutToSnippet.insert(p_snippet->getShortcut(), p_snippet); + } } -void SnippetMgr::applySnippet(const QString &p_name, - vte::VTextEdit *p_textEdit, - const OverrideMap &p_overrides) const -{ - auto snippet = find(p_name); - if (!snippet) { - return; +void SnippetMgr::applySnippet(const QString &p_name, vte::VTextEdit *p_textEdit, + const OverrideMap &p_overrides) const { + auto snippet = find(p_name); + if (!snippet) { + return; + } + Q_ASSERT(snippet->isValid()); + + auto cursor = p_textEdit->textCursor(); + cursor.beginEditBlock(); + + // Get selected text. + const auto selectedText = p_textEdit->selectedText(); + p_textEdit->removeSelectedText(); + + QString appliedText; + int cursorOffset = 0; + + auto it = p_overrides.find(p_name); + if (it != p_overrides.end()) { + appliedText = it.value(); + cursorOffset = appliedText.size(); + } else { + // Fetch indentation of first line. + QString indentationSpaces; + if (snippet->isIndentAsFirstLineEnabled()) { + indentationSpaces = vte::TextEditUtils::fetchIndentationSpaces(cursor.block()); } - Q_ASSERT(snippet->isValid()); - auto cursor = p_textEdit->textCursor(); - cursor.beginEditBlock(); + appliedText = snippet->apply(selectedText, indentationSpaces, cursorOffset); + appliedText = applySnippetBySymbol(appliedText, selectedText, cursorOffset, p_overrides); + } + + const int beforePos = cursor.position(); + cursor.insertText(appliedText); + cursor.setPosition(beforePos + cursorOffset); + + cursor.endEditBlock(); + p_textEdit->setTextCursor(cursor); +} + +QString SnippetMgr::applySnippetBySymbol(const QString &p_content, + const OverrideMap &p_overrides) const { + int offset = 0; + return applySnippetBySymbol(p_content, QString(), offset, p_overrides); +} + +QString SnippetMgr::applySnippetBySymbol(const QString &p_content, const QString &p_selectedText, + int &p_cursorOffset, + const OverrideMap &p_overrides) const { + QString content(p_content); + + int maxTimesAtSamePos = 100; + + QRegularExpression regExp(c_snippetSymbolRegExp); + int pos = 0; + while (pos < content.size()) { + QRegularExpressionMatch match; + int idx = content.indexOf(regExp, pos, &match); + if (idx == -1) { + break; + } - // Get selected text. - const auto selectedText = p_textEdit->selectedText(); - p_textEdit->removeSelectedText(); + const auto snippetName = match.captured(1); + auto snippet = find(snippetName); + if (!snippet) { + // Skip it. + pos = idx + match.capturedLength(0); + continue; + } - QString appliedText; - int cursorOffset = 0; + QString afterText; - auto it = p_overrides.find(p_name); + auto it = p_overrides.find(snippetName); if (it != p_overrides.end()) { - appliedText = it.value(); - cursorOffset = appliedText.size(); + afterText = it.value(); } else { - // Fetch indentation of first line. - QString indentationSpaces; - if (snippet->isIndentAsFirstLineEnabled()) { - indentationSpaces = vte::TextEditUtils::fetchIndentationSpaces(cursor.block()); - } - - appliedText = snippet->apply(selectedText, indentationSpaces, cursorOffset); - appliedText = applySnippetBySymbol(appliedText, selectedText, cursorOffset, p_overrides); - } + const auto indentationSpaces = + vte::TextUtils::fetchIndentationSpacesInMultiLines(content, idx); - const int beforePos = cursor.position(); - cursor.insertText(appliedText); - cursor.setPosition(beforePos + cursorOffset); + // Ignore the cursor mark. + int ignoredCursorOffset = 0; + afterText = snippet->apply(p_selectedText, indentationSpaces, ignoredCursorOffset); + } - cursor.endEditBlock(); - p_textEdit->setTextCursor(cursor); -} + content.replace(idx, match.capturedLength(0), afterText); -QString SnippetMgr::applySnippetBySymbol(const QString &p_content, - const OverrideMap &p_overrides) const -{ - int offset = 0; - return applySnippetBySymbol(p_content, QString(), offset, p_overrides); -} + // Maintain the cursor offset. + if (p_cursorOffset > idx) { + if (p_cursorOffset < idx + match.capturedLength(0)) { + p_cursorOffset = idx; + } else { + p_cursorOffset += (afterText.size() - match.capturedLength(0)); + } + } -QString SnippetMgr::applySnippetBySymbol(const QString &p_content, - const QString &p_selectedText, - int &p_cursorOffset, - const OverrideMap &p_overrides) const -{ - QString content(p_content); - - int maxTimesAtSamePos = 100; - - QRegularExpression regExp(c_snippetSymbolRegExp); - int pos = 0; - while (pos < content.size()) { - QRegularExpressionMatch match; - int idx = content.indexOf(regExp, pos, &match); - if (idx == -1) { - break; - } - - const auto snippetName = match.captured(1); - auto snippet = find(snippetName); - if (!snippet) { - // Skip it. - pos = idx + match.capturedLength(0); - continue; - } - - QString afterText; - - auto it = p_overrides.find(snippetName); - if (it != p_overrides.end()) { - afterText = it.value(); - } else { - const auto indentationSpaces = vte::TextUtils::fetchIndentationSpacesInMultiLines(content, idx); - - // Ignore the cursor mark. - int ignoredCursorOffset = 0; - afterText = snippet->apply(p_selectedText, indentationSpaces, ignoredCursorOffset); - } - - content.replace(idx, match.capturedLength(0), afterText); - - // Maintain the cursor offset. - if (p_cursorOffset > idx) { - if (p_cursorOffset < idx + match.capturedLength(0)) { - p_cursorOffset = idx; - } else { - p_cursorOffset += (afterText.size() - match.capturedLength(0)); - } - } - - // @afterText may still contains snippet symbol. - if (pos == idx) { - if (--maxTimesAtSamePos == 0) { - break; - } - } else { - maxTimesAtSamePos = 100; - } - pos = idx; + // @afterText may still contains snippet symbol. + if (pos == idx) { + if (--maxTimesAtSamePos == 0) { + break; + } + } else { + maxTimesAtSamePos = 100; } + pos = idx; + } - return content; + return content; } // Used as the function template for some date/time related dynamic snippets. -static QString formattedDateTime(const QString &p_format) -{ - return QDateTime::currentDateTime().toString(p_format); +static QString formattedDateTime(const QString &p_format) { + return QDateTime::currentDateTime().toString(p_format); } -QVector> SnippetMgr::loadBuiltInSnippets() const -{ - QVector> snippets; - - addDynamicSnippet(snippets, - "d", - tr("the day as number without a leading zero (`1` to `31`)"), - std::bind(formattedDateTime, "d")); - addDynamicSnippet(snippets, - "dd", - tr("the day as number with a leading zero (`01` to `31`)"), - std::bind(formattedDateTime, "dd")); - addDynamicSnippet(snippets, - "ddd", - tr("the abbreviated localized day name (e.g. `Mon` to `Sun`)"), - std::bind(formattedDateTime, "ddd")); - addDynamicSnippet(snippets, - "dddd", - tr("the long localized day name (e.g. `Monday` to `Sunday`)"), - std::bind(formattedDateTime, "dddd")); - addDynamicSnippet(snippets, - "M", - tr("the month as number without a leading zero (`1` to `12`)"), - std::bind(formattedDateTime, "M")); - addDynamicSnippet(snippets, - "MM", - tr("the month as number with a leading zero (`01` to `12`)"), - std::bind(formattedDateTime, "MM")); - addDynamicSnippet(snippets, - "MMM", - tr("the abbreviated localized month name (e.g. `Jan` to `Dec`)"), - std::bind(formattedDateTime, "MMM")); - addDynamicSnippet(snippets, - "MMMM", - tr("the long localized month name (e.g. `January` to `December`)"), - std::bind(formattedDateTime, "MMMM")); - addDynamicSnippet(snippets, - "yy", - tr("the year as two digit numbers (`00` to `99`)"), - std::bind(formattedDateTime, "yy")); - addDynamicSnippet(snippets, - "yyyy", - tr("the year as four digit numbers"), - std::bind(formattedDateTime, "yyyy")); - addDynamicSnippet(snippets, - "w", - tr("the week number without a leading zero (`1` to `53`)"), - [](const QString &) { - return QString::number(QDate::currentDate().weekNumber()); - }); - addDynamicSnippet(snippets, - "ww", - tr("the week number with a leading zero (`01` to `53`)"), - [](const QString &) { - return Utils::intToString(QDate::currentDate().weekNumber(), 2); - }); - addDynamicSnippet(snippets, - "H", - tr("the hour without a leading zero (`0` to `23` even with AM/PM display)"), - std::bind(formattedDateTime, "H")); - addDynamicSnippet(snippets, - "HH", - tr("the hour with a leading zero (`00` to `23` even with AM/PM display)"), - std::bind(formattedDateTime, "HH")); - addDynamicSnippet(snippets, - "m", - tr("the minute without a leading zero (`0` to `59`)"), - std::bind(formattedDateTime, "m")); - addDynamicSnippet(snippets, - "mm", - tr("the minute with a leading zero (`00` to `59`)"), - std::bind(formattedDateTime, "mm")); - addDynamicSnippet(snippets, - "s", - tr("the second without a leading zero (`0` to `59`)"), - std::bind(formattedDateTime, "s")); - addDynamicSnippet(snippets, - "ss", - tr("the second with a leading zero (`00` to `59`)"), - std::bind(formattedDateTime, "ss")); - addDynamicSnippet(snippets, - "date", - tr("date (`2021-02-24`)"), - std::bind(formattedDateTime, "yyyy-MM-dd")); - addDynamicSnippet(snippets, - "da", - tr("the abbreviated date (`20210224`)"), - std::bind(formattedDateTime, "yyyyMMdd")); - addDynamicSnippet(snippets, - "time", - tr("time (`16:51:02`)"), - std::bind(formattedDateTime, "hh:mm:ss")); - addDynamicSnippet(snippets, - "datetime", - tr("date and time (`2021-02-24_16:51:02`)"), - std::bind(formattedDateTime, "yyyy-MM-dd_hh:mm:ss")); - - // These snippets need override to fill the real value. - // Check generateOverrides(). - addDynamicSnippet(snippets, - QStringLiteral("note"), - tr("name of current note"), - [](const QString &) { - return tr("[Value Not Available]"); - }); - addDynamicSnippet(snippets, - QStringLiteral("no"), - tr("complete base name of current note"), - [](const QString &) { - return tr("[Value Not Available]"); - }); - return snippets; +QVector> SnippetMgr::loadBuiltInSnippets() const { + QVector> snippets; + + addDynamicSnippet(snippets, "d", tr("the day as number without a leading zero (`1` to `31`)"), + std::bind(formattedDateTime, "d")); + addDynamicSnippet(snippets, "dd", tr("the day as number with a leading zero (`01` to `31`)"), + std::bind(formattedDateTime, "dd")); + addDynamicSnippet(snippets, "ddd", tr("the abbreviated localized day name (e.g. `Mon` to `Sun`)"), + std::bind(formattedDateTime, "ddd")); + addDynamicSnippet(snippets, "dddd", tr("the long localized day name (e.g. `Monday` to `Sunday`)"), + std::bind(formattedDateTime, "dddd")); + addDynamicSnippet(snippets, "M", tr("the month as number without a leading zero (`1` to `12`)"), + std::bind(formattedDateTime, "M")); + addDynamicSnippet(snippets, "MM", tr("the month as number with a leading zero (`01` to `12`)"), + std::bind(formattedDateTime, "MM")); + addDynamicSnippet(snippets, "MMM", + tr("the abbreviated localized month name (e.g. `Jan` to `Dec`)"), + std::bind(formattedDateTime, "MMM")); + addDynamicSnippet(snippets, "MMMM", + tr("the long localized month name (e.g. `January` to `December`)"), + std::bind(formattedDateTime, "MMMM")); + addDynamicSnippet(snippets, "yy", tr("the year as two digit numbers (`00` to `99`)"), + std::bind(formattedDateTime, "yy")); + addDynamicSnippet(snippets, "yyyy", tr("the year as four digit numbers"), + std::bind(formattedDateTime, "yyyy")); + addDynamicSnippet( + snippets, "w", tr("the week number without a leading zero (`1` to `53`)"), + [](const QString &) { return QString::number(QDate::currentDate().weekNumber()); }); + addDynamicSnippet( + snippets, "ww", tr("the week number with a leading zero (`01` to `53`)"), + [](const QString &) { return Utils::intToString(QDate::currentDate().weekNumber(), 2); }); + addDynamicSnippet(snippets, "H", + tr("the hour without a leading zero (`0` to `23` even with AM/PM display)"), + std::bind(formattedDateTime, "H")); + addDynamicSnippet(snippets, "HH", + tr("the hour with a leading zero (`00` to `23` even with AM/PM display)"), + std::bind(formattedDateTime, "HH")); + addDynamicSnippet(snippets, "m", tr("the minute without a leading zero (`0` to `59`)"), + std::bind(formattedDateTime, "m")); + addDynamicSnippet(snippets, "mm", tr("the minute with a leading zero (`00` to `59`)"), + std::bind(formattedDateTime, "mm")); + addDynamicSnippet(snippets, "s", tr("the second without a leading zero (`0` to `59`)"), + std::bind(formattedDateTime, "s")); + addDynamicSnippet(snippets, "ss", tr("the second with a leading zero (`00` to `59`)"), + std::bind(formattedDateTime, "ss")); + addDynamicSnippet(snippets, "date", tr("date (`2021-02-24`)"), + std::bind(formattedDateTime, "yyyy-MM-dd")); + addDynamicSnippet(snippets, "da", tr("the abbreviated date (`20210224`)"), + std::bind(formattedDateTime, "yyyyMMdd")); + addDynamicSnippet(snippets, "time", tr("time (`16:51:02`)"), + std::bind(formattedDateTime, "hh:mm:ss")); + addDynamicSnippet(snippets, "datetime", tr("date and time (`2021-02-24_16:51:02`)"), + std::bind(formattedDateTime, "yyyy-MM-dd_hh:mm:ss")); + + // These snippets need override to fill the real value. + // Check generateOverrides(). + addDynamicSnippet(snippets, QStringLiteral("note"), tr("name of current note"), + [](const QString &) { return tr("[Value Not Available]"); }); + addDynamicSnippet(snippets, QStringLiteral("no"), tr("complete base name of current note"), + [](const QString &) { return tr("[Value Not Available]"); }); + return snippets; } void SnippetMgr::addDynamicSnippet(QVector> &p_snippets, - const QString &p_name, - const QString &p_description, - const DynamicSnippet::Callback &p_callback) -{ - auto snippet = QSharedPointer::create(p_name, p_description, p_callback); - p_snippets.push_back(snippet); + const QString &p_name, const QString &p_description, + const DynamicSnippet::Callback &p_callback) { + auto snippet = QSharedPointer::create(p_name, p_description, p_callback); + p_snippets.push_back(snippet); } -SnippetMgr::OverrideMap SnippetMgr::generateOverrides(const Buffer *p_buffer) -{ - OverrideMap overrides; - if (p_buffer) { - overrides.insert(QStringLiteral("note"), p_buffer->getName()); - overrides.insert(QStringLiteral("no"), QFileInfo(p_buffer->getName()).completeBaseName()); - } - return overrides; +SnippetMgr::OverrideMap SnippetMgr::generateOverrides(const Buffer *p_buffer) { + OverrideMap overrides; + if (p_buffer) { + overrides.insert(QStringLiteral("note"), p_buffer->getName()); + overrides.insert(QStringLiteral("no"), QFileInfo(p_buffer->getName()).completeBaseName()); + } + return overrides; } -SnippetMgr::OverrideMap SnippetMgr::generateOverrides(const QString &p_fileName) -{ - OverrideMap overrides; - overrides.insert(QStringLiteral("note"), p_fileName); - overrides.insert(QStringLiteral("no"), QFileInfo(p_fileName).completeBaseName()); - return overrides; +SnippetMgr::OverrideMap SnippetMgr::generateOverrides(const QString &p_fileName) { + OverrideMap overrides; + overrides.insert(QStringLiteral("note"), p_fileName); + overrides.insert(QStringLiteral("no"), QFileInfo(p_fileName).completeBaseName()); + return overrides; } -QString SnippetMgr::generateSnippetSymbol(const QString &p_snippetName) -{ - return c_snippetSymbolGuard + p_snippetName + c_snippetSymbolGuard; +QString SnippetMgr::generateSnippetSymbol(const QString &p_snippetName) { + return c_snippetSymbolGuard + p_snippetName + c_snippetSymbolGuard; } diff --git a/src/snippet/snippetmgr.h b/src/snippet/snippetmgr.h index d3ea94b0cd..e9fe43f778 100644 --- a/src/snippet/snippetmgr.h +++ b/src/snippet/snippetmgr.h @@ -1,111 +1,105 @@ #ifndef SNIPPETMGR_H #define SNIPPETMGR_H -#include -#include #include +#include #include +#include #include #include "dynamicsnippet.h" -namespace vte -{ - class VTextEdit; +namespace vte { +class VTextEdit; } -namespace vnotex -{ - class Buffer; +namespace vnotex { +class Buffer; - class SnippetMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - typedef QMap OverrideMap; +class SnippetMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + typedef QMap OverrideMap; - static SnippetMgr &getInst() - { - static SnippetMgr inst; - return inst; - } + static SnippetMgr &getInst() { + static SnippetMgr inst; + return inst; + } - QString getSnippetFolder() const; + QString getSnippetFolder() const; - const QVector> &getSnippets() const; + const QVector> &getSnippets() const; - // @p_exemption: include it even it is occupied by one snippet. - QVector getAvailableShortcuts(int p_exemption = Snippet::InvalidShortcut) const; + // @p_exemption: include it even it is occupied by one snippet. + QVector getAvailableShortcuts(int p_exemption = Snippet::InvalidShortcut) const; - QSharedPointer find(const QString &p_name, Qt::CaseSensitivity p_cs = Qt::CaseSensitive) const; + QSharedPointer find(const QString &p_name, + Qt::CaseSensitivity p_cs = Qt::CaseSensitive) const; - void addSnippet(const QSharedPointer &p_snippet); + void addSnippet(const QSharedPointer &p_snippet); - void removeSnippet(const QString &p_name); + void removeSnippet(const QString &p_name); - void updateSnippet(const QString &p_name, const QSharedPointer &p_snippet); + void updateSnippet(const QString &p_name, const QSharedPointer &p_snippet); - // Apply snippet @p_name directly in current cursor position. - // For snippets in @p_overrides, we just provide simple contents without nested snippets. - void applySnippet(const QString &p_name, - vte::VTextEdit *p_textEdit, - const OverrideMap &p_overrides = OverrideMap()) const; + // Apply snippet @p_name directly in current cursor position. + // For snippets in @p_overrides, we just provide simple contents without nested snippets. + void applySnippet(const QString &p_name, vte::VTextEdit *p_textEdit, + const OverrideMap &p_overrides = OverrideMap()) const; - // Resolve %snippet_name% as snippet and apply recursively. - // Will update @p_cursorOffset if needed. - // For snippets in @p_overrides, we just provide simple contents without nested snippets. - QString applySnippetBySymbol(const QString &p_content, - const QString &p_selectedText, - int &p_cursorOffset, - const OverrideMap &p_overrides = OverrideMap()) const; + // Resolve %snippet_name% as snippet and apply recursively. + // Will update @p_cursorOffset if needed. + // For snippets in @p_overrides, we just provide simple contents without nested snippets. + QString applySnippetBySymbol(const QString &p_content, const QString &p_selectedText, + int &p_cursorOffset, + const OverrideMap &p_overrides = OverrideMap()) const; - QString applySnippetBySymbol(const QString &p_content, - const OverrideMap &p_overrides = OverrideMap()) const; + QString applySnippetBySymbol(const QString &p_content, + const OverrideMap &p_overrides = OverrideMap()) const; - // Generate standard overrides for given buffer. - static OverrideMap generateOverrides(const Buffer *p_buffer); + // Generate standard overrides for given buffer. + static OverrideMap generateOverrides(const Buffer *p_buffer); - // Generate standard overrides for given file name. - static OverrideMap generateOverrides(const QString &p_fileName); + // Generate standard overrides for given file name. + static OverrideMap generateOverrides(const QString &p_fileName); - static QString generateSnippetSymbol(const QString &p_snippetName); + static QString generateSnippetSymbol(const QString &p_snippetName); - static const QChar c_snippetSymbolGuard; + static const QChar c_snippetSymbolGuard; - // %name%. - // Captured texts: - // 1 - The name of the snippet. - static const QString c_snippetSymbolRegExp; + // %name%. + // Captured texts: + // 1 - The name of the snippet. + static const QString c_snippetSymbolRegExp; - private: - SnippetMgr(); +private: + SnippetMgr(); - void loadSnippets(); + void loadSnippets(); - QSharedPointer loadSnippet(const QString &p_snippetFile) const; + QSharedPointer loadSnippet(const QString &p_snippetFile) const; - void saveSnippet(const QSharedPointer &p_snippet); + void saveSnippet(const QSharedPointer &p_snippet); - QString getSnippetFile(const QSharedPointer &p_snippet) const; + QString getSnippetFile(const QSharedPointer &p_snippet) const; - void addOneSnippet(const QSharedPointer &p_snippet); + void addOneSnippet(const QSharedPointer &p_snippet); - void removeSnippetFromShortcutMap(const QSharedPointer &p_snippet); + void removeSnippetFromShortcutMap(const QSharedPointer &p_snippet); - void addSnippetToShortcutMap(const QSharedPointer &p_snippet); + void addSnippetToShortcutMap(const QSharedPointer &p_snippet); - QVector> loadBuiltInSnippets() const; + QVector> loadBuiltInSnippets() const; - static void addDynamicSnippet(QVector> &p_snippets, - const QString &p_name, - const QString &p_description, - const DynamicSnippet::Callback &p_callback); + static void addDynamicSnippet(QVector> &p_snippets, const QString &p_name, + const QString &p_description, + const DynamicSnippet::Callback &p_callback); - QVector> m_snippets; + QVector> m_snippets; - QMap> m_shortcutToSnippet; - }; -} + QMap> m_shortcutToSnippet; +}; +} // namespace vnotex #endif // SNIPPETMGR_H diff --git a/src/task/shellexecution.cpp b/src/task/shellexecution.cpp index 1b421b7f4f..260b5f1143 100644 --- a/src/task/shellexecution.cpp +++ b/src/task/shellexecution.cpp @@ -5,68 +5,60 @@ using namespace vnotex; -void ShellExecution::setupProcess(QProcess *p_process, - const QString &p_program, - const QStringList &p_args, - const QString &p_shellExec, - const QStringList &p_shellArgs) -{ - auto shellExec = p_shellExec.isNull() ? defaultShell() : p_shellExec; - auto shellArgs = p_shellArgs.isEmpty() ? defaultShellArguments(shellExec) : p_shellArgs; +void ShellExecution::setupProcess(QProcess *p_process, const QString &p_program, + const QStringList &p_args, const QString &p_shellExec, + const QStringList &p_shellArgs) { + auto shellExec = p_shellExec.isNull() ? defaultShell() : p_shellExec; + auto shellArgs = p_shellArgs.isEmpty() ? defaultShellArguments(shellExec) : p_shellArgs; - p_process->setProgram(shellExec); + p_process->setProgram(shellExec); - const auto shell = shellBasename(p_shellExec); - QStringList allArgs(shellArgs); - if (shell == "bash") { - allArgs << (QStringList() << p_program << quoteSpaces(p_args)).join(' '); - } else { - allArgs << p_program << p_args; - } - p_process->setArguments(allArgs); + const auto shell = shellBasename(p_shellExec); + QStringList allArgs(shellArgs); + if (shell == "bash") { + allArgs << (QStringList() << p_program << quoteSpaces(p_args)).join(' '); + } else { + allArgs << p_program << p_args; + } + p_process->setArguments(allArgs); } -QString ShellExecution::shellBasename(const QString &p_shell) -{ - return QFileInfo(p_shell).baseName().toLower(); +QString ShellExecution::shellBasename(const QString &p_shell) { + return QFileInfo(p_shell).baseName().toLower(); } -QString ShellExecution::defaultShell() -{ +QString ShellExecution::defaultShell() { #ifdef Q_OS_WIN - return QStringLiteral("PowerShell.exe"); + return QStringLiteral("PowerShell.exe"); #else - return QStringLiteral("/bin/bash"); + return QStringLiteral("/bin/bash"); #endif } -QStringList ShellExecution::defaultShellArguments(const QString &p_shell) -{ - auto shell = shellBasename(p_shell); - if (shell == "cmd") { - return {"/C"}; - } else if (shell == "powershell" || p_shell == "pwsh") { - return {"-Command"}; - } else if (shell == "bash") { - return {"-c"}; - } - return {}; +QStringList ShellExecution::defaultShellArguments(const QString &p_shell) { + auto shell = shellBasename(p_shell); + if (shell == "cmd") { + return {"/C"}; + } else if (shell == "powershell" || p_shell == "pwsh") { + return {"-Command"}; + } else if (shell == "bash") { + return {"-c"}; + } + return {}; } -QString ShellExecution::quoteSpace(const QString &p_arg) -{ - if (p_arg.contains(QLatin1Char(' '))) { - return QLatin1Char('"') + p_arg + QLatin1Char('"'); - } else { - return p_arg; - } +QString ShellExecution::quoteSpace(const QString &p_arg) { + if (p_arg.contains(QLatin1Char(' '))) { + return QLatin1Char('"') + p_arg + QLatin1Char('"'); + } else { + return p_arg; + } } -QStringList ShellExecution::quoteSpaces(const QStringList &p_args) -{ - QStringList args; - for (const auto &arg : p_args) { - args << quoteSpace(arg); - } - return args; +QStringList ShellExecution::quoteSpaces(const QStringList &p_args) { + QStringList args; + for (const auto &arg : p_args) { + args << quoteSpace(arg); + } + return args; } diff --git a/src/task/shellexecution.h b/src/task/shellexecution.h index 188e5d1735..35722785dc 100644 --- a/src/task/shellexecution.h +++ b/src/task/shellexecution.h @@ -5,30 +5,27 @@ class QProcess; -namespace vnotex -{ - class ShellExecution - { - public: - ShellExecution() = delete; +namespace vnotex { +class ShellExecution { +public: + ShellExecution() = delete; - static void setupProcess(QProcess *p_process, - const QString &p_program, - const QStringList &p_args = QStringList(), - const QString &p_shellExec = QString(), - const QStringList &p_shellArgs = QStringList()); + static void setupProcess(QProcess *p_process, const QString &p_program, + const QStringList &p_args = QStringList(), + const QString &p_shellExec = QString(), + const QStringList &p_shellArgs = QStringList()); - static QString defaultShell(); + static QString defaultShell(); - static QStringList defaultShellArguments(const QString &p_shell); + static QStringList defaultShellArguments(const QString &p_shell); - private: - static QString shellBasename(const QString &p_shell); +private: + static QString shellBasename(const QString &p_shell); - static QString quoteSpace(const QString &p_arg); + static QString quoteSpace(const QString &p_arg); - static QStringList quoteSpaces(const QStringList &p_args); - }; -} + static QStringList quoteSpaces(const QStringList &p_args); +}; +} // namespace vnotex #endif // SHELLEXECUTION_H diff --git a/src/task/task.cpp b/src/task/task.cpp index 5d973b35ee..dfd399a207 100644 --- a/src/task/task.cpp +++ b/src/task/task.cpp @@ -1,25 +1,25 @@ #include "task.h" -#include -#include -#include -#include -#include #include -#include +#include #include -#include -#include +#include +#include #include +#include #include +#include +#include #include +#include +#include -#include -#include -#include +#include #include +#include #include -#include +#include +#include #include "shellexecution.h" #include "taskmgr.h" @@ -28,561 +28,481 @@ using namespace vnotex; QString Task::s_latestVersion = "0.1.3"; -QSharedPointer Task::fromFile(const QString &p_file, const QString &p_locale, TaskMgr *p_taskMgr) -{ - QSharedPointer task(new Task(p_locale, p_file, p_taskMgr, nullptr)); - const auto obj = FileUtils::readJsonFile(p_file); - if (fromJson(task.data(), obj)) { - return task; - } - return nullptr; +QSharedPointer Task::fromFile(const QString &p_file, const QString &p_locale, + TaskMgr *p_taskMgr) { + QSharedPointer task(new Task(p_locale, p_file, p_taskMgr, nullptr)); + const auto obj = FileUtils::readJsonFile(p_file); + if (fromJson(task.data(), obj)) { + return task; + } + return nullptr; } -bool Task::fromJson(Task *p_task, const QJsonObject &p_obj) -{ - // For child task, it will inherit the version from parent. - if (p_obj.contains("version")) { - p_task->m_dto.version = p_obj["version"].toString(); - } - - const auto version = QVersionNumber::fromString(p_task->getVersion()); - if (version.isNull()) { - qWarning() << "invalid task" << p_task->m_dto._source; - return false; - } - - if (version < QVersionNumber(1, 0, 0)) { - return fromJsonV0(p_task, p_obj); - } else { - qWarning() << "unknown task version" << version << p_task->m_dto._source; - return false; - } +bool Task::fromJson(Task *p_task, const QJsonObject &p_obj) { + // For child task, it will inherit the version from parent. + if (p_obj.contains("version")) { + p_task->m_dto.version = p_obj["version"].toString(); + } + + const auto version = QVersionNumber::fromString(p_task->getVersion()); + if (version.isNull()) { + qWarning() << "invalid task" << p_task->m_dto._source; + return false; + } + + if (version < QVersionNumber(1, 0, 0)) { + return fromJsonV0(p_task, p_obj); + } else { + qWarning() << "unknown task version" << version << p_task->m_dto._source; + return false; + } } -bool Task::fromJsonV0(Task *p_task, const QJsonObject &p_obj, bool p_mergeTasks) -{ - if (p_obj.contains("type")) { - p_task->m_dto.type = p_obj["type"].toString(); - } +bool Task::fromJsonV0(Task *p_task, const QJsonObject &p_obj, bool p_mergeTasks) { + if (p_obj.contains("type")) { + p_task->m_dto.type = p_obj["type"].toString(); + } - if (p_obj.contains("icon")) { - QString iconPath = p_obj["icon"].toString(); - if (!iconPath.isEmpty()) { - if (QDir::isRelativePath(iconPath)) { - iconPath = QFileInfo(p_task->m_dto._source).dir().absoluteFilePath(iconPath); - } - - if (QFileInfo::exists(iconPath)) { - p_task->m_dto.icon = iconPath; - } else { - qWarning() << "task icon does not exist" << p_task->getLabel() << iconPath; - } - } - } + if (p_obj.contains("icon")) { + QString iconPath = p_obj["icon"].toString(); + if (!iconPath.isEmpty()) { + if (QDir::isRelativePath(iconPath)) { + iconPath = QFileInfo(p_task->m_dto._source).dir().absoluteFilePath(iconPath); + } - if (p_obj.contains("shortcut")) { - p_task->m_dto.shortcut = p_obj["shortcut"].toString(); + if (QFileInfo::exists(iconPath)) { + p_task->m_dto.icon = iconPath; + } else { + qWarning() << "task icon does not exist" << p_task->getLabel() << iconPath; + } } + } - if (p_obj.contains("type")) { - p_task->m_dto.type = p_obj["type"].toString(); - } + if (p_obj.contains("shortcut")) { + p_task->m_dto.shortcut = p_obj["shortcut"].toString(); + } - if (p_obj.contains("command")) { - p_task->m_dto.command = getLocaleString(p_obj["command"], p_task->m_locale); - } + if (p_obj.contains("type")) { + p_task->m_dto.type = p_obj["type"].toString(); + } - if (p_obj.contains("args")) { - p_task->m_dto.args = getLocaleStringList(p_obj["args"], p_task->m_locale); - } + if (p_obj.contains("command")) { + p_task->m_dto.command = getLocaleString(p_obj["command"], p_task->m_locale); + } - if (p_obj.contains("label")) { - p_task->m_dto.label = getLocaleString(p_obj["label"], p_task->m_locale); - } else if (p_task->m_dto.label.isNull() && !p_task->m_dto.command.isNull()) { - p_task->m_dto.label = p_task->m_dto.command; - } + if (p_obj.contains("args")) { + p_task->m_dto.args = getLocaleStringList(p_obj["args"], p_task->m_locale); + } - if (p_obj.contains("options")) { - auto options = p_obj["options"].toObject(); + if (p_obj.contains("label")) { + p_task->m_dto.label = getLocaleString(p_obj["label"], p_task->m_locale); + } else if (p_task->m_dto.label.isNull() && !p_task->m_dto.command.isNull()) { + p_task->m_dto.label = p_task->m_dto.command; + } - if (options.contains("cwd")) { - p_task->m_dto.options.cwd = options["cwd"].toString(); - } + if (p_obj.contains("options")) { + auto options = p_obj["options"].toObject(); - if (options.contains("env")) { - p_task->m_dto.options.env.clear(); - auto env = options["env"].toObject(); - for (auto it = env.begin(); it != env.end(); it++) { - auto value = getLocaleString(it.value(), p_task->m_locale); - p_task->m_dto.options.env.insert(it.key(), value); - } - } + if (options.contains("cwd")) { + p_task->m_dto.options.cwd = options["cwd"].toString(); + } + + if (options.contains("env")) { + p_task->m_dto.options.env.clear(); + auto env = options["env"].toObject(); + for (auto it = env.begin(); it != env.end(); it++) { + auto value = getLocaleString(it.value(), p_task->m_locale); + p_task->m_dto.options.env.insert(it.key(), value); + } + } - if (options.contains("shell") && p_task->getType() == "shell") { - auto shell = options["shell"].toObject(); + if (options.contains("shell") && p_task->getType() == "shell") { + auto shell = options["shell"].toObject(); - if (shell.contains("executable")) { - p_task->m_dto.options.shell.executable = shell["executable"].toString(); - } + if (shell.contains("executable")) { + p_task->m_dto.options.shell.executable = shell["executable"].toString(); + } - if (shell.contains("args")) { - p_task->m_dto.options.shell.args.clear(); + if (shell.contains("args")) { + p_task->m_dto.options.shell.args.clear(); - const auto arr = shell["args"].toArray(); - for (int i = 0; i < arr.size(); ++i) { - p_task->m_dto.options.shell.args << arr[i].toString(); - } - } + const auto arr = shell["args"].toArray(); + for (int i = 0; i < arr.size(); ++i) { + p_task->m_dto.options.shell.args << arr[i].toString(); } + } } + } - if (p_obj.contains("tasks")) { - if (!p_mergeTasks) { - p_task->m_children.clear(); - } + if (p_obj.contains("tasks")) { + if (!p_mergeTasks) { + p_task->m_children.clear(); + } - auto arr = p_obj["tasks"].toArray(); - for (int i = 0; i < arr.size(); ++i) { - QScopedPointer childTask(new Task(p_task->m_locale, p_task->getFile(), p_task->m_taskMgr, p_task)); - if (fromJson(childTask.data(), arr[i].toObject())) { - connect(childTask.data(), &Task::outputRequested, - p_task, &Task::outputRequested); - p_task->m_children.append(childTask.take()); - } + auto arr = p_obj["tasks"].toArray(); + for (int i = 0; i < arr.size(); ++i) { + QScopedPointer childTask( + new Task(p_task->m_locale, p_task->getFile(), p_task->m_taskMgr, p_task)); + if (fromJson(childTask.data(), arr[i].toObject())) { + connect(childTask.data(), &Task::outputRequested, p_task, &Task::outputRequested); + p_task->m_children.append(childTask.take()); + } + } + } + + if (p_obj.contains("inputs")) { + p_task->m_dto.inputs.clear(); + auto arr = p_obj["inputs"].toArray(); + for (int i = 0; i < arr.size(); ++i) { + const auto inputObj = arr[i].toObject(); + InputDTO input; + if (inputObj.contains("id")) { + input.id = inputObj["id"].toString(); + } else { + qWarning() << "Input configuration not contains id"; + } + + if (inputObj.contains("type")) { + input.type = inputObj["type"].toString(); + } else { + input.type = "promptString"; + } + + if (inputObj.contains("description")) { + input.description = getLocaleString(inputObj["description"], p_task->m_locale); + } + + if (inputObj.contains("default")) { + input.default_ = getLocaleString(inputObj["default"], p_task->m_locale); + } + + if (input.type == "promptString" && inputObj.contains("password")) { + input.password = inputObj["password"].toBool(); + } else { + input.password = false; + } + + if (input.type == "pickString") { + if (inputObj.contains("options")) { + input.options = getLocaleStringList(inputObj["options"], p_task->m_locale); } - } - if (p_obj.contains("inputs")) { - p_task->m_dto.inputs.clear(); - auto arr = p_obj["inputs"].toArray(); - for (int i = 0; i < arr.size(); ++i) { - const auto inputObj = arr[i].toObject(); - InputDTO input; - if (inputObj.contains("id")) { - input.id = inputObj["id"].toString(); - } else { - qWarning() << "Input configuration not contains id"; - } - - if (inputObj.contains("type")) { - input.type = inputObj["type"].toString(); - } else { - input.type = "promptString"; - } - - if (inputObj.contains("description")) { - input.description = getLocaleString(inputObj["description"], p_task->m_locale); - } - - if (inputObj.contains("default")) { - input.default_ = getLocaleString(inputObj["default"], p_task->m_locale); - } - - if (input.type == "promptString" && inputObj.contains("password")) { - input.password = inputObj["password"].toBool(); - } else { - input.password = false; - } - - if (input.type == "pickString") { - if (inputObj.contains("options")) { - input.options = getLocaleStringList(inputObj["options"], p_task->m_locale); - } - - if (!input.default_.isNull() && !input.options.contains(input.default_)) { - qWarning() << "default of input must be one of the option values"; - } - } - - p_task->m_dto.inputs << input; + if (!input.default_.isNull() && !input.options.contains(input.default_)) { + qWarning() << "default of input must be one of the option values"; } + } + + p_task->m_dto.inputs << input; } + } - if (p_obj.contains("messages")) { - p_task->m_dto.messages.clear(); - auto arr = p_obj["messages"].toArray(); - for (int i = 0; i < arr.size(); ++i) { - const auto msgObj = arr[i].toObject(); - MessageDTO msg; - if (msgObj.contains("id")) { - msg.id = msgObj["id"].toString(); - } else { - qWarning() << "Message configuration not contain id"; - } - - if (msgObj.contains("type")) { - msg.type = msgObj["type"].toString(); - } else { - msg.type = "information"; - } - - if (msgObj.contains("title")) { - msg.title = getLocaleString(msgObj["title"], p_task->m_locale); - } - - if (msgObj.contains("text")) { - msg.text = getLocaleString(msgObj["text"], p_task->m_locale); - } - - if (msgObj.contains("detailedText")) { - msg.detailedText = getLocaleString(msgObj["detailedText"], p_task->m_locale); - } - - if (msgObj.contains("buttons")) { - auto buttonsArr = msgObj["buttons"].toArray(); - for (int j = 0; j < buttonsArr.size(); ++j) { - const auto btnObj = buttonsArr[j].toObject(); - ButtonDTO btn; - btn.text = getLocaleString(btnObj["text"], p_task->m_locale); - msg.buttons << btn; - } - } - - p_task->m_dto.messages << msg; + if (p_obj.contains("messages")) { + p_task->m_dto.messages.clear(); + auto arr = p_obj["messages"].toArray(); + for (int i = 0; i < arr.size(); ++i) { + const auto msgObj = arr[i].toObject(); + MessageDTO msg; + if (msgObj.contains("id")) { + msg.id = msgObj["id"].toString(); + } else { + qWarning() << "Message configuration not contain id"; + } + + if (msgObj.contains("type")) { + msg.type = msgObj["type"].toString(); + } else { + msg.type = "information"; + } + + if (msgObj.contains("title")) { + msg.title = getLocaleString(msgObj["title"], p_task->m_locale); + } + + if (msgObj.contains("text")) { + msg.text = getLocaleString(msgObj["text"], p_task->m_locale); + } + + if (msgObj.contains("detailedText")) { + msg.detailedText = getLocaleString(msgObj["detailedText"], p_task->m_locale); + } + + if (msgObj.contains("buttons")) { + auto buttonsArr = msgObj["buttons"].toArray(); + for (int j = 0; j < buttonsArr.size(); ++j) { + const auto btnObj = buttonsArr[j].toObject(); + ButtonDTO btn; + btn.text = getLocaleString(btnObj["text"], p_task->m_locale); + msg.buttons << btn; } + } + + p_task->m_dto.messages << msg; } + } - // OS-specific task configuration -#if defined (Q_OS_WIN) - #define OS_SPEC "windows" -#elif defined (Q_OS_MACOS) - #define OS_SPEC "osx" + // OS-specific task configuration +#if defined(Q_OS_WIN) +#define OS_SPEC "windows" +#elif defined(Q_OS_MACOS) +#define OS_SPEC "osx" #else - #define OS_SPEC "linux" +#define OS_SPEC "linux" #endif - if (p_obj.contains(OS_SPEC)) { - const auto osObj = p_obj[OS_SPEC].toObject(); - fromJsonV0(p_task, osObj, true); - } + if (p_obj.contains(OS_SPEC)) { + const auto osObj = p_obj[OS_SPEC].toObject(); + fromJsonV0(p_task, osObj, true); + } #undef OS_SPEC - return true; + return true; } -const QString &Task::getVersion() const -{ - return m_dto.version; -} +const QString &Task::getVersion() const { return m_dto.version; } -const QString &Task::getType() const -{ - return m_dto.type; -} +const QString &Task::getType() const { return m_dto.type; } -QString Task::getCommand() -{ - return variableMgr().evaluate(this, m_dto.command); -} +QString Task::getCommand() { return variableMgr().evaluate(this, m_dto.command); } -QStringList Task::getArgs() -{ - return variableMgr().evaluate(this, m_dto.args); -} +QStringList Task::getArgs() { return variableMgr().evaluate(this, m_dto.args); } -const QString &Task::getLabel() const -{ - return m_dto.label; -} +const QString &Task::getLabel() const { return m_dto.label; } -const QString &Task::getIcon() const -{ - return m_dto.icon; -} +const QString &Task::getIcon() const { return m_dto.icon; } -const QString &Task::getShortcut() const -{ - return m_dto.shortcut; -} +const QString &Task::getShortcut() const { return m_dto.shortcut; } -QString Task::getOptionsCwd() -{ - auto cwd = m_dto.options.cwd; - if (!cwd.isNull()) { - return variableMgr().evaluate(this, cwd); - } +QString Task::getOptionsCwd() { + auto cwd = m_dto.options.cwd; + if (!cwd.isNull()) { + return variableMgr().evaluate(this, cwd); + } - auto notebook = TaskVariableMgr::getCurrentNotebook(); - if (notebook) { - cwd = notebook->getRootFolderAbsolutePath(); - } + auto notebook = TaskVariableMgr::getCurrentNotebook(); + if (notebook) { + cwd = notebook->getRootFolderAbsolutePath(); + } - if (!cwd.isNull()) { - return cwd; - } + if (!cwd.isNull()) { + return cwd; + } - auto buffer = TaskVariableMgr::getCurrentBuffer(); - if (buffer) { - return QFileInfo(buffer->getPath()).dir().absolutePath(); - } + auto buffer = TaskVariableMgr::getCurrentBuffer(); + if (buffer) { + return QFileInfo(buffer->getPath()).dir().absolutePath(); + } - return QFileInfo(m_dto._source).dir().absolutePath(); + return QFileInfo(m_dto._source).dir().absolutePath(); } -const QMap &Task::getOptionsEnv() const -{ - return m_dto.options.env; -} +const QMap &Task::getOptionsEnv() const { return m_dto.options.env; } -const QString &Task::getOptionsShellExecutable() const -{ - return m_dto.options.shell.executable; -} +const QString &Task::getOptionsShellExecutable() const { return m_dto.options.shell.executable; } -QStringList Task::getOptionsShellArgs() -{ - if (m_dto.options.shell.args.isEmpty()) { - return ShellExecution::defaultShellArguments(m_dto.options.shell.executable); - } else { - return variableMgr().evaluate(this, m_dto.options.shell.args); - } +QStringList Task::getOptionsShellArgs() { + if (m_dto.options.shell.args.isEmpty()) { + return ShellExecution::defaultShellArguments(m_dto.options.shell.executable); + } else { + return variableMgr().evaluate(this, m_dto.options.shell.args); + } } -const QVector &Task::getChildren() const -{ - return m_children; -} +const QVector &Task::getChildren() const { return m_children; } -const QVector &Task::getInputs() const -{ - return m_dto.inputs; -} +const QVector &Task::getInputs() const { return m_dto.inputs; } -const InputDTO *Task::findInput(const QString &p_id) const -{ - for (const auto &input : m_dto.inputs) { - if (input.id == p_id) { - return &input; - } +const InputDTO *Task::findInput(const QString &p_id) const { + for (const auto &input : m_dto.inputs) { + if (input.id == p_id) { + return &input; } + } - qWarning() << "input" << p_id << "not found for task" << getLabel(); - return nullptr; + qWarning() << "input" << p_id << "not found for task" << getLabel(); + return nullptr; } -const MessageDTO *Task::findMessage(const QString &p_id) const -{ - for (const auto &msg : m_dto.messages) { - if (msg.id == p_id) { - return &msg; - } +const MessageDTO *Task::findMessage(const QString &p_id) const { + for (const auto &msg : m_dto.messages) { + if (msg.id == p_id) { + return &msg; } + } - qWarning() << "message" << p_id << "not found for task" << getLabel(); - return nullptr; -} - -const QString &Task::getFile() const -{ - return m_dto._source; + qWarning() << "message" << p_id << "not found for task" << getLabel(); + return nullptr; } -Task::Task(const QString &p_locale, - const QString &p_file, - TaskMgr *p_taskMgr, - QObject *p_parent) - : QObject(p_parent), - m_taskMgr(p_taskMgr), - m_locale(p_locale) -{ - m_dto._source = p_file; - m_dto.version = s_latestVersion; - m_dto.type = "shell"; - m_dto.options.shell.executable = ShellExecution::defaultShell(); - - // Inherit configuration. - m_parent = qobject_cast(p_parent); - if (m_parent) { - m_dto.version = m_parent->m_dto.version; - m_dto.type = m_parent->m_dto.type; - m_dto.command = m_parent->m_dto.command; - m_dto.args = m_parent->m_dto.args; - m_dto.options.cwd = m_parent->m_dto.options.cwd; - m_dto.options.env = m_parent->m_dto.options.env; - m_dto.options.shell.executable = m_parent->m_dto.options.shell.executable; - m_dto.options.shell.args = m_parent->m_dto.options.shell.args; - // Do not inherit label/inputs/tasks. - } else { - m_dto.label = QFileInfo(p_file).baseName(); - } +const QString &Task::getFile() const { return m_dto._source; } + +Task::Task(const QString &p_locale, const QString &p_file, TaskMgr *p_taskMgr, QObject *p_parent) + : QObject(p_parent), m_taskMgr(p_taskMgr), m_locale(p_locale) { + m_dto._source = p_file; + m_dto.version = s_latestVersion; + m_dto.type = "shell"; + m_dto.options.shell.executable = ShellExecution::defaultShell(); + + // Inherit configuration. + m_parent = qobject_cast(p_parent); + if (m_parent) { + m_dto.version = m_parent->m_dto.version; + m_dto.type = m_parent->m_dto.type; + m_dto.command = m_parent->m_dto.command; + m_dto.args = m_parent->m_dto.args; + m_dto.options.cwd = m_parent->m_dto.options.cwd; + m_dto.options.env = m_parent->m_dto.options.env; + m_dto.options.shell.executable = m_parent->m_dto.options.shell.executable; + m_dto.options.shell.args = m_parent->m_dto.options.shell.args; + // Do not inherit label/inputs/tasks. + } else { + m_dto.label = QFileInfo(p_file).baseName(); + } } -QProcess *Task::setupProcess() -{ - setCancelled(false); +QProcess *Task::setupProcess() { + setCancelled(false); - auto command = getCommand(); - if (command.isEmpty()) { - return nullptr; - } + auto command = getCommand(); + if (command.isEmpty()) { + return nullptr; + } - QScopedPointer scopedProcess(new QProcess(this)); + QScopedPointer scopedProcess(new QProcess(this)); - auto process = scopedProcess.data(); - process->setWorkingDirectory(getOptionsCwd()); + auto process = scopedProcess.data(); + process->setWorkingDirectory(getOptionsCwd()); - const auto &optionsEnv = getOptionsEnv(); - if (!optionsEnv.isEmpty()) { - auto env = QProcessEnvironment::systemEnvironment(); - for (auto it = optionsEnv.begin(); it != optionsEnv.end(); it++) { - env.insert(it.key(), it.value()); - } - process->setProcessEnvironment(env); + const auto &optionsEnv = getOptionsEnv(); + if (!optionsEnv.isEmpty()) { + auto env = QProcessEnvironment::systemEnvironment(); + for (auto it = optionsEnv.begin(); it != optionsEnv.end(); it++) { + env.insert(it.key(), it.value()); } + process->setProcessEnvironment(env); + } - const auto args = getArgs(); - const auto &type = getType(); - - if (type == "shell") { - ShellExecution::setupProcess(process, - command, - args, - getOptionsShellExecutable(), - getOptionsShellArgs()); - } else if (getType() == "process") { - process->setProgram(command); - process->setArguments(args); - } + const auto args = getArgs(); + const auto &type = getType(); - if (isCancelled()) { - return nullptr; - } + if (type == "shell") { + ShellExecution::setupProcess(process, command, args, getOptionsShellExecutable(), + getOptionsShellArgs()); + } else if (getType() == "process") { + process->setProgram(command); + process->setArguments(args); + } - scopedProcess.take(); - - connect(process, &QProcess::started, - this, [this]() { - emit outputRequested(tr("[Task (%1) started]\n").arg(getLabel())); - }); - connect(process, &QProcess::readyReadStandardOutput, - this, [this, process]() { - auto text = decodeText(process->readAllStandardOutput()); - // TODO: interaction with process. - emit outputRequested(text); - }); - connect(process, &QProcess::readyReadStandardError, - this, [this, process]() { - auto text = process->readAllStandardError(); - emit outputRequested(decodeText(text)); - }); - connect(process, &QProcess::errorOccurred, - this, [this](QProcess::ProcessError error) { - emit outputRequested(tr("[Task (%1) error occurred (%2)]\n").arg(getLabel()).arg(error)); - }); - connect(process, QOverload::of(&QProcess::finished), - this, [this, process](int exitCode) { - emit outputRequested(tr("\n[Task (%1) finished (%2)]\n").arg(getLabel()).arg(exitCode)); - process->deleteLater(); - }); - - return process; + if (isCancelled()) { + return nullptr; + } + + scopedProcess.take(); + + connect(process, &QProcess::started, this, + [this]() { emit outputRequested(tr("[Task (%1) started]\n").arg(getLabel())); }); + connect(process, &QProcess::readyReadStandardOutput, this, [this, process]() { + auto text = decodeText(process->readAllStandardOutput()); + // TODO: interaction with process. + emit outputRequested(text); + }); + connect(process, &QProcess::readyReadStandardError, this, [this, process]() { + auto text = process->readAllStandardError(); + emit outputRequested(decodeText(text)); + }); + connect(process, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) { + emit outputRequested(tr("[Task (%1) error occurred (%2)]\n").arg(getLabel()).arg(error)); + }); + connect(process, QOverload::of(&QProcess::finished), this, + [this, process](int exitCode) { + emit outputRequested(tr("\n[Task (%1) finished (%2)]\n").arg(getLabel()).arg(exitCode)); + process->deleteLater(); + }); + + return process; } -void Task::run() -{ - QProcess *process; - try { - process = setupProcess(); - } catch (const char *msg) { - qWarning() << "exception while setup process" << msg; - return ; - } - - if (process) { - qDebug() << "run task" << process->program() << process->arguments(); - process->start(); - } +void Task::run() { + QProcess *process; + try { + process = setupProcess(); + } catch (const char *msg) { + qWarning() << "exception while setup process" << msg; + return; + } + + if (process) { + qDebug() << "run task" << process->program() << process->arguments(); + process->start(); + } } -const TaskDTO &Task::getDTO() const -{ - return m_dto; -} +const TaskDTO &Task::getDTO() const { return m_dto; } -QString Task::decodeText(const QByteArray &p_text) -{ - static QByteArrayList codecNames = { - "UTF-8", - "System", - "UTF-16", - "GB18030" - }; - - for (const auto &name : codecNames) { - auto text = decodeText(p_text, name); - if (!text.isNull()) { - return text; - } +QString Task::decodeText(const QByteArray &p_text) { + static QByteArrayList codecNames = {"UTF-8", "System", "UTF-16", "GB18030"}; + + for (const auto &name : codecNames) { + auto text = decodeText(p_text, name); + if (!text.isNull()) { + return text; } + } - return QString::fromLocal8Bit(p_text); + return QString::fromLocal8Bit(p_text); } -QString Task::decodeText(const QByteArray &p_text, const QByteArray &p_name) -{ - auto codec = QTextCodec::codecForName(p_name); - if (codec) { - QTextCodec::ConverterState state; - auto text = codec->toUnicode(p_text.data(), p_text.size(), &state); - if (state.invalidChars > 0) { - return QString(); - } - return text; - } - return QString(); +QString Task::decodeText(const QByteArray &p_text, const QByteArray &p_name) { + auto codec = QTextCodec::codecForName(p_name); + if (codec) { + QTextCodec::ConverterState state; + auto text = codec->toUnicode(p_text.data(), p_text.size(), &state); + if (state.invalidChars > 0) { + return QString(); + } + return text; + } + return QString(); } -QString Task::getLocaleString(const QJsonValue &p_value, const QString &p_locale) -{ - if (p_value.isObject()) { - auto obj = p_value.toObject(); - if (obj.contains(p_locale)) { - return obj.value(p_locale).toString(); - } else { - qWarning() << "value of locale not found" << p_locale; - if (!obj.isEmpty()){ - return obj.begin().value().toString(); - } else { - return QString(); - } - } +QString Task::getLocaleString(const QJsonValue &p_value, const QString &p_locale) { + if (p_value.isObject()) { + auto obj = p_value.toObject(); + if (obj.contains(p_locale)) { + return obj.value(p_locale).toString(); } else { - return p_value.toString(); - } + qWarning() << "value of locale not found" << p_locale; + if (!obj.isEmpty()) { + return obj.begin().value().toString(); + } else { + return QString(); + } + } + } else { + return p_value.toString(); + } } -QStringList Task::getLocaleStringList(const QJsonValue &p_value, const QString &p_locale) -{ - QStringList strs; - const auto arr = p_value.toArray(); - for (int i = 0; i < arr.size(); ++i) { - strs << getLocaleString(arr[i], p_locale); - } - return strs; +QStringList Task::getLocaleStringList(const QJsonValue &p_value, const QString &p_locale) { + QStringList strs; + const auto arr = p_value.toArray(); + for (int i = 0; i < arr.size(); ++i) { + strs << getLocaleString(arr[i], p_locale); + } + return strs; } -QStringList Task::getStringList(const QJsonValue &p_value) -{ - QStringList strs; - const auto arr = p_value.toArray(); - for (int i = 0; i < arr.size(); ++i) { - strs << arr[i].toString(); - } - return strs; +QStringList Task::getStringList(const QJsonValue &p_value) { + QStringList strs; + const auto arr = p_value.toArray(); + for (int i = 0; i < arr.size(); ++i) { + strs << arr[i].toString(); + } + return strs; } -const TaskVariableMgr &Task::variableMgr() const -{ - return m_taskMgr->getVariableMgr(); -} +const TaskVariableMgr &Task::variableMgr() const { return m_taskMgr->getVariableMgr(); } -bool Task::isCancelled() const -{ - return m_cancelled; -} +bool Task::isCancelled() const { return m_cancelled; } -void Task::setCancelled(bool p_cancelled) -{ - m_cancelled = p_cancelled; -} +void Task::setCancelled(bool p_cancelled) { m_cancelled = p_cancelled; } diff --git a/src/task/task.h b/src/task/task.h index 75e3564daa..45e2ef5094 100644 --- a/src/task/task.h +++ b/src/task/task.h @@ -3,195 +3,183 @@ #include -#include #include #include +#include class QAction; class QProcess; class QJsonObject; -namespace tests -{ - class TestTask; +namespace tests { +class TestTask; } -namespace vnotex -{ - struct ButtonDTO - { - QString text; - }; +namespace vnotex { +struct ButtonDTO { + QString text; +}; - struct InputDTO - { - QString id; +struct InputDTO { + QString id; - QString type; + QString type; - QString description; + QString description; - QString default_; + QString default_; - bool password; + bool password; - QStringList options; - }; + QStringList options; +}; - struct MessageDTO - { - QString id; +struct MessageDTO { + QString id; - QString type; + QString type; - QString title; + QString title; - QString text; + QString text; - QString detailedText; + QString detailedText; - QVector buttons; - }; + QVector buttons; +}; - struct ShellOptionsDTO - { - QString executable; +struct ShellOptionsDTO { + QString executable; - QStringList args; - }; + QStringList args; +}; - struct TaskOptionsDTO - { - QString cwd; +struct TaskOptionsDTO { + QString cwd; - QMap env; + QMap env; - ShellOptionsDTO shell; - }; + ShellOptionsDTO shell; +}; - struct TaskDTO - { - QString version; +struct TaskDTO { + QString version; - QString type; + QString type; - QString command; + QString command; - QStringList args; + QStringList args; - QString label; + QString label; - QString icon; + QString icon; - QString shortcut; + QString shortcut; - QVector inputs; + QVector inputs; - QVector messages; + QVector messages; - TaskOptionsDTO options; + TaskOptionsDTO options; - QString _scope; + QString _scope; - QString _source; - }; + QString _source; +}; - class TaskMgr; - class TaskVariableMgr; +class TaskMgr; +class TaskVariableMgr; - class Task : public QObject - { - Q_OBJECT - public: - friend class tests::TestTask; +class Task : public QObject { + Q_OBJECT +public: + friend class tests::TestTask; - // For top level Task, use QSharedPointer instead of QObject to manage ownership. - static QSharedPointer fromFile(const QString &p_file, const QString &p_locale, TaskMgr *p_taskMgr); + // For top level Task, use QSharedPointer instead of QObject to manage ownership. + static QSharedPointer fromFile(const QString &p_file, const QString &p_locale, + TaskMgr *p_taskMgr); - void run(); + void run(); - const TaskDTO &getDTO() const; + const TaskDTO &getDTO() const; - const QString &getVersion() const; + const QString &getVersion() const; - const QString &getType() const; + const QString &getType() const; - QString getCommand(); + QString getCommand(); - QStringList getArgs(); + QStringList getArgs(); - const QString &getLabel() const; + const QString &getLabel() const; - const QString &getIcon() const; + const QString &getIcon() const; - const QString &getShortcut() const; + const QString &getShortcut() const; - QString getOptionsCwd(); + QString getOptionsCwd(); - const QMap &getOptionsEnv() const; + const QMap &getOptionsEnv() const; - const QString &getOptionsShellExecutable() const; + const QString &getOptionsShellExecutable() const; - QStringList getOptionsShellArgs(); + QStringList getOptionsShellArgs(); - const QVector &getChildren() const; + const QVector &getChildren() const; - const QVector &getInputs() const; + const QVector &getInputs() const; - const InputDTO *findInput(const QString &p_id) const; + const InputDTO *findInput(const QString &p_id) const; - const MessageDTO *findMessage(const QString &p_id) const; + const MessageDTO *findMessage(const QString &p_id) const; - const QString &getFile() const; + const QString &getFile() const; - bool isCancelled() const; + bool isCancelled() const; - void setCancelled(bool p_cancelled); + void setCancelled(bool p_cancelled); - static QString s_latestVersion; + static QString s_latestVersion; - static QString getLocaleString(const QJsonValue &p_value, - const QString &p_locale); + static QString getLocaleString(const QJsonValue &p_value, const QString &p_locale); - static QStringList getLocaleStringList(const QJsonValue &p_value, - const QString &p_locale); + static QStringList getLocaleStringList(const QJsonValue &p_value, const QString &p_locale); - static QStringList getStringList(const QJsonValue &p_value); + static QStringList getStringList(const QJsonValue &p_value); - static QString decodeText(const QByteArray &p_text); + static QString decodeText(const QByteArray &p_text); - signals: - void outputRequested(const QString &p_text) const; +signals: + void outputRequested(const QString &p_text) const; - private: - Task(const QString &p_locale, - const QString &p_file, - TaskMgr *p_taskMgr, - QObject *p_parent = nullptr); +private: + Task(const QString &p_locale, const QString &p_file, TaskMgr *p_taskMgr, + QObject *p_parent = nullptr); - // Must call start() or delete the returned QProcess. - QProcess *setupProcess(); + // Must call start() or delete the returned QProcess. + QProcess *setupProcess(); - const TaskVariableMgr &variableMgr() const; + const TaskVariableMgr &variableMgr() const; - static bool fromJson(Task *p_task, const QJsonObject &p_obj); + static bool fromJson(Task *p_task, const QJsonObject &p_obj); - static bool fromJsonV0(Task *p_task, const QJsonObject &p_obj, bool p_mergeTasks = false); + static bool fromJsonV0(Task *p_task, const QJsonObject &p_obj, bool p_mergeTasks = false); - static QString decodeText(const QByteArray &p_text, const QByteArray &p_name); + static QString decodeText(const QByteArray &p_text, const QByteArray &p_name); - Task *m_parent = nullptr; + Task *m_parent = nullptr; - QVector m_children; + QVector m_children; - TaskMgr *m_taskMgr = nullptr; + TaskMgr *m_taskMgr = nullptr; - TaskDTO m_dto; + TaskDTO m_dto; - QString m_locale; + QString m_locale; - bool m_cancelled = false; - }; -} // ns vnotex + bool m_cancelled = false; +}; +} // namespace vnotex #endif // TASK_H diff --git a/src/task/taskmgr.cpp b/src/task/taskmgr.cpp index 299501ed98..97e9a51543 100644 --- a/src/task/taskmgr.cpp +++ b/src/task/taskmgr.cpp @@ -1,119 +1,90 @@ #include "taskmgr.h" -#include #include +#include #include #include #include -#include #include -#include +#include #include +#include using namespace vnotex; -TaskMgr::TaskMgr(QObject *p_parent) - : QObject(p_parent), - m_variableMgr(this) -{ -} +TaskMgr::TaskMgr(QObject *p_parent) : QObject(p_parent), m_variableMgr(this) {} -void TaskMgr::init() -{ - m_variableMgr.init(); +void TaskMgr::init() { + m_variableMgr.init(); - // Load all tasks and watch the location. - loadAllTasks(); + // Load all tasks and watch the location. + loadAllTasks(); - connect(&VNoteX::getInst().getNotebookMgr(), &NotebookMgr::currentNotebookChanged, - this, [this]() { - loadNotebookTasks(); - emit tasksUpdated(); - }); + connect(&VNoteX::getInst().getNotebookMgr(), &NotebookMgr::currentNotebookChanged, this, + [this]() { + loadNotebookTasks(); + emit tasksUpdated(); + }); } -void TaskMgr::reload() -{ - loadAllTasks(); -} +void TaskMgr::reload() { loadAllTasks(); } -const QVector> &TaskMgr::getAppTasks() const -{ - return m_appTasks; -} +const QVector> &TaskMgr::getAppTasks() const { return m_appTasks; } -const QVector> &TaskMgr::getUserTasks() const -{ - return m_userTasks; -} +const QVector> &TaskMgr::getUserTasks() const { return m_userTasks; } -const QVector> &TaskMgr::getNotebookTasks() const -{ - return m_notebookTasks; -} +const QVector> &TaskMgr::getNotebookTasks() const { return m_notebookTasks; } -QString TaskMgr::getNotebookTaskFolder() -{ - auto nb = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); - if (nb) { - const auto folderPath = nb->getConfigFolderAbsolutePath(); - if (!folderPath.isEmpty()) { - return PathUtils::concatenateFilePath(folderPath, QStringLiteral("tasks")); - } +QString TaskMgr::getNotebookTaskFolder() { + auto nb = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); + if (nb) { + const auto folderPath = nb->getConfigFolderAbsolutePath(); + if (!folderPath.isEmpty()) { + return PathUtils::concatenateFilePath(folderPath, QStringLiteral("tasks")); } - return QString(); + } + return QString(); } -void TaskMgr::loadAllTasks() -{ - loadGlobalTasks(); +void TaskMgr::loadAllTasks() { + loadGlobalTasks(); - loadNotebookTasks(); + loadNotebookTasks(); - emit tasksUpdated(); + emit tasksUpdated(); } -void TaskMgr::loadNotebookTasks() -{ - loadTasksFromFolder(m_notebookTasks, getNotebookTaskFolder()); -} +void TaskMgr::loadNotebookTasks() { loadTasksFromFolder(m_notebookTasks, getNotebookTaskFolder()); } -void TaskMgr::loadGlobalTasks() -{ - loadTasksFromFolder(m_appTasks, ConfigMgr::getInst().getAppTaskFolder()); - loadTasksFromFolder(m_userTasks, ConfigMgr::getInst().getUserTaskFolder()); +void TaskMgr::loadGlobalTasks() { + loadTasksFromFolder(m_appTasks, ConfigMgr::getInst().getAppTaskFolder()); + loadTasksFromFolder(m_userTasks, ConfigMgr::getInst().getUserTaskFolder()); } -void TaskMgr::loadTasksFromFolder(QVector> &p_tasks, const QString &p_folder) -{ - qDebug() << "load tasks from folder" << p_folder; - p_tasks.clear(); - - if (p_folder.isEmpty()) { - return; - } - - const auto taskFiles = FileUtils::entryListRecursively(p_folder, {"*.json"}, QDir::Files); - for (const auto &file : taskFiles) { - auto task = loadTask(file); - if (task) { - qDebug() << "loaded task" << task->getLabel(); - connect(task.data(), &Task::outputRequested, - this, &TaskMgr::taskOutputRequested); - p_tasks.append(task); - } +void TaskMgr::loadTasksFromFolder(QVector> &p_tasks, const QString &p_folder) { + qDebug() << "load tasks from folder" << p_folder; + p_tasks.clear(); + + if (p_folder.isEmpty()) { + return; + } + + const auto taskFiles = FileUtils::entryListRecursively(p_folder, {"*.json"}, QDir::Files); + for (const auto &file : taskFiles) { + auto task = loadTask(file); + if (task) { + qDebug() << "loaded task" << task->getLabel(); + connect(task.data(), &Task::outputRequested, this, &TaskMgr::taskOutputRequested); + p_tasks.append(task); } + } } -QSharedPointer TaskMgr::loadTask(const QString &p_taskFile) -{ - const auto localeStr = ConfigMgr::getInst().getCoreConfig().getLocaleToUse(); - auto task = Task::fromFile(p_taskFile, localeStr, this); - return task; +QSharedPointer TaskMgr::loadTask(const QString &p_taskFile) { + const auto localeStr = ConfigMgr::getInst().getCoreConfig().getLocaleToUse(); + auto task = Task::fromFile(p_taskFile, localeStr, this); + return task; } -const TaskVariableMgr &TaskMgr::getVariableMgr() const -{ - return m_variableMgr; -} +const TaskVariableMgr &TaskMgr::getVariableMgr() const { return m_variableMgr; } diff --git a/src/task/taskmgr.h b/src/task/taskmgr.h index 22195166b8..cab2f01886 100644 --- a/src/task/taskmgr.h +++ b/src/task/taskmgr.h @@ -4,60 +4,58 @@ #include #include -#include #include +#include #include "task.h" #include "taskvariablemgr.h" -namespace vnotex -{ - class TaskMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - explicit TaskMgr(QObject *p_parent = nullptr); +namespace vnotex { +class TaskMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + explicit TaskMgr(QObject *p_parent = nullptr); - // It will be invoked after MainWindow show. - void init(); + // It will be invoked after MainWindow show. + void init(); - void reload(); + void reload(); - const QVector> &getAppTasks() const; + const QVector> &getAppTasks() const; - const QVector> &getUserTasks() const; + const QVector> &getUserTasks() const; - const QVector> &getNotebookTasks() const; + const QVector> &getNotebookTasks() const; - static QString getNotebookTaskFolder(); + static QString getNotebookTaskFolder(); - const TaskVariableMgr &getVariableMgr() const; + const TaskVariableMgr &getVariableMgr() const; - signals: - void tasksUpdated(); +signals: + void tasksUpdated(); - void taskOutputRequested(const QString &p_text) const; + void taskOutputRequested(const QString &p_text) const; - private: - void loadAllTasks(); +private: + void loadAllTasks(); - void loadNotebookTasks(); + void loadNotebookTasks(); - void loadGlobalTasks(); + void loadGlobalTasks(); - void loadTasksFromFolder(QVector> &p_tasks, const QString &p_folder); + void loadTasksFromFolder(QVector> &p_tasks, const QString &p_folder); - // Return nullptr if not a valid task. - QSharedPointer loadTask(const QString &p_taskFile); + // Return nullptr if not a valid task. + QSharedPointer loadTask(const QString &p_taskFile); - QVector> m_appTasks; + QVector> m_appTasks; - QVector> m_userTasks; + QVector> m_userTasks; - QVector> m_notebookTasks; + QVector> m_notebookTasks; - TaskVariableMgr m_variableMgr; - }; -} // ns vnotex + TaskVariableMgr m_variableMgr; +}; +} // namespace vnotex #endif // TASKMGR_H diff --git a/src/task/taskvariablemgr.cpp b/src/task/taskvariablemgr.cpp index cbc88b53a0..6bc840d26f 100644 --- a/src/task/taskvariablemgr.cpp +++ b/src/task/taskvariablemgr.cpp @@ -1,435 +1,408 @@ #include "taskvariablemgr.h" -#include -#include #include +#include +#include #include +#include #include -#include -#include -#include +#include #include -#include #include -#include -#include -#include +#include +#include +#include #include +#include +#include #include -#include -#include +#include +#include #include -#include +#include +#include "shellexecution.h" #include "task.h" #include "taskmgr.h" -#include "shellexecution.h" using namespace vnotex; - TaskVariable::TaskVariable(const QString &p_name, const Func &p_func) - : m_name(p_name), - m_func(p_func) -{ -} + : m_name(p_name), m_func(p_func) {} -QString TaskVariable::evaluate(Task *p_task, const QString &p_value) const -{ - return m_func(p_task, p_value); +QString TaskVariable::evaluate(Task *p_task, const QString &p_value) const { + return m_func(p_task, p_value); } +const QString TaskVariableMgr::c_variableSymbolRegExp = + QString(R"(\$\{([^${}:]+)(?::([^${}:]+))?\})"); -const QString TaskVariableMgr::c_variableSymbolRegExp = QString(R"(\$\{([^${}:]+)(?::([^${}:]+))?\})"); +TaskVariableMgr::TaskVariableMgr(TaskMgr *p_taskMgr) : m_taskMgr(p_taskMgr) {} -TaskVariableMgr::TaskVariableMgr(TaskMgr *p_taskMgr) - : m_taskMgr(p_taskMgr) -{ -} +void TaskVariableMgr::init() { initVariables(); } -void TaskVariableMgr::init() -{ - initVariables(); -} +void TaskVariableMgr::initVariables() { + m_variables.clear(); -void TaskVariableMgr::initVariables() -{ - m_variables.clear(); + m_needUpdateSystemEnvironment = true; - m_needUpdateSystemEnvironment = true; + initNotebookVariables(); - initNotebookVariables(); + initBufferVariables(); - initBufferVariables(); + initTaskVariables(); - initTaskVariables(); + initMagicVariables(); - initMagicVariables(); + initEnvironmentVariables(); - initEnvironmentVariables(); + initConfigVariables(); - initConfigVariables(); + initInputVariables(); - initInputVariables(); - - initShellVariables(); + initShellVariables(); } -void TaskVariableMgr::initNotebookVariables() -{ - addVariable("notebookFolder", [](Task *, const QString &) { - auto notebook = TaskVariableMgr::getCurrentNotebook(); - if (notebook) { - return PathUtils::cleanPath(notebook->getRootFolderAbsolutePath()); - } else { - return QString(); - } - }); - addVariable("notebookFolderName", [](Task *, const QString &) { - auto notebook = TaskVariableMgr::getCurrentNotebook(); - if (notebook) { - return PathUtils::dirName(notebook->getRootFolderPath()); - } else { - return QString(); - } - }); - addVariable("notebookName", [](Task *, const QString &) { - auto notebook = TaskVariableMgr::getCurrentNotebook(); - if (notebook) { - return notebook->getName(); - } else { - return QString(); - } - }); - addVariable("notebookDescription", [](Task *, const QString &) { - auto notebook = TaskVariableMgr::getCurrentNotebook(); - if (notebook) { - return notebook->getDescription(); - } else { - return QString(); - } - }); +void TaskVariableMgr::initNotebookVariables() { + addVariable("notebookFolder", [](Task *, const QString &) { + auto notebook = TaskVariableMgr::getCurrentNotebook(); + if (notebook) { + return PathUtils::cleanPath(notebook->getRootFolderAbsolutePath()); + } else { + return QString(); + } + }); + addVariable("notebookFolderName", [](Task *, const QString &) { + auto notebook = TaskVariableMgr::getCurrentNotebook(); + if (notebook) { + return PathUtils::dirName(notebook->getRootFolderPath()); + } else { + return QString(); + } + }); + addVariable("notebookName", [](Task *, const QString &) { + auto notebook = TaskVariableMgr::getCurrentNotebook(); + if (notebook) { + return notebook->getName(); + } else { + return QString(); + } + }); + addVariable("notebookDescription", [](Task *, const QString &) { + auto notebook = TaskVariableMgr::getCurrentNotebook(); + if (notebook) { + return notebook->getDescription(); + } else { + return QString(); + } + }); } -void TaskVariableMgr::initBufferVariables() -{ - addVariable("buffer", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - return PathUtils::cleanPath(buffer->getPath()); - } - return QString(); - }); - addVariable("bufferNotebookFolder", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - auto node = buffer->getNode(); - if (node) { - return PathUtils::cleanPath(node->getNotebook()->getRootFolderAbsolutePath()); - } - } - return QString(); - }); - addVariable("bufferRelativePath", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - auto node = buffer->getNode(); - if (node) { - return PathUtils::cleanPath(node->fetchPath()); - } else { - return PathUtils::cleanPath(buffer->getPath()); - } - } - return QString(); - }); - addVariable("bufferName", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - return PathUtils::fileName(buffer->getPath()); - } - return QString(); - }); - addVariable("bufferBaseName", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - return QFileInfo(buffer->getPath()).completeBaseName(); - } - return QString(); - }); - addVariable("bufferDir", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - return PathUtils::parentDirPath(buffer->getPath()); - } - return QString(); - }); - addVariable("bufferExt", [](Task *, const QString &) { - auto buffer = getCurrentBuffer(); - if (buffer) { - return QFileInfo(buffer->getPath()).suffix(); - } - return QString(); - }); - addVariable("selectedText", [](Task *, const QString &) { - auto win = getCurrentViewWindow(); - if (win) { - return win->selectedText(); - } - return QString(); - }); +void TaskVariableMgr::initBufferVariables() { + addVariable("buffer", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + return PathUtils::cleanPath(buffer->getPath()); + } + return QString(); + }); + addVariable("bufferNotebookFolder", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + auto node = buffer->getNode(); + if (node) { + return PathUtils::cleanPath(node->getNotebook()->getRootFolderAbsolutePath()); + } + } + return QString(); + }); + addVariable("bufferRelativePath", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + auto node = buffer->getNode(); + if (node) { + return PathUtils::cleanPath(node->fetchPath()); + } else { + return PathUtils::cleanPath(buffer->getPath()); + } + } + return QString(); + }); + addVariable("bufferName", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + return PathUtils::fileName(buffer->getPath()); + } + return QString(); + }); + addVariable("bufferBaseName", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + return QFileInfo(buffer->getPath()).completeBaseName(); + } + return QString(); + }); + addVariable("bufferDir", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + return PathUtils::parentDirPath(buffer->getPath()); + } + return QString(); + }); + addVariable("bufferExt", [](Task *, const QString &) { + auto buffer = getCurrentBuffer(); + if (buffer) { + return QFileInfo(buffer->getPath()).suffix(); + } + return QString(); + }); + addVariable("selectedText", [](Task *, const QString &) { + auto win = getCurrentViewWindow(); + if (win) { + return win->selectedText(); + } + return QString(); + }); } -void TaskVariableMgr::initTaskVariables() -{ - addVariable("cwd", [](Task *task, const QString &) { - return PathUtils::cleanPath(task->getOptionsCwd()); - }); - addVariable("taskFile", [](Task *task, const QString &) { - return PathUtils::cleanPath(task->getFile()); - }); - addVariable("taskDir", [](Task *task, const QString &) { - return PathUtils::parentDirPath(task->getFile()); - }); - addVariable("exeFile", [](Task *, const QString &) { - return PathUtils::cleanPath(qApp->applicationFilePath()); - }); - addVariable("pathSeparator", [](Task *, const QString &) { - return QDir::separator(); - }); - addVariable("notebookTaskFolder", [this](Task *, const QString &) { - return PathUtils::cleanPath(m_taskMgr->getNotebookTaskFolder()); - }); - addVariable("userTaskFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getUserTaskFolder()); - }); - addVariable("appTaskFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getAppTaskFolder()); - }); - addVariable("userThemeFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getUserThemeFolder()); - }); - addVariable("appThemeFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getAppThemeFolder()); - }); - addVariable("userDocsFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getUserDocsFolder()); - }); - addVariable("appDocsFolder", [](Task *, const QString &) { - return PathUtils::cleanPath(ConfigMgr::getInst().getAppDocsFolder()); - }); +void TaskVariableMgr::initTaskVariables() { + addVariable("cwd", [](Task *task, const QString &) { + return PathUtils::cleanPath(task->getOptionsCwd()); + }); + addVariable("taskFile", + [](Task *task, const QString &) { return PathUtils::cleanPath(task->getFile()); }); + addVariable("taskDir", [](Task *task, const QString &) { + return PathUtils::parentDirPath(task->getFile()); + }); + addVariable("exeFile", [](Task *, const QString &) { + return PathUtils::cleanPath(qApp->applicationFilePath()); + }); + addVariable("pathSeparator", [](Task *, const QString &) { return QDir::separator(); }); + addVariable("notebookTaskFolder", [this](Task *, const QString &) { + return PathUtils::cleanPath(m_taskMgr->getNotebookTaskFolder()); + }); + addVariable("userTaskFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getUserTaskFolder()); + }); + addVariable("appTaskFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getAppTaskFolder()); + }); + addVariable("userThemeFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getUserThemeFolder()); + }); + addVariable("appThemeFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getAppThemeFolder()); + }); + addVariable("userDocsFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getUserDocsFolder()); + }); + addVariable("appDocsFolder", [](Task *, const QString &) { + return PathUtils::cleanPath(ConfigMgr::getInst().getAppDocsFolder()); + }); } -void TaskVariableMgr::initMagicVariables() -{ - addVariable("magic", [](Task *, const QString &val) { - if (val.isEmpty()) { - return QString(); - } +void TaskVariableMgr::initMagicVariables() { + addVariable("magic", [](Task *, const QString &val) { + if (val.isEmpty()) { + return QString(); + } - auto overrides = SnippetMgr::generateOverrides(getCurrentBuffer()); - return SnippetMgr::getInst().applySnippetBySymbol(SnippetMgr::generateSnippetSymbol(val), overrides); - }); + auto overrides = SnippetMgr::generateOverrides(getCurrentBuffer()); + return SnippetMgr::getInst().applySnippetBySymbol(SnippetMgr::generateSnippetSymbol(val), + overrides); + }); } -void TaskVariableMgr::initEnvironmentVariables() -{ - addVariable("env", [this](Task *, const QString &val) { - if (val.isEmpty()) { - return QString(); - } - if (m_needUpdateSystemEnvironment) { - m_needUpdateSystemEnvironment = false; - m_systemEnv = QProcessEnvironment::systemEnvironment(); - } - return m_systemEnv.value(val); - }); +void TaskVariableMgr::initEnvironmentVariables() { + addVariable("env", [this](Task *, const QString &val) { + if (val.isEmpty()) { + return QString(); + } + if (m_needUpdateSystemEnvironment) { + m_needUpdateSystemEnvironment = false; + m_systemEnv = QProcessEnvironment::systemEnvironment(); + } + return m_systemEnv.value(val); + }); } -void TaskVariableMgr::initConfigVariables() -{ - // ${config:main.core.shortcuts.FullScreen}. - addVariable("config", [](Task *, const QString &val) { - if (val.isEmpty()) { - return QString(); - } - auto jsonVal = ConfigMgr::getInst().parseAndReadConfig(val); - switch (jsonVal.type()) { - case QJsonValue::Bool: - return jsonVal.toBool() ? QStringLiteral("1") : QStringLiteral("0"); - break; - - case QJsonValue::Double: - return QString::number(jsonVal.toDouble()); - break; - - case QJsonValue::String: - return jsonVal.toString(); - break; - - default: - return QString(); - } - }); +void TaskVariableMgr::initConfigVariables() { + // ${config:main.core.shortcuts.FullScreen}. + addVariable("config", [](Task *, const QString &val) { + if (val.isEmpty()) { + return QString(); + } + auto jsonVal = ConfigMgr::getInst().parseAndReadConfig(val); + switch (jsonVal.type()) { + case QJsonValue::Bool: + return jsonVal.toBool() ? QStringLiteral("1") : QStringLiteral("0"); + break; + + case QJsonValue::Double: + return QString::number(jsonVal.toDouble()); + break; + + case QJsonValue::String: + return jsonVal.toString(); + break; + + default: + return QString(); + } + }); } -void TaskVariableMgr::initInputVariables() -{ - // ${input:inputId}. - addVariable("input", [this](Task *task, const QString &val) { - if (val.isEmpty()) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("task (%1) with empty input id").arg(task->getLabel())); - } - - auto input = task->findInput(val); - if (!input) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("task (%1) with invalid input id (%2)").arg(task->getLabel(), val)); - } - - if (input->type == "promptString") { - const auto desc = evaluate(task, input->description); - const auto defaultText = evaluate(task, input->default_); - QInputDialog dialog(VNoteX::getInst().getMainWindow()); - dialog.setInputMode(QInputDialog::TextInput); - dialog.setTextEchoMode(input->password ? QLineEdit::Password : QLineEdit::Normal); - dialog.setWindowTitle(task->getLabel()); - dialog.setLabelText(desc); - dialog.setTextValue(defaultText); - if (dialog.exec() == QDialog::Accepted) { - return dialog.textValue(); - } else { - task->setCancelled(true); - return QString(); - } - } else if (input->type == "pickString") { - const auto desc = evaluate(task, input->description); - SelectDialog dialog(task->getLabel(), desc, VNoteX::getInst().getMainWindow()); - for (int i = 0; i < input->options.size(); i++) { - dialog.addSelection(input->options.at(i), i); - } - - if (dialog.exec() == QDialog::Accepted) { - int selection = dialog.getSelection(); - return input->options.at(selection); - } else { - task->setCancelled(true); - return QString(); - } - } else { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("task (%1) with invalid input type (%2)(%3)").arg(task->getLabel(), input->id, input->type)); - } +void TaskVariableMgr::initInputVariables() { + // ${input:inputId}. + addVariable("input", [this](Task *task, const QString &val) { + if (val.isEmpty()) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("task (%1) with empty input id").arg(task->getLabel())); + } + + auto input = task->findInput(val); + if (!input) { + Exception::throwOne( + Exception::Type::InvalidArgument, + QStringLiteral("task (%1) with invalid input id (%2)").arg(task->getLabel(), val)); + } + if (input->type == "promptString") { + const auto desc = evaluate(task, input->description); + const auto defaultText = evaluate(task, input->default_); + QInputDialog dialog(VNoteX::getInst().getMainWindow()); + dialog.setInputMode(QInputDialog::TextInput); + dialog.setTextEchoMode(input->password ? QLineEdit::Password : QLineEdit::Normal); + dialog.setWindowTitle(task->getLabel()); + dialog.setLabelText(desc); + dialog.setTextValue(defaultText); + if (dialog.exec() == QDialog::Accepted) { + return dialog.textValue(); + } else { + task->setCancelled(true); + return QString(); + } + } else if (input->type == "pickString") { + const auto desc = evaluate(task, input->description); + SelectDialog dialog(task->getLabel(), desc, VNoteX::getInst().getMainWindow()); + for (int i = 0; i < input->options.size(); i++) { + dialog.addSelection(input->options.at(i), i); + } + + if (dialog.exec() == QDialog::Accepted) { + int selection = dialog.getSelection(); + return input->options.at(selection); + } else { + task->setCancelled(true); return QString(); - }); + } + } else { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("task (%1) with invalid input type (%2)(%3)") + .arg(task->getLabel(), input->id, input->type)); + } + + return QString(); + }); } -void TaskVariableMgr::initShellVariables() -{ - // ${shell:command}. - addVariable("shell", [this](Task *task, const QString &val) { - QProcess process; - process.setWorkingDirectory(task->getOptionsCwd()); - ShellExecution::setupProcess(&process, val); - process.start(); - const int timeout = 1000; - if (!process.waitForStarted(timeout) || !process.waitForFinished(timeout)) { - Exception::throwOne(Exception::Type::InvalidArgument, - QStringLiteral("task (%1) failed to fetch shell variable (%2)").arg(task->getLabel(), val)); - } - return Task::decodeText(process.readAllStandardOutput()); - }); +void TaskVariableMgr::initShellVariables() { + // ${shell:command}. + addVariable("shell", [this](Task *task, const QString &val) { + QProcess process; + process.setWorkingDirectory(task->getOptionsCwd()); + ShellExecution::setupProcess(&process, val); + process.start(); + const int timeout = 1000; + if (!process.waitForStarted(timeout) || !process.waitForFinished(timeout)) { + Exception::throwOne(Exception::Type::InvalidArgument, + QStringLiteral("task (%1) failed to fetch shell variable (%2)") + .arg(task->getLabel(), val)); + } + return Task::decodeText(process.readAllStandardOutput()); + }); } -void TaskVariableMgr::addVariable(const QString &p_name, const TaskVariable::Func &p_func) -{ - Q_ASSERT(!m_variables.contains(p_name)); +void TaskVariableMgr::addVariable(const QString &p_name, const TaskVariable::Func &p_func) { + Q_ASSERT(!m_variables.contains(p_name)); - m_variables.insert(p_name, TaskVariable(p_name, p_func)); + m_variables.insert(p_name, TaskVariable(p_name, p_func)); } -const ViewWindow *TaskVariableMgr::getCurrentViewWindow() -{ - return VNoteX::getInst().getMainWindow()->getViewArea()->getCurrentViewWindow(); +const ViewWindow *TaskVariableMgr::getCurrentViewWindow() { + return VNoteX::getInst().getMainWindow()->getViewArea()->getCurrentViewWindow(); } -Buffer *TaskVariableMgr::getCurrentBuffer() -{ - auto win = getCurrentViewWindow(); - if (win) { - return win->getBuffer(); - } - return nullptr; +Buffer *TaskVariableMgr::getCurrentBuffer() { + auto win = getCurrentViewWindow(); + if (win) { + return win->getBuffer(); + } + return nullptr; } -QSharedPointer TaskVariableMgr::getCurrentNotebook() -{ - return VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); +QSharedPointer TaskVariableMgr::getCurrentNotebook() { + return VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); } -QString TaskVariableMgr::evaluate(Task *p_task, const QString &p_text) const -{ - QString content(p_text); - - int maxTimesAtSamePos = 100; - - QRegularExpression regExp(c_variableSymbolRegExp); - int pos = 0; - while (pos < content.size()) { - QRegularExpressionMatch match; - int idx = content.indexOf(regExp, pos, &match); - if (idx == -1) { - break; - } - - const auto varName = match.captured(1).trimmed(); - const auto varValue = match.captured(2).trimmed(); - auto var = findVariable(varName); - if (!var) { - // Skip it. - pos = idx + match.capturedLength(0); - continue; - } - - const auto afterText = var->evaluate(p_task, varValue); - content.replace(idx, match.capturedLength(0), afterText); - - // @afterText may still contains variable symbol. - if (pos == idx) { - if (--maxTimesAtSamePos == 0) { - break; - } - } else { - maxTimesAtSamePos = 100; - } - pos = idx; +QString TaskVariableMgr::evaluate(Task *p_task, const QString &p_text) const { + QString content(p_text); + + int maxTimesAtSamePos = 100; + + QRegularExpression regExp(c_variableSymbolRegExp); + int pos = 0; + while (pos < content.size()) { + QRegularExpressionMatch match; + int idx = content.indexOf(regExp, pos, &match); + if (idx == -1) { + break; } - return content; -} + const auto varName = match.captured(1).trimmed(); + const auto varValue = match.captured(2).trimmed(); + auto var = findVariable(varName); + if (!var) { + // Skip it. + pos = idx + match.capturedLength(0); + continue; + } + + const auto afterText = var->evaluate(p_task, varValue); + content.replace(idx, match.capturedLength(0), afterText); -QStringList TaskVariableMgr::evaluate(Task *p_task, const QStringList &p_texts) const -{ - QStringList strs; - for (const auto &str : p_texts) { - strs << evaluate(p_task, str); + // @afterText may still contains variable symbol. + if (pos == idx) { + if (--maxTimesAtSamePos == 0) { + break; + } + } else { + maxTimesAtSamePos = 100; } - return strs; + pos = idx; + } + + return content; } -const TaskVariable *TaskVariableMgr::findVariable(const QString &p_name) const -{ - auto it = m_variables.find(p_name); - if (it != m_variables.end()) { - return &(it.value()); - } +QStringList TaskVariableMgr::evaluate(Task *p_task, const QStringList &p_texts) const { + QStringList strs; + for (const auto &str : p_texts) { + strs << evaluate(p_task, str); + } + return strs; +} + +const TaskVariable *TaskVariableMgr::findVariable(const QString &p_name) const { + auto it = m_variables.find(p_name); + if (it != m_variables.end()) { + return &(it.value()); + } - return nullptr; + return nullptr; } -void TaskVariableMgr::overrideVariable(const QString &p_name, const TaskVariable::Func &p_func) -{ - m_variables.insert(p_name, TaskVariable(p_name, p_func)); +void TaskVariableMgr::overrideVariable(const QString &p_name, const TaskVariable::Func &p_func) { + m_variables.insert(p_name, TaskVariable(p_name, p_func)); } diff --git a/src/task/taskvariablemgr.h b/src/task/taskvariablemgr.h index 9b1c9f381d..fc919eb523 100644 --- a/src/task/taskvariablemgr.h +++ b/src/task/taskvariablemgr.h @@ -6,100 +6,96 @@ #include #include -#include -#include -#include #include +#include +#include +#include -namespace vnotex -{ - class Task; - class Notebook; - class Buffer; - class ViewWindow; - class TaskMgr; - - class TaskVariable - { - public: - typedef std::function Func; +namespace vnotex { +class Task; +class Notebook; +class Buffer; +class ViewWindow; +class TaskMgr; - TaskVariable(const QString &p_name, const Func &p_func); +class TaskVariable { +public: + typedef std::function Func; - QString evaluate(Task *p_task, const QString &p_value) const; + TaskVariable(const QString &p_name, const Func &p_func); - private: - QString m_name; + QString evaluate(Task *p_task, const QString &p_value) const; - Func m_func; - }; +private: + QString m_name; + Func m_func; +}; - class TaskVariableMgr : private Noncopyable - { - public: - explicit TaskVariableMgr(TaskMgr *p_taskMgr); +class TaskVariableMgr : private Noncopyable { +public: + explicit TaskVariableMgr(TaskMgr *p_taskMgr); - void init(); + void init(); - QString evaluate(Task *p_task, const QString &p_text) const; + QString evaluate(Task *p_task, const QString &p_text) const; - QStringList evaluate(Task *p_task, const QStringList &p_texts) const; + QStringList evaluate(Task *p_task, const QStringList &p_texts) const; - // Used for UT. - void overrideVariable(const QString &p_name, const TaskVariable::Func &p_func); + // Used for UT. + void overrideVariable(const QString &p_name, const TaskVariable::Func &p_func); - static Buffer *getCurrentBuffer(); + static Buffer *getCurrentBuffer(); - static QSharedPointer getCurrentNotebook(); + static QSharedPointer getCurrentNotebook(); - private: - void initVariables(); +private: + void initVariables(); - void initNotebookVariables(); + void initNotebookVariables(); - void initBufferVariables(); + void initBufferVariables(); - void initTaskVariables(); + void initTaskVariables(); - void initMagicVariables(); + void initMagicVariables(); - void initEnvironmentVariables(); + void initEnvironmentVariables(); - void initConfigVariables(); + void initConfigVariables(); - void initInputVariables(); + void initInputVariables(); - void initShellVariables(); + void initShellVariables(); - void addVariable(const QString &p_name, const TaskVariable::Func &p_func); + void addVariable(const QString &p_name, const TaskVariable::Func &p_func); - const TaskVariable *findVariable(const QString &p_name) const; + const TaskVariable *findVariable(const QString &p_name) const; - /* - QString evaluateInputVariables(const QString &p_text, - const Task *p_task) const; + /* + QString evaluateInputVariables(const QString &p_text, + const Task *p_task) const; - QString evaluateShellVariables(const QString &p_text, - const Task *p_task) const; - */ + QString evaluateShellVariables(const QString &p_text, + const Task *p_task) const; + */ - static const ViewWindow *getCurrentViewWindow(); + static const ViewWindow *getCurrentViewWindow(); - TaskMgr *m_taskMgr = nullptr; + TaskMgr *m_taskMgr = nullptr; - QHash m_variables; + QHash m_variables; - bool m_needUpdateSystemEnvironment = true; + bool m_needUpdateSystemEnvironment = true; - QProcessEnvironment m_systemEnv; + QProcessEnvironment m_systemEnv; - // %{name[:value]}%. - // Captured texts: - // 1 - The name of the variable (trim needed). - // 2 - The value option of the variable if available (trim needed). - static const QString c_variableSymbolRegExp; - }; -} // ns vnotex + // %{name[:value]}%. + // Captured texts: + // 1 - The name of the variable (trim needed). + // 2 - The value option of the variable if available (trim needed). + static const QString c_variableSymbolRegExp; +}; +} // namespace vnotex #endif // TASKVARIABLEMGR_H diff --git a/src/unitedentry/entrypopup.cpp b/src/unitedentry/entrypopup.cpp index 4c8667bab8..3eb01deb06 100644 --- a/src/unitedentry/entrypopup.cpp +++ b/src/unitedentry/entrypopup.cpp @@ -1,46 +1,41 @@ #include "entrypopup.h" -#include #include +#include #include using namespace vnotex; -EntryPopup::EntryPopup(QWidget *p_parent) - : QFrame(p_parent) -{ - Q_ASSERT(p_parent); - auto layout = new QVBoxLayout(this); - Q_UNUSED(layout); +EntryPopup::EntryPopup(QWidget *p_parent) : QFrame(p_parent) { + Q_ASSERT(p_parent); + auto layout = new QVBoxLayout(this); + Q_UNUSED(layout); } -EntryPopup::~EntryPopup() -{ - if (m_widget) { - takeWidget(m_widget.data()); - } +EntryPopup::~EntryPopup() { + if (m_widget) { + takeWidget(m_widget.data()); + } } -void EntryPopup::setWidget(const QSharedPointer &p_widget) -{ - if (p_widget == m_widget) { - return; - } - - if (m_widget) { - takeWidget(m_widget.data()); - } - - m_widget = p_widget; - if (m_widget) { - layout()->addWidget(m_widget.data()); - m_widget->show(); - } +void EntryPopup::setWidget(const QSharedPointer &p_widget) { + if (p_widget == m_widget) { + return; + } + + if (m_widget) { + takeWidget(m_widget.data()); + } + + m_widget = p_widget; + if (m_widget) { + layout()->addWidget(m_widget.data()); + m_widget->show(); + } } -void EntryPopup::takeWidget(QWidget *p_widget) -{ - layout()->removeWidget(p_widget); - p_widget->hide(); - p_widget->setParent(nullptr); +void EntryPopup::takeWidget(QWidget *p_widget) { + layout()->removeWidget(p_widget); + p_widget->hide(); + p_widget->setParent(nullptr); } diff --git a/src/unitedentry/entrypopup.h b/src/unitedentry/entrypopup.h index 0798a52aee..afa69c1074 100644 --- a/src/unitedentry/entrypopup.h +++ b/src/unitedentry/entrypopup.h @@ -4,24 +4,22 @@ #include #include -namespace vnotex -{ - class EntryPopup : public QFrame - { - Q_OBJECT - public: - explicit EntryPopup(QWidget *p_parent = nullptr); +namespace vnotex { +class EntryPopup : public QFrame { + Q_OBJECT +public: + explicit EntryPopup(QWidget *p_parent = nullptr); - ~EntryPopup(); + ~EntryPopup(); - void setWidget(const QSharedPointer &p_widget); + void setWidget(const QSharedPointer &p_widget); - private: - void takeWidget(QWidget *p_widget); +private: + void takeWidget(QWidget *p_widget); - private: - QSharedPointer m_widget = nullptr; - }; -} +private: + QSharedPointer m_widget = nullptr; +}; +} // namespace vnotex #endif // ENTRYPOPUP_H diff --git a/src/unitedentry/entrywidgetfactory.cpp b/src/unitedentry/entrywidgetfactory.cpp index e96bdb6e4a..56f65fa0b7 100644 --- a/src/unitedentry/entrywidgetfactory.cpp +++ b/src/unitedentry/entrywidgetfactory.cpp @@ -2,28 +2,26 @@ #include -#include #include +#include using namespace vnotex; -QSharedPointer EntryWidgetFactory::createTreeWidget(int p_columnCount) -{ - auto tree = QSharedPointer::create(TreeWidget::Flag::EnhancedStyle, nullptr); - tree->setColumnCount(p_columnCount); - tree->setHeaderHidden(true); - TreeWidget::showHorizontalScrollbar(tree.data()); - return tree; +QSharedPointer EntryWidgetFactory::createTreeWidget(int p_columnCount) { + auto tree = QSharedPointer::create(TreeWidget::Flag::EnhancedStyle, nullptr); + tree->setColumnCount(p_columnCount); + tree->setHeaderHidden(true); + TreeWidget::showHorizontalScrollbar(tree.data()); + return tree; } -QSharedPointer EntryWidgetFactory::createLabel(const QString &p_info) -{ - auto label = QSharedPointer::create(p_info, nullptr); - label->setAlignment(Qt::AlignTop | Qt::AlignLeft); +QSharedPointer EntryWidgetFactory::createLabel(const QString &p_info) { + auto label = QSharedPointer::create(p_info, nullptr); + label->setAlignment(Qt::AlignTop | Qt::AlignLeft); - auto fnt = label->font(); - fnt.setPointSize(fnt.pointSize() + 2); - label->setFont(fnt); + auto fnt = label->font(); + fnt.setPointSize(fnt.pointSize() + 2); + label->setFont(fnt); - return label; + return label; } diff --git a/src/unitedentry/entrywidgetfactory.h b/src/unitedentry/entrywidgetfactory.h index e402709e44..854c7ade21 100644 --- a/src/unitedentry/entrywidgetfactory.h +++ b/src/unitedentry/entrywidgetfactory.h @@ -7,17 +7,15 @@ class QTreeWidget; class QLabel; class QString; -namespace vnotex -{ - class EntryWidgetFactory - { - public: - EntryWidgetFactory() = delete; +namespace vnotex { +class EntryWidgetFactory { +public: + EntryWidgetFactory() = delete; - static QSharedPointer createTreeWidget(int p_columnCount); + static QSharedPointer createTreeWidget(int p_columnCount); - static QSharedPointer createLabel(const QString &p_info); - }; -} + static QSharedPointer createLabel(const QString &p_info); +}; +} // namespace vnotex #endif // ENTRYWIDGETFACTORY_H diff --git a/src/unitedentry/findunitedentry.cpp b/src/unitedentry/findunitedentry.cpp index 938d123d7f..921e22d35e 100644 --- a/src/unitedentry/findunitedentry.cpp +++ b/src/unitedentry/findunitedentry.cpp @@ -1,348 +1,326 @@ #include "findunitedentry.h" -#include #include -#include #include +#include +#include -#include -#include -#include +#include "entrywidgetfactory.h" +#include "unitedentryhelper.h" +#include "unitedentrymgr.h" +#include +#include #include -#include +#include #include #include +#include #include -#include -#include +#include #include -#include "unitedentryhelper.h" -#include "entrywidgetfactory.h" -#include "unitedentrymgr.h" using namespace vnotex; FindUnitedEntry::FindUnitedEntry(const QSharedPointer &p_provider, - UnitedEntryMgr *p_mgr, - QObject *p_parent) - : IUnitedEntry("find", - tr("Search for files in notebooks"), - p_mgr, - p_parent), - m_provider(p_provider) -{ - m_processTimer = new QTimer(this); - m_processTimer->setSingleShot(true); - m_processTimer->setInterval(500); - connect(m_processTimer, &QTimer::timeout, - this, &FindUnitedEntry::doProcessInternal); + UnitedEntryMgr *p_mgr, QObject *p_parent) + : IUnitedEntry("find", tr("Search for files in notebooks"), p_mgr, p_parent), + m_provider(p_provider) { + m_processTimer = new QTimer(this); + m_processTimer->setSingleShot(true); + m_processTimer->setInterval(500); + connect(m_processTimer, &QTimer::timeout, this, &FindUnitedEntry::doProcessInternal); } -void FindUnitedEntry::initOnFirstProcess() -{ - m_parser.setApplicationDescription(tr("Search for files in notebooks with advanced options for scope, object, target and so on.")); +void FindUnitedEntry::initOnFirstProcess() { + m_parser.setApplicationDescription(tr( + "Search for files in notebooks with advanced options for scope, object, target and so on.")); - m_parser.addPositionalArgument("keywords", tr("Keywords to search for.")); + m_parser.addPositionalArgument("keywords", tr("Keywords to search for.")); - QCommandLineOption scopeOpt({"s", "scope"}, - tr("Search scope. Possible values: buffer/folder/notebook/all_notebook."), - tr("search_scope"), - "notebook"); - m_parser.addOption(scopeOpt); + QCommandLineOption scopeOpt( + {"s", "scope"}, tr("Search scope. Possible values: buffer/folder/notebook/all_notebook."), + tr("search_scope"), "notebook"); + m_parser.addOption(scopeOpt); - QCommandLineOption objectOpt({"b", "object"}, - tr("Search objects. Possible values: name/content/tag/path."), - tr("search_objects")); - objectOpt.setDefaultValues({"name", "content"}); - m_parser.addOption(objectOpt); + QCommandLineOption objectOpt({"b", "object"}, + tr("Search objects. Possible values: name/content/tag/path."), + tr("search_objects")); + objectOpt.setDefaultValues({"name", "content"}); + m_parser.addOption(objectOpt); - QCommandLineOption targetOpt({"t", "target"}, - tr("Search targets. Possible values: file/folder/notebook."), - tr("search_targets")); - targetOpt.setDefaultValues({"file", "folder"}); - m_parser.addOption(targetOpt); + QCommandLineOption targetOpt({"t", "target"}, + tr("Search targets. Possible values: file/folder/notebook."), + tr("search_targets")); + targetOpt.setDefaultValues({"file", "folder"}); + m_parser.addOption(targetOpt); - QCommandLineOption patternOpt({"p", "pattern"}, - tr("Wildcard pattern of files to search."), - tr("file_pattern")); - m_parser.addOption(patternOpt); + QCommandLineOption patternOpt({"p", "pattern"}, tr("Wildcard pattern of files to search."), + tr("file_pattern")); + m_parser.addOption(patternOpt); - SearchToken::addSearchOptionsToCommand(&m_parser); + SearchToken::addSearchOptionsToCommand(&m_parser); } -void FindUnitedEntry::processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) -{ - // Do another timer delay here since it is a very expensive operation. - m_processTimer->stop(); +void FindUnitedEntry::processInternal( + const QString &p_args, + const std::function &)> &p_popupWidgetFunc) { + // Do another timer delay here since it is a very expensive operation. + m_processTimer->stop(); + + Q_ASSERT(!isOngoing()); + + setOngoing(true); + + auto args = ProcessUtils::parseCombinedArgString(p_args); + // The parser needs the first arg to be the application name. + args.prepend(name()); + bool ret = m_parser.parse(args); + const auto positionalArgs = m_parser.positionalArguments(); + if (!ret) { + auto label = EntryWidgetFactory::createLabel(m_parser.errorText()); + p_popupWidgetFunc(label); + finish(); + return; + } + if (positionalArgs.isEmpty()) { + auto label = EntryWidgetFactory::createLabel(getHelpText()); + p_popupWidgetFunc(label); + finish(); + return; + } + + auto opt = collectOptions(); + if (m_searchOption && m_searchOption->strictEquals(*opt)) { + // Reuse last result. + p_popupWidgetFunc(m_resultTree); + finish(); + return; + } - Q_ASSERT(!isOngoing()); + m_searchOption = opt; - setOngoing(true); + m_searchTokenOfSession.clear(); - auto args = ProcessUtils::parseCombinedArgString(p_args); - // The parser needs the first arg to be the application name. - args.prepend(name()); - bool ret = m_parser.parse(args); - const auto positionalArgs = m_parser.positionalArguments(); - if (!ret) { - auto label = EntryWidgetFactory::createLabel(m_parser.errorText()); - p_popupWidgetFunc(label); - finish(); - return; - } - if (positionalArgs.isEmpty()) { - auto label = EntryWidgetFactory::createLabel(getHelpText()); - p_popupWidgetFunc(label); - finish(); - return; - } + prepareResultTree(); - auto opt = collectOptions(); - if (m_searchOption && m_searchOption->strictEquals(*opt)) { - // Reuse last result. - p_popupWidgetFunc(m_resultTree); - finish(); - return; - } + p_popupWidgetFunc(m_resultTree); - m_searchOption = opt; + m_processTimer->start(); +} - m_searchTokenOfSession.clear(); +QSharedPointer FindUnitedEntry::collectOptions() const { + auto opt = QSharedPointer::create(); - prepareResultTree(); + opt->m_engine = SearchEngine::Internal; - p_popupWidgetFunc(m_resultTree); + opt->m_keyword = m_parser.positionalArguments().join(QLatin1Char(' ')); + Q_ASSERT(!opt->m_keyword.isEmpty()); - m_processTimer->start(); -} + opt->m_filePattern = m_parser.value("p"); -QSharedPointer FindUnitedEntry::collectOptions() const -{ - auto opt = QSharedPointer::create(); - - opt->m_engine = SearchEngine::Internal; - - opt->m_keyword = m_parser.positionalArguments().join(QLatin1Char(' ')); - Q_ASSERT(!opt->m_keyword.isEmpty()); - - opt->m_filePattern = m_parser.value("p"); - - { - SearchScope scope = SearchScope::CurrentNotebook; - const auto scopeStr = m_parser.value("s"); - if (scopeStr == QStringLiteral("buffer")) { - scope = SearchScope::Buffers; - } else if (scopeStr == QStringLiteral("folder")) { - scope = SearchScope::CurrentFolder; - } else if (scopeStr == QStringLiteral("notebook")) { - scope = SearchScope::CurrentNotebook; - } else if (scopeStr == QStringLiteral("all_notebook")) { - scope = SearchScope::AllNotebooks; - } - opt->m_scope = scope; + { + SearchScope scope = SearchScope::CurrentNotebook; + const auto scopeStr = m_parser.value("s"); + if (scopeStr == QStringLiteral("buffer")) { + scope = SearchScope::Buffers; + } else if (scopeStr == QStringLiteral("folder")) { + scope = SearchScope::CurrentFolder; + } else if (scopeStr == QStringLiteral("notebook")) { + scope = SearchScope::CurrentNotebook; + } else if (scopeStr == QStringLiteral("all_notebook")) { + scope = SearchScope::AllNotebooks; } - - { - SearchObjects objects = SearchObject::ObjectNone; - const auto objectStrs = m_parser.values("b"); - for (const auto &str : objectStrs) { - if (str == QStringLiteral("name")) { - objects |= SearchObject::SearchName; - } else if (str == QStringLiteral("content")) { - objects |= SearchObject::SearchContent; - } else if (str == QStringLiteral("tag")) { - objects |= SearchObject::SearchTag; - } else if (str == QStringLiteral("path")) { - objects |= SearchObject::SearchPath; - } - } - opt->m_objects = objects; + opt->m_scope = scope; + } + + { + SearchObjects objects = SearchObject::ObjectNone; + const auto objectStrs = m_parser.values("b"); + for (const auto &str : objectStrs) { + if (str == QStringLiteral("name")) { + objects |= SearchObject::SearchName; + } else if (str == QStringLiteral("content")) { + objects |= SearchObject::SearchContent; + } else if (str == QStringLiteral("tag")) { + objects |= SearchObject::SearchTag; + } else if (str == QStringLiteral("path")) { + objects |= SearchObject::SearchPath; + } } - - { - SearchTargets targets = SearchTarget::TargetNone; - auto targetStrs = m_parser.values("t"); - for (const auto &str : targetStrs) { - if (str == QStringLiteral("file")) { - targets |= SearchTarget::SearchFile; - } else if (str == QStringLiteral("folder")) { - targets |= SearchTarget::SearchFolder; - } else if (str == QStringLiteral("notebook")) { - targets |= SearchTarget::SearchNotebook; - } - } - opt->m_targets = targets; + opt->m_objects = objects; + } + + { + SearchTargets targets = SearchTarget::TargetNone; + auto targetStrs = m_parser.values("t"); + for (const auto &str : targetStrs) { + if (str == QStringLiteral("file")) { + targets |= SearchTarget::SearchFile; + } else if (str == QStringLiteral("folder")) { + targets |= SearchTarget::SearchFolder; + } else if (str == QStringLiteral("notebook")) { + targets |= SearchTarget::SearchNotebook; + } } + opt->m_targets = targets; + } - { - FindOptions options = FindOption::FindNone; - if (m_parser.isSet("c")) { - options |= FindOption::CaseSensitive; - } - if (m_parser.isSet("r")) { - options |= FindOption::RegularExpression; - } - if (m_parser.isSet("w")) { - options |= FindOption::WholeWordOnly; - } - if (m_parser.isSet("f")) { - options |= FindOption::FuzzySearch; - } - opt->m_findOptions = options; + { + FindOptions options = FindOption::FindNone; + if (m_parser.isSet("c")) { + options |= FindOption::CaseSensitive; } + if (m_parser.isSet("r")) { + options |= FindOption::RegularExpression; + } + if (m_parser.isSet("w")) { + options |= FindOption::WholeWordOnly; + } + if (m_parser.isSet("f")) { + options |= FindOption::FuzzySearch; + } + opt->m_findOptions = options; + } - return opt; + return opt; } -QString FindUnitedEntry::getHelpText() const -{ - auto text = m_parser.helpText(); - // Skip the first line containing the application name. - return text.mid(text.indexOf('\n') + 1); +QString FindUnitedEntry::getHelpText() const { + auto text = m_parser.helpText(); + // Skip the first line containing the application name. + return text.mid(text.indexOf('\n') + 1); } -Searcher *FindUnitedEntry::getSearcher() -{ - if (!m_searcher) { - m_searcher = new Searcher(this); - connect(m_searcher, &Searcher::resultItemAdded, - this, [this](const QSharedPointer &p_item) { - addLocation(p_item->m_location); - }); - connect(m_searcher, &Searcher::resultItemsAdded, - this, [this](const QVector> &p_items) { - for (const auto &item : p_items) { - addLocation(item->m_location); - } - }); - connect(m_searcher, &Searcher::finished, - this, &FindUnitedEntry::handleSearchFinished); - } - return m_searcher; +Searcher *FindUnitedEntry::getSearcher() { + if (!m_searcher) { + m_searcher = new Searcher(this); + connect(m_searcher, &Searcher::resultItemAdded, this, + [this](const QSharedPointer &p_item) { + addLocation(p_item->m_location); + }); + connect(m_searcher, &Searcher::resultItemsAdded, this, + [this](const QVector> &p_items) { + for (const auto &item : p_items) { + addLocation(item->m_location); + } + }); + connect(m_searcher, &Searcher::finished, this, &FindUnitedEntry::handleSearchFinished); + } + return m_searcher; } -void FindUnitedEntry::handleSearchFinished(SearchState p_state) -{ - if (p_state != SearchState::Busy) { - getSearcher()->clear(); - finish(); - } +void FindUnitedEntry::handleSearchFinished(SearchState p_state) { + if (p_state != SearchState::Busy) { + getSearcher()->clear(); + finish(); + } } -void FindUnitedEntry::prepareResultTree() -{ - if (!m_resultTree) { - m_resultTree = EntryWidgetFactory::createTreeWidget(1); - connect(m_resultTree.data(), &QTreeWidget::itemActivated, - this, &FindUnitedEntry::handleItemActivated); - } +void FindUnitedEntry::prepareResultTree() { + if (!m_resultTree) { + m_resultTree = EntryWidgetFactory::createTreeWidget(1); + connect(m_resultTree.data(), &QTreeWidget::itemActivated, this, + &FindUnitedEntry::handleItemActivated); + } - m_resultTree->clear(); + m_resultTree->clear(); } -void FindUnitedEntry::addLocation(const ComplexLocation &p_location) -{ - auto item = new QTreeWidgetItem(m_resultTree.data()); - item->setText(0, p_location.m_displayPath); - item->setIcon(0, UnitedEntryHelper::itemIcon(UnitedEntryHelper::locationTypeToItemType(p_location.m_type))); - item->setData(0, Qt::UserRole, p_location.m_path); - item->setToolTip(0, p_location.m_path); - - // Add sub items. - for (const auto &line : p_location.m_lines) { - auto subItem = new QTreeWidgetItem(item); - - // Truncate the text. - if (line.m_text.size() > 500) { - subItem->setText(0, line.m_text.left(500)); - } else { - subItem->setText(0, line.m_text); - } - - if (!line.m_segments.isEmpty()) { - subItem->setData(0, HighlightsRole, QVariant::fromValue(line.m_segments)); - } - - subItem->setData(0, Qt::UserRole, line.m_lineNumber); +void FindUnitedEntry::addLocation(const ComplexLocation &p_location) { + auto item = new QTreeWidgetItem(m_resultTree.data()); + item->setText(0, p_location.m_displayPath); + item->setIcon( + 0, UnitedEntryHelper::itemIcon(UnitedEntryHelper::locationTypeToItemType(p_location.m_type))); + item->setData(0, Qt::UserRole, p_location.m_path); + item->setToolTip(0, p_location.m_path); + + // Add sub items. + for (const auto &line : p_location.m_lines) { + auto subItem = new QTreeWidgetItem(item); + + // Truncate the text. + if (line.m_text.size() > 500) { + subItem->setText(0, line.m_text.left(500)); + } else { + subItem->setText(0, line.m_text); } - if (m_mgr->getExpandAllEnabled()) { - item->setExpanded(true); + if (!line.m_segments.isEmpty()) { + subItem->setData(0, HighlightsRole, QVariant::fromValue(line.m_segments)); } - if (m_resultTree->topLevelItemCount() == 1) { - m_resultTree->setCurrentItem(item); - } + subItem->setData(0, Qt::UserRole, line.m_lineNumber); + } + + if (m_mgr->getExpandAllEnabled()) { + item->setExpanded(true); + } + + if (m_resultTree->topLevelItemCount() == 1) { + m_resultTree->setCurrentItem(item); + } } -void FindUnitedEntry::doProcessInternal() -{ - if (isAskedToStop()) { - finish(); - return; - } +void FindUnitedEntry::doProcessInternal() { + if (isAskedToStop()) { + finish(); + return; + } - QString msg; - auto state = SearchHelper::searchOnProvider(getSearcher(), m_searchOption, m_provider, msg); - if (!msg.isEmpty()) { - qWarning() << msg; - } + QString msg; + auto state = SearchHelper::searchOnProvider(getSearcher(), m_searchOption, m_provider, msg); + if (!msg.isEmpty()) { + qWarning() << msg; + } - handleSearchFinished(state); + handleSearchFinished(state); } -void FindUnitedEntry::stop() -{ - IUnitedEntry::stop(); +void FindUnitedEntry::stop() { + IUnitedEntry::stop(); - if (m_processTimer->isActive()) { - m_processTimer->stop(); - // Let it go finished. - doProcessInternal(); - } + if (m_processTimer->isActive()) { + m_processTimer->stop(); + // Let it go finished. + doProcessInternal(); + } } -void FindUnitedEntry::finish() -{ - setOngoing(false); - emit finished(); +void FindUnitedEntry::finish() { + setOngoing(false); + emit finished(); } -QSharedPointer FindUnitedEntry::currentPopupWidget() const -{ - return m_resultTree; -} +QSharedPointer FindUnitedEntry::currentPopupWidget() const { return m_resultTree; } -void FindUnitedEntry::handleItemActivated(QTreeWidgetItem *p_item, int p_column) -{ - Q_UNUSED(p_column); +void FindUnitedEntry::handleItemActivated(QTreeWidgetItem *p_item, int p_column) { + Q_UNUSED(p_column); - if (!m_searchTokenOfSession) { - if (m_searchOption->m_objects & SearchObject::SearchContent) { - m_searchTokenOfSession = QSharedPointer::create(getSearcher()->getToken()); - } + if (!m_searchTokenOfSession) { + if (m_searchOption->m_objects & SearchObject::SearchContent) { + m_searchTokenOfSession = QSharedPointer::create(getSearcher()->getToken()); } - - // TODO: decode the path of location and handle different types of destination. - auto paras = QSharedPointer::create(); - - QString itemPath; - auto pa = p_item->parent(); - if (pa) { - itemPath = pa->data(0, Qt::UserRole).toString(); - paras->m_lineNumber = p_item->data(0, Qt::UserRole).toInt(); - } else { - itemPath = p_item->data(0, Qt::UserRole).toString(); - // Use the first line number if there is any. - if (p_item->childCount() > 0) { - auto childItem = p_item->child(0); - paras->m_lineNumber = childItem->data(0, Qt::UserRole).toInt(); - } + } + + // TODO: decode the path of location and handle different types of destination. + auto paras = QSharedPointer::create(); + + QString itemPath; + auto pa = p_item->parent(); + if (pa) { + itemPath = pa->data(0, Qt::UserRole).toString(); + paras->m_lineNumber = p_item->data(0, Qt::UserRole).toInt(); + } else { + itemPath = p_item->data(0, Qt::UserRole).toString(); + // Use the first line number if there is any. + if (p_item->childCount() > 0) { + auto childItem = p_item->child(0); + paras->m_lineNumber = childItem->data(0, Qt::UserRole).toInt(); } + } - paras->m_searchToken = m_searchTokenOfSession; - emit VNoteX::getInst().openFileRequested(itemPath, paras); + paras->m_searchToken = m_searchTokenOfSession; + emit VNoteX::getInst().openFileRequested(itemPath, paras); - emit itemActivated(true, false); + emit itemActivated(true, false); } diff --git a/src/unitedentry/findunitedentry.h b/src/unitedentry/findunitedentry.h index 6831ead3af..0e730d78b1 100644 --- a/src/unitedentry/findunitedentry.h +++ b/src/unitedentry/findunitedentry.h @@ -12,64 +12,63 @@ class QTreeWidget; class QTreeWidgetItem; class QTimer; -namespace vnotex -{ - class Searcher; - class ISearchInfoProvider; - struct ComplexLocation; - class SearchToken; +namespace vnotex { +class Searcher; +class ISearchInfoProvider; +struct ComplexLocation; +class SearchToken; - class FindUnitedEntry : public IUnitedEntry - { - Q_OBJECT - public: - FindUnitedEntry(const QSharedPointer &p_provider, - UnitedEntryMgr *p_mgr, - QObject *p_parent = nullptr); +class FindUnitedEntry : public IUnitedEntry { + Q_OBJECT +public: + FindUnitedEntry(const QSharedPointer &p_provider, UnitedEntryMgr *p_mgr, + QObject *p_parent = nullptr); - void stop() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; - QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; + QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; - protected: - void initOnFirstProcess() Q_DECL_OVERRIDE; +protected: + void initOnFirstProcess() Q_DECL_OVERRIDE; - void processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE; + void + processInternal(const QString &p_args, + const std::function &)> &p_popupWidgetFunc) + Q_DECL_OVERRIDE; - private: - QString getHelpText() const; +private: + QString getHelpText() const; - QSharedPointer collectOptions() const; + QSharedPointer collectOptions() const; - Searcher *getSearcher(); + Searcher *getSearcher(); - void handleSearchFinished(SearchState p_state); + void handleSearchFinished(SearchState p_state); - void prepareResultTree(); + void prepareResultTree(); - void addLocation(const ComplexLocation &p_location); + void addLocation(const ComplexLocation &p_location); - void doProcessInternal(); + void doProcessInternal(); - void finish(); + void finish(); - void handleItemActivated(QTreeWidgetItem *p_item, int p_column); + void handleItemActivated(QTreeWidgetItem *p_item, int p_column); - QSharedPointer m_provider; + QSharedPointer m_provider; - QCommandLineParser m_parser; + QCommandLineParser m_parser; - Searcher *m_searcher = nullptr; + Searcher *m_searcher = nullptr; - QSharedPointer m_resultTree; + QSharedPointer m_resultTree; - QTimer *m_processTimer = nullptr; + QTimer *m_processTimer = nullptr; - QSharedPointer m_searchOption; + QSharedPointer m_searchOption; - QSharedPointer m_searchTokenOfSession; - }; -} + QSharedPointer m_searchTokenOfSession; +}; +} // namespace vnotex #endif // FINDUNITEDENTRY_H diff --git a/src/unitedentry/helpunitedentry.cpp b/src/unitedentry/helpunitedentry.cpp index de0357ef1f..fb33a0b1a0 100644 --- a/src/unitedentry/helpunitedentry.cpp +++ b/src/unitedentry/helpunitedentry.cpp @@ -7,42 +7,33 @@ using namespace vnotex; HelpUnitedEntry::HelpUnitedEntry(UnitedEntryMgr *p_mgr, QObject *p_parent) - : IUnitedEntry("help", - tr("Help information about United Entry"), - p_mgr, - p_parent) -{ + : IUnitedEntry("help", tr("Help information about United Entry"), p_mgr, p_parent) {} + +QSharedPointer HelpUnitedEntry::currentPopupWidget() const { return m_infoTree; } + +void HelpUnitedEntry::initOnFirstProcess() { + m_infoTree = EntryWidgetFactory::createTreeWidget(2); + m_infoTree->setHeaderHidden(false); + m_infoTree->setHeaderLabels(QStringList() << tr("Shortcut") << tr("Description")); + + QVector shortcuts = {{"Esc/Ctrl+[", tr("Close United Entry")}, + {"Up/Ctrl+K", tr("Go to previous item")}, + {"Down/Ctrl+J", tr("Go to next item")}, + {"Ctrl+L", tr("Go to the item one level up")}, + {"Ctrl+I", tr("Expand/Collapse current item")}, + {"Ctrl+B", tr("Expand/Collapse all the items")}, + {"Enter", tr("Activate current item")}, + {"Ctrl+E", tr("Clear the input except the entry name")}, + {"Ctrl+F", tr("Select the entry name")}, + {"Ctrl+D", tr("Stop current entry")}}; + for (const auto &shortcut : shortcuts) { + m_infoTree->addTopLevelItem(new QTreeWidgetItem(shortcut)); + } } -QSharedPointer HelpUnitedEntry::currentPopupWidget() const -{ - return m_infoTree; -} - -void HelpUnitedEntry::initOnFirstProcess() -{ - m_infoTree = EntryWidgetFactory::createTreeWidget(2); - m_infoTree->setHeaderHidden(false); - m_infoTree->setHeaderLabels(QStringList() << tr("Shortcut") << tr("Description")); - - QVector shortcuts = {{"Esc/Ctrl+[", tr("Close United Entry")}, - {"Up/Ctrl+K", tr("Go to previous item")}, - {"Down/Ctrl+J", tr("Go to next item")}, - {"Ctrl+L", tr("Go to the item one level up")}, - {"Ctrl+I", tr("Expand/Collapse current item")}, - {"Ctrl+B", tr("Expand/Collapse all the items")}, - {"Enter", tr("Activate current item")}, - {"Ctrl+E", tr("Clear the input except the entry name")}, - {"Ctrl+F", tr("Select the entry name")}, - {"Ctrl+D", tr("Stop current entry")}}; - for (const auto &shortcut : shortcuts) { - m_infoTree->addTopLevelItem(new QTreeWidgetItem(shortcut)); - } -} - -void HelpUnitedEntry::processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) -{ - Q_UNUSED(p_args); - p_popupWidgetFunc(m_infoTree); +void HelpUnitedEntry::processInternal( + const QString &p_args, + const std::function &)> &p_popupWidgetFunc) { + Q_UNUSED(p_args); + p_popupWidgetFunc(m_infoTree); } diff --git a/src/unitedentry/helpunitedentry.h b/src/unitedentry/helpunitedentry.h index dea737e116..19d8533286 100644 --- a/src/unitedentry/helpunitedentry.h +++ b/src/unitedentry/helpunitedentry.h @@ -7,25 +7,25 @@ class QTreeWidget; -namespace vnotex -{ - class HelpUnitedEntry : public IUnitedEntry - { - Q_OBJECT - public: - HelpUnitedEntry(UnitedEntryMgr *p_mgr, QObject *p_parent = nullptr); - - QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; - - protected: - void initOnFirstProcess() Q_DECL_OVERRIDE; - - void processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE; - - private: - QSharedPointer m_infoTree; - }; -} +namespace vnotex { +class HelpUnitedEntry : public IUnitedEntry { + Q_OBJECT +public: + HelpUnitedEntry(UnitedEntryMgr *p_mgr, QObject *p_parent = nullptr); + + QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; + +protected: + void initOnFirstProcess() Q_DECL_OVERRIDE; + + void + processInternal(const QString &p_args, + const std::function &)> &p_popupWidgetFunc) + Q_DECL_OVERRIDE; + +private: + QSharedPointer m_infoTree; +}; +} // namespace vnotex #endif // HELPUNITEDENTRY_H diff --git a/src/unitedentry/iunitedentry.cpp b/src/unitedentry/iunitedentry.cpp index 7abbad8131..a58fb4101c 100644 --- a/src/unitedentry/iunitedentry.cpp +++ b/src/unitedentry/iunitedentry.cpp @@ -1,9 +1,9 @@ #include "iunitedentry.h" -#include #include #include #include +#include #include @@ -11,137 +11,102 @@ using namespace vnotex; -IUnitedEntry::IUnitedEntry(const QString &p_name, - const QString &p_description, - UnitedEntryMgr *p_mgr, - QObject *p_parent) - : QObject(p_parent), - m_mgr(p_mgr), - m_name(p_name), - m_description(p_description) -{ -} +IUnitedEntry::IUnitedEntry(const QString &p_name, const QString &p_description, + UnitedEntryMgr *p_mgr, QObject *p_parent) + : QObject(p_parent), m_mgr(p_mgr), m_name(p_name), m_description(p_description) {} -const QString &IUnitedEntry::name() const -{ - return m_name; -} +const QString &IUnitedEntry::name() const { return m_name; } -QString IUnitedEntry::description() const -{ - return m_description; -} +QString IUnitedEntry::description() const { return m_description; } -void IUnitedEntry::process(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) -{ - if (!m_initialized) { - m_initialized = true; +void IUnitedEntry::process( + const QString &p_args, + const std::function &)> &p_popupWidgetFunc) { + if (!m_initialized) { + m_initialized = true; - initOnFirstProcess(); - } + initOnFirstProcess(); + } - m_askedToStop.storeRelaxed(0); + m_askedToStop.storeRelaxed(0); - return processInternal(p_args, p_popupWidgetFunc); + return processInternal(p_args, p_popupWidgetFunc); } -void IUnitedEntry::stop() -{ - m_askedToStop.storeRelaxed(1); -} +void IUnitedEntry::stop() { m_askedToStop.storeRelaxed(1); } -bool IUnitedEntry::isAskedToStop() const -{ - return m_askedToStop.loadAcquire() == 1; -} +bool IUnitedEntry::isAskedToStop() const { return m_askedToStop.loadAcquire() == 1; } -void IUnitedEntry::setOngoing(bool p_ongoing) -{ - m_ongoing = p_ongoing; -} +void IUnitedEntry::setOngoing(bool p_ongoing) { m_ongoing = p_ongoing; } -bool IUnitedEntry::isOngoing() const -{ - return m_ongoing; -} +bool IUnitedEntry::isOngoing() const { return m_ongoing; } -void IUnitedEntry::handleAction(Action p_act) -{ - auto widget = currentPopupWidget(); - if (!widget) { - return; - } - handleActionCommon(p_act, widget.data()); +void IUnitedEntry::handleAction(Action p_act) { + auto widget = currentPopupWidget(); + if (!widget) { + return; + } + handleActionCommon(p_act, widget.data()); } -void IUnitedEntry::handleActionCommon(Action p_act, QWidget *p_widget) -{ - switch (p_act) - { - case Action::NextItem: - { - auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); - QCoreApplication::postEvent(p_widget, eve); - break; - } - - case Action::PreviousItem: - { - auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); - QCoreApplication::postEvent(p_widget, eve); - break; - } - - case Action::Activate: - { - auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); - QCoreApplication::postEvent(p_widget, eve); - break; +void IUnitedEntry::handleActionCommon(Action p_act, QWidget *p_widget) { + switch (p_act) { + case Action::NextItem: { + auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, eve); + break; + } + + case Action::PreviousItem: { + auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, eve); + break; + } + + case Action::Activate: { + auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, eve); + break; + } + + case Action::LevelUp: { + auto treeWidget = dynamic_cast(p_widget); + if (treeWidget) { + TreeWidget::selectParentItem(treeWidget); } - - case Action::LevelUp: - { - auto treeWidget = dynamic_cast(p_widget); - if (treeWidget) { - TreeWidget::selectParentItem(treeWidget); - } - break; + break; + } + + case Action::ExpandCollapse: { + auto treeWidget = dynamic_cast(p_widget); + if (treeWidget) { + auto item = treeWidget->currentItem(); + if (item) { + item->setExpanded(!item->isExpanded()); + } } - - case Action::ExpandCollapse: - { - auto treeWidget = dynamic_cast(p_widget); - if (treeWidget) { - auto item = treeWidget->currentItem(); - if (item) { - item->setExpanded(!item->isExpanded()); - } - } - break; + break; + } + + case Action::ExpandCollapseAll: { + auto treeWidget = dynamic_cast(p_widget); + if (treeWidget) { + if (TreeWidget::isExpanded(treeWidget)) { + treeWidget->collapseAll(); + } else { + treeWidget->expandAll(); + } } + break; + } - case Action::ExpandCollapseAll: - { - auto treeWidget = dynamic_cast(p_widget); - if (treeWidget) { - if (TreeWidget::isExpanded(treeWidget)) { - treeWidget->collapseAll(); - } else { - treeWidget->expandAll(); - } - } - break; - } - - default: - Q_ASSERT(false); - break; - } + default: + Q_ASSERT(false); + break; + } } -bool IUnitedEntry::isAliasOf(const IUnitedEntry *p_entry) const -{ - Q_UNUSED(p_entry); - return false; +bool IUnitedEntry::isAliasOf(const IUnitedEntry *p_entry) const { + Q_UNUSED(p_entry); + return false; } diff --git a/src/unitedentry/iunitedentry.h b/src/unitedentry/iunitedentry.h index 99daee3366..c2571c7b5f 100644 --- a/src/unitedentry/iunitedentry.h +++ b/src/unitedentry/iunitedentry.h @@ -7,77 +7,73 @@ #include -namespace vnotex -{ - class UnitedEntryMgr; +namespace vnotex { +class UnitedEntryMgr; - // Interface of a UnitedEntry. - class IUnitedEntry : public QObject - { - Q_OBJECT - public: - enum class Action - { - NextItem, - PreviousItem, - Activate, - LevelUp, - ExpandCollapse, - ExpandCollapseAll - }; +// Interface of a UnitedEntry. +class IUnitedEntry : public QObject { + Q_OBJECT +public: + enum class Action { + NextItem, + PreviousItem, + Activate, + LevelUp, + ExpandCollapse, + ExpandCollapseAll + }; - IUnitedEntry(const QString &p_name, - const QString &p_description, - UnitedEntryMgr *p_mgr, - QObject *p_parent = nullptr); + IUnitedEntry(const QString &p_name, const QString &p_description, UnitedEntryMgr *p_mgr, + QObject *p_parent = nullptr); - const QString &name() const; + const QString &name() const; - virtual QString description() const; + virtual QString description() const; - void process(const QString &p_args, - const std::function &)> &p_popupWidgetFunc); + void process(const QString &p_args, + const std::function &)> &p_popupWidgetFunc); - virtual bool isOngoing() const; + virtual bool isOngoing() const; - virtual void stop(); + virtual void stop(); - virtual void handleAction(Action p_act); + virtual void handleAction(Action p_act); - virtual QSharedPointer currentPopupWidget() const = 0; + virtual QSharedPointer currentPopupWidget() const = 0; - virtual bool isAliasOf(const IUnitedEntry *p_entry) const; + virtual bool isAliasOf(const IUnitedEntry *p_entry) const; - static void handleActionCommon(Action p_act, QWidget *p_widget); + static void handleActionCommon(Action p_act, QWidget *p_widget); - signals: - void finished(); +signals: + void finished(); - void itemActivated(bool p_quit, bool p_restoreFocus); + void itemActivated(bool p_quit, bool p_restoreFocus); - protected: - virtual void initOnFirstProcess() = 0; +protected: + virtual void initOnFirstProcess() = 0; - virtual void processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) = 0; + virtual void processInternal( + const QString &p_args, + const std::function &)> &p_popupWidgetFunc) = 0; - bool isAskedToStop() const; + bool isAskedToStop() const; - virtual void setOngoing(bool p_ongoing); + virtual void setOngoing(bool p_ongoing); - UnitedEntryMgr *m_mgr = nullptr; + UnitedEntryMgr *m_mgr = nullptr; - private: - bool m_initialized = false; +private: + bool m_initialized = false; - QString m_name; + QString m_name; - QString m_description; + QString m_description; - QAtomicInt m_askedToStop = 0; + QAtomicInt m_askedToStop = 0; - bool m_ongoing = false; - }; -} + bool m_ongoing = false; +}; +} // namespace vnotex #endif // IUNITEDENTRY_H diff --git a/src/unitedentry/unitedentry.cpp b/src/unitedentry/unitedentry.cpp index bcf95842c5..71d651b63f 100644 --- a/src/unitedentry/unitedentry.cpp +++ b/src/unitedentry/unitedentry.cpp @@ -1,530 +1,496 @@ #include "unitedentry.h" -#include -#include #include -#include +#include #include +#include +#include #include +#include +#include +#include #include -#include +#include #include #include -#include -#include -#include -#include +#include -#include -#include -#include #include #include -#include #include #include -#include +#include #include +#include +#include +#include +#include #include "entrypopup.h" #include "entrywidgetfactory.h" -#include "unitedentrymgr.h" #include "iunitedentry.h" #include "unitedentryhelper.h" +#include "unitedentrymgr.h" using namespace vnotex; UnitedEntry::UnitedEntry(QMainWindow *p_mainWindow) - : QFrame(p_mainWindow), - m_mainWindow(p_mainWindow) -{ - m_processTimer = new QTimer(this); - m_processTimer->setSingleShot(true); - m_processTimer->setInterval(300); - connect(m_processTimer, &QTimer::timeout, - this, &UnitedEntry::processInput); + : QFrame(p_mainWindow), m_mainWindow(p_mainWindow) { + m_processTimer = new QTimer(this); + m_processTimer->setSingleShot(true); + m_processTimer->setInterval(300); + connect(m_processTimer, &QTimer::timeout, this, &UnitedEntry::processInput); - setupUI(); + setupUI(); #if defined(Q_OS_MACOS) || defined(Q_OS_MAC) - setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); - setWindowModality(Qt::ApplicationModal); + setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); + setWindowModality(Qt::ApplicationModal); #else - setWindowFlags(Qt::ToolTip); + setWindowFlags(Qt::ToolTip); #endif - connect(qApp, &QApplication::focusChanged, - this, &UnitedEntry::handleFocusChanged); + connect(qApp, &QApplication::focusChanged, this, &UnitedEntry::handleFocusChanged); - connect(&UnitedEntryMgr::getInst(), &UnitedEntryMgr::entryFinished, - this, &UnitedEntry::handleEntryFinished); - connect(&UnitedEntryMgr::getInst(), &UnitedEntryMgr::entryItemActivated, - this, &UnitedEntry::handleEntryItemActivated); + connect(&UnitedEntryMgr::getInst(), &UnitedEntryMgr::entryFinished, this, + &UnitedEntry::handleEntryFinished); + connect(&UnitedEntryMgr::getInst(), &UnitedEntryMgr::entryItemActivated, this, + &UnitedEntry::handleEntryItemActivated); } -UnitedEntry::~UnitedEntry() -{ -} +UnitedEntry::~UnitedEntry() {} -void UnitedEntry::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); +void UnitedEntry::setupUI() { + auto mainLayout = new QVBoxLayout(this); - // Line edit. - m_lineEdit = WidgetsFactory::createLineEditWithSnippet(this); - mainLayout->addWidget(m_lineEdit); - m_lineEdit->setPlaceholderText(tr("Type to command")); - m_lineEdit->setClearButtonEnabled(true); - m_lineEdit->installEventFilter(this); - connect(m_lineEdit, &QLineEdit::textChanged, - m_processTimer, QOverload<>::of(&QTimer::start)); - setFocusProxy(m_lineEdit); + // Line edit. + m_lineEdit = WidgetsFactory::createLineEditWithSnippet(this); + mainLayout->addWidget(m_lineEdit); + m_lineEdit->setPlaceholderText(tr("Type to command")); + m_lineEdit->setClearButtonEnabled(true); + m_lineEdit->installEventFilter(this); + connect(m_lineEdit, &QLineEdit::textChanged, m_processTimer, QOverload<>::of(&QTimer::start)); + setFocusProxy(m_lineEdit); - setupActions(); + setupActions(); - // Popup. - m_popup = new EntryPopup(this); - mainLayout->addWidget(m_popup); - m_popup->installEventFilter(this); + // Popup. + m_popup = new EntryPopup(this); + mainLayout->addWidget(m_popup); + m_popup->installEventFilter(this); - hide(); + hide(); } -QString UnitedEntry::getTriggerActionText() const -{ - return tr("United Entry"); -} +QString UnitedEntry::getTriggerActionText() const { return tr("United Entry"); } -QAction *UnitedEntry::getTriggerAction() -{ - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - const auto fg = themeMgr.paletteColor("widgets#unitedentry#icon#fg"); +QAction *UnitedEntry::getTriggerAction() { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + const auto fg = themeMgr.paletteColor("widgets#unitedentry#icon#fg"); - const auto icon = IconUtils::fetchIcon(themeMgr.getIconFile("united_entry.svg"), fg); - auto act = new QAction(icon, getTriggerActionText(), this); - connect(act, &QAction::triggered, - this, &UnitedEntry::activateUnitedEntry); + const auto icon = IconUtils::fetchIcon(themeMgr.getIconFile("united_entry.svg"), fg); + auto act = new QAction(icon, getTriggerActionText(), this); + connect(act, &QAction::triggered, this, &UnitedEntry::activateUnitedEntry); - const auto shortcut = ConfigMgr::getInst().getCoreConfig().getShortcut(CoreConfig::Shortcut::UnitedEntry); - WidgetUtils::addActionShortcut(act, shortcut, Qt::ApplicationShortcut); + const auto shortcut = + ConfigMgr::getInst().getCoreConfig().getShortcut(CoreConfig::Shortcut::UnitedEntry); + WidgetUtils::addActionShortcut(act, shortcut, Qt::ApplicationShortcut); - return act; + return act; } -void UnitedEntry::setupActions() -{ - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - const auto fg = themeMgr.paletteColor("widgets#unitedentry#icon#fg"); - const auto busyFg = themeMgr.paletteColor("widgets#unitedentry#icon#busy#fg"); - - // Menu. - const auto menuIcon = IconUtils::fetchIcon(themeMgr.getIconFile("menu.svg"), fg); - m_menuIconAction = m_lineEdit->addAction(menuIcon, QLineEdit::ActionPosition::TrailingPosition); - m_menuIconAction->setText(tr("Options")); - - auto menu = WidgetsFactory::createMenu(this); - m_menuIconAction->setMenu(menu); - - { - auto expandAct = menu->addAction(tr("Expand All"), - this, - [](bool checked) { - ConfigMgr::getInst().getWidgetConfig().setUnitedEntryExpandAllEnabled(checked); - UnitedEntryMgr::getInst().setExpandAllEnabled(checked); - }); - expandAct->setCheckable(true); - expandAct->setChecked(ConfigMgr::getInst().getWidgetConfig().getUnitedEntryExpandAllEnabled()); - UnitedEntryMgr::getInst().setExpandAllEnabled(expandAct->isChecked()); - } - - connect(m_menuIconAction, &QAction::triggered, - this, [this]() { - const auto pos = QCursor::pos(); - auto menu = m_menuIconAction->menu(); - menu->exec(pos); - }); - - // Busy. - const auto busyIcon = IconUtils::fetchIcon(themeMgr.getIconFile("busy.svg"), busyFg); - m_busyIconAction = m_lineEdit->addAction(busyIcon, QLineEdit::ActionPosition::TrailingPosition); - m_busyIconAction->setText(tr("Busy")); - m_busyIconAction->setVisible(false); +void UnitedEntry::setupActions() { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + const auto fg = themeMgr.paletteColor("widgets#unitedentry#icon#fg"); + const auto busyFg = themeMgr.paletteColor("widgets#unitedentry#icon#busy#fg"); + + // Menu. + const auto menuIcon = IconUtils::fetchIcon(themeMgr.getIconFile("menu.svg"), fg); + m_menuIconAction = m_lineEdit->addAction(menuIcon, QLineEdit::ActionPosition::TrailingPosition); + m_menuIconAction->setText(tr("Options")); + + auto menu = WidgetsFactory::createMenu(this); + m_menuIconAction->setMenu(menu); + + { + auto expandAct = menu->addAction(tr("Expand All"), this, [](bool checked) { + ConfigMgr::getInst().getWidgetConfig().setUnitedEntryExpandAllEnabled(checked); + UnitedEntryMgr::getInst().setExpandAllEnabled(checked); + }); + expandAct->setCheckable(true); + expandAct->setChecked(ConfigMgr::getInst().getWidgetConfig().getUnitedEntryExpandAllEnabled()); + UnitedEntryMgr::getInst().setExpandAllEnabled(expandAct->isChecked()); + } + + connect(m_menuIconAction, &QAction::triggered, this, [this]() { + const auto pos = QCursor::pos(); + auto menu = m_menuIconAction->menu(); + menu->exec(pos); + }); + + // Busy. + const auto busyIcon = IconUtils::fetchIcon(themeMgr.getIconFile("busy.svg"), busyFg); + m_busyIconAction = m_lineEdit->addAction(busyIcon, QLineEdit::ActionPosition::TrailingPosition); + m_busyIconAction->setText(tr("Busy")); + m_busyIconAction->setVisible(false); } -void UnitedEntry::activateUnitedEntry() -{ - if (m_activated) { - return; - } +void UnitedEntry::activateUnitedEntry() { + if (m_activated) { + return; + } - if (!UnitedEntryMgr::getInst().isInitialized()) { - return; - } + if (!UnitedEntryMgr::getInst().isInitialized()) { + return; + } - m_activated = true; + m_activated = true; - m_previousFocusWidget = QApplication::focusWidget(); + m_previousFocusWidget = QApplication::focusWidget(); - show(); + show(); - m_processTimer->stop(); - processInput(); + m_processTimer->stop(); + processInput(); - m_lineEdit->selectAll(); - m_lineEdit->setFocus(); + m_lineEdit->selectAll(); + m_lineEdit->setFocus(); } -void UnitedEntry::deactivateUnitedEntry() -{ - if (!m_activated) { - return; - } +void UnitedEntry::deactivateUnitedEntry() { + if (!m_activated) { + return; + } - m_activated = false; - m_previousFocusWidget = nullptr; + m_activated = false; + m_previousFocusWidget = nullptr; - hide(); + hide(); } -bool UnitedEntry::handleLineEditKeyPress(QKeyEvent *p_event) -{ - const int key = p_event->key(); - const int modifiers = p_event->modifiers(); - IUnitedEntry::Action act = IUnitedEntry::Action::NextItem; - switch (key) { - case Qt::Key_BracketLeft: - if (!WidgetUtils::isViControlModifier(modifiers)) { - break; - } - Q_FALLTHROUGH(); - case Qt::Key_Escape: - exitUnitedEntry(); - return true; - - // Up/Down Ctrl+K/J to navigate to previous/next item. - case Qt::Key_Up: - act = IUnitedEntry::Action::PreviousItem; - Q_FALLTHROUGH(); - case Qt::Key_Down: - if (m_lastEntry) { - m_lastEntry->handleAction(act); - } else if (m_entryListWidget && m_entryListWidget->isVisible()) { - IUnitedEntry::handleActionCommon(act, m_entryListWidget.data()); - } - return true; - - case Qt::Key_K: - act = IUnitedEntry::Action::PreviousItem; - Q_FALLTHROUGH(); - case Qt::Key_J: - if (WidgetUtils::isViControlModifier(modifiers)) { - if (m_lastEntry) { - m_lastEntry->handleAction(act); - } else if (m_entryListWidget && m_entryListWidget->isVisible()) { - IUnitedEntry::handleActionCommon(act, m_entryListWidget.data()); - } - return true; - } - break; - - case Qt::Key_Enter: - Q_FALLTHROUGH(); - case Qt::Key_Return: - if (m_lastEntry) { - m_lastEntry->handleAction(IUnitedEntry::Action::Activate); - } - return true; - - case Qt::Key_E: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Eliminate input till the entry name. - const auto text = m_lineEdit->evaluatedText(); - const auto entry = UnitedEntryHelper::parseUserEntry(text); - if (!entry.m_name.isEmpty()) { - m_lineEdit->setText(entry.m_name + QLatin1Char(' ')); - } - return true; - } - break; - - case Qt::Key_F: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Select the entry name. - const auto text = m_lineEdit->evaluatedText(); - const auto entry = UnitedEntryHelper::parseUserEntry(text); - if (!entry.m_name.isEmpty()) { - m_lineEdit->setSelection(0, entry.m_name.size()); - } - return true; - } - break; - - case Qt::Key_D: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Stop the entry. - if (m_lastEntry) { - m_lastEntry->stop(); - } - return true; - } - break; - - case Qt::Key_L: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Go up one level. - if (m_lastEntry) { - m_lastEntry->handleAction(IUnitedEntry::Action::LevelUp); - } - return true; - } - break; - - case Qt::Key_I: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Expand/Collapse the item. - if (m_lastEntry) { - m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapse); - } - return true; - } - break; +bool UnitedEntry::handleLineEditKeyPress(QKeyEvent *p_event) { + const int key = p_event->key(); + const int modifiers = p_event->modifiers(); + IUnitedEntry::Action act = IUnitedEntry::Action::NextItem; + switch (key) { + case Qt::Key_BracketLeft: + if (!WidgetUtils::isViControlModifier(modifiers)) { + break; + } + Q_FALLTHROUGH(); + case Qt::Key_Escape: + exitUnitedEntry(); + return true; + + // Up/Down Ctrl+K/J to navigate to previous/next item. + case Qt::Key_Up: + act = IUnitedEntry::Action::PreviousItem; + Q_FALLTHROUGH(); + case Qt::Key_Down: + if (m_lastEntry) { + m_lastEntry->handleAction(act); + } else if (m_entryListWidget && m_entryListWidget->isVisible()) { + IUnitedEntry::handleActionCommon(act, m_entryListWidget.data()); + } + return true; + + case Qt::Key_K: + act = IUnitedEntry::Action::PreviousItem; + Q_FALLTHROUGH(); + case Qt::Key_J: + if (WidgetUtils::isViControlModifier(modifiers)) { + if (m_lastEntry) { + m_lastEntry->handleAction(act); + } else if (m_entryListWidget && m_entryListWidget->isVisible()) { + IUnitedEntry::handleActionCommon(act, m_entryListWidget.data()); + } + return true; + } + break; - case Qt::Key_B: - if (WidgetUtils::isViControlModifier(modifiers)) { - // Expand/Collapse all the items. - if (m_lastEntry) { - m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapseAll); - } - return true; - } - break; + case Qt::Key_Enter: + Q_FALLTHROUGH(); + case Qt::Key_Return: + if (m_lastEntry) { + m_lastEntry->handleAction(IUnitedEntry::Action::Activate); + } + return true; + + case Qt::Key_E: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Eliminate input till the entry name. + const auto text = m_lineEdit->evaluatedText(); + const auto entry = UnitedEntryHelper::parseUserEntry(text); + if (!entry.m_name.isEmpty()) { + m_lineEdit->setText(entry.m_name + QLatin1Char(' ')); + } + return true; + } + break; + + case Qt::Key_F: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Select the entry name. + const auto text = m_lineEdit->evaluatedText(); + const auto entry = UnitedEntryHelper::parseUserEntry(text); + if (!entry.m_name.isEmpty()) { + m_lineEdit->setSelection(0, entry.m_name.size()); + } + return true; + } + break; - default: - break; + case Qt::Key_D: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Stop the entry. + if (m_lastEntry) { + m_lastEntry->stop(); + } + return true; + } + break; + + case Qt::Key_L: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Go up one level. + if (m_lastEntry) { + m_lastEntry->handleAction(IUnitedEntry::Action::LevelUp); + } + return true; + } + break; + + case Qt::Key_I: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Expand/Collapse the item. + if (m_lastEntry) { + m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapse); + } + return true; } + break; + + case Qt::Key_B: + if (WidgetUtils::isViControlModifier(modifiers)) { + // Expand/Collapse all the items. + if (m_lastEntry) { + m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapseAll); + } + return true; + } + break; + + default: + break; + } - return false; + return false; } -void UnitedEntry::clear() -{ - m_lineEdit->clear(); - m_lineEdit->setFocus(); +void UnitedEntry::clear() { + m_lineEdit->clear(); + m_lineEdit->setFocus(); } -void UnitedEntry::processInput() -{ - m_hasPending = false; +void UnitedEntry::processInput() { + m_hasPending = false; - if (!m_activated) { - return; - } + if (!m_activated) { + return; + } - if (m_lastEntry && m_lastEntry->isOngoing()) { - m_hasPending = true; - m_lastEntry->stop(); - return; - } + if (m_lastEntry && m_lastEntry->isOngoing()) { + m_hasPending = true; + m_lastEntry->stop(); + return; + } - const auto text = m_lineEdit->evaluatedText(); - const auto entry = UnitedEntryHelper::parseUserEntry(text); - if (entry.m_name.isEmpty()) { - filterEntryListWidgetEntries(entry.m_name); - popupWidget(getEntryListWidget()); - m_lastEntry.clear(); - return; + const auto text = m_lineEdit->evaluatedText(); + const auto entry = UnitedEntryHelper::parseUserEntry(text); + if (entry.m_name.isEmpty()) { + filterEntryListWidgetEntries(entry.m_name); + popupWidget(getEntryListWidget()); + m_lastEntry.clear(); + return; + } + + // Filter the help widget if space after entry name is not entered yet. + if (entry.m_name == text.trimmed() && !text.back().isSpace()) { + if (filterEntryListWidgetEntries(entry.m_name)) { + popupWidget(getEntryListWidget()); + m_lastEntry.clear(); + return; + } + } else { + if (!m_lastEntry || m_lastEntry->name() == entry.m_name) { + m_lastEntry = UnitedEntryMgr::getInst().findEntry(entry.m_name); } - // Filter the help widget if space after entry name is not entered yet. - if (entry.m_name == text.trimmed() && !text.back().isSpace()) { - if (filterEntryListWidgetEntries(entry.m_name)) { - popupWidget(getEntryListWidget()); - m_lastEntry.clear(); - return; - } - } else { - if (!m_lastEntry || m_lastEntry->name() == entry.m_name) { - m_lastEntry = UnitedEntryMgr::getInst().findEntry(entry.m_name); - } - - if (m_lastEntry) { - // Found. - setBusy(true); - m_lastEntry->process(entry.m_args, std::bind(&UnitedEntry::popupWidget, this, std::placeholders::_1)); - return; - } + if (m_lastEntry) { + // Found. + setBusy(true); + m_lastEntry->process(entry.m_args, + std::bind(&UnitedEntry::popupWidget, this, std::placeholders::_1)); + return; } + } - // No entry found. - popupWidget(getInfoWidget(tr("Unknown entry: %1").arg(entry.m_name))); - m_lastEntry.clear(); + // No entry found. + popupWidget(getInfoWidget(tr("Unknown entry: %1").arg(entry.m_name))); + m_lastEntry.clear(); } -void UnitedEntry::popupWidget(const QSharedPointer &p_widget) -{ - m_popup->setWidget(p_widget); +void UnitedEntry::popupWidget(const QSharedPointer &p_widget) { + m_popup->setWidget(p_widget); - m_lineEdit->setFocus(); + m_lineEdit->setFocus(); } -const QSharedPointer &UnitedEntry::getEntryListWidget() -{ - if (!m_entryListWidget) { - m_entryListWidget = EntryWidgetFactory::createTreeWidget(2); - m_entryListWidget->setHeaderHidden(false); - m_entryListWidget->setHeaderLabels(QStringList() << tr("Entry") << tr("Description")); +const QSharedPointer &UnitedEntry::getEntryListWidget() { + if (!m_entryListWidget) { + m_entryListWidget = EntryWidgetFactory::createTreeWidget(2); + m_entryListWidget->setHeaderHidden(false); + m_entryListWidget->setHeaderLabels(QStringList() << tr("Entry") << tr("Description")); - const auto entries = UnitedEntryMgr::getInst().getEntries(); - for (const auto &entry : entries) { - m_entryListWidget->addTopLevelItem(new QTreeWidgetItem({entry->name(), entry->description()})); - } + const auto entries = UnitedEntryMgr::getInst().getEntries(); + for (const auto &entry : entries) { + m_entryListWidget->addTopLevelItem( + new QTreeWidgetItem({entry->name(), entry->description()})); } + } - return m_entryListWidget; + return m_entryListWidget; } -QSharedPointer UnitedEntry::getInfoWidget(const QString &p_info) -{ - return EntryWidgetFactory::createLabel(p_info); +QSharedPointer UnitedEntry::getInfoWidget(const QString &p_info) { + return EntryWidgetFactory::createLabel(p_info); } -bool UnitedEntry::filterEntryListWidgetEntries(const QString &p_name) -{ - const auto &entryListWidget = getEntryListWidget(); - - if (p_name.isEmpty()) { - for (int i = 0; i < entryListWidget->topLevelItemCount(); ++i) { - entryListWidget->topLevelItem(i)->setHidden(false); - } - return true; - } +bool UnitedEntry::filterEntryListWidgetEntries(const QString &p_name) { + const auto &entryListWidget = getEntryListWidget(); - auto items = entryListWidget->findItems(p_name, Qt::MatchStartsWith); + if (p_name.isEmpty()) { for (int i = 0; i < entryListWidget->topLevelItemCount(); ++i) { - entryListWidget->topLevelItem(i)->setHidden(true); + entryListWidget->topLevelItem(i)->setHidden(false); } - for (const auto &item : items) { - item->setHidden(false); - } - return !items.isEmpty(); + return true; + } + + auto items = entryListWidget->findItems(p_name, Qt::MatchStartsWith); + for (int i = 0; i < entryListWidget->topLevelItemCount(); ++i) { + entryListWidget->topLevelItem(i)->setHidden(true); + } + for (const auto &item : items) { + item->setHidden(false); + } + return !items.isEmpty(); } -void UnitedEntry::handleEntryFinished(IUnitedEntry *p_entry) -{ - if (p_entry != m_lastEntry.data()) { - return; - } +void UnitedEntry::handleEntryFinished(IUnitedEntry *p_entry) { + if (p_entry != m_lastEntry.data()) { + return; + } - setBusy(false); + setBusy(false); - if (m_hasPending) { - m_processTimer->start(); - } + if (m_hasPending) { + m_processTimer->start(); + } } -void UnitedEntry::handleEntryItemActivated(IUnitedEntry *p_entry, bool p_quit, bool p_restoreFocus) -{ - if (p_entry != m_lastEntry.data()) { - return; - } +void UnitedEntry::handleEntryItemActivated(IUnitedEntry *p_entry, bool p_quit, + bool p_restoreFocus) { + if (p_entry != m_lastEntry.data()) { + return; + } - if (p_quit) { - if (p_restoreFocus) { - exitUnitedEntry(); - } else { - deactivateUnitedEntry(); - } + if (p_quit) { + if (p_restoreFocus) { + exitUnitedEntry(); + } else { + deactivateUnitedEntry(); } + } } -void UnitedEntry::setBusy(bool p_busy) -{ - m_busyIconAction->setVisible(p_busy); -} +void UnitedEntry::setBusy(bool p_busy) { m_busyIconAction->setVisible(p_busy); } -bool UnitedEntry::eventFilter(QObject *p_watched, QEvent *p_event) -{ - if (p_watched == m_popup) { - if (p_event->type() == QEvent::KeyPress) { - auto eve = static_cast(p_event); - switch (eve->key()) { - case Qt::Key_BracketLeft: - if (!WidgetUtils::isViControlModifier(eve->modifiers())) { - break; - } - Q_FALLTHROUGH(); - case Qt::Key_Escape: - exitUnitedEntry(); - return true; - - default: - break; - } - } - } else if (p_watched == m_lineEdit) { - if (p_event->type() == QEvent::KeyPress) { - auto eve = static_cast(p_event); - if (handleLineEditKeyPress(eve)) { - return true; - } +bool UnitedEntry::eventFilter(QObject *p_watched, QEvent *p_event) { + if (p_watched == m_popup) { + if (p_event->type() == QEvent::KeyPress) { + auto eve = static_cast(p_event); + switch (eve->key()) { + case Qt::Key_BracketLeft: + if (!WidgetUtils::isViControlModifier(eve->modifiers())) { + break; } + Q_FALLTHROUGH(); + case Qt::Key_Escape: + exitUnitedEntry(); + return true; + + default: + break; + } + } + } else if (p_watched == m_lineEdit) { + if (p_event->type() == QEvent::KeyPress) { + auto eve = static_cast(p_event); + if (handleLineEditKeyPress(eve)) { + return true; + } } + } - return QFrame::eventFilter(p_watched, p_event); + return QFrame::eventFilter(p_watched, p_event); } -void UnitedEntry::exitUnitedEntry() -{ - if (m_previousFocusWidget) { - // Deactivate and focus previous widget. - m_previousFocusWidget->setFocus(); - } else { - m_mainWindow->setFocus(); - } - deactivateUnitedEntry(); +void UnitedEntry::exitUnitedEntry() { + if (m_previousFocusWidget) { + // Deactivate and focus previous widget. + m_previousFocusWidget->setFocus(); + } else { + m_mainWindow->setFocus(); + } + deactivateUnitedEntry(); } -void UnitedEntry::showEvent(QShowEvent *p_event) -{ - QFrame::showEvent(p_event); +void UnitedEntry::showEvent(QShowEvent *p_event) { + QFrame::showEvent(p_event); - // Fix input method issue. - activateWindow(); + // Fix input method issue. + activateWindow(); - m_lineEdit->setFocus(); + m_lineEdit->setFocus(); - updateGeometryToContents(); + updateGeometryToContents(); } -void UnitedEntry::updateGeometryToContents() -{ - adjustSize(); +void UnitedEntry::updateGeometryToContents() { + adjustSize(); - const auto winSize = m_mainWindow->size(); - const auto sz = preferredSize(); - auto pos = parentWidget()->mapToGlobal(QPoint((winSize.width() - sz.width()) / 2, - (winSize.height() - sz.height()) / 2)); - setGeometry(QRect(pos, preferredSize())); + const auto winSize = m_mainWindow->size(); + const auto sz = preferredSize(); + auto pos = parentWidget()->mapToGlobal( + QPoint((winSize.width() - sz.width()) / 2, (winSize.height() - sz.height()) / 2)); + setGeometry(QRect(pos, preferredSize())); } -QSize UnitedEntry::preferredSize() const -{ - const int minWidth = 400; - const int minHeight = 300; - - const auto winSize = m_mainWindow->size(); - int w = minWidth; - int h = sizeHint().height(); - w = qMax(w, qMin(winSize.width() / 2, 900)); - h = qMax(h, qMin(winSize.height() - 300, 800)); - return QSize(qMax(minWidth, w), qMax(h, minHeight)); +QSize UnitedEntry::preferredSize() const { + const int minWidth = 400; + const int minHeight = 300; + + const auto winSize = m_mainWindow->size(); + int w = minWidth; + int h = sizeHint().height(); + w = qMax(w, qMin(winSize.width() / 2, 900)); + h = qMax(h, qMin(winSize.height() - 300, 800)); + return QSize(qMax(minWidth, w), qMax(h, minHeight)); } -void UnitedEntry::handleFocusChanged(QWidget *p_old, QWidget *p_now) -{ - Q_UNUSED(p_old); - if (m_activated && - (!p_now || (p_now != this && !WidgetUtils::isOrAncestorOf(this, p_now)))) { - deactivateUnitedEntry(); - } +void UnitedEntry::handleFocusChanged(QWidget *p_old, QWidget *p_now) { + Q_UNUSED(p_old); + if (m_activated && (!p_now || (p_now != this && !WidgetUtils::isOrAncestorOf(this, p_now)))) { + deactivateUnitedEntry(); + } } diff --git a/src/unitedentry/unitedentry.h b/src/unitedentry/unitedentry.h index cb837b36bb..8a556dd2f7 100644 --- a/src/unitedentry/unitedentry.h +++ b/src/unitedentry/unitedentry.h @@ -10,90 +10,88 @@ class QTreeWidget; class QLabel; class QMainWindow; -namespace vnotex -{ - class LineEditWithSnippet; - class EntryPopup; - class IUnitedEntry; +namespace vnotex { +class LineEditWithSnippet; +class EntryPopup; +class IUnitedEntry; - class UnitedEntry : public QFrame - { - Q_OBJECT - public: - explicit UnitedEntry(QMainWindow *p_mainWindow); +class UnitedEntry : public QFrame { + Q_OBJECT +public: + explicit UnitedEntry(QMainWindow *p_mainWindow); - ~UnitedEntry(); + ~UnitedEntry(); - bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE; - QAction *getTriggerAction(); + QAction *getTriggerAction(); - QString getTriggerActionText() const; + QString getTriggerActionText() const; - protected: - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; +protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupActions(); + void setupActions(); - void activateUnitedEntry(); + void activateUnitedEntry(); - void deactivateUnitedEntry(); + void deactivateUnitedEntry(); - void clear(); + void clear(); - void processInput(); + void processInput(); - void handleFocusChanged(QWidget *p_old, QWidget *p_now); + void handleFocusChanged(QWidget *p_old, QWidget *p_now); - const QSharedPointer &getEntryListWidget(); + const QSharedPointer &getEntryListWidget(); - QSharedPointer getInfoWidget(const QString &p_info); + QSharedPointer getInfoWidget(const QString &p_info); - void popupWidget(const QSharedPointer &p_widget); + void popupWidget(const QSharedPointer &p_widget); - // Return true if there is any entry visible. - bool filterEntryListWidgetEntries(const QString &p_name); + // Return true if there is any entry visible. + bool filterEntryListWidgetEntries(const QString &p_name); - void handleEntryFinished(IUnitedEntry *p_entry); + void handleEntryFinished(IUnitedEntry *p_entry); - void handleEntryItemActivated(IUnitedEntry *p_entry, bool p_quit, bool p_restoreFocus); + void handleEntryItemActivated(IUnitedEntry *p_entry, bool p_quit, bool p_restoreFocus); - void setBusy(bool p_busy); + void setBusy(bool p_busy); - void exitUnitedEntry(); + void exitUnitedEntry(); - void updateGeometryToContents(); + void updateGeometryToContents(); - QSize preferredSize() const; + QSize preferredSize() const; - // Return true if want to stop the propogation. - bool handleLineEditKeyPress(QKeyEvent *p_event); + // Return true if want to stop the propogation. + bool handleLineEditKeyPress(QKeyEvent *p_event); - QMainWindow *m_mainWindow = nullptr; + QMainWindow *m_mainWindow = nullptr; - LineEditWithSnippet *m_lineEdit = nullptr; + LineEditWithSnippet *m_lineEdit = nullptr; - EntryPopup *m_popup = nullptr; + EntryPopup *m_popup = nullptr; - QAction *m_menuIconAction = nullptr; + QAction *m_menuIconAction = nullptr; - QAction *m_busyIconAction = nullptr; + QAction *m_busyIconAction = nullptr; - bool m_activated = false; + bool m_activated = false; - QWidget *m_previousFocusWidget = nullptr; + QWidget *m_previousFocusWidget = nullptr; - QTimer *m_processTimer = nullptr; + QTimer *m_processTimer = nullptr; - QSharedPointer m_entryListWidget = nullptr; + QSharedPointer m_entryListWidget = nullptr; - QSharedPointer m_lastEntry; + QSharedPointer m_lastEntry; - bool m_hasPending = false; - }; -} + bool m_hasPending = false; +}; +} // namespace vnotex #endif // UNITEDENTRY_H diff --git a/src/unitedentry/unitedentryalias.cpp b/src/unitedentry/unitedentryalias.cpp index aefe3c5c6d..75fd89f559 100644 --- a/src/unitedentry/unitedentryalias.cpp +++ b/src/unitedentry/unitedentryalias.cpp @@ -3,104 +3,84 @@ #include #include -#include "unitedentrymgr.h" #include "entrywidgetfactory.h" +#include "unitedentrymgr.h" using namespace vnotex; -UnitedEntryAlias::UnitedEntryAlias(const QString &p_name, - const QString &p_description, - const QString &p_value, - UnitedEntryMgr *p_mgr, - QObject *p_parent) - : IUnitedEntry(p_name, p_description, p_mgr, p_parent), - m_value(p_value) -{ - m_alias = UnitedEntryHelper::parseUserEntry(m_value); +UnitedEntryAlias::UnitedEntryAlias(const QString &p_name, const QString &p_description, + const QString &p_value, UnitedEntryMgr *p_mgr, QObject *p_parent) + : IUnitedEntry(p_name, p_description, p_mgr, p_parent), m_value(p_value) { + m_alias = UnitedEntryHelper::parseUserEntry(m_value); } -UnitedEntryAlias::UnitedEntryAlias(const QJsonObject &p_obj, - UnitedEntryMgr *p_mgr, +UnitedEntryAlias::UnitedEntryAlias(const QJsonObject &p_obj, UnitedEntryMgr *p_mgr, QObject *p_parent) : UnitedEntryAlias(p_obj[QStringLiteral("name")].toString(), p_obj[QStringLiteral("description")].toString(), - p_obj[QStringLiteral("value")].toString(), - p_mgr, - p_parent) -{ -} + p_obj[QStringLiteral("value")].toString(), p_mgr, p_parent) {} -QString UnitedEntryAlias::description() const -{ - return tr("[Alias] ") + IUnitedEntry::description(); +QString UnitedEntryAlias::description() const { + return tr("[Alias] ") + IUnitedEntry::description(); } -QJsonObject UnitedEntryAlias::toJson() const -{ - QJsonObject obj; - obj[QStringLiteral("name")] = name(); - obj[QStringLiteral("description")] = description(); - obj[QStringLiteral("value")] = m_value; - return obj; +QJsonObject UnitedEntryAlias::toJson() const { + QJsonObject obj; + obj[QStringLiteral("name")] = name(); + obj[QStringLiteral("description")] = description(); + obj[QStringLiteral("value")] = m_value; + return obj; } -void UnitedEntryAlias::initOnFirstProcess() -{ - m_realEntry = m_mgr->findEntry(m_alias.m_name).data(); - if (!m_realEntry) { - qWarning() << "invalid UnitedEntry alias" << name() << m_value; - } else { - connect(m_realEntry, &IUnitedEntry::finished, - this, &IUnitedEntry::finished); - connect(m_realEntry, &IUnitedEntry::itemActivated, - this, &IUnitedEntry::itemActivated); - } +void UnitedEntryAlias::initOnFirstProcess() { + m_realEntry = m_mgr->findEntry(m_alias.m_name).data(); + if (!m_realEntry) { + qWarning() << "invalid UnitedEntry alias" << name() << m_value; + } else { + connect(m_realEntry, &IUnitedEntry::finished, this, &IUnitedEntry::finished); + connect(m_realEntry, &IUnitedEntry::itemActivated, this, &IUnitedEntry::itemActivated); + } } -void UnitedEntryAlias::processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) -{ - if (!m_realEntry) { - auto label = EntryWidgetFactory::createLabel(tr("Invalid United Entry alias: %1").arg(m_value)); - p_popupWidgetFunc(label); - emit finished(); - return; - } - - m_realEntry->process(m_alias.m_args + " " + p_args, p_popupWidgetFunc); +void UnitedEntryAlias::processInternal( + const QString &p_args, + const std::function &)> &p_popupWidgetFunc) { + if (!m_realEntry) { + auto label = EntryWidgetFactory::createLabel(tr("Invalid United Entry alias: %1").arg(m_value)); + p_popupWidgetFunc(label); + emit finished(); + return; + } + + m_realEntry->process(m_alias.m_args + " " + p_args, p_popupWidgetFunc); } -bool UnitedEntryAlias::isOngoing() const -{ - if (m_realEntry) { - return m_realEntry->isOngoing(); - } - return false; +bool UnitedEntryAlias::isOngoing() const { + if (m_realEntry) { + return m_realEntry->isOngoing(); + } + return false; } -void UnitedEntryAlias::setOngoing(bool p_ongoing) -{ - Q_UNUSED(p_ongoing); - Q_ASSERT(false); +void UnitedEntryAlias::setOngoing(bool p_ongoing) { + Q_UNUSED(p_ongoing); + Q_ASSERT(false); } -void UnitedEntryAlias::handleAction(Action p_act) -{ - if (m_realEntry) { - m_realEntry->handleAction(p_act); - } +void UnitedEntryAlias::handleAction(Action p_act) { + if (m_realEntry) { + m_realEntry->handleAction(p_act); + } } -QSharedPointer UnitedEntryAlias::currentPopupWidget() const -{ - if (m_realEntry) { - return m_realEntry->currentPopupWidget(); - } +QSharedPointer UnitedEntryAlias::currentPopupWidget() const { + if (m_realEntry) { + return m_realEntry->currentPopupWidget(); + } - return nullptr; + return nullptr; } -bool UnitedEntryAlias::isAliasOf(const IUnitedEntry *p_entry) const -{ - return p_entry == m_realEntry; +bool UnitedEntryAlias::isAliasOf(const IUnitedEntry *p_entry) const { + return p_entry == m_realEntry; } diff --git a/src/unitedentry/unitedentryalias.h b/src/unitedentry/unitedentryalias.h index 312493a762..a6fe701a92 100644 --- a/src/unitedentry/unitedentryalias.h +++ b/src/unitedentry/unitedentryalias.h @@ -7,52 +7,47 @@ #include "unitedentryhelper.h" -namespace vnotex -{ - class UnitedEntryMgr; +namespace vnotex { +class UnitedEntryMgr; - // UnitedEntry which points to another UnitedEntry. - class UnitedEntryAlias : public IUnitedEntry - { - Q_OBJECT - public: - UnitedEntryAlias(const QString &p_name, - const QString &p_description, - const QString &p_value, - UnitedEntryMgr *p_mgr, - QObject *p_parent = nullptr); +// UnitedEntry which points to another UnitedEntry. +class UnitedEntryAlias : public IUnitedEntry { + Q_OBJECT +public: + UnitedEntryAlias(const QString &p_name, const QString &p_description, const QString &p_value, + UnitedEntryMgr *p_mgr, QObject *p_parent = nullptr); - UnitedEntryAlias(const QJsonObject &p_obj, - UnitedEntryMgr *p_mgr, - QObject *p_parent = nullptr); + UnitedEntryAlias(const QJsonObject &p_obj, UnitedEntryMgr *p_mgr, QObject *p_parent = nullptr); - QJsonObject toJson() const; + QJsonObject toJson() const; - QString description() const Q_DECL_OVERRIDE; + QString description() const Q_DECL_OVERRIDE; - bool isOngoing() const Q_DECL_OVERRIDE; + bool isOngoing() const Q_DECL_OVERRIDE; - void handleAction(Action p_act) Q_DECL_OVERRIDE; + void handleAction(Action p_act) Q_DECL_OVERRIDE; - QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; + QSharedPointer currentPopupWidget() const Q_DECL_OVERRIDE; - bool isAliasOf(const IUnitedEntry *p_entry) const Q_DECL_OVERRIDE; + bool isAliasOf(const IUnitedEntry *p_entry) const Q_DECL_OVERRIDE; - protected: - void initOnFirstProcess() Q_DECL_OVERRIDE; +protected: + void initOnFirstProcess() Q_DECL_OVERRIDE; - void processInternal(const QString &p_args, - const std::function &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE; + void + processInternal(const QString &p_args, + const std::function &)> &p_popupWidgetFunc) + Q_DECL_OVERRIDE; - void setOngoing(bool p_ongoing) Q_DECL_OVERRIDE; + void setOngoing(bool p_ongoing) Q_DECL_OVERRIDE; - private: - QString m_value; +private: + QString m_value; - UnitedEntryHelper::UserEntry m_alias; + UnitedEntryHelper::UserEntry m_alias; - IUnitedEntry *m_realEntry = nullptr; - }; -} + IUnitedEntry *m_realEntry = nullptr; +}; +} // namespace vnotex #endif // UNITEDENTRYALIAS_H diff --git a/src/unitedentry/unitedentryhelper.cpp b/src/unitedentry/unitedentryhelper.cpp index 183e45a1ce..4b3e4bf6f1 100644 --- a/src/unitedentry/unitedentryhelper.cpp +++ b/src/unitedentry/unitedentryhelper.cpp @@ -2,69 +2,67 @@ #include -#include #include +#include #include using namespace vnotex; -UnitedEntryHelper::UserEntry UnitedEntryHelper::parseUserEntry(const QString &p_text) -{ - UserEntry entry; +UnitedEntryHelper::UserEntry UnitedEntryHelper::parseUserEntry(const QString &p_text) { + UserEntry entry; - const auto text = p_text.trimmed(); + const auto text = p_text.trimmed(); - if (text.isEmpty()) { - return entry; - } + if (text.isEmpty()) { + return entry; + } - int idx = text.indexOf(QLatin1Char(' ')); - if (idx == -1) { - entry.m_name = text.toLower(); - } else { - entry.m_name = text.left(idx).toLower(); - entry.m_args = text.mid(idx).trimmed(); - } + int idx = text.indexOf(QLatin1Char(' ')); + if (idx == -1) { + entry.m_name = text.toLower(); + } else { + entry.m_name = text.left(idx).toLower(); + entry.m_args = text.mid(idx).trimmed(); + } - return entry; + return entry; } -const QIcon &UnitedEntryHelper::itemIcon(ItemType p_type) -{ - static QIcon icons[ItemType::MaxItemType]; +const QIcon &UnitedEntryHelper::itemIcon(ItemType p_type) { + static QIcon icons[ItemType::MaxItemType]; - if (icons[0].isNull()) { - // Init. - const QString nodeIconFgName = "base#icon#fg"; - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - const auto fg = themeMgr.paletteColor(nodeIconFgName); + if (icons[0].isNull()) { + // Init. + const QString nodeIconFgName = "base#icon#fg"; + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + const auto fg = themeMgr.paletteColor(nodeIconFgName); - icons[ItemType::Buffer] = IconUtils::fetchIcon(themeMgr.getIconFile("buffer.svg"), fg); - icons[ItemType::File] = IconUtils::fetchIcon(themeMgr.getIconFile("file_node.svg"), fg); - icons[ItemType::Folder] = IconUtils::fetchIcon(themeMgr.getIconFile("folder_node.svg"), fg); - icons[ItemType::Notebook] = IconUtils::fetchIcon(themeMgr.getIconFile("notebook_default.svg"), fg); - icons[ItemType::Other] = IconUtils::fetchIcon(themeMgr.getIconFile("other_item.svg"), fg); - } + icons[ItemType::Buffer] = IconUtils::fetchIcon(themeMgr.getIconFile("buffer.svg"), fg); + icons[ItemType::File] = IconUtils::fetchIcon(themeMgr.getIconFile("file_node.svg"), fg); + icons[ItemType::Folder] = IconUtils::fetchIcon(themeMgr.getIconFile("folder_node.svg"), fg); + icons[ItemType::Notebook] = + IconUtils::fetchIcon(themeMgr.getIconFile("notebook_default.svg"), fg); + icons[ItemType::Other] = IconUtils::fetchIcon(themeMgr.getIconFile("other_item.svg"), fg); + } - return icons[p_type]; + return icons[p_type]; } -UnitedEntryHelper::ItemType UnitedEntryHelper::locationTypeToItemType(LocationType p_type) -{ - switch (p_type) { - case LocationType::Buffer: - return ItemType::Buffer; +UnitedEntryHelper::ItemType UnitedEntryHelper::locationTypeToItemType(LocationType p_type) { + switch (p_type) { + case LocationType::Buffer: + return ItemType::Buffer; - case LocationType::File: - return ItemType::File; + case LocationType::File: + return ItemType::File; - case LocationType::Folder: - return ItemType::Folder; + case LocationType::Folder: + return ItemType::Folder; - case LocationType::Notebook: - return ItemType::Notebook; + case LocationType::Notebook: + return ItemType::Notebook; - default: - return ItemType::Other; - } + default: + return ItemType::Other; + } } diff --git a/src/unitedentry/unitedentryhelper.h b/src/unitedentry/unitedentryhelper.h index 60cded5ef5..2b767bccaa 100644 --- a/src/unitedentry/unitedentryhelper.h +++ b/src/unitedentry/unitedentryhelper.h @@ -7,37 +7,26 @@ class QIcon; -namespace vnotex -{ - class UnitedEntryHelper - { - public: - struct UserEntry - { - QString m_name; - - QString m_args; - }; - - enum ItemType - { - Buffer, - File, - Folder, - Notebook, - Other, - MaxItemType - }; - - UnitedEntryHelper() = delete; - - static UserEntry parseUserEntry(const QString &p_text); - - static const QIcon &itemIcon(ItemType p_type); - - static ItemType locationTypeToItemType(LocationType p_type); - }; - -} +namespace vnotex { +class UnitedEntryHelper { +public: + struct UserEntry { + QString m_name; + + QString m_args; + }; + + enum ItemType { Buffer, File, Folder, Notebook, Other, MaxItemType }; + + UnitedEntryHelper() = delete; + + static UserEntry parseUserEntry(const QString &p_text); + + static const QIcon &itemIcon(ItemType p_type); + + static ItemType locationTypeToItemType(LocationType p_type); +}; + +} // namespace vnotex #endif // UNITEDENTRYHELPER_H diff --git a/src/unitedentry/unitedentrymgr.cpp b/src/unitedentry/unitedentrymgr.cpp index 2bea909497..d62ee52300 100644 --- a/src/unitedentry/unitedentrymgr.cpp +++ b/src/unitedentry/unitedentrymgr.cpp @@ -11,74 +11,55 @@ using namespace vnotex; -UnitedEntryMgr::UnitedEntryMgr(QObject *p_parent) - : QObject(p_parent) -{ -} +UnitedEntryMgr::UnitedEntryMgr(QObject *p_parent) : QObject(p_parent) {} -void UnitedEntryMgr::init() -{ - if (m_initialized) { - return; - } +void UnitedEntryMgr::init() { + if (m_initialized) { + return; + } - m_initialized = true; + m_initialized = true; - // Built-in entries. - const auto mainWindow = VNoteX::getInst().getMainWindow(); - addEntry(QSharedPointer::create(SearchInfoProvider::create(mainWindow), this)); + // Built-in entries. + const auto mainWindow = VNoteX::getInst().getMainWindow(); + addEntry(QSharedPointer::create(SearchInfoProvider::create(mainWindow), this)); - addEntry(QSharedPointer::create(this)); + addEntry(QSharedPointer::create(this)); - // Alias from config. - const auto &config = ConfigMgr::getInst().getCoreConfig(); - const auto &aliasArr = config.getUnitedEntryAlias(); - for (int i = 0; i < aliasArr.size(); ++i) { - auto entry = QSharedPointer::create(aliasArr[i].toObject(), this); - addEntry(entry); - } + // Alias from config. + const auto &config = ConfigMgr::getInst().getCoreConfig(); + const auto &aliasArr = config.getUnitedEntryAlias(); + for (int i = 0; i < aliasArr.size(); ++i) { + auto entry = QSharedPointer::create(aliasArr[i].toObject(), this); + addEntry(entry); + } } -void UnitedEntryMgr::addEntry(const QSharedPointer &p_entry) -{ - Q_ASSERT(!m_entries.contains(p_entry->name())); - m_entries.insert(p_entry->name(), p_entry); - connect(p_entry.data(), &IUnitedEntry::finished, - this, [this]() { - emit entryFinished(reinterpret_cast(sender())); - }); - connect(p_entry.data(), &IUnitedEntry::itemActivated, - this, [this](bool quit, bool restoreFocus) { - emit entryItemActivated(reinterpret_cast(sender()), quit, restoreFocus); - }); +void UnitedEntryMgr::addEntry(const QSharedPointer &p_entry) { + Q_ASSERT(!m_entries.contains(p_entry->name())); + m_entries.insert(p_entry->name(), p_entry); + connect(p_entry.data(), &IUnitedEntry::finished, this, + [this]() { emit entryFinished(reinterpret_cast(sender())); }); + connect(p_entry.data(), &IUnitedEntry::itemActivated, this, [this](bool quit, bool restoreFocus) { + emit entryItemActivated(reinterpret_cast(sender()), quit, restoreFocus); + }); } -QList> UnitedEntryMgr::getEntries() const -{ - return m_entries.values(); +QList> UnitedEntryMgr::getEntries() const { + return m_entries.values(); } -QSharedPointer UnitedEntryMgr::findEntry(const QString &p_name) const -{ - auto it = m_entries.find(p_name); - if (it == m_entries.end()) { - return nullptr; - } +QSharedPointer UnitedEntryMgr::findEntry(const QString &p_name) const { + auto it = m_entries.find(p_name); + if (it == m_entries.end()) { + return nullptr; + } - return it.value(); + return it.value(); } -bool UnitedEntryMgr::isInitialized() const -{ - return m_initialized; -} +bool UnitedEntryMgr::isInitialized() const { return m_initialized; } -bool UnitedEntryMgr::getExpandAllEnabled() const -{ - return m_expandAllEnabled; -} +bool UnitedEntryMgr::getExpandAllEnabled() const { return m_expandAllEnabled; } -void UnitedEntryMgr::setExpandAllEnabled(bool p_enabled) -{ - m_expandAllEnabled = p_enabled; -} +void UnitedEntryMgr::setExpandAllEnabled(bool p_enabled) { m_expandAllEnabled = p_enabled; } diff --git a/src/unitedentry/unitedentrymgr.h b/src/unitedentry/unitedentrymgr.h index d8812cb96d..69ce3e68e9 100644 --- a/src/unitedentry/unitedentrymgr.h +++ b/src/unitedentry/unitedentrymgr.h @@ -1,54 +1,51 @@ #ifndef UNITEDENTRYMGR_H #define UNITEDENTRYMGR_H +#include #include #include -#include #include -namespace vnotex -{ - class IUnitedEntry; +namespace vnotex { +class IUnitedEntry; - class UnitedEntryMgr : public QObject, private Noncopyable - { - Q_OBJECT - public: - static UnitedEntryMgr &getInst() - { - static UnitedEntryMgr inst; - inst.init(); - return inst; - } +class UnitedEntryMgr : public QObject, private Noncopyable { + Q_OBJECT +public: + static UnitedEntryMgr &getInst() { + static UnitedEntryMgr inst; + inst.init(); + return inst; + } - void init(); + void init(); - QList> getEntries() const; + QList> getEntries() const; - QSharedPointer findEntry(const QString &p_name) const; + QSharedPointer findEntry(const QString &p_name) const; - bool isInitialized() const; + bool isInitialized() const; - bool getExpandAllEnabled() const; - void setExpandAllEnabled(bool p_enabled); + bool getExpandAllEnabled() const; + void setExpandAllEnabled(bool p_enabled); - signals: - void entryFinished(IUnitedEntry *p_entry); +signals: + void entryFinished(IUnitedEntry *p_entry); - void entryItemActivated(IUnitedEntry *p_entry, bool p_quit, bool p_restoreFocus); + void entryItemActivated(IUnitedEntry *p_entry, bool p_quit, bool p_restoreFocus); - private: - explicit UnitedEntryMgr(QObject *p_parent = nullptr); +private: + explicit UnitedEntryMgr(QObject *p_parent = nullptr); - void addEntry(const QSharedPointer &p_entry); + void addEntry(const QSharedPointer &p_entry); - bool m_initialized = false; + bool m_initialized = false; - QMap> m_entries; + QMap> m_entries; - bool m_expandAllEnabled = false; - }; -} + bool m_expandAllEnabled = false; +}; +} // namespace vnotex #endif // UNITEDENTRYMGR_H diff --git a/src/utils/asyncworker.cpp b/src/utils/asyncworker.cpp index 7fc550746a..d700511229 100644 --- a/src/utils/asyncworker.cpp +++ b/src/utils/asyncworker.cpp @@ -2,36 +2,21 @@ using namespace vnotex; -AsyncWorker::AsyncWorker(QObject *p_parent) - : QThread(p_parent) -{ -} +AsyncWorker::AsyncWorker(QObject *p_parent) : QThread(p_parent) {} -void AsyncWorker::stop() -{ - m_askedToStop.fetchAndStoreAcquire(1); -} +void AsyncWorker::stop() { m_askedToStop.fetchAndStoreAcquire(1); } -bool AsyncWorker::isAskedToStop() const -{ - return m_askedToStop.loadAcquire() == 1; -} +bool AsyncWorker::isAskedToStop() const { return m_askedToStop.loadAcquire() == 1; } +AsyncWorkerWithFunctor::AsyncWorkerWithFunctor(QObject *p_parent) : QThread(p_parent) {} -AsyncWorkerWithFunctor::AsyncWorkerWithFunctor(QObject *p_parent) - : QThread(p_parent) -{ -} - -void AsyncWorkerWithFunctor::doWork(const Functor &p_functor) -{ - Q_ASSERT(!isRunning()); - m_functor = p_functor; - start(); +void AsyncWorkerWithFunctor::doWork(const Functor &p_functor) { + Q_ASSERT(!isRunning()); + m_functor = p_functor; + start(); } -void AsyncWorkerWithFunctor::run() -{ - Q_ASSERT(m_functor); - m_functor(); +void AsyncWorkerWithFunctor::run() { + Q_ASSERT(m_functor); + m_functor(); } diff --git a/src/utils/asyncworker.h b/src/utils/asyncworker.h index 05e713f49f..5b0d313a3e 100644 --- a/src/utils/asyncworker.h +++ b/src/utils/asyncworker.h @@ -5,41 +5,37 @@ #include -namespace vnotex -{ - class AsyncWorker : public QThread - { - Q_OBJECT - public: - explicit AsyncWorker(QObject *p_parent = nullptr); +namespace vnotex { +class AsyncWorker : public QThread { + Q_OBJECT +public: + explicit AsyncWorker(QObject *p_parent = nullptr); - public slots: - void stop(); +public slots: + void stop(); - protected: - bool isAskedToStop() const; +protected: + bool isAskedToStop() const; - private: - QAtomicInt m_askedToStop = 0; - }; +private: + QAtomicInt m_askedToStop = 0; +}; +class AsyncWorkerWithFunctor : public QThread { + Q_OBJECT +public: + typedef std::function Functor; - class AsyncWorkerWithFunctor : public QThread - { - Q_OBJECT - public: - typedef std::function Functor; + explicit AsyncWorkerWithFunctor(QObject *p_parent = nullptr); - explicit AsyncWorkerWithFunctor(QObject *p_parent = nullptr); + void doWork(const Functor &p_functor); - void doWork(const Functor &p_functor); +protected: + void run() Q_DECL_OVERRIDE; - protected: - void run() Q_DECL_OVERRIDE; - - private: - Functor m_functor; - }; -} +private: + Functor m_functor; +}; +} // namespace vnotex #endif // ASYNCWORKER_H diff --git a/src/utils/callbackpool.cpp b/src/utils/callbackpool.cpp index b58f59392c..e18daf33fa 100644 --- a/src/utils/callbackpool.cpp +++ b/src/utils/callbackpool.cpp @@ -4,26 +4,21 @@ using namespace vnotex; -quint64 CallbackPool::add(const Callback &p_callback) -{ - static quint64 nextId = 0; - quint64 id = nextId++; - m_pool.insert(id, p_callback); - return id; +quint64 CallbackPool::add(const Callback &p_callback) { + static quint64 nextId = 0; + quint64 id = nextId++; + m_pool.insert(id, p_callback); + return id; } -void CallbackPool::call(quint64 p_id, void *p_data) -{ - auto it = m_pool.find(p_id); - if (it != m_pool.end()) { - it.value()(p_data); - m_pool.erase(it); - } else { - qWarning() << "failed to locate callback in pool with id" << p_id; - } +void CallbackPool::call(quint64 p_id, void *p_data) { + auto it = m_pool.find(p_id); + if (it != m_pool.end()) { + it.value()(p_data); + m_pool.erase(it); + } else { + qWarning() << "failed to locate callback in pool with id" << p_id; + } } -void CallbackPool::clear() -{ - m_pool.clear(); -} +void CallbackPool::clear() { m_pool.clear(); } diff --git a/src/utils/callbackpool.h b/src/utils/callbackpool.h index c33819f98f..1380bed7d0 100644 --- a/src/utils/callbackpool.h +++ b/src/utils/callbackpool.h @@ -5,25 +5,23 @@ #include -namespace vnotex -{ - // Manage callbacks with id. - class CallbackPool - { - public: - typedef std::function Callback; +namespace vnotex { +// Manage callbacks with id. +class CallbackPool { +public: + typedef std::function Callback; - CallbackPool() = default; + CallbackPool() = default; - quint64 add(const Callback &p_callback); + quint64 add(const Callback &p_callback); - void call(quint64 p_id, void *p_data); + void call(quint64 p_id, void *p_data); - void clear(); + void clear(); - private: - QMap m_pool; - }; -} +private: + QMap m_pool; +}; +} // namespace vnotex #endif // CALLBACKPOOL_H diff --git a/src/utils/clipboardutils.cpp b/src/utils/clipboardutils.cpp index f72a389b01..db487e68fd 100644 --- a/src/utils/clipboardutils.cpp +++ b/src/utils/clipboardutils.cpp @@ -1,237 +1,219 @@ #include "clipboardutils.h" -#include -#include +#include #include -#include #include -#include -#include #include +#include +#include +#include +#include -#include "utils.h" -#include "pathutils.h" #include "fileutils.h" +#include "pathutils.h" +#include "utils.h" using namespace vnotex; -QString ClipboardUtils::getTextFromClipboard() -{ - QClipboard *clipboard = QApplication::clipboard(); - QString subType(QStringLiteral("plain")); - return clipboard->text(subType, QClipboard::Clipboard); +QString ClipboardUtils::getTextFromClipboard() { + QClipboard *clipboard = QApplication::clipboard(); + QString subType(QStringLiteral("plain")); + return clipboard->text(subType, QClipboard::Clipboard); } -void ClipboardUtils::setTextToClipboard(const QString &p_text) -{ - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(p_text); +void ClipboardUtils::setTextToClipboard(const QString &p_text) { + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(p_text); } -void ClipboardUtils::setLinkToClipboard(const QString &p_link) -{ - QClipboard *clipboard = QApplication::clipboard(); - setMimeDataToClipboard(clipboard, linkMimeData(p_link).release()); +void ClipboardUtils::setLinkToClipboard(const QString &p_link) { + QClipboard *clipboard = QApplication::clipboard(); + setMimeDataToClipboard(clipboard, linkMimeData(p_link).release()); } -void ClipboardUtils::clearClipboard() -{ - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(QString()); +void ClipboardUtils::clearClipboard() { + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(QString()); } -void ClipboardUtils::setMimeDataToClipboard(QClipboard *p_clipboard, - QMimeData *p_mimeData, - QClipboard::Mode p_mode) -{ +void ClipboardUtils::setMimeDataToClipboard(QClipboard *p_clipboard, QMimeData *p_mimeData, + QClipboard::Mode p_mode) { #if defined(Q_OS_WIN) || defined(Q_OS_LINUX) - // On Windows, setMimeData() may fail. We will repeatedly retry until succeed. - // On Linux, QXcbClipboard::setMimeData: Cannot set X11 selection owner. - setMimeDataLoop(p_clipboard, p_mimeData, p_mode); + // On Windows, setMimeData() may fail. We will repeatedly retry until succeed. + // On Linux, QXcbClipboard::setMimeData: Cannot set X11 selection owner. + setMimeDataLoop(p_clipboard, p_mimeData, p_mode); #else - p_clipboard->setMimeData(p_mimeData, p_mode); + p_clipboard->setMimeData(p_mimeData, p_mode); #endif } -bool ClipboardUtils::mimeDataEquals(const QMimeData *p_a, const QMimeData *p_b) -{ - if (!p_a && !p_b) { - return true; - } +bool ClipboardUtils::mimeDataEquals(const QMimeData *p_a, const QMimeData *p_b) { + if (!p_a && !p_b) { + return true; + } - if ((p_a && !p_b) || (!p_a && p_b)) { - return false; - } + if ((p_a && !p_b) || (!p_a && p_b)) { + return false; + } - if (p_a->hasUrls()) { - if (!p_b->hasUrls()) { - return false; - } + if (p_a->hasUrls()) { + if (!p_b->hasUrls()) { + return false; + } - if (p_a->urls() != p_b->urls()) { - return false; - } - } else if (p_b->hasUrls()) { - return false; + if (p_a->urls() != p_b->urls()) { + return false; } + } else if (p_b->hasUrls()) { + return false; + } - if (p_a->hasText()) { - if (!p_b->hasText()) { - return false; - } + if (p_a->hasText()) { + if (!p_b->hasText()) { + return false; + } - if (p_a->text() != p_b->text()) { - return false; - } - } else if (p_b->hasText()) { - return false; + if (p_a->text() != p_b->text()) { + return false; } + } else if (p_b->hasText()) { + return false; + } - if (p_a->hasColor()) { - if (!p_b->hasColor()) { - return false; - } + if (p_a->hasColor()) { + if (!p_b->hasColor()) { + return false; + } - if (p_a->colorData() != p_b->colorData()) { - return false; - } - } else if (p_b->hasColor()) { - return false; + if (p_a->colorData() != p_b->colorData()) { + return false; } + } else if (p_b->hasColor()) { + return false; + } - if (p_a->hasHtml()) { - if (!p_b->hasHtml()) { - return false; - } + if (p_a->hasHtml()) { + if (!p_b->hasHtml()) { + return false; + } - if (p_a->html() != p_b->html()) { - return false; - } - } else if (p_b->hasHtml()) { - return false; + if (p_a->html() != p_b->html()) { + return false; } + } else if (p_b->hasHtml()) { + return false; + } - if (p_a->hasImage()) { - if (!p_b->hasImage()) { - return false; - } + if (p_a->hasImage()) { + if (!p_b->hasImage()) { + return false; + } - if (p_a->imageData() != p_b->imageData()) { - return false; - } - } else if (p_b->hasImage()) { - return false; + if (p_a->imageData() != p_b->imageData()) { + return false; } + } else if (p_b->hasImage()) { + return false; + } - return true; + return true; } -void ClipboardUtils::setMimeDataLoop(QClipboard *p_clipboard, - QMimeData *p_mimeData, - QClipboard::Mode p_mode) -{ - for (int i = 0; i < 100; ++i) { - // Make a backup. - auto tmp = cloneMimeData(p_mimeData); - - p_clipboard->setMimeData(p_mimeData, p_mode); - const QMimeData *out = p_clipboard->mimeData(p_mode); - if (mimeDataEquals(tmp.get(), out)) { - return; - } - - qDebug() << "failed to set mimeData, retry" << i; - p_mimeData = tmp.release(); - Utils::sleepWait(100 /* ms */); +void ClipboardUtils::setMimeDataLoop(QClipboard *p_clipboard, QMimeData *p_mimeData, + QClipboard::Mode p_mode) { + for (int i = 0; i < 100; ++i) { + // Make a backup. + auto tmp = cloneMimeData(p_mimeData); + + p_clipboard->setMimeData(p_mimeData, p_mode); + const QMimeData *out = p_clipboard->mimeData(p_mode); + if (mimeDataEquals(tmp.get(), out)) { + return; } - delete p_mimeData; + qDebug() << "failed to set mimeData, retry" << i; + p_mimeData = tmp.release(); + Utils::sleepWait(100 /* ms */); + } + + delete p_mimeData; } -std::unique_ptr ClipboardUtils::cloneMimeData(const QMimeData *p_mimeData) -{ - std::unique_ptr da(new QMimeData()); - if (p_mimeData->hasUrls()) { - da->setUrls(p_mimeData->urls()); - } +std::unique_ptr ClipboardUtils::cloneMimeData(const QMimeData *p_mimeData) { + std::unique_ptr da(new QMimeData()); + if (p_mimeData->hasUrls()) { + da->setUrls(p_mimeData->urls()); + } - if (p_mimeData->hasText()) { - da->setText(p_mimeData->text()); - } + if (p_mimeData->hasText()) { + da->setText(p_mimeData->text()); + } - if (p_mimeData->hasColor()) { - da->setColorData(p_mimeData->colorData()); - } + if (p_mimeData->hasColor()) { + da->setColorData(p_mimeData->colorData()); + } - if (p_mimeData->hasHtml()) { - da->setHtml(p_mimeData->html()); - } + if (p_mimeData->hasHtml()) { + da->setHtml(p_mimeData->html()); + } - if (p_mimeData->hasImage()) { - da->setImageData(p_mimeData->imageData()); - } + if (p_mimeData->hasImage()) { + da->setImageData(p_mimeData->imageData()); + } - return da; + return da; } -void ClipboardUtils::setImageToClipboard(QClipboard *p_clipboard, - const QImage &p_image, - QClipboard::Mode p_mode) -{ +void ClipboardUtils::setImageToClipboard(QClipboard *p_clipboard, const QImage &p_image, + QClipboard::Mode p_mode) { #if defined(Q_OS_WIN) || defined(Q_OS_LINUX) - // On Windows, setImage() may fail. We will repeatedly retry until succeed. - // On Linux, QXcbClipboard::setMimeData: Cannot set X11 selection owner. - setImageLoop(p_clipboard, p_image, p_mode); + // On Windows, setImage() may fail. We will repeatedly retry until succeed. + // On Linux, QXcbClipboard::setMimeData: Cannot set X11 selection owner. + setImageLoop(p_clipboard, p_image, p_mode); #else - p_clipboard->setImage(p_image, p_mode); + p_clipboard->setImage(p_image, p_mode); #endif } +void ClipboardUtils::setImageLoop(QClipboard *p_clipboard, const QImage &p_image, + QClipboard::Mode p_mode) { + for (int i = 0; i < 100; ++i) { + p_clipboard->setImage(p_image, p_mode); -void ClipboardUtils::setImageLoop(QClipboard *p_clipboard, - const QImage &p_image, - QClipboard::Mode p_mode) -{ - for (int i = 0; i < 100; ++i) { - p_clipboard->setImage(p_image, p_mode); - - QImage image = p_clipboard->image(p_mode); - if (!image.isNull()) { - break; - } - - qWarning() << "failed to set image, retry" << i; - Utils::sleepWait(100 /* ms */); + QImage image = p_clipboard->image(p_mode); + if (!image.isNull()) { + break; } + + qWarning() << "failed to set image, retry" << i; + Utils::sleepWait(100 /* ms */); + } } -std::unique_ptr ClipboardUtils::linkMimeData(const QString &p_link) -{ - QList urls; - urls.append(PathUtils::pathToUrl(p_link)); - std::unique_ptr data(new QMimeData()); - data->setUrls(urls); +std::unique_ptr ClipboardUtils::linkMimeData(const QString &p_link) { + QList urls; + urls.append(PathUtils::pathToUrl(p_link)); + std::unique_ptr data(new QMimeData()); + data->setUrls(urls); - QString text = urls[0].toEncoded(); + QString text = urls[0].toEncoded(); #if defined(Q_OS_WIN) - if (urls[0].isLocalFile()) { - text = urls[0].toString(QUrl::EncodeSpaces); - } + if (urls[0].isLocalFile()) { + text = urls[0].toString(QUrl::EncodeSpaces); + } #endif - data->setText(text); - return data; + data->setText(text); + return data; } -void ClipboardUtils::setLocalFileToClipboard(QClipboard *p_clipboard, - const QString &p_filePath, - QClipboard::Mode p_mode) -{ - // Check if the file exists - if (!FileUtils::existsCaseInsensitive(p_filePath)) { - qWarning() << "ClipboardUtils::setLocalFileToClipboard: file does not exist:" << p_filePath; - return; - } +void ClipboardUtils::setLocalFileToClipboard(QClipboard *p_clipboard, const QString &p_filePath, + QClipboard::Mode p_mode) { + // Check if the file exists + if (!FileUtils::existsCaseInsensitive(p_filePath)) { + qWarning() << "ClipboardUtils::setLocalFileToClipboard: file does not exist:" << p_filePath; + return; + } - setMimeDataToClipboard(p_clipboard, linkMimeData(p_filePath).release(), p_mode); + setMimeDataToClipboard(p_clipboard, linkMimeData(p_filePath).release(), p_mode); } diff --git a/src/utils/clipboardutils.h b/src/utils/clipboardutils.h index f6f0ca3d11..bed8fa6671 100644 --- a/src/utils/clipboardutils.h +++ b/src/utils/clipboardutils.h @@ -5,50 +5,42 @@ #include -namespace vnotex -{ - class ClipboardUtils - { - public: - ClipboardUtils() = delete; +namespace vnotex { +class ClipboardUtils { +public: + ClipboardUtils() = delete; - static QString getTextFromClipboard(); + static QString getTextFromClipboard(); - static void setTextToClipboard(const QString &p_text); + static void setTextToClipboard(const QString &p_text); - static void setLinkToClipboard(const QString &p_link); + static void setLinkToClipboard(const QString &p_link); - // @p_mimeData will be owned by utils. - static void setMimeDataToClipboard(QClipboard *p_clipboard, - QMimeData *p_mimeData, - QClipboard::Mode p_mode = QClipboard::Clipboard); + // @p_mimeData will be owned by utils. + static void setMimeDataToClipboard(QClipboard *p_clipboard, QMimeData *p_mimeData, + QClipboard::Mode p_mode = QClipboard::Clipboard); - static void clearClipboard(); + static void clearClipboard(); - static std::unique_ptr cloneMimeData(const QMimeData *p_mimeData); + static std::unique_ptr cloneMimeData(const QMimeData *p_mimeData); - static void setImageToClipboard(QClipboard *p_clipboard, - const QImage &p_image, - QClipboard::Mode p_mode = QClipboard::Clipboard); + static void setImageToClipboard(QClipboard *p_clipboard, const QImage &p_image, + QClipboard::Mode p_mode = QClipboard::Clipboard); - // Set a local file to clipboard. - static void setLocalFileToClipboard(QClipboard *p_clipboard, - const QString &p_filePath, - QClipboard::Mode p_mode = QClipboard::Clipboard); + // Set a local file to clipboard. + static void setLocalFileToClipboard(QClipboard *p_clipboard, const QString &p_filePath, + QClipboard::Mode p_mode = QClipboard::Clipboard); - private: - static bool mimeDataEquals(const QMimeData *p_a, const QMimeData *p_b); +private: + static bool mimeDataEquals(const QMimeData *p_a, const QMimeData *p_b); - static void setMimeDataLoop(QClipboard *p_clipboard, - QMimeData *p_mimeData, - QClipboard::Mode p_mode); + static void setMimeDataLoop(QClipboard *p_clipboard, QMimeData *p_mimeData, + QClipboard::Mode p_mode); - static void setImageLoop(QClipboard *p_clipboard, - const QImage &p_image, - QClipboard::Mode p_mode); + static void setImageLoop(QClipboard *p_clipboard, const QImage &p_image, QClipboard::Mode p_mode); - static std::unique_ptr linkMimeData(const QString &p_link); - }; -} // ns vnotex + static std::unique_ptr linkMimeData(const QString &p_link); +}; +} // namespace vnotex #endif // CLIPBOARDUTILS_H diff --git a/src/utils/contentmediautils.cpp b/src/utils/contentmediautils.cpp index 785061b945..ce37b9dcee 100644 --- a/src/utils/contentmediautils.cpp +++ b/src/utils/contentmediautils.cpp @@ -1,218 +1,194 @@ #include "contentmediautils.h" #include -#include -#include #include +#include #include +#include -#include #include +#include #include #include #include -#include -#include -#include #include +#include +#include +#include using namespace vnotex; -void ContentMediaUtils::copyMediaFiles(Node *p_node, - INotebookBackend *p_backend, - const QString &p_destFilePath) -{ - Q_ASSERT(p_node->hasContent()); - auto file = p_node->getContentFile(); - if (file->getContentType().isMarkdown()) { - copyMarkdownMediaFiles(file->read(), - PathUtils::parentDirPath(file->getContentPath()), - p_backend, - p_destFilePath); - } +void ContentMediaUtils::copyMediaFiles(Node *p_node, INotebookBackend *p_backend, + const QString &p_destFilePath) { + Q_ASSERT(p_node->hasContent()); + auto file = p_node->getContentFile(); + if (file->getContentType().isMarkdown()) { + copyMarkdownMediaFiles(file->read(), PathUtils::parentDirPath(file->getContentPath()), + p_backend, p_destFilePath); + } } -void ContentMediaUtils::copyMediaFiles(const QString &p_filePath, - INotebookBackend *p_backend, - const QString &p_destFilePath) -{ - const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath); - if (fileType.isMarkdown()) { - copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath), - PathUtils::parentDirPath(p_filePath), - p_backend, - p_destFilePath); - } +void ContentMediaUtils::copyMediaFiles(const QString &p_filePath, INotebookBackend *p_backend, + const QString &p_destFilePath) { + const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath); + if (fileType.isMarkdown()) { + copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath), + PathUtils::parentDirPath(p_filePath), p_backend, p_destFilePath); + } } -void ContentMediaUtils::copyMediaFiles(const File *p_file, - const QString &p_destFilePath) -{ - if (p_file->getContentType().isMarkdown()) { - copyMarkdownMediaFiles(p_file->read(), - p_file->getResourcePath(), - nullptr, - p_destFilePath); - } +void ContentMediaUtils::copyMediaFiles(const File *p_file, const QString &p_destFilePath) { + if (p_file->getContentType().isMarkdown()) { + copyMarkdownMediaFiles(p_file->read(), p_file->getResourcePath(), nullptr, p_destFilePath); + } } -void ContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content, - const QString &p_basePath, +void ContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content, const QString &p_basePath, INotebookBackend *p_backend, - const QString &p_destFilePath) -{ - auto content = p_content; - - // Images. - const auto images = - vte::MarkdownUtils::fetchImagesFromMarkdownText(content, - p_basePath, - vte::MarkdownLink::TypeFlag::LocalRelativeInternal); - - QDir destDir(PathUtils::parentDirPath(p_destFilePath)); - QSet handledImages; - QHash renamedImages; - int lastPos = content.size(); - for (const auto &link : images) { - Q_ASSERT(link.m_urlInLinkPos < lastPos); - lastPos = link.m_urlInLinkPos; - - qDebug() << "link" << link.m_path << link.m_urlInLink; - - if (handledImages.contains(link.m_path)) { - auto it = renamedImages.find(link.m_path); - if (it != renamedImages.end()) { - content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), it.value()); - } - continue; - } - - handledImages.insert(link.m_path); - - if (!QFileInfo::exists(link.m_path)) { - qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink; - continue; - } - - // Get the relative path of the image and apply it to the dest file path. - const auto decodedUrlInLink = vte::TextUtils::decodeUrl(link.m_urlInLink); - const auto oldDestFilePath = destDir.filePath(decodedUrlInLink); - destDir.mkpath(PathUtils::parentDirPath(oldDestFilePath)); - auto destFilePath = p_backend ? p_backend->renameIfExistsCaseInsensitive(oldDestFilePath) - : FileUtils::renameIfExistsCaseInsensitive(oldDestFilePath); - if (oldDestFilePath != destFilePath) { - // Rename happens. - const auto oldFileName = PathUtils::fileName(oldDestFilePath); - const auto newFileName = PathUtils::fileName(destFilePath); - qWarning() << QStringLiteral("image name conflicts when copy, renamed from (%1) to (%2)").arg(oldFileName, newFileName); - - // Update the text content. - const auto encodedOldFileName = PathUtils::fileName(link.m_urlInLink); - const auto encodedNewFileName = vte::TextUtils::encodeUrl(newFileName); - auto newUrlInLink(link.m_urlInLink); - newUrlInLink.replace(newUrlInLink.size() - encodedOldFileName.size(), - encodedOldFileName.size(), - encodedNewFileName); - - content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), newUrlInLink); - renamedImages.insert(link.m_path, newUrlInLink); - } - - if (p_backend) { - p_backend->copyFile(link.m_path, destFilePath); - } else { - FileUtils::copyFile(link.m_path, destFilePath); - } + const QString &p_destFilePath) { + auto content = p_content; + + // Images. + const auto images = vte::MarkdownUtils::fetchImagesFromMarkdownText( + content, p_basePath, vte::MarkdownLink::TypeFlag::LocalRelativeInternal); + + QDir destDir(PathUtils::parentDirPath(p_destFilePath)); + QSet handledImages; + QHash renamedImages; + int lastPos = content.size(); + for (const auto &link : images) { + Q_ASSERT(link.m_urlInLinkPos < lastPos); + lastPos = link.m_urlInLinkPos; + + qDebug() << "link" << link.m_path << link.m_urlInLink; + + if (handledImages.contains(link.m_path)) { + auto it = renamedImages.find(link.m_path); + if (it != renamedImages.end()) { + content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), it.value()); + } + continue; } - if (!renamedImages.isEmpty()) { - if (p_backend) { - p_backend->writeFile(p_destFilePath, content); - } else { - FileUtils::writeFile(p_destFilePath, content); - } + handledImages.insert(link.m_path); + + if (!QFileInfo::exists(link.m_path)) { + qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink; + continue; } -} -void ContentMediaUtils::removeMediaFiles(Node *p_node) -{ - Q_ASSERT(p_node->hasContent()); - auto file = p_node->getContentFile(); - if (file->getContentType().isMarkdown()) { - removeMarkdownMediaFiles(file.data(), p_node->getBackend()); + // Get the relative path of the image and apply it to the dest file path. + const auto decodedUrlInLink = vte::TextUtils::decodeUrl(link.m_urlInLink); + const auto oldDestFilePath = destDir.filePath(decodedUrlInLink); + destDir.mkpath(PathUtils::parentDirPath(oldDestFilePath)); + auto destFilePath = p_backend ? p_backend->renameIfExistsCaseInsensitive(oldDestFilePath) + : FileUtils::renameIfExistsCaseInsensitive(oldDestFilePath); + if (oldDestFilePath != destFilePath) { + // Rename happens. + const auto oldFileName = PathUtils::fileName(oldDestFilePath); + const auto newFileName = PathUtils::fileName(destFilePath); + qWarning() << QStringLiteral("image name conflicts when copy, renamed from (%1) to (%2)") + .arg(oldFileName, newFileName); + + // Update the text content. + const auto encodedOldFileName = PathUtils::fileName(link.m_urlInLink); + const auto encodedNewFileName = vte::TextUtils::encodeUrl(newFileName); + auto newUrlInLink(link.m_urlInLink); + newUrlInLink.replace(newUrlInLink.size() - encodedOldFileName.size(), + encodedOldFileName.size(), encodedNewFileName); + + content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), newUrlInLink); + renamedImages.insert(link.m_path, newUrlInLink); } -} -void ContentMediaUtils::removeMarkdownMediaFiles(const File *p_file, INotebookBackend *p_backend) -{ - auto content = p_file->read(); - - // Images. - const auto images = - vte::MarkdownUtils::fetchImagesFromMarkdownText(content, - p_file->getResourcePath(), - vte::MarkdownLink::TypeFlag::LocalRelativeInternal); - - QSet handledImages; - for (const auto &link : images) { - if (handledImages.contains(link.m_path)) { - continue; - } - - handledImages.insert(link.m_path); - - if (!QFileInfo::exists(link.m_path)) { - qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink; - continue; - } - p_backend->removeFile(link.m_path); + if (p_backend) { + p_backend->copyFile(link.m_path, destFilePath); + } else { + FileUtils::copyFile(link.m_path, destFilePath); } + } + + if (!renamedImages.isEmpty()) { + if (p_backend) { + p_backend->writeFile(p_destFilePath, content); + } else { + FileUtils::writeFile(p_destFilePath, content); + } + } } -void ContentMediaUtils::copyAttachment(Node *p_node, - INotebookBackend *p_backend, - const QString &p_destFilePath, - const QString &p_destAttachmentFolderPath) -{ - Q_ASSERT(p_node->hasContent()); - Q_ASSERT(!p_node->getAttachmentFolder().isEmpty()); - - // Copy the whole folder. - const auto srcAttachmentFolderPath = p_node->fetchAttachmentFolderPath(); - try { - if (p_backend) { - p_backend->copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath); - } else { - FileUtils::copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath); - } - } catch (Exception &e) { - qWarning() << "failed to copy attachment folder" << srcAttachmentFolderPath << e.what(); - return; +void ContentMediaUtils::removeMediaFiles(Node *p_node) { + Q_ASSERT(p_node->hasContent()); + auto file = p_node->getContentFile(); + if (file->getContentType().isMarkdown()) { + removeMarkdownMediaFiles(file.data(), p_node->getBackend()); + } +} + +void ContentMediaUtils::removeMarkdownMediaFiles(const File *p_file, INotebookBackend *p_backend) { + auto content = p_file->read(); + + // Images. + const auto images = vte::MarkdownUtils::fetchImagesFromMarkdownText( + content, p_file->getResourcePath(), vte::MarkdownLink::TypeFlag::LocalRelativeInternal); + + QSet handledImages; + for (const auto &link : images) { + if (handledImages.contains(link.m_path)) { + continue; } - // Check if we need to modify links in content. - // FIXME: check the whole relative path. - if (p_node->getAttachmentFolder() == PathUtils::dirName(p_destAttachmentFolderPath)) { - return; + handledImages.insert(link.m_path); + + if (!QFileInfo::exists(link.m_path)) { + qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink; + continue; } + p_backend->removeFile(link.m_path); + } +} - auto file = p_node->getContentFile(); - if (file->getContentType().isMarkdown()) { - fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath); +void ContentMediaUtils::copyAttachment(Node *p_node, INotebookBackend *p_backend, + const QString &p_destFilePath, + const QString &p_destAttachmentFolderPath) { + Q_ASSERT(p_node->hasContent()); + Q_ASSERT(!p_node->getAttachmentFolder().isEmpty()); + + // Copy the whole folder. + const auto srcAttachmentFolderPath = p_node->fetchAttachmentFolderPath(); + try { + if (p_backend) { + p_backend->copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath); + } else { + FileUtils::copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath); } + } catch (Exception &e) { + qWarning() << "failed to copy attachment folder" << srcAttachmentFolderPath << e.what(); + return; + } + + // Check if we need to modify links in content. + // FIXME: check the whole relative path. + if (p_node->getAttachmentFolder() == PathUtils::dirName(p_destAttachmentFolderPath)) { + return; + } + + auto file = p_node->getContentFile(); + if (file->getContentType().isMarkdown()) { + fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, + p_destAttachmentFolderPath); + } } void ContentMediaUtils::fixMarkdownLinks(const QString &p_srcFolderPath, - INotebookBackend *p_backend, - const QString &p_destFilePath, - const QString &p_destFolderPath) -{ - // TODO. - Q_UNUSED(p_srcFolderPath); - Q_UNUSED(p_backend); - Q_UNUSED(p_destFilePath); - Q_UNUSED(p_destFolderPath); + INotebookBackend *p_backend, const QString &p_destFilePath, + const QString &p_destFolderPath) { + // TODO. + Q_UNUSED(p_srcFolderPath); + Q_UNUSED(p_backend); + Q_UNUSED(p_destFilePath); + Q_UNUSED(p_destFolderPath); } diff --git a/src/utils/contentmediautils.h b/src/utils/contentmediautils.h index 4288c04a1c..7b5cf89959 100644 --- a/src/utils/contentmediautils.h +++ b/src/utils/contentmediautils.h @@ -3,54 +3,44 @@ #include -namespace vnotex -{ - class INotebookBackend; - class Node; - class File; - - // Utils to operate on the media files from node's content. - class ContentMediaUtils - { - public: - ContentMediaUtils() = delete; - - // Fetch media files from @p_node and copy them to dest folder. - // @p_destFilePath: @p_node has been copied to @p_destFilePath. - static void copyMediaFiles(Node *p_node, - INotebookBackend *p_backend, - const QString &p_destFilePath); - - // @p_filePath: the file path to read the content for parse. - static void copyMediaFiles(const QString &p_filePath, - INotebookBackend *p_backend, - const QString &p_destFilePath); - - static void copyMediaFiles(const File *p_file, - const QString &p_destFilePath); - - static void removeMediaFiles(Node *p_node); - - // Copy attachment folder. - static void copyAttachment(Node *p_node, - INotebookBackend *p_backend, - const QString &p_destFilePath, - const QString &p_destAttachmentFolderPath); - - private: - static void copyMarkdownMediaFiles(const QString &p_content, - const QString &p_basePath, - INotebookBackend *p_backend, - const QString &p_destFilePath); - - static void removeMarkdownMediaFiles(const File *p_file, INotebookBackend *p_backend); - - // Fix local relative internal links locating in @p_srcFolderPath. - static void fixMarkdownLinks(const QString &p_srcFolderPath, - INotebookBackend *p_backend, - const QString &p_destFilePath, - const QString &p_destFolderPath); - }; -} +namespace vnotex { +class INotebookBackend; +class Node; +class File; + +// Utils to operate on the media files from node's content. +class ContentMediaUtils { +public: + ContentMediaUtils() = delete; + + // Fetch media files from @p_node and copy them to dest folder. + // @p_destFilePath: @p_node has been copied to @p_destFilePath. + static void copyMediaFiles(Node *p_node, INotebookBackend *p_backend, + const QString &p_destFilePath); + + // @p_filePath: the file path to read the content for parse. + static void copyMediaFiles(const QString &p_filePath, INotebookBackend *p_backend, + const QString &p_destFilePath); + + static void copyMediaFiles(const File *p_file, const QString &p_destFilePath); + + static void removeMediaFiles(Node *p_node); + + // Copy attachment folder. + static void copyAttachment(Node *p_node, INotebookBackend *p_backend, + const QString &p_destFilePath, + const QString &p_destAttachmentFolderPath); + +private: + static void copyMarkdownMediaFiles(const QString &p_content, const QString &p_basePath, + INotebookBackend *p_backend, const QString &p_destFilePath); + + static void removeMarkdownMediaFiles(const File *p_file, INotebookBackend *p_backend); + + // Fix local relative internal links locating in @p_srcFolderPath. + static void fixMarkdownLinks(const QString &p_srcFolderPath, INotebookBackend *p_backend, + const QString &p_destFilePath, const QString &p_destFolderPath); +}; +} // namespace vnotex #endif // CONTENTMEDIAUTILS_H diff --git a/src/utils/docsutils.cpp b/src/utils/docsutils.cpp index 9884938f08..8b9c6f74c8 100644 --- a/src/utils/docsutils.cpp +++ b/src/utils/docsutils.cpp @@ -10,48 +10,40 @@ QStringList DocsUtils::s_searchPaths; QString DocsUtils::s_locale = "en_US"; -void DocsUtils::addSearchPath(const QString &p_path) -{ - s_searchPaths.append(p_path); -} +void DocsUtils::addSearchPath(const QString &p_path) { s_searchPaths.append(p_path); } -QString DocsUtils::getDocText(const QString &p_baseName) -{ - auto filePath = getDocFile(p_baseName); - if (!filePath.isEmpty()) { - return FileUtils::readTextFile(filePath); - } +QString DocsUtils::getDocText(const QString &p_baseName) { + auto filePath = getDocFile(p_baseName); + if (!filePath.isEmpty()) { + return FileUtils::readTextFile(filePath); + } - return ""; + return ""; } -QString DocsUtils::getDocFile(const QString &p_baseName) -{ - const auto shortLocale = s_locale.split('_')[0]; - - const auto fullLocaleName = QStringLiteral("%1/%2").arg(s_locale, p_baseName); - const auto shortLocaleName = QStringLiteral("%1/%2").arg(shortLocale, p_baseName); - const auto defaultLocaleName = QStringLiteral("%1/%2").arg(QStringLiteral("en"), p_baseName); - - for (const auto &pa : s_searchPaths) { - QDir dir(pa); - if (!dir.exists()) { - continue; - } - - if (dir.exists(fullLocaleName)) { - return dir.filePath(fullLocaleName); - } else if (dir.exists(shortLocaleName)) { - return dir.filePath(shortLocaleName); - } else if (dir.exists(defaultLocaleName)) { - return dir.filePath(defaultLocaleName); - } +QString DocsUtils::getDocFile(const QString &p_baseName) { + const auto shortLocale = s_locale.split('_')[0]; + + const auto fullLocaleName = QStringLiteral("%1/%2").arg(s_locale, p_baseName); + const auto shortLocaleName = QStringLiteral("%1/%2").arg(shortLocale, p_baseName); + const auto defaultLocaleName = QStringLiteral("%1/%2").arg(QStringLiteral("en"), p_baseName); + + for (const auto &pa : s_searchPaths) { + QDir dir(pa); + if (!dir.exists()) { + continue; } - return ""; -} + if (dir.exists(fullLocaleName)) { + return dir.filePath(fullLocaleName); + } else if (dir.exists(shortLocaleName)) { + return dir.filePath(shortLocaleName); + } else if (dir.exists(defaultLocaleName)) { + return dir.filePath(defaultLocaleName); + } + } -void DocsUtils::setLocale(const QString &p_locale) -{ - s_locale = p_locale; + return ""; } + +void DocsUtils::setLocale(const QString &p_locale) { s_locale = p_locale; } diff --git a/src/utils/docsutils.h b/src/utils/docsutils.h index d1e6b5cd78..9fc66ef1e7 100644 --- a/src/utils/docsutils.h +++ b/src/utils/docsutils.h @@ -3,26 +3,24 @@ #include -namespace vnotex -{ - class DocsUtils - { - public: - DocsUtils() = delete; +namespace vnotex { +class DocsUtils { +public: + DocsUtils() = delete; - static QString getDocText(const QString &p_baseName); + static QString getDocText(const QString &p_baseName); - static QString getDocFile(const QString &p_baseName); + static QString getDocFile(const QString &p_baseName); - static void addSearchPath(const QString &p_path); + static void addSearchPath(const QString &p_path); - static void setLocale(const QString &p_locale); + static void setLocale(const QString &p_locale); - private: - static QStringList s_searchPaths; +private: + static QStringList s_searchPaths; - static QString s_locale; - }; -} + static QString s_locale; +}; +} // namespace vnotex #endif // DOCSUTILS_H diff --git a/src/utils/fileutils.cpp b/src/utils/fileutils.cpp index 0925a53d4b..4dfa9583e6 100644 --- a/src/utils/fileutils.cpp +++ b/src/utils/fileutils.cpp @@ -1,10 +1,10 @@ #include "fileutils.h" +#include #include +#include #include -#include #include -#include #include #include @@ -14,372 +14,343 @@ using namespace vnotex; -QByteArray FileUtils::readFile(const QString &p_filePath) -{ - QFile file(p_filePath); - if (!file.open(QIODevice::ReadOnly)) { - Exception::throwOne(Exception::Type::FailToReadFile, - QStringLiteral("failed to read file: %1").arg(p_filePath)); - } +QByteArray FileUtils::readFile(const QString &p_filePath) { + QFile file(p_filePath); + if (!file.open(QIODevice::ReadOnly)) { + Exception::throwOne(Exception::Type::FailToReadFile, + QStringLiteral("failed to read file: %1").arg(p_filePath)); + } - return file.readAll(); + return file.readAll(); } -QString FileUtils::readTextFile(const QString &p_filePath) -{ - QFile file(p_filePath); - if (!file.open(QIODevice::ReadOnly)) { - Exception::throwOne(Exception::Type::FailToReadFile, - QStringLiteral("failed to read file: %1").arg(p_filePath)); - } - - // TODO: determine the encoding of the text. - QString text(file.readAll()); - file.close(); - return text; +QString FileUtils::readTextFile(const QString &p_filePath) { + QFile file(p_filePath); + if (!file.open(QIODevice::ReadOnly)) { + Exception::throwOne(Exception::Type::FailToReadFile, + QStringLiteral("failed to read file: %1").arg(p_filePath)); + } + + // TODO: determine the encoding of the text. + QString text(file.readAll()); + file.close(); + return text; } -QJsonObject FileUtils::readJsonFile(const QString &p_filePath) -{ - return QJsonDocument::fromJson(readFile(p_filePath)).object(); +QJsonObject FileUtils::readJsonFile(const QString &p_filePath) { + return QJsonDocument::fromJson(readFile(p_filePath)).object(); } -void FileUtils::writeFile(const QString &p_filePath, const QByteArray &p_data) -{ - QFile file(p_filePath); - if (!file.open(QIODevice::WriteOnly)) { - Exception::throwOne(Exception::Type::FailToWriteFile, - QStringLiteral("failed to write to file: %1").arg(p_filePath)); - } +void FileUtils::writeFile(const QString &p_filePath, const QByteArray &p_data) { + QFile file(p_filePath); + if (!file.open(QIODevice::WriteOnly)) { + Exception::throwOne(Exception::Type::FailToWriteFile, + QStringLiteral("failed to write to file: %1").arg(p_filePath)); + } - file.write(p_data); - file.close(); + file.write(p_data); + file.close(); } -void FileUtils::writeFile(const QString &p_filePath, const QString &p_text) -{ - QFile file(p_filePath); - if (!file.open(QIODevice::WriteOnly)) { - Exception::throwOne(Exception::Type::FailToWriteFile, - QStringLiteral("failed to write to file: %1").arg(p_filePath)); - } +void FileUtils::writeFile(const QString &p_filePath, const QString &p_text) { + QFile file(p_filePath); + if (!file.open(QIODevice::WriteOnly)) { + Exception::throwOne(Exception::Type::FailToWriteFile, + QStringLiteral("failed to write to file: %1").arg(p_filePath)); + } - QTextStream stream(&file); - stream << p_text; - file.close(); + QTextStream stream(&file); + stream << p_text; + file.close(); } -void FileUtils::writeFile(const QString &p_filePath, const QJsonObject &p_jobj) -{ - writeFile(p_filePath, QJsonDocument(p_jobj).toJson()); +void FileUtils::writeFile(const QString &p_filePath, const QJsonObject &p_jobj) { + writeFile(p_filePath, QJsonDocument(p_jobj).toJson()); } -void FileUtils::renameFile(const QString &p_path, const QString &p_name) -{ - Q_ASSERT(PathUtils::isLegalFileName(p_name)); - QString newFilePath(PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_path), p_name)); - QFile file(p_path); - if (!file.exists() || !file.rename(newFilePath)) { - Exception::throwOne(Exception::Type::FailToRenameFile, - QStringLiteral("failed to rename file: %1").arg(p_path)); - } +void FileUtils::renameFile(const QString &p_path, const QString &p_name) { + Q_ASSERT(PathUtils::isLegalFileName(p_name)); + QString newFilePath(PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_path), p_name)); + QFile file(p_path); + if (!file.exists() || !file.rename(newFilePath)) { + Exception::throwOne(Exception::Type::FailToRenameFile, + QStringLiteral("failed to rename file: %1").arg(p_path)); + } } -bool FileUtils::childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name) -{ - QDir dir(p_dirPath); - if (!dir.exists()) { - return false; - } +bool FileUtils::childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name) { + QDir dir(p_dirPath); + if (!dir.exists()) { + return false; + } - auto name = p_name.toLower(); - auto children = dir.entryList(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot); - for (const auto &child : children) { - if (child.toLower() == name) { - return true; - } + auto name = p_name.toLower(); + auto children = dir.entryList(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot); + for (const auto &child : children) { + if (child.toLower() == name) { + return true; } + } - return false; + return false; } -bool FileUtils::existsCaseInsensitive(const QString &p_path) -{ - return childExistsCaseInsensitive(PathUtils::parentDirPath(p_path), PathUtils::fileName(p_path)); +bool FileUtils::existsCaseInsensitive(const QString &p_path) { + return childExistsCaseInsensitive(PathUtils::parentDirPath(p_path), PathUtils::fileName(p_path)); } -void FileUtils::copyFile(const QString &p_filePath, - const QString &p_destPath, - bool p_move) -{ - if (PathUtils::areSamePaths(p_filePath, p_destPath)) { - return; - } +void FileUtils::copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move) { + if (PathUtils::areSamePaths(p_filePath, p_destPath)) { + return; + } - QDir dir; - if (!dir.mkpath(PathUtils::parentDirPath(p_destPath))) { - Exception::throwOne(Exception::Type::FailToCreateDir, - QStringLiteral("failed to create directory: %1").arg(PathUtils::parentDirPath(p_destPath))); - } + QDir dir; + if (!dir.mkpath(PathUtils::parentDirPath(p_destPath))) { + Exception::throwOne( + Exception::Type::FailToCreateDir, + QStringLiteral("failed to create directory: %1").arg(PathUtils::parentDirPath(p_destPath))); + } - bool failed = false; - if (p_move) { - QFile file(p_filePath); - if (!file.rename(p_destPath)) { - failed = true; - } - } else { - if (!QFile::copy(p_filePath, p_destPath)) { - failed = true; - } + bool failed = false; + if (p_move) { + QFile file(p_filePath); + if (!file.rename(p_destPath)) { + failed = true; } - - if (failed) { - Exception::throwOne(Exception::Type::FailToCopyFile, - QStringLiteral("failed to copy file: %1 %2").arg(p_filePath, p_destPath)); + } else { + if (!QFile::copy(p_filePath, p_destPath)) { + failed = true; } + } + + if (failed) { + Exception::throwOne(Exception::Type::FailToCopyFile, + QStringLiteral("failed to copy file: %1 %2").arg(p_filePath, p_destPath)); + } } -void FileUtils::copyDir(const QString &p_dirPath, - const QString &p_destPath, - bool p_move) -{ - if (PathUtils::areSamePaths(p_dirPath, p_destPath)) { - return; +void FileUtils::copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move) { + if (PathUtils::areSamePaths(p_dirPath, p_destPath)) { + return; + } + + if (QFileInfo::exists(p_destPath)) { + Exception::throwOne(Exception::Type::FailToCopyDir, + QStringLiteral("target directory %1 already exists").arg(p_destPath)); + } + + // QDir.rename() could not move directory across dirves. + + // Create target directory. + QDir destDir(p_destPath); + if (!destDir.mkpath(p_destPath)) { + Exception::throwOne(Exception::Type::FailToCreateDir, + QStringLiteral("failed to create directory: %1").arg(p_destPath)); + } + + // Copy directory contents recursively. + QDir srcDir(p_dirPath); + auto nodes = srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoSymLinks | + QDir::NoDotAndDotDot); + for (const auto &node : nodes) { + auto name = node.fileName(); + if (node.isDir()) { + copyDir(srcDir.filePath(name), destDir.filePath(name), p_move); + } else { + Q_ASSERT(node.isFile()); + copyFile(srcDir.filePath(name), destDir.filePath(name), p_move); } + } - if (QFileInfo::exists(p_destPath)) { - Exception::throwOne(Exception::Type::FailToCopyDir, - QStringLiteral("target directory %1 already exists").arg(p_destPath)); + if (p_move) { + if (!destDir.rmdir(p_dirPath)) { + Exception::throwOne( + Exception::Type::FailToRemoveDir, + QStringLiteral("failed to remove source directory after move: %1").arg(p_dirPath)); } + } +} - // QDir.rename() could not move directory across dirves. - - // Create target directory. - QDir destDir(p_destPath); - if (!destDir.mkpath(p_destPath)) { - Exception::throwOne(Exception::Type::FailToCreateDir, - QStringLiteral("failed to create directory: %1").arg(p_destPath)); +QString FileUtils::renameIfExistsCaseInsensitive(const QString &p_path) { + QFileInfo fi(p_path); + auto dirPath = fi.absolutePath(); + auto baseName = fi.completeBaseName(); + auto suffix = fi.suffix(); + auto name = fi.fileName(); + int idx = 1; + while (childExistsCaseInsensitive(dirPath, name)) { + name = QStringLiteral("%1_%2").arg(baseName, QString::number(idx)); + if (!suffix.isEmpty()) { + name += QStringLiteral(".") + suffix; } - // Copy directory contents recursively. - QDir srcDir(p_dirPath); - auto nodes = srcDir.entryInfoList(QDir::Dirs - | QDir::Files - | QDir::Hidden - | QDir::NoSymLinks - | QDir::NoDotAndDotDot); - for (const auto &node : nodes) { - auto name = node.fileName(); - if (node.isDir()) { - copyDir(srcDir.filePath(name), destDir.filePath(name), p_move); - } else { - Q_ASSERT(node.isFile()); - copyFile(srcDir.filePath(name), destDir.filePath(name), p_move); - } - } + ++idx; + } - if (p_move) { - if (!destDir.rmdir(p_dirPath)) { - Exception::throwOne(Exception::Type::FailToRemoveDir, - QStringLiteral("failed to remove source directory after move: %1").arg(p_dirPath)); - } - } + return PathUtils::concatenateFilePath(dirPath, name); } -QString FileUtils::renameIfExistsCaseInsensitive(const QString &p_path) -{ - QFileInfo fi(p_path); - auto dirPath = fi.absolutePath(); - auto baseName = fi.completeBaseName(); - auto suffix = fi.suffix(); - auto name = fi.fileName(); - int idx = 1; - while (childExistsCaseInsensitive(dirPath, name)) { - name = QStringLiteral("%1_%2").arg(baseName, QString::number(idx)); - if (!suffix.isEmpty()) { - name += QStringLiteral(".") + suffix; - } - - ++idx; - } - - return PathUtils::concatenateFilePath(dirPath, name); +void FileUtils::removeFile(const QString &p_filePath) { + Q_ASSERT(!QFileInfo::exists(p_filePath) || QFileInfo(p_filePath).isFile()); + QFile file(p_filePath); + if (!file.remove()) { + Exception::throwOne(Exception::Type::FailToRemoveFile, + QStringLiteral("failed to remove file: %1").arg(p_filePath)); + } } -void FileUtils::removeFile(const QString &p_filePath) -{ - Q_ASSERT(!QFileInfo::exists(p_filePath) || QFileInfo(p_filePath).isFile()); - QFile file(p_filePath); - if (!file.remove()) { - Exception::throwOne(Exception::Type::FailToRemoveFile, - QStringLiteral("failed to remove file: %1").arg(p_filePath)); - } -} - -bool FileUtils::removeDirIfEmpty(const QString &p_dirPath) -{ - QDir dir(p_dirPath); - if (!dir.isEmpty()) { - return false; - } +bool FileUtils::removeDirIfEmpty(const QString &p_dirPath) { + QDir dir(p_dirPath); + if (!dir.isEmpty()) { + return false; + } - if (!dir.rmdir(p_dirPath)) { - Exception::throwOne(Exception::Type::FailToRemoveFile, - QStringLiteral("failed to remove directory: %1").arg(p_dirPath)); - return false; - } + if (!dir.rmdir(p_dirPath)) { + Exception::throwOne(Exception::Type::FailToRemoveFile, + QStringLiteral("failed to remove directory: %1").arg(p_dirPath)); + return false; + } - return true; + return true; } -void FileUtils::removeDir(const QString &p_dirPath) -{ - QDir dir(p_dirPath); - if (!dir.removeRecursively()) { - Exception::throwOne(Exception::Type::FailToRemoveFile, - QStringLiteral("failed to remove directory recursively: %1").arg(p_dirPath)); - } +void FileUtils::removeDir(const QString &p_dirPath) { + QDir dir(p_dirPath); + if (!dir.removeRecursively()) { + Exception::throwOne( + Exception::Type::FailToRemoveFile, + QStringLiteral("failed to remove directory recursively: %1").arg(p_dirPath)); + } } -bool FileUtils::isPlatformNameCaseSensitive() -{ +bool FileUtils::isPlatformNameCaseSensitive() { #if defined(Q_OS_WIN) - return false; + return false; #else - return true; + return true; #endif } -bool FileUtils::isText(const QString &p_filePath) -{ - QMimeDatabase mimeDatabase; - auto mimeType = mimeDatabase.mimeTypeForFile(p_filePath); - const auto name = mimeType.name(); - if (name.startsWith(QStringLiteral("text/")) || name == QStringLiteral("application/x-zerosize")) { - return true; - } +bool FileUtils::isText(const QString &p_filePath) { + QMimeDatabase mimeDatabase; + auto mimeType = mimeDatabase.mimeTypeForFile(p_filePath); + const auto name = mimeType.name(); + if (name.startsWith(QStringLiteral("text/")) || + name == QStringLiteral("application/x-zerosize")) { + return true; + } - return mimeType.inherits(QStringLiteral("text/plain")); + return mimeType.inherits(QStringLiteral("text/plain")); } -bool FileUtils::isImage(const QString &p_filePath) -{ - QMimeDatabase mimeDatabase; - auto mimeType = mimeDatabase.mimeTypeForFile(p_filePath); - if (mimeType.name().startsWith(QStringLiteral("image/"))) { - return true; - } - return false; +bool FileUtils::isImage(const QString &p_filePath) { + QMimeDatabase mimeDatabase; + auto mimeType = mimeDatabase.mimeTypeForFile(p_filePath); + if (mimeType.name().startsWith(QStringLiteral("image/"))) { + return true; + } + return false; } -QImage FileUtils::imageFromFile(const QString &p_filePath) -{ - QImage img(p_filePath); - if (!img.isNull()) { - return img; - } - - // @p_filePath may has a wrong suffix which indicates a wrong image format. - img.loadFromData(readFile(p_filePath)); +QImage FileUtils::imageFromFile(const QString &p_filePath) { + QImage img(p_filePath); + if (!img.isNull()) { return img; -} + } -QPixmap FileUtils::pixmapFromFile(const QString &p_filePath) -{ - QPixmap pixmap; - pixmap.loadFromData(readFile(p_filePath)); - return pixmap; + // @p_filePath may has a wrong suffix which indicates a wrong image format. + img.loadFromData(readFile(p_filePath)); + return img; } -QString FileUtils::generateUniqueFileName(const QString &p_folderPath, - const QString &p_hints, - const QString &p_suffix) -{ - auto fileName = generateRandomFileName(p_hints, p_suffix); - int suffixIdx = fileName.lastIndexOf(QLatin1Char('.')); - auto baseName = suffixIdx == -1 ? fileName : fileName.left(suffixIdx); - auto suffix = suffixIdx == -1 ? QStringLiteral("") : fileName.mid(suffixIdx); - int index = 1; - while (childExistsCaseInsensitive(p_folderPath, fileName)) { - fileName = QStringLiteral("%1_%2%3").arg(baseName, QString::number(index++), suffix); - } +QPixmap FileUtils::pixmapFromFile(const QString &p_filePath) { + QPixmap pixmap; + pixmap.loadFromData(readFile(p_filePath)); + return pixmap; +} - return fileName; +QString FileUtils::generateUniqueFileName(const QString &p_folderPath, const QString &p_hints, + const QString &p_suffix) { + auto fileName = generateRandomFileName(p_hints, p_suffix); + int suffixIdx = fileName.lastIndexOf(QLatin1Char('.')); + auto baseName = suffixIdx == -1 ? fileName : fileName.left(suffixIdx); + auto suffix = suffixIdx == -1 ? QStringLiteral("") : fileName.mid(suffixIdx); + int index = 1; + while (childExistsCaseInsensitive(p_folderPath, fileName)) { + fileName = QStringLiteral("%1_%2%3").arg(baseName, QString::number(index++), suffix); + } + + return fileName; } -QString FileUtils::generateRandomFileName(const QString &p_hints, const QString &p_suffix) -{ - Q_UNUSED(p_hints); +QString FileUtils::generateRandomFileName(const QString &p_hints, const QString &p_suffix) { + Q_UNUSED(p_hints); - // Do not use toSecsSinceEpoch() here since we want a short name. - const QString timeStamp(QDateTime::currentDateTime().toString(QStringLiteral("sszzzmmHHyyMMdd"))); - const QString baseName(QString::number(timeStamp.toLongLong() + QRandomGenerator::global()->generate())); + // Do not use toSecsSinceEpoch() here since we want a short name. + const QString timeStamp(QDateTime::currentDateTime().toString(QStringLiteral("sszzzmmHHyyMMdd"))); + const QString baseName( + QString::number(timeStamp.toLongLong() + QRandomGenerator::global()->generate())); - QString suffix; - if (!p_suffix.isEmpty()) { - suffix = QLatin1Char('.') + p_suffix.toLower(); - } + QString suffix; + if (!p_suffix.isEmpty()) { + suffix = QLatin1Char('.') + p_suffix.toLower(); + } - return baseName + suffix; + return baseName + suffix; } -QTemporaryFile *FileUtils::createTemporaryFile(const QString &p_suffix) -{ - QString xx = p_suffix.isEmpty() ? QStringLiteral("XXXXXX") : QStringLiteral("XXXXXX."); - return new QTemporaryFile(QDir::tempPath() + QDir::separator() + xx + p_suffix); +QTemporaryFile *FileUtils::createTemporaryFile(const QString &p_suffix) { + QString xx = p_suffix.isEmpty() ? QStringLiteral("XXXXXX") : QStringLiteral("XXXXXX."); + return new QTemporaryFile(QDir::tempPath() + QDir::separator() + xx + p_suffix); } QString FileUtils::generateFileNameWithSequence(const QString &p_folderPath, const QString &p_baseName, - const QString &p_suffix) -{ - auto fileName = p_suffix.isEmpty() ? p_baseName : p_baseName + QLatin1Char('.') + p_suffix; - auto suffix = p_suffix.isEmpty() ? QString() : QStringLiteral(".") + p_suffix; - int index = 1; - while (childExistsCaseInsensitive(p_folderPath, fileName)) { - fileName = QStringLiteral("%1_%2%3").arg(p_baseName, QString::number(index++), suffix); - } - - return fileName; + const QString &p_suffix) { + auto fileName = p_suffix.isEmpty() ? p_baseName : p_baseName + QLatin1Char('.') + p_suffix; + auto suffix = p_suffix.isEmpty() ? QString() : QStringLiteral(".") + p_suffix; + int index = 1; + while (childExistsCaseInsensitive(p_folderPath, fileName)) { + fileName = QStringLiteral("%1_%2%3").arg(p_baseName, QString::number(index++), suffix); + } + + return fileName; } -void FileUtils::removeEmptyDir(const QString &p_dirPath) -{ - QDir dir(p_dirPath); - if (dir.isEmpty()) { - return; - } - - auto childDirs = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); - for (const auto &child : childDirs) { - const auto childPath = child.absoluteFilePath(); - removeEmptyDir(childPath); - removeDirIfEmpty(childPath); - } +void FileUtils::removeEmptyDir(const QString &p_dirPath) { + QDir dir(p_dirPath); + if (dir.isEmpty()) { + return; + } + + auto childDirs = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); + for (const auto &child : childDirs) { + const auto childPath = child.absoluteFilePath(); + removeEmptyDir(childPath); + removeDirIfEmpty(childPath); + } } QStringList FileUtils::entryListRecursively(const QString &p_dirPath, const QStringList &p_nameFilters, - QDir::Filters p_filters) -{ - QStringList entries; + QDir::Filters p_filters) { + QStringList entries; - QDir dir(p_dirPath); - if (!dir.exists()) { - return entries; - } + QDir dir(p_dirPath); + if (!dir.exists()) { + return entries; + } - const auto curEntries = dir.entryList(p_nameFilters, p_filters | QDir::NoDotAndDotDot); - for (const auto &e : curEntries) { - entries.append(PathUtils::concatenateFilePath(p_dirPath, e)); - } + const auto curEntries = dir.entryList(p_nameFilters, p_filters | QDir::NoDotAndDotDot); + for (const auto &e : curEntries) { + entries.append(PathUtils::concatenateFilePath(p_dirPath, e)); + } - const auto subdirs = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (const auto &subdir : subdirs) { - const auto dirPath = PathUtils::concatenateFilePath(p_dirPath, subdir); - entries.append(entryListRecursively(dirPath, p_nameFilters, p_filters)); - } + const auto subdirs = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (const auto &subdir : subdirs) { + const auto dirPath = PathUtils::concatenateFilePath(p_dirPath, subdir); + entries.append(entryListRecursively(dirPath, p_nameFilters, p_filters)); + } - return entries; + return entries; } diff --git a/src/utils/fileutils.h b/src/utils/fileutils.h index 90a07b8aa4..9b4ae897a1 100644 --- a/src/utils/fileutils.h +++ b/src/utils/fileutils.h @@ -2,89 +2,82 @@ #define FILEUTILS_H #include -#include +#include #include -#include #include -#include +#include +#include class QTemporaryFile; -namespace vnotex -{ - class FileUtils - { - public: - FileUtils() = delete; +namespace vnotex { +class FileUtils { +public: + FileUtils() = delete; - static QByteArray readFile(const QString &p_filePath); + static QByteArray readFile(const QString &p_filePath); - static QString readTextFile(const QString &p_filePath); + static QString readTextFile(const QString &p_filePath); - static QJsonObject readJsonFile(const QString &p_filePath); + static QJsonObject readJsonFile(const QString &p_filePath); - static void writeFile(const QString &p_filePath, const QByteArray &p_data); + static void writeFile(const QString &p_filePath, const QByteArray &p_data); - static void writeFile(const QString &p_filePath, const QString &p_text); + static void writeFile(const QString &p_filePath, const QString &p_text); - static void writeFile(const QString &p_filePath, const QJsonObject &p_jobj); + static void writeFile(const QString &p_filePath, const QJsonObject &p_jobj); - // Rename file or dir. - static void renameFile(const QString &p_path, const QString &p_name); + // Rename file or dir. + static void renameFile(const QString &p_path, const QString &p_name); - static bool childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name); + static bool childExistsCaseInsensitive(const QString &p_dirPath, const QString &p_name); - static bool existsCaseInsensitive(const QString &p_path); + static bool existsCaseInsensitive(const QString &p_path); - static void copyFile(const QString &p_filePath, - const QString &p_destPath, - bool p_move = false); + static void copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move = false); - static void copyDir(const QString &p_dirPath, - const QString &p_destPath, - bool p_move = false); + static void copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move = false); - static void removeFile(const QString &p_filePath); + static void removeFile(const QString &p_filePath); - // Return false if it is not deleted due to non-empty. - static bool removeDirIfEmpty(const QString &p_dirPath); + // Return false if it is not deleted due to non-empty. + static bool removeDirIfEmpty(const QString &p_dirPath); - static void removeDir(const QString &p_dirPath); + static void removeDir(const QString &p_dirPath); - static QString renameIfExistsCaseInsensitive(const QString &p_path); + static QString renameIfExistsCaseInsensitive(const QString &p_path); - static bool isPlatformNameCaseSensitive(); + static bool isPlatformNameCaseSensitive(); - static bool isText(const QString &p_filePath); + static bool isText(const QString &p_filePath); - static bool isImage(const QString &p_filePath); + static bool isImage(const QString &p_filePath); - static QImage imageFromFile(const QString &p_filePath); + static QImage imageFromFile(const QString &p_filePath); - static QPixmap pixmapFromFile(const QString &p_filePath); + static QPixmap pixmapFromFile(const QString &p_filePath); - static QString generateUniqueFileName(const QString &p_folderPath, - const QString &p_hints, - const QString &p_suffix); + static QString generateUniqueFileName(const QString &p_folderPath, const QString &p_hints, + const QString &p_suffix); - static QString generateRandomFileName(const QString &p_hints, const QString &p_suffix); + static QString generateRandomFileName(const QString &p_hints, const QString &p_suffix); - static QString generateFileNameWithSequence(const QString &p_folderPath, - const QString &p_baseName, - const QString &p_suffix = QString()); + static QString generateFileNameWithSequence(const QString &p_folderPath, + const QString &p_baseName, + const QString &p_suffix = QString()); - static QTemporaryFile *createTemporaryFile(const QString &p_suffix); + static QTemporaryFile *createTemporaryFile(const QString &p_suffix); - // Go through @p_dirPath recursively and delete all empty dirs. - // @p_dirPath itself is not deleted. - static void removeEmptyDir(const QString &p_dirPath); + // Go through @p_dirPath recursively and delete all empty dirs. + // @p_dirPath itself is not deleted. + static void removeEmptyDir(const QString &p_dirPath); - // Go through @p_dirPath recursively and get all entrys. - // @p_nameFilters is for each dir, not for all. - static QStringList entryListRecursively(const QString &p_dirPath, - const QStringList &p_nameFilters, - QDir::Filters p_filters = QDir::NoFilter); - }; -} // ns vnotex + // Go through @p_dirPath recursively and get all entrys. + // @p_nameFilters is for each dir, not for all. + static QStringList entryListRecursively(const QString &p_dirPath, + const QStringList &p_nameFilters, + QDir::Filters p_filters = QDir::NoFilter); +}; +} // namespace vnotex #endif // FILEUTILS_H diff --git a/src/utils/htmlutils.cpp b/src/utils/htmlutils.cpp index 58500d763b..ad1947ba54 100644 --- a/src/utils/htmlutils.cpp +++ b/src/utils/htmlutils.cpp @@ -4,29 +4,26 @@ using namespace vnotex; -bool HtmlUtils::hasOnlyImgTag(const QString &p_html) -{ - // Tricky. - QRegularExpression reg(QStringLiteral("<(?:p|span|div) ")); - return !p_html.contains(reg); +bool HtmlUtils::hasOnlyImgTag(const QString &p_html) { + // Tricky. + QRegularExpression reg(QStringLiteral("<(?:p|span|div) ")); + return !p_html.contains(reg); } -QString HtmlUtils::escapeHtml(QString p_text) -{ - p_text.replace(">", ">").replace("<", "<").replace("&", "&"); - return p_text; +QString HtmlUtils::escapeHtml(QString p_text) { + p_text.replace(">", ">").replace("<", "<").replace("&", "&"); + return p_text; } -QString HtmlUtils::unicodeEncode(const QString &p_text) -{ - QString encodedStr; - for (const auto ch : p_text) { - if (ch.unicode() > 255) { - encodedStr += QStringLiteral("&#%1;").arg(static_cast(ch.unicode())); - } else { - encodedStr += ch; - } +QString HtmlUtils::unicodeEncode(const QString &p_text) { + QString encodedStr; + for (const auto ch : p_text) { + if (ch.unicode() > 255) { + encodedStr += QStringLiteral("&#%1;").arg(static_cast(ch.unicode())); + } else { + encodedStr += ch; } + } - return encodedStr; + return encodedStr; } diff --git a/src/utils/htmlutils.h b/src/utils/htmlutils.h index f49239b227..29a23e0d80 100644 --- a/src/utils/htmlutils.h +++ b/src/utils/htmlutils.h @@ -3,19 +3,17 @@ #include -namespace vnotex -{ - class HtmlUtils - { - public: - HtmlUtils() = delete; +namespace vnotex { +class HtmlUtils { +public: + HtmlUtils() = delete; - static bool hasOnlyImgTag(const QString &p_html); + static bool hasOnlyImgTag(const QString &p_html); - static QString escapeHtml(QString p_text); + static QString escapeHtml(QString p_text); - static QString unicodeEncode(const QString &p_text); - }; -} + static QString unicodeEncode(const QString &p_text); +}; +} // namespace vnotex #endif // HTMLUTILS_H diff --git a/src/utils/iconutils.cpp b/src/utils/iconutils.cpp index 673ec71796..2d1e467871 100644 --- a/src/utils/iconutils.cpp +++ b/src/utils/iconutils.cpp @@ -1,11 +1,11 @@ #include "iconutils.h" -#include +#include #include -#include #include #include -#include +#include +#include #include @@ -18,174 +18,157 @@ QString IconUtils::s_defaultIconForeground; QString IconUtils::s_defaultIconDisabledForeground; QIcon IconUtils::fetchIcon(const QString &p_iconFile, - const QVector &p_overriddenColors, - qreal p_angle) -{ - const auto suffix = QFileInfo(p_iconFile).suffix().toLower().toStdString(); - if (p_overriddenColors.isEmpty() || suffix != "svg") { - return QIcon(p_iconFile); - } - - auto content = FileUtils::readTextFile(p_iconFile); - if (content.isEmpty()) { - return QIcon(); + const QVector &p_overriddenColors, qreal p_angle) { + const auto suffix = QFileInfo(p_iconFile).suffix().toLower().toStdString(); + if (p_overriddenColors.isEmpty() || suffix != "svg") { + return QIcon(p_iconFile); + } + + auto content = FileUtils::readTextFile(p_iconFile); + if (content.isEmpty()) { + return QIcon(); + } + + if (!isMonochrome(content)) { + return QIcon(p_iconFile); + } + + QIcon icon; + for (const auto &color : p_overriddenColors) { + auto overriddenContent = replaceForegroundOfIcon(content, color.m_foreground); + 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); + } - if (!isMonochrome(content)) { - return QIcon(p_iconFile); - } + return icon; +} - QIcon icon; - for (const auto &color : p_overriddenColors) { - auto overriddenContent = replaceForegroundOfIcon(content, color.m_foreground); - 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); - } +QIcon IconUtils::fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground) { + QVector colors; + if (!p_overriddenForeground.isEmpty()) { + colors.push_back(OverriddenColor(p_overriddenForeground, QIcon::Normal, QIcon::Off)); + } - return icon; + return fetchIcon(p_iconFile, colors); } -QIcon IconUtils::fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground) -{ - QVector colors; - if (!p_overriddenForeground.isEmpty()) { - colors.push_back(OverriddenColor(p_overriddenForeground, QIcon::Normal, QIcon::Off)); - } +QString IconUtils::replaceForegroundOfIcon(const QString &p_iconContent, + const QString &p_foreground) { + if (p_foreground.isEmpty()) { + return p_iconContent; + } + + // Negative lookahead to avoid fill="none". + QRegularExpression styleRe(R"((\s|"|;)(fill|stroke)(:|(="))(?!none)[^;"]*)"); + if (p_iconContent.indexOf(styleRe) > -1) { + auto newContent(p_iconContent); + newContent.replace(styleRe, QStringLiteral("\\1\\2\\3%1").arg(p_foreground)); + return newContent; + } - return fetchIcon(p_iconFile, colors); + return p_iconContent; } -QString IconUtils::replaceForegroundOfIcon(const QString &p_iconContent, const QString &p_foreground) -{ - if (p_foreground.isEmpty()) { - return p_iconContent; +bool IconUtils::isMonochrome(const QString &p_iconContent) { + // Match color-hex codes. + QRegularExpression monoRe("#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})"); + + QString lastColor = ""; + int pos = 0; + while (pos < p_iconContent.size()) { + QRegularExpressionMatch match; + int idx = p_iconContent.indexOf(monoRe, pos, &match); + if (idx == -1) { + break; } - // Negative lookahead to avoid fill="none". - QRegularExpression styleRe(R"((\s|"|;)(fill|stroke)(:|(="))(?!none)[^;"]*)"); - if (p_iconContent.indexOf(styleRe) > -1) { - auto newContent(p_iconContent); - newContent.replace(styleRe, QStringLiteral("\\1\\2\\3%1").arg(p_foreground)); - return newContent; + auto curColor = match.captured(1).toLower(); + if (curColor.size() == 3) { + for (int i = curColor.size() - 1; i >= 0; --i) { + curColor.insert(i, curColor[i]); + } } - return p_iconContent; -} - -bool IconUtils::isMonochrome(const QString &p_iconContent) -{ - // Match color-hex codes. - QRegularExpression monoRe("#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})"); - - QString lastColor = ""; - int pos = 0; - while (pos < p_iconContent.size()) { - QRegularExpressionMatch match; - int idx = p_iconContent.indexOf(monoRe, pos, &match); - if (idx == -1) { - break; - } - - auto curColor = match.captured(1).toLower(); - if (curColor.size() == 3) { - for (int i = curColor.size() - 1; i >= 0; --i) { - curColor.insert(i, curColor[i]); - } - } - - if (lastColor != curColor) { - if (lastColor.isEmpty()) { - lastColor = curColor; - } else { - return false; - } - } - - pos += match.capturedLength(); + if (lastColor != curColor) { + if (lastColor.isEmpty()) { + lastColor = curColor; + } else { + return false; + } } - return true; -} + pos += match.capturedLength(); + } -QIcon IconUtils::fetchIcon(const QString &p_iconFile) -{ - return fetchIcon(p_iconFile, s_defaultIconForeground); + return true; } -void IconUtils::setDefaultIconForeground(const QString &p_fg, const QString &p_disabledFg) -{ - s_defaultIconForeground = p_fg; - s_defaultIconDisabledForeground = p_disabledFg; +QIcon IconUtils::fetchIcon(const QString &p_iconFile) { + return fetchIcon(p_iconFile, s_defaultIconForeground); } -QIcon IconUtils::fetchIconWithDisabledState(const QString &p_iconFile) -{ - QVector colors; - colors.push_back(OverriddenColor(s_defaultIconForeground, QIcon::Normal, QIcon::Off)); - colors.push_back(OverriddenColor(s_defaultIconDisabledForeground, QIcon::Disabled, QIcon::Off)); - return fetchIcon(p_iconFile, colors); +void IconUtils::setDefaultIconForeground(const QString &p_fg, const QString &p_disabledFg) { + s_defaultIconForeground = p_fg; + s_defaultIconDisabledForeground = p_disabledFg; } -QIcon IconUtils::drawTextIcon(const QString &p_text, - const QString &p_fg, - const QString &p_border) -{ - return drawTextRectIcon(p_text, p_fg, "", p_border, 56, 56, 8); +QIcon IconUtils::fetchIconWithDisabledState(const QString &p_iconFile) { + QVector colors; + colors.push_back(OverriddenColor(s_defaultIconForeground, QIcon::Normal, QIcon::Off)); + colors.push_back(OverriddenColor(s_defaultIconDisabledForeground, QIcon::Disabled, QIcon::Off)); + return fetchIcon(p_iconFile, colors); } -QIcon IconUtils::drawTextRectIcon(const QString &p_text, - const QString &p_fg, - const QString &p_bg, - const QString &p_border, - int p_rectWidth, - int p_rectHeight, - int p_rectRadius) -{ - const int wid = 64; - QPixmap pixmap(wid, wid); - pixmap.fill(Qt::transparent); - - QPainter painter(&pixmap); - painter.setRenderHint(QPainter::Antialiasing); - - QPainterPath bgPath; - bgPath.addRoundedRect(QRect((wid - p_rectWidth) / 2, (wid - p_rectHeight) / 2, p_rectWidth, p_rectHeight), - p_rectRadius, - p_rectRadius); - - if (!p_bg.isEmpty()) { - painter.fillPath(bgPath, QColor(p_bg)); - } - - const int strokeWidth = 3; - - if (!p_border.isEmpty()) { - QPen pen(QColor(p_border), strokeWidth); - painter.setPen(pen); - painter.drawPath(bgPath); - } - - if (!p_text.isEmpty()) { - QPen pen(QColor(p_fg), strokeWidth); - painter.setPen(pen); - - auto font = painter.font(); - font.setPointSize(36); - font.setBold(true); - painter.setFont(font); - - auto requriedRect = painter.boundingRect(bgPath.boundingRect(), - Qt::AlignCenter, - p_text); - painter.drawText(requriedRect, p_text); - } +QIcon IconUtils::drawTextIcon(const QString &p_text, const QString &p_fg, const QString &p_border) { + return drawTextRectIcon(p_text, p_fg, "", p_border, 56, 56, 8); +} - QIcon icon; - icon.addPixmap(pixmap); - return icon; +QIcon IconUtils::drawTextRectIcon(const QString &p_text, const QString &p_fg, const QString &p_bg, + const QString &p_border, int p_rectWidth, int p_rectHeight, + int p_rectRadius) { + const int wid = 64; + QPixmap pixmap(wid, wid); + pixmap.fill(Qt::transparent); + + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + + QPainterPath bgPath; + bgPath.addRoundedRect( + QRect((wid - p_rectWidth) / 2, (wid - p_rectHeight) / 2, p_rectWidth, p_rectHeight), + p_rectRadius, p_rectRadius); + + if (!p_bg.isEmpty()) { + painter.fillPath(bgPath, QColor(p_bg)); + } + + const int strokeWidth = 3; + + if (!p_border.isEmpty()) { + QPen pen(QColor(p_border), strokeWidth); + painter.setPen(pen); + painter.drawPath(bgPath); + } + + if (!p_text.isEmpty()) { + QPen pen(QColor(p_fg), strokeWidth); + painter.setPen(pen); + + auto font = painter.font(); + font.setPointSize(36); + font.setBold(true); + painter.setFont(font); + + auto requriedRect = painter.boundingRect(bgPath.boundingRect(), Qt::AlignCenter, p_text); + painter.drawText(requriedRect, p_text); + } + + QIcon icon; + icon.addPixmap(pixmap); + return icon; } diff --git a/src/utils/iconutils.h b/src/utils/iconutils.h index f65ed7d1d1..24f63bd8a7 100644 --- a/src/utils/iconutils.h +++ b/src/utils/iconutils.h @@ -1,73 +1,54 @@ #ifndef ICONUTILS_H #define ICONUTILS_H +#include #include #include -#include -namespace vnotex -{ - class IconUtils - { - public: - IconUtils() = delete; - - struct OverriddenColor - { - OverriddenColor() - : m_mode(QIcon::Normal), - m_state(QIcon::Off) - { - } - - OverriddenColor(const QString &p_foreground, - QIcon::Mode p_mode = QIcon::Normal, - QIcon::State p_state = QIcon::Off) - : m_foreground(p_foreground), - m_mode(p_mode), - m_state(p_state) - { - } - - QString m_foreground; - QIcon::Mode m_mode; - QIcon::State m_state; - }; - - static void setDefaultIconForeground(const QString &p_fg, const QString &p_disabledFg); - - static QIcon fetchIcon(const QString &p_iconFile, - const QVector &p_overriddenColors, - qreal p_angle = -1); - - static QIcon fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground); - - // Fetch icon from @p_iconFile with icon_fg as overridden foreground color. - static QIcon fetchIcon(const QString &p_iconFile); - - static QIcon fetchIconWithDisabledState(const QString &p_iconFile); - - static QIcon drawTextIcon(const QString &p_text, - const QString &p_fg, - const QString &p_border); - - static QIcon drawTextRectIcon(const QString &p_text, - const QString &p_fg, - const QString &p_bg, - const QString &p_border, - int p_rectWidth = 56, - int p_rectHeight = 56, - int p_rectRadius = 0); - - private: - static QString replaceForegroundOfIcon(const QString &p_iconContent, const QString &p_foreground); - - static QString s_defaultIconForeground; - - static QString s_defaultIconDisabledForeground; - - static bool isMonochrome(const QString &p_iconContent); - }; -} // ns vnotex +namespace vnotex { +class IconUtils { +public: + IconUtils() = delete; + + struct OverriddenColor { + OverriddenColor() : m_mode(QIcon::Normal), m_state(QIcon::Off) {} + + OverriddenColor(const QString &p_foreground, QIcon::Mode p_mode = QIcon::Normal, + QIcon::State p_state = QIcon::Off) + : m_foreground(p_foreground), m_mode(p_mode), m_state(p_state) {} + + QString m_foreground; + QIcon::Mode m_mode; + QIcon::State m_state; + }; + + static void setDefaultIconForeground(const QString &p_fg, const QString &p_disabledFg); + + static QIcon fetchIcon(const QString &p_iconFile, + const QVector &p_overriddenColors, qreal p_angle = -1); + + static QIcon fetchIcon(const QString &p_iconFile, const QString &p_overriddenForeground); + + // Fetch icon from @p_iconFile with icon_fg as overridden foreground color. + static QIcon fetchIcon(const QString &p_iconFile); + + static QIcon fetchIconWithDisabledState(const QString &p_iconFile); + + static QIcon drawTextIcon(const QString &p_text, const QString &p_fg, const QString &p_border); + + static QIcon drawTextRectIcon(const QString &p_text, const QString &p_fg, const QString &p_bg, + const QString &p_border, int p_rectWidth = 56, + int p_rectHeight = 56, int p_rectRadius = 0); + +private: + static QString replaceForegroundOfIcon(const QString &p_iconContent, const QString &p_foreground); + + static QString s_defaultIconForeground; + + static QString s_defaultIconDisabledForeground; + + static bool isMonochrome(const QString &p_iconContent); +}; +} // namespace vnotex #endif // ICONUTILS_H diff --git a/src/utils/imageutils.cpp b/src/utils/imageutils.cpp index 5d98941d0b..46ecd7d4e9 100644 --- a/src/utils/imageutils.cpp +++ b/src/utils/imageutils.cpp @@ -4,15 +4,13 @@ using namespace vnotex; -QImage::Format ImageUtils::guessImageFormat(const QByteArray &p_data) -{ - auto image = QImage::fromData(p_data); - return image.format(); +QImage::Format ImageUtils::guessImageFormat(const QByteArray &p_data) { + auto image = QImage::fromData(p_data); + return image.format(); } -QString ImageUtils::guessImageSuffix(const QByteArray &p_data) -{ - QMimeDatabase mimeDb; - auto mimeType = mimeDb.mimeTypeForData(p_data); - return mimeType.preferredSuffix(); +QString ImageUtils::guessImageSuffix(const QByteArray &p_data) { + QMimeDatabase mimeDb; + auto mimeType = mimeDb.mimeTypeForData(p_data); + return mimeType.preferredSuffix(); } diff --git a/src/utils/imageutils.h b/src/utils/imageutils.h index e9daeeda92..8ffbec83d0 100644 --- a/src/utils/imageutils.h +++ b/src/utils/imageutils.h @@ -3,17 +3,15 @@ #include -namespace vnotex -{ - class ImageUtils - { - public: - ImageUtils() = delete; +namespace vnotex { +class ImageUtils { +public: + ImageUtils() = delete; - static QImage::Format guessImageFormat(const QByteArray &p_data); + static QImage::Format guessImageFormat(const QByteArray &p_data); - static QString guessImageSuffix(const QByteArray &p_data); - }; -} + static QString guessImageSuffix(const QByteArray &p_data); +}; +} // namespace vnotex #endif // IMAGEUTILS_H diff --git a/src/utils/pathutils.cpp b/src/utils/pathutils.cpp index 247a587a9f..9a4aeb3694 100644 --- a/src/utils/pathutils.cpp +++ b/src/utils/pathutils.cpp @@ -2,247 +2,224 @@ #include #include -#include #include +#include using namespace vnotex; -const QString PathUtils::c_fileNameRegularExpression = QStringLiteral("\\A(?:[^\\\\/:\\*\\?\"<>\\|\\s]| )+\\z"); +const QString PathUtils::c_fileNameRegularExpression = + QStringLiteral("\\A(?:[^\\\\/:\\*\\?\"<>\\|\\s]| )+\\z"); -QString PathUtils::parentDirPath(const QString &p_path) -{ - if (p_path.isEmpty()) { - return p_path; - } +QString PathUtils::parentDirPath(const QString &p_path) { + if (p_path.isEmpty()) { + return p_path; + } - QFileInfo info(p_path); - return cleanPath(info.absolutePath()); + QFileInfo info(p_path); + return cleanPath(info.absolutePath()); } -QString PathUtils::dirOrParentDirPath(const QString &p_path) -{ - if (p_path.isEmpty()) { - return p_path; - } +QString PathUtils::dirOrParentDirPath(const QString &p_path) { + if (p_path.isEmpty()) { + return p_path; + } - QFileInfo info(p_path); - if (info.isDir()) { - return p_path; - } else { - return info.absolutePath(); - } + QFileInfo info(p_path); + if (info.isDir()) { + return p_path; + } else { + return info.absolutePath(); + } } -bool PathUtils::isEmptyDir(const QString &p_path) -{ - QFileInfo fi(p_path); - if (!fi.exists()) { - return true; - } +bool PathUtils::isEmptyDir(const QString &p_path) { + QFileInfo fi(p_path); + if (!fi.exists()) { + return true; + } - return fi.isDir() && QDir(p_path).isEmpty(); + return fi.isDir() && QDir(p_path).isEmpty(); } -QString PathUtils::concatenateFilePath(const QString &p_dirPath, const QString &p_name) -{ - QString dirPath = cleanPath(p_dirPath); - if (p_name.isEmpty()) { - return dirPath; - } +QString PathUtils::concatenateFilePath(const QString &p_dirPath, const QString &p_name) { + QString dirPath = cleanPath(p_dirPath); + if (p_name.isEmpty()) { + return dirPath; + } - if (dirPath.isEmpty()) { - return p_name; - } + if (dirPath.isEmpty()) { + return p_name; + } - return dirPath + "/" + p_name; + return dirPath + "/" + p_name; } -QString PathUtils::dirName(const QString &p_path) -{ - Q_ASSERT(!QFileInfo::exists(p_path) || QFileInfo(p_path).isDir()); - return QDir(p_path).dirName(); +QString PathUtils::dirName(const QString &p_path) { + Q_ASSERT(!QFileInfo::exists(p_path) || QFileInfo(p_path).isDir()); + return QDir(p_path).dirName(); } -QString PathUtils::fileName(const QString &p_path) -{ - QFileInfo fi(p_path); - return fi.fileName(); +QString PathUtils::fileName(const QString &p_path) { + QFileInfo fi(p_path); + return fi.fileName(); } -QString PathUtils::fileNameCheap(const QString &p_path) -{ - int idx = p_path.lastIndexOf(QRegularExpression("[\\\\/]")); - if (idx == -1) { - return p_path; - } - return p_path.mid(idx + 1); +QString PathUtils::fileNameCheap(const QString &p_path) { + int idx = p_path.lastIndexOf(QRegularExpression("[\\\\/]")); + if (idx == -1) { + return p_path; + } + return p_path.mid(idx + 1); } -QString PathUtils::normalizePath(const QString &p_path) -{ - Q_ASSERT(isLocalFile(p_path)); +QString PathUtils::normalizePath(const QString &p_path) { + Q_ASSERT(isLocalFile(p_path)); - auto absPath = QDir::cleanPath(QDir(p_path).absolutePath()); + auto absPath = QDir::cleanPath(QDir(p_path).absolutePath()); #if defined(Q_OS_WIN) - return absPath.toLower(); + return absPath.toLower(); #else - return absPath; + return absPath; #endif } -bool PathUtils::areSamePaths(const QString &p_a, const QString &p_b) -{ - return normalizePath(p_a) == normalizePath(p_b); +bool PathUtils::areSamePaths(const QString &p_a, const QString &p_b) { + return normalizePath(p_a) == normalizePath(p_b); } -bool PathUtils::pathContains(const QString &p_dir, const QString &p_path) -{ - auto rel = relativePath(p_dir, p_path); - if (rel.startsWith(QStringLiteral("../")) || rel == QStringLiteral("..")) { - return false; - } +bool PathUtils::pathContains(const QString &p_dir, const QString &p_path) { + auto rel = relativePath(p_dir, p_path); + if (rel.startsWith(QStringLiteral("../")) || rel == QStringLiteral("..")) { + return false; + } - if (QFileInfo(rel).isAbsolute()) { - return false; - } + if (QFileInfo(rel).isAbsolute()) { + return false; + } - return true; + return true; } -bool PathUtils::isLegalFileName(const QString &p_name) -{ - QRegularExpression nameRe(c_fileNameRegularExpression); - auto match = nameRe.match(p_name); - return match.hasMatch(); +bool PathUtils::isLegalFileName(const QString &p_name) { + QRegularExpression nameRe(c_fileNameRegularExpression); + auto match = nameRe.match(p_name); + return match.hasMatch(); } -bool PathUtils::isLegalPath(const QString &p_path) -{ - // Ensure each part of the @p_path is a valid file name until we come to - // an existing parent directory. - if (p_path.isEmpty()) { - return false; - } +bool PathUtils::isLegalPath(const QString &p_path) { + // Ensure each part of the @p_path is a valid file name until we come to + // an existing parent directory. + if (p_path.isEmpty()) { + return false; + } - if (QFileInfo::exists(p_path)) { + if (QFileInfo::exists(p_path)) { #if defined(Q_OS_WIN) - // On Windows, "/" and ":" will also make exists() return true. - if (p_path.startsWith('/') || p_path == ":") { - return false; - } + // On Windows, "/" and ":" will also make exists() return true. + if (p_path.startsWith('/') || p_path == ":") { + return false; + } #endif - return true; + return true; + } + + bool ret = false; + QString basePath = parentDirPath(p_path); + QString name = dirName(p_path); + QRegularExpression nameRegExp(c_fileNameRegularExpression); + while (!name.isEmpty()) { + auto match = nameRegExp.match(name); + if (!match.hasMatch()) { + break; } - bool ret = false; - QString basePath = parentDirPath(p_path); - QString name = dirName(p_path); - QRegularExpression nameRegExp(c_fileNameRegularExpression); - while (!name.isEmpty()) { - auto match = nameRegExp.match(name); - if (!match.hasMatch()) { - break; - } - - if (QFileInfo::exists(basePath)) { - ret = true; + if (QFileInfo::exists(basePath)) { + ret = true; #if defined(Q_OS_WIN) - // On Windows, "/" and ":" will also make exists() return true. - if (basePath.startsWith('/') || basePath == ":") { - ret = false; - } + // On Windows, "/" and ":" will also make exists() return true. + if (basePath.startsWith('/') || basePath == ":") { + ret = false; + } #endif - break; - } - - basePath = parentDirPath(basePath); - name = dirName(basePath); + break; } - return ret; + basePath = parentDirPath(basePath); + name = dirName(basePath); + } + + return ret; } -QString PathUtils::relativePath(const QString &p_dir, const QString &p_path) -{ - QDir dir(p_dir); - return cleanPath(dir.relativeFilePath(p_path)); +QString PathUtils::relativePath(const QString &p_dir, const QString &p_path) { + QDir dir(p_dir); + return cleanPath(dir.relativeFilePath(p_path)); } -QUrl PathUtils::pathToUrl(const QString &p_path) -{ - // Need to judge the path: Url, local file, resource file. - QUrl url; - QFileInfo pathInfo(p_path); - if (pathInfo.exists()) { - if (pathInfo.isNativePath()) { - // Local file. - url = QUrl::fromLocalFile(p_path); - } else { - // Resource file. - url = QUrl(QStringLiteral("qrc") + p_path); - } +QUrl PathUtils::pathToUrl(const QString &p_path) { + // Need to judge the path: Url, local file, resource file. + QUrl url; + QFileInfo pathInfo(p_path); + if (pathInfo.exists()) { + if (pathInfo.isNativePath()) { + // Local file. + url = QUrl::fromLocalFile(p_path); } else { - // Url. - url = QUrl(p_path); + // Resource file. + url = QUrl(QStringLiteral("qrc") + p_path); } + } else { + // Url. + url = QUrl(p_path); + } - return url; + return url; } -QString PathUtils::urlToPath(const QUrl &p_url) -{ - if (p_url.isLocalFile()) { - return p_url.toLocalFile(); - } else { - return p_url.toString(); - } +QString PathUtils::urlToPath(const QUrl &p_url) { + if (p_url.isLocalFile()) { + return p_url.toLocalFile(); + } else { + return p_url.toString(); + } } -QString PathUtils::encodeSpacesInPath(const QString &p_path) -{ - QString tmp(p_path); - tmp.replace(QLatin1Char(' '), QStringLiteral("%20")); - return tmp; +QString PathUtils::encodeSpacesInPath(const QString &p_path) { + QString tmp(p_path); + tmp.replace(QLatin1Char(' '), QStringLiteral("%20")); + return tmp; } -void PathUtils::prependDotIfRelative(QString &p_path) -{ - if (QDir::isRelativePath(p_path) - && !p_path.startsWith(QStringLiteral("."))) { - p_path.prepend(QStringLiteral("./")); - } +void PathUtils::prependDotIfRelative(QString &p_path) { + if (QDir::isRelativePath(p_path) && !p_path.startsWith(QStringLiteral("."))) { + p_path.prepend(QStringLiteral("./")); + } } -QString PathUtils::removeUrlParameters(const QString &p_url) -{ - int idx = p_url.indexOf(QLatin1Char('?')); - if (idx > -1) { - return p_url.left(idx); - } - return p_url; +QString PathUtils::removeUrlParameters(const QString &p_url) { + int idx = p_url.indexOf(QLatin1Char('?')); + if (idx > -1) { + return p_url.left(idx); + } + return p_url; } -bool PathUtils::isImageUrl(const QString &p_url) -{ - QFileInfo info(removeUrlParameters(p_url)); - return QImageReader::supportedImageFormats().contains(info.suffix().toLower().toLatin1()); +bool PathUtils::isImageUrl(const QString &p_url) { + QFileInfo info(removeUrlParameters(p_url)); + return QImageReader::supportedImageFormats().contains(info.suffix().toLower().toLatin1()); } -bool PathUtils::isDir(const QString &p_path) -{ - return QFileInfo(p_path).isDir(); -} +bool PathUtils::isDir(const QString &p_path) { return QFileInfo(p_path).isDir(); } -bool PathUtils::isLocalFile(const QString &p_path) -{ - if (p_path.isEmpty()) { - return true; - } +bool PathUtils::isLocalFile(const QString &p_path) { + if (p_path.isEmpty()) { + return true; + } - QRegularExpression regExp("^(?:ftp|http|https)://"); - if (regExp.match(p_path).hasMatch()) { - return false; - } + QRegularExpression regExp("^(?:ftp|http|https)://"); + if (regExp.match(p_path).hasMatch()) { + return false; + } - return true; + return true; } diff --git a/src/utils/pathutils.h b/src/utils/pathutils.h index 2817453e10..f98f4fb15e 100644 --- a/src/utils/pathutils.h +++ b/src/utils/pathutils.h @@ -1,84 +1,76 @@ #ifndef PATHUTILS_H #define PATHUTILS_H -#include #include +#include #include -namespace vnotex -{ - class PathUtils - { - public: - PathUtils() = delete; +namespace vnotex { +class PathUtils { +public: + PathUtils() = delete; - static QString cleanPath(const QString &p_path) - { - return QDir::cleanPath(p_path); - } + static QString cleanPath(const QString &p_path) { return QDir::cleanPath(p_path); } - // See testParentDirPath(). - static QString parentDirPath(const QString &p_path); + // See testParentDirPath(). + static QString parentDirPath(const QString &p_path); - // Return @p_path if it is a dir. Otherwise, return its parent dir. - static QString dirOrParentDirPath(const QString &p_path); + // Return @p_path if it is a dir. Otherwise, return its parent dir. + static QString dirOrParentDirPath(const QString &p_path); - // Whether @p_path is a dir. - static bool isDir(const QString &p_path); + // Whether @p_path is a dir. + static bool isDir(const QString &p_path); - // Whether @p_folderPath is an empty directory. - static bool isEmptyDir(const QString &p_path); + // Whether @p_folderPath is an empty directory. + static bool isEmptyDir(const QString &p_path); - // Concatenate @p_dirPath and @p_name. - static QString concatenateFilePath(const QString &p_dirPath, const QString &p_name); + // Concatenate @p_dirPath and @p_name. + static QString concatenateFilePath(const QString &p_dirPath, const QString &p_name); - // Get dir name of @p_path directory. - static QString dirName(const QString &p_path); + // Get dir name of @p_path directory. + static QString dirName(const QString &p_path); - // Get file name of @p_path file/directory. - static QString fileName(const QString &p_path); + // Get file name of @p_path file/directory. + static QString fileName(const QString &p_path); - static QString fileNameCheap(const QString &p_path); + static QString fileNameCheap(const QString &p_path); - static QString absolutePath(const QString &p_path) - { - return QDir(p_path).absolutePath(); - } + static QString absolutePath(const QString &p_path) { return QDir(p_path).absolutePath(); } - // Normalize @p_path for comparision. - static QString normalizePath(const QString &p_path); + // Normalize @p_path for comparision. + static QString normalizePath(const QString &p_path); - // Whether two paths point to the same file/directory. - static bool areSamePaths(const QString &p_a, const QString &p_b); + // Whether two paths point to the same file/directory. + static bool areSamePaths(const QString &p_a, const QString &p_b); - // Whether @p_dir contains @p_path. - static bool pathContains(const QString &p_dir, const QString &p_path); + // Whether @p_dir contains @p_path. + static bool pathContains(const QString &p_dir, const QString &p_path); - static bool isLegalFileName(const QString &p_name); + static bool isLegalFileName(const QString &p_name); - static bool isLegalPath(const QString &p_path); + static bool isLegalPath(const QString &p_path); - // Return relative path of @p_path to @p_dir. - static QString relativePath(const QString &p_dir, const QString &p_path); + // Return relative path of @p_path to @p_dir. + static QString relativePath(const QString &p_dir, const QString &p_path); - static QUrl pathToUrl(const QString &p_path); + static QUrl pathToUrl(const QString &p_path); - static QString urlToPath(const QUrl &p_url); + static QString urlToPath(const QUrl &p_url); - static QString encodeSpacesInPath(const QString &p_path); + static QString encodeSpacesInPath(const QString &p_path); - static void prependDotIfRelative(QString &p_path); + static void prependDotIfRelative(QString &p_path); - static QString removeUrlParameters(const QString &p_url); + static QString removeUrlParameters(const QString &p_url); - static bool isImageUrl(const QString &p_url); + static bool isImageUrl(const QString &p_url); - static bool isLocalFile(const QString &p_path); + static bool isLocalFile(const QString &p_path); - // Regular expression string for file/folder name. - // Forbidden chars: \/:*?"<>| and whitespaces except spaces. - static const QString c_fileNameRegularExpression; - }; -} // ns vnotex + // Regular expression string for file/folder name. + // Forbidden chars: \/:*?"<>| and whitespaces except spaces. + static const QString c_fileNameRegularExpression; +}; +} // namespace vnotex #endif // PATHUTILS_H diff --git a/src/utils/printutils.cpp b/src/utils/printutils.cpp index 0a1e9813e1..3130b8a668 100644 --- a/src/utils/printutils.cpp +++ b/src/utils/printutils.cpp @@ -1,22 +1,22 @@ #include "printutils.h" -#include #include +#include using namespace vnotex; -QSharedPointer PrintUtils::promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent) -{ - auto printer = QSharedPointer::create(); +QSharedPointer PrintUtils::promptForPrint(bool p_printSelectionEnabled, + QWidget *p_parent) { + auto printer = QSharedPointer::create(); - QPrintDialog dialog(printer.data(), p_parent); - if (p_printSelectionEnabled) { - dialog.setOption(QAbstractPrintDialog::PrintSelection); - } + QPrintDialog dialog(printer.data(), p_parent); + if (p_printSelectionEnabled) { + dialog.setOption(QAbstractPrintDialog::PrintSelection); + } - if (dialog.exec() == QDialog::Accepted) { - return printer; - } + if (dialog.exec() == QDialog::Accepted) { + return printer; + } - return nullptr; + return nullptr; } diff --git a/src/utils/printutils.h b/src/utils/printutils.h index af1701e681..6958768eb1 100644 --- a/src/utils/printutils.h +++ b/src/utils/printutils.h @@ -6,16 +6,14 @@ class QPrinter; class QWidget; -namespace vnotex -{ - class PrintUtils - { - public: - PrintUtils() = delete; +namespace vnotex { +class PrintUtils { +public: + PrintUtils() = delete; - // Return null if user cancel the print. - static QSharedPointer promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent); - }; -} + // Return null if user cancel the print. + static QSharedPointer promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent); +}; +} // namespace vnotex #endif // PRINTUTILS_H diff --git a/src/utils/processutils.cpp b/src/utils/processutils.cpp index edf34510fa..14dc7a376e 100644 --- a/src/utils/processutils.cpp +++ b/src/utils/processutils.cpp @@ -1,182 +1,169 @@ #include "processutils.h" +#include #include #include -#include #include "utils.h" using namespace vnotex; -ProcessUtils::State ProcessUtils::start(const QString &p_program, - const QStringList &p_args, - const QByteArray &p_stdIn, - int &p_exitCodeOnSuccess, - QByteArray &p_stdOut, - QByteArray &p_stdErr) -{ - QScopedPointer proc(new QProcess()); - proc->start(p_program, p_args); - return handleProcess(proc.data(), p_stdIn, p_exitCodeOnSuccess, p_stdOut, p_stdErr); +ProcessUtils::State ProcessUtils::start(const QString &p_program, const QStringList &p_args, + const QByteArray &p_stdIn, int &p_exitCodeOnSuccess, + QByteArray &p_stdOut, QByteArray &p_stdErr) { + QScopedPointer proc(new QProcess()); + proc->start(p_program, p_args); + return handleProcess(proc.data(), p_stdIn, p_exitCodeOnSuccess, p_stdOut, p_stdErr); } -ProcessUtils::State ProcessUtils::handleProcess(QProcess *p_process, - const QByteArray &p_stdIn, - int &p_exitCodeOnSuccess, - QByteArray &p_stdOut, - QByteArray &p_stdErr) -{ - if (!p_process->waitForStarted()) { - return State::FailedToStart; +ProcessUtils::State ProcessUtils::handleProcess(QProcess *p_process, const QByteArray &p_stdIn, + int &p_exitCodeOnSuccess, QByteArray &p_stdOut, + QByteArray &p_stdErr) { + if (!p_process->waitForStarted()) { + return State::FailedToStart; + } + + if (!p_stdIn.isEmpty()) { + if (p_process->write(p_stdIn) == -1) { + p_process->closeWriteChannel(); + qWarning() << "failed to write to stdin of QProcess" << p_process->errorString(); + return State::FailedToWrite; + } else { + p_process->closeWriteChannel(); } + } - if (!p_stdIn.isEmpty()) { - if (p_process->write(p_stdIn) == -1) { - p_process->closeWriteChannel(); - qWarning() << "failed to write to stdin of QProcess" << p_process->errorString(); - return State::FailedToWrite; - } else { - p_process->closeWriteChannel(); - } - } + p_process->waitForFinished(); - p_process->waitForFinished(); + State state = State::Succeeded; + if (p_process->exitStatus() == QProcess::CrashExit) { + state = State::Crashed; + } else { + p_exitCodeOnSuccess = p_process->exitCode(); + } - State state = State::Succeeded; - if (p_process->exitStatus() == QProcess::CrashExit) { - state = State::Crashed; - } else { - p_exitCodeOnSuccess = p_process->exitCode(); + p_stdOut = p_process->readAllStandardOutput(); + p_stdErr = p_process->readAllStandardError(); + return state; +} + +QStringList ProcessUtils::parseCombinedArgString(const QString &p_args) { + QStringList args; + QString tmp; + int quoteCount = 0; + bool inQuote = false; + + // Handle quoting. + // Tokens can be surrounded by double quotes "hello world". + // Three consecutive double quotes represent the quote character itself. + for (int i = 0; i < p_args.size(); ++i) { + if (p_args.at(i) == QLatin1Char('"')) { + ++quoteCount; + if (quoteCount == 3) { + // Third consecutive quote. + quoteCount = 0; + tmp += p_args.at(i); + } + + continue; } - p_stdOut = p_process->readAllStandardOutput(); - p_stdErr = p_process->readAllStandardError(); - return state; -} + if (quoteCount) { + if (quoteCount == 1) { + inQuote = !inQuote; + } -QStringList ProcessUtils::parseCombinedArgString(const QString &p_args) -{ - QStringList args; - QString tmp; - int quoteCount = 0; - bool inQuote = false; - - // Handle quoting. - // Tokens can be surrounded by double quotes "hello world". - // Three consecutive double quotes represent the quote character itself. - for (int i = 0; i < p_args.size(); ++i) { - if (p_args.at(i) == QLatin1Char('"')) { - ++quoteCount; - if (quoteCount == 3) { - // Third consecutive quote. - quoteCount = 0; - tmp += p_args.at(i); - } - - continue; - } - - if (quoteCount) { - if (quoteCount == 1) { - inQuote = !inQuote; - } - - quoteCount = 0; - } - - if (!inQuote && p_args.at(i).isSpace()) { - if (!tmp.isEmpty()) { - args += tmp; - tmp.clear(); - } - } else { - tmp += p_args.at(i); - } + quoteCount = 0; } - if (!tmp.isEmpty()) { + if (!inQuote && p_args.at(i).isSpace()) { + if (!tmp.isEmpty()) { args += tmp; + tmp.clear(); + } + } else { + tmp += p_args.at(i); } + } + + if (!tmp.isEmpty()) { + args += tmp; + } - return args; + return args; } -QString ProcessUtils::combineArgString(const QStringList &p_args) -{ - QString argStr; - for (const auto &arg : p_args) { - QString tmp(arg); - tmp.replace("\"", "\"\"\""); - if (tmp.contains(' ')) { - tmp = '"' + tmp + '"'; - } - - if (argStr.isEmpty()) { - argStr = tmp; - } else { - argStr = argStr + ' ' + tmp; - } +QString ProcessUtils::combineArgString(const QStringList &p_args) { + QString argStr; + for (const auto &arg : p_args) { + QString tmp(arg); + tmp.replace("\"", "\"\"\""); + if (tmp.contains(' ')) { + tmp = '"' + tmp + '"'; } - return argStr; + if (argStr.isEmpty()) { + argStr = tmp; + } else { + argStr = argStr + ' ' + tmp; + } + } + + return argStr; } -ProcessUtils::State ProcessUtils::start(const QString &p_program, - const QStringList &p_args, +ProcessUtils::State ProcessUtils::start(const QString &p_program, const QStringList &p_args, const std::function &p_logger, - const bool &p_askedToStop) -{ - QProcess proc; - proc.start(p_program, p_args); - return handleProcess(&proc, p_logger, p_askedToStop); + const bool &p_askedToStop) { + QProcess proc; + proc.start(p_program, p_args); + return handleProcess(&proc, p_logger, p_askedToStop); } ProcessUtils::State ProcessUtils::start(const QString &p_command, const std::function &p_logger, - const bool &p_askedToStop) -{ - QProcess proc; - proc.start(p_command); - return handleProcess(&proc, p_logger, p_askedToStop); + const bool &p_askedToStop) { + QProcess proc; + proc.start(p_command); + return handleProcess(&proc, p_logger, p_askedToStop); } -ProcessUtils::State ProcessUtils::handleProcess(QProcess *p_process, - const std::function &p_logger, - const bool &p_askedToStop) -{ - if (!p_process->waitForStarted()) { - return State::FailedToStart; +ProcessUtils::State +ProcessUtils::handleProcess(QProcess *p_process, + const std::function &p_logger, + const bool &p_askedToStop) { + if (!p_process->waitForStarted()) { + return State::FailedToStart; + } + + while (p_process->state() != QProcess::NotRunning) { + Utils::sleepWait(100); + + auto outBa = p_process->readAllStandardOutput(); + auto errBa = p_process->readAllStandardError(); + QString msg; + if (!outBa.isEmpty()) { + msg += QString::fromLocal8Bit(outBa); + } + if (!errBa.isEmpty()) { + msg += QString::fromLocal8Bit(errBa); + } + if (!msg.isEmpty()) { + p_logger(msg); } - while (p_process->state() != QProcess::NotRunning) { - Utils::sleepWait(100); - - auto outBa = p_process->readAllStandardOutput(); - auto errBa = p_process->readAllStandardError(); - QString msg; - if (!outBa.isEmpty()) { - msg += QString::fromLocal8Bit(outBa); - } - if (!errBa.isEmpty()) { - msg += QString::fromLocal8Bit(errBa); - } - if (!msg.isEmpty()) { - p_logger(msg); - } - - if (p_askedToStop) { - break; - } + if (p_askedToStop) { + break; } + } - return p_process->exitStatus() == QProcess::NormalExit ? State::Succeeded : State::Crashed; + return p_process->exitStatus() == QProcess::NormalExit ? State::Succeeded : State::Crashed; } -void ProcessUtils::startDetached(const QString &p_command) -{ - Q_ASSERT(!p_command.isEmpty()); - auto process = new QProcess(); - QObject::connect(process, QOverload::of(&QProcess::finished), - process, &QProcess::deleteLater); - process->start(p_command); +void ProcessUtils::startDetached(const QString &p_command) { + Q_ASSERT(!p_command.isEmpty()); + auto process = new QProcess(); + QObject::connect(process, QOverload::of(&QProcess::finished), process, + &QProcess::deleteLater); + process->start(p_command); } diff --git a/src/utils/processutils.h b/src/utils/processutils.h index 6873e48410..58c30ba75f 100644 --- a/src/utils/processutils.h +++ b/src/utils/processutils.h @@ -3,60 +3,43 @@ #include -#include #include +#include class QProcess; -namespace vnotex -{ - class ProcessUtils - { - public: - enum State - { - Succeeded, - Crashed, - FailedToStart, - FailedToWrite - }; - - ProcessUtils() = delete; - - static State start(const QString &p_program, - const QStringList &p_args, - const QByteArray &p_stdIn, - int &p_exitCodeOnSuccess, - QByteArray &p_stdOut, - QByteArray &p_stdErr); - - static State start(const QString &p_program, - const QStringList &p_args, - const std::function &p_logger, - const bool &p_askedToStop); - - static State start(const QString &p_command, - const std::function &p_logger, - const bool &p_askedToStop); - - static void startDetached(const QString &p_command); - - // Copied from QProcess code. - static QStringList parseCombinedArgString(const QString &p_args); - - static QString combineArgString(const QStringList &p_args); - - private: - static State handleProcess(QProcess *p_process, - const QByteArray &p_stdIn, - int &p_exitCodeOnSuccess, - QByteArray &p_stdOut, - QByteArray &p_stdErr); - - static State handleProcess(QProcess *p_process, - const std::function &p_logger, - const bool &p_askedToStop); - }; -} +namespace vnotex { +class ProcessUtils { +public: + enum State { Succeeded, Crashed, FailedToStart, FailedToWrite }; + + ProcessUtils() = delete; + + static State start(const QString &p_program, const QStringList &p_args, const QByteArray &p_stdIn, + int &p_exitCodeOnSuccess, QByteArray &p_stdOut, QByteArray &p_stdErr); + + static State start(const QString &p_program, const QStringList &p_args, + const std::function &p_logger, + const bool &p_askedToStop); + + static State start(const QString &p_command, const std::function &p_logger, + const bool &p_askedToStop); + + static void startDetached(const QString &p_command); + + // Copied from QProcess code. + static QStringList parseCombinedArgString(const QString &p_args); + + static QString combineArgString(const QStringList &p_args); + +private: + static State handleProcess(QProcess *p_process, const QByteArray &p_stdIn, + int &p_exitCodeOnSuccess, QByteArray &p_stdOut, QByteArray &p_stdErr); + + static State handleProcess(QProcess *p_process, + const std::function &p_logger, + const bool &p_askedToStop); +}; +} // namespace vnotex #endif // PROCESSUTILS_H diff --git a/src/utils/urldragdroputils.cpp b/src/utils/urldragdroputils.cpp index 137f288073..0b11084766 100644 --- a/src/utils/urldragdroputils.cpp +++ b/src/utils/urldragdroputils.cpp @@ -2,43 +2,42 @@ #include #include -#include #include +#include #include using namespace vnotex; -bool UrlDragDropUtils::handleDragEnterEvent(QDragEnterEvent *p_event) -{ - if (p_event->mimeData()->hasFormat(QStringLiteral("text/uri-list"))) { - p_event->acceptProposedAction(); - return true; - } +bool UrlDragDropUtils::handleDragEnterEvent(QDragEnterEvent *p_event) { + if (p_event->mimeData()->hasFormat(QStringLiteral("text/uri-list"))) { + p_event->acceptProposedAction(); + return true; + } - return false; + return false; } -bool UrlDragDropUtils::handleDropEvent(QDropEvent *p_event, std::function p_func) -{ - const QMimeData *mime = p_event->mimeData(); - if (mime->hasFormat(QStringLiteral("text/uri-list")) && mime->hasUrls()) { - QStringList files; - const auto urls = mime->urls(); - for (const auto &url : urls) { - if (url.isLocalFile()) { - QFileInfo info(url.toLocalFile()); - if (info.exists() && info.isFile()) { - files << PathUtils::cleanPath(info.absoluteFilePath()); - } - } +bool UrlDragDropUtils::handleDropEvent(QDropEvent *p_event, + std::function p_func) { + const QMimeData *mime = p_event->mimeData(); + if (mime->hasFormat(QStringLiteral("text/uri-list")) && mime->hasUrls()) { + QStringList files; + const auto urls = mime->urls(); + for (const auto &url : urls) { + if (url.isLocalFile()) { + QFileInfo info(url.toLocalFile()); + if (info.exists() && info.isFile()) { + files << PathUtils::cleanPath(info.absoluteFilePath()); } + } + } - p_func(files); + p_func(files); - p_event->acceptProposedAction(); - return true; - } + p_event->acceptProposedAction(); + return true; + } - return false; + return false; } diff --git a/src/utils/urldragdroputils.h b/src/utils/urldragdroputils.h index 7579c6865f..ba53015dc5 100644 --- a/src/utils/urldragdroputils.h +++ b/src/utils/urldragdroputils.h @@ -8,18 +8,16 @@ class QDragEnterEvent; class QDropEvent; -namespace vnotex -{ - // Help to handle Url-related Drag&Drop events. - class UrlDragDropUtils - { - public: - UrlDragDropUtils() = delete; +namespace vnotex { +// Help to handle Url-related Drag&Drop events. +class UrlDragDropUtils { +public: + UrlDragDropUtils() = delete; - static bool handleDragEnterEvent(QDragEnterEvent *p_event); + static bool handleDragEnterEvent(QDragEnterEvent *p_event); - static bool handleDropEvent(QDropEvent *p_event, std::function p_func); - }; -} + static bool handleDropEvent(QDropEvent *p_event, std::function p_func); +}; +} // namespace vnotex #endif // URLDRAGDROPUTILS_H diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 97a875ed32..88f53f358b 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -1,222 +1,200 @@ #include "utils.h" -#include +#include #include -#include -#include +#include #include -#include -#include -#include -#include #include #include -#include +#include +#include #include +#include +#include +#include +#include #include using namespace vnotex; -void Utils::sleepWait(int p_milliseconds) -{ - if (p_milliseconds <= 0) { - return; - } +void Utils::sleepWait(int p_milliseconds) { + if (p_milliseconds <= 0) { + return; + } - QElapsedTimer t; - t.start(); - while (t.elapsed() < p_milliseconds) { - QCoreApplication::processEvents(); - } + QElapsedTimer t; + t.start(); + while (t.elapsed() < p_milliseconds) { + QCoreApplication::processEvents(); + } } -void Utils::appendMsg(QString &p_msg, const QString &p_new) -{ - if (p_msg.isEmpty()) { - p_msg = p_new; - } else { - p_msg += '\n' + p_new; - } +void Utils::appendMsg(QString &p_msg, const QString &p_new) { + if (p_msg.isEmpty()) { + p_msg = p_new; + } else { + p_msg += '\n' + p_new; + } } -QString Utils::dateTimeString(const QDateTime &p_dateTime) -{ - QLocale locale; - return locale.toString(p_dateTime.date()) - + " " - + p_dateTime.time().toString(Qt::TextDate); +QString Utils::dateTimeString(const QDateTime &p_dateTime) { + QLocale locale; + return locale.toString(p_dateTime.date()) + " " + p_dateTime.time().toString(Qt::TextDate); } -QString Utils::dateTimeStringUniform(const QDateTime &p_dateTime) -{ - return p_dateTime.toString(Qt::ISODate); +QString Utils::dateTimeStringUniform(const QDateTime &p_dateTime) { + return p_dateTime.toString(Qt::ISODate); } -QDateTime Utils::dateTimeFromStringUniform(const QString &p_str) -{ - return QDateTime::fromString(p_str, Qt::ISODate); +QDateTime Utils::dateTimeFromStringUniform(const QString &p_str) { + return QDateTime::fromString(p_str, Qt::ISODate); } -QChar Utils::keyToChar(int p_key, bool p_lowerCase) -{ - auto keyStr = QKeySequence(p_key).toString(); - if (keyStr.size() == 1) { - return p_lowerCase ? keyStr[0].toLower() : keyStr[0]; - } +QChar Utils::keyToChar(int p_key, bool p_lowerCase) { + auto keyStr = QKeySequence(p_key).toString(); + if (keyStr.size() == 1) { + return p_lowerCase ? keyStr[0].toLower() : keyStr[0]; + } - return QChar(); + return QChar(); } -QString Utils::pickAvailableFontFamily(const QStringList &p_families) -{ +QString Utils::pickAvailableFontFamily(const QStringList &p_families) { #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - auto availableFonts = QFontDatabase().families(); + auto availableFonts = QFontDatabase().families(); #else - auto availableFonts = QFontDatabase::families(); + auto availableFonts = QFontDatabase::families(); #endif - for (const auto& f : p_families) { - auto family = f.trimmed(); - if (family.isEmpty()) { - continue; - } - - QRegularExpression regExp("\\[.*\\]"); - for (auto availableFont : availableFonts) { - availableFont.remove(regExp); - availableFont = availableFont.trimmed(); - if (family == availableFont - || family.toLower() == availableFont.toLower()) { - return availableFont; - } - } + for (const auto &f : p_families) { + auto family = f.trimmed(); + if (family.isEmpty()) { + continue; + } + + QRegularExpression regExp("\\[.*\\]"); + for (auto availableFont : availableFonts) { + availableFont.remove(regExp); + availableFont = availableFont.trimmed(); + if (family == availableFont || family.toLower() == availableFont.toLower()) { + return availableFont; + } } + } - return QString(); + return QString(); } -QPixmap Utils::svgToPixmap(const QByteArray &p_content, - QRgb p_background, - qreal p_scaleFactor) -{ - QSvgRenderer renderer(p_content); - QSize deSz = renderer.defaultSize(); - if (p_scaleFactor > 0) { - deSz *= p_scaleFactor; - } +QPixmap Utils::svgToPixmap(const QByteArray &p_content, QRgb p_background, qreal p_scaleFactor) { + QSvgRenderer renderer(p_content); + QSize deSz = renderer.defaultSize(); + if (p_scaleFactor > 0) { + deSz *= p_scaleFactor; + } - QPixmap pm(deSz); - if (p_background == 0x0) { - // Fill a transparent background to avoid glitchy preview. - pm.fill(QColor(255, 255, 255, 0)); - } else { - pm.fill(p_background); - } + QPixmap pm(deSz); + if (p_background == 0x0) { + // Fill a transparent background to avoid glitchy preview. + pm.fill(QColor(255, 255, 255, 0)); + } else { + pm.fill(p_background); + } - QPainter painter(&pm); - renderer.render(&painter); - return pm; + QPainter painter(&pm); + renderer.render(&painter); + return pm; } -bool Utils::fuzzyEqual(qreal p_a, qreal p_b) -{ - return std::abs(p_a - p_b) < std::pow(10, -6); -} +bool Utils::fuzzyEqual(qreal p_a, qreal p_b) { return std::abs(p_a - p_b) < std::pow(10, -6); } -QString Utils::boolToString(bool p_val) -{ - return p_val ? QStringLiteral("true") : QStringLiteral("false"); +QString Utils::boolToString(bool p_val) { + return p_val ? QStringLiteral("true") : QStringLiteral("false"); } -QString Utils::intToString(int p_val, int p_width) -{ - auto str = QString::number(p_val); - if (str.size() < p_width) { - str.prepend(QString(p_width - str.size(), QLatin1Char('0'))); - } - return str; +QString Utils::intToString(int p_val, int p_width) { + auto str = QString::number(p_val); + if (str.size() < p_width) { + str.prepend(QString(p_width - str.size(), QLatin1Char('0'))); + } + return str; } -QByteArray Utils::toJsonString(const QJsonObject &p_obj) -{ - QJsonDocument doc(p_obj); - return doc.toJson(QJsonDocument::Compact); +QByteArray Utils::toJsonString(const QJsonObject &p_obj) { + QJsonDocument doc(p_obj); + return doc.toJson(QJsonDocument::Compact); } -QJsonObject Utils::fromJsonString(const QByteArray &p_data) -{ - return QJsonDocument::fromJson(p_data).object(); +QJsonObject Utils::fromJsonString(const QByteArray &p_data) { + return QJsonDocument::fromJson(p_data).object(); } -QJsonValue Utils::parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp) -{ - // abc[0] or abc. - QRegularExpression regExp(R"(^([^\[\]\s]+)(?:\[(\d+)\])?$)"); - - QJsonValue val(p_obj); - - bool valid = true; - const auto tokens = p_exp.split(QLatin1Char('.')); - for (int i = 0; i < tokens.size(); ++i) { - const auto &token = tokens[i]; - if (token.isEmpty()) { - continue; - } - - auto match = regExp.match(token); - if (!match.hasMatch()) { - valid = false; - break; - } - - const auto key = match.captured(1); - const auto obj = val.toObject(); - if (obj.contains(key)) { - val = obj.value(key); - } else { - valid = false; - break; - } - - if (!match.captured(2).isEmpty()) { - // Array. - const auto arr = val.toArray(); - int idx = match.captured(2).toInt(); - if (idx < 0 || idx >= arr.size()) { - valid = false; - break; - } - - val = arr[idx]; - } +QJsonValue Utils::parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp) { + // abc[0] or abc. + QRegularExpression regExp(R"(^([^\[\]\s]+)(?:\[(\d+)\])?$)"); + + QJsonValue val(p_obj); + + bool valid = true; + const auto tokens = p_exp.split(QLatin1Char('.')); + for (int i = 0; i < tokens.size(); ++i) { + const auto &token = tokens[i]; + if (token.isEmpty()) { + continue; } - if (!valid) { - qWarning() << "invalid expression to parse for JSON" << p_exp; - return QJsonValue(); + auto match = regExp.match(token); + if (!match.hasMatch()) { + valid = false; + break; } - return val; -} + const auto key = match.captured(1); + const auto obj = val.toObject(); + if (obj.contains(key)) { + val = obj.value(key); + } else { + valid = false; + break; + } -QColor Utils::toColor(const QString &p_color) -{ - // rgb(123, 123, 123). - QRegularExpression rgbTripleRegExp(R"(^rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)$)", QRegularExpression::CaseInsensitiveOption); - auto match = rgbTripleRegExp.match(p_color); - if (match.hasMatch()) { - return QColor(match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt()); + if (!match.captured(2).isEmpty()) { + // Array. + const auto arr = val.toArray(); + int idx = match.captured(2).toInt(); + if (idx < 0 || idx >= arr.size()) { + valid = false; + break; + } + + val = arr[idx]; } + } + + if (!valid) { + qWarning() << "invalid expression to parse for JSON" << p_exp; + return QJsonValue(); + } - return QColor(p_color); + return val; } -QStringList Utils::toLower(const QStringList &p_list) -{ - QStringList lowerList; - for (const auto &ele : p_list) { - lowerList << ele.toLower(); - } - return lowerList; +QColor Utils::toColor(const QString &p_color) { + // rgb(123, 123, 123). + QRegularExpression rgbTripleRegExp(R"(^rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)$)", + QRegularExpression::CaseInsensitiveOption); + auto match = rgbTripleRegExp.match(p_color); + if (match.hasMatch()) { + return QColor(match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt()); + } + + return QColor(p_color); +} + +QStringList Utils::toLower(const QStringList &p_list) { + QStringList lowerList; + for (const auto &ele : p_list) { + lowerList << ele.toLower(); + } + return lowerList; } diff --git a/src/utils/utils.h b/src/utils/utils.h index 1f6b72dd32..c3e92bca3e 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -1,71 +1,67 @@ #ifndef UTILS_H #define UTILS_H -#include -#include #include +#include #include +#include #if !defined(V_ASSERT) - #define V_ASSERT(cond) ((!(cond)) ? qt_assert(#cond, __FILE__, __LINE__) : qt_noop()) +#define V_ASSERT(cond) ((!(cond)) ? qt_assert(#cond, __FILE__, __LINE__) : qt_noop()) #endif // Thanks to CGAL/cgal. #ifndef __has_attribute - #define __has_attribute(x) 0 // Compatibility with non-clang compilers. +#define __has_attribute(x) 0 // Compatibility with non-clang compilers. #endif #ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 // Compatibility with non-supporting compilers. +#define __has_cpp_attribute(x) 0 // Compatibility with non-supporting compilers. #endif class QWidget; class QJsonObject; -namespace vnotex -{ - class Utils - { - public: - Utils() = delete; +namespace vnotex { +class Utils { +public: + Utils() = delete; - static void sleepWait(int p_milliseconds); + static void sleepWait(int p_milliseconds); - // Append @p_new to @p_msg as a new line. - static void appendMsg(QString &p_msg, const QString &p_new); + // Append @p_new to @p_msg as a new line. + static void appendMsg(QString &p_msg, const QString &p_new); - static QString dateTimeString(const QDateTime &p_dateTime); + static QString dateTimeString(const QDateTime &p_dateTime); - static QString dateTimeStringUniform(const QDateTime &p_dateTime); + static QString dateTimeStringUniform(const QDateTime &p_dateTime); - static QDateTime dateTimeFromStringUniform(const QString &p_str); + static QDateTime dateTimeFromStringUniform(const QString &p_str); - static QChar keyToChar(int p_key, bool p_lowerCase); + static QChar keyToChar(int p_key, bool p_lowerCase); - static QString pickAvailableFontFamily(const QStringList &p_families); + static QString pickAvailableFontFamily(const QStringList &p_families); - static QPixmap svgToPixmap(const QByteArray &p_content, - QRgb p_background, - qreal p_scaleFactor); + static QPixmap svgToPixmap(const QByteArray &p_content, QRgb p_background, qreal p_scaleFactor); - static bool fuzzyEqual(qreal p_a, qreal p_b); + static bool fuzzyEqual(qreal p_a, qreal p_b); - static QString boolToString(bool p_val); + static QString boolToString(bool p_val); - static QString intToString(int p_val, int p_width = 0); + static QString intToString(int p_val, int p_width = 0); - static QByteArray toJsonString(const QJsonObject &p_obj); + static QByteArray toJsonString(const QJsonObject &p_obj); - static QJsonObject fromJsonString(const QByteArray &p_data); + static QJsonObject fromJsonString(const QByteArray &p_data); - // Parse @p_exp into tokens and read the target value from @p_obj. - // Format: obj1.obj2.arr[2].obj3. - static QJsonValue parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp); + // Parse @p_exp into tokens and read the target value from @p_obj. + // Format: obj1.obj2.arr[2].obj3. + static QJsonValue parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp); - static QColor toColor(const QString &p_color); + static QColor toColor(const QString &p_color); - static QStringList toLower(const QStringList &p_list); - }; -} // ns vnotex + static QStringList toLower(const QStringList &p_list); +}; +} // namespace vnotex #endif // UTILS_H diff --git a/src/utils/vxurlutils.cpp b/src/utils/vxurlutils.cpp index bf39ee6c69..1587f53eb8 100644 --- a/src/utils/vxurlutils.cpp +++ b/src/utils/vxurlutils.cpp @@ -1,14 +1,14 @@ #include "vxurlutils.h" -#include #include #include +#include #include #include #include -#include #include +#include #include "pathutils.h" #include @@ -19,151 +19,150 @@ using namespace vnotex; -QString VxUrlUtils::generateVxURL(const QString &p_signature, const QString &p_filePath) -{ - return QString("#%1:%2").arg(p_signature, p_filePath); +QString VxUrlUtils::generateVxURL(const QString &p_signature, const QString &p_filePath) { + return QString("#%1:%2").arg(p_signature, p_filePath); } -QString VxUrlUtils::getSignatureFromVxURL(const QString &p_vxUrl) -{ - QString signature = p_vxUrl; - // check if file is "#signature:fileFullName" - if (signature.startsWith('#')) { - signature = signature.mid(1); // remove '#' - if (signature.contains(':')) { - signature = signature.split(':').first(); // get 'signature' - return signature; - } - } // if not 'signature', return original 'vxUrl' - return p_vxUrl; +QString VxUrlUtils::getSignatureFromVxURL(const QString &p_vxUrl) { + QString signature = p_vxUrl; + // check if file is "#signature:fileFullName" + if (signature.startsWith('#')) { + signature = signature.mid(1); // remove '#' + if (signature.contains(':')) { + signature = signature.split(':').first(); // get 'signature' + return signature; + } + } // if not 'signature', return original 'vxUrl' + return p_vxUrl; } QString VxUrlUtils::getFilePathFromVxURL(const QString &p_vxUrl) { - QString filePath = p_vxUrl; - // check if file is "#signature:fileFullName" - if (p_vxUrl.startsWith('#')) { - int colonPos = p_vxUrl.indexOf(':'); - if (colonPos != -1) { - filePath = p_vxUrl.mid(colonPos + 1); - return filePath; - } - } // if not 'filePath', return original 'vxUrl' - return p_vxUrl; + QString filePath = p_vxUrl; + // check if file is "#signature:fileFullName" + if (p_vxUrl.startsWith('#')) { + int colonPos = p_vxUrl.indexOf(':'); + if (colonPos != -1) { + filePath = p_vxUrl.mid(colonPos + 1); + return filePath; + } + } // if not 'filePath', return original 'vxUrl' + return p_vxUrl; } QString VxUrlUtils::getFileNameFromVxURL(const QString &p_vxUrl) { - QString filePath = VxUrlUtils::getFilePathFromVxURL(p_vxUrl); + QString filePath = VxUrlUtils::getFilePathFromVxURL(p_vxUrl); - return PathUtils::fileName(filePath); + return PathUtils::fileName(filePath); } -QString VxUrlUtils::getSignatureFromFilePath(const QString &p_filePath) -{ - QFileInfo fileInfo(p_filePath); - QString vxJsonPath; - QString currentFileName; - // get file's signature from vx.json - if (fileInfo.isFile()) { - QString dirPath = PathUtils::parentDirPath(p_filePath); - vxJsonPath = PathUtils::concatenateFilePath(dirPath, "vx.json"); - currentFileName = PathUtils::fileName(p_filePath); - } else if (fileInfo.isDir()) { - vxJsonPath = PathUtils::concatenateFilePath(p_filePath, "vx.json"); - currentFileName = PathUtils::fileName(p_filePath); - } else { - return QString(); +QString VxUrlUtils::getSignatureFromFilePath(const QString &p_filePath) { + QFileInfo fileInfo(p_filePath); + QString vxJsonPath; + QString currentFileName; + // get file's signature from vx.json + if (fileInfo.isFile()) { + QString dirPath = PathUtils::parentDirPath(p_filePath); + vxJsonPath = PathUtils::concatenateFilePath(dirPath, "vx.json"); + currentFileName = PathUtils::fileName(p_filePath); + } else if (fileInfo.isDir()) { + vxJsonPath = PathUtils::concatenateFilePath(p_filePath, "vx.json"); + currentFileName = PathUtils::fileName(p_filePath); + } else { + return QString(); + } + + QFile vxFile(vxJsonPath); + if (!vxFile.open(QIODevice::ReadOnly)) { + return QString(); + } + + QByteArray data = vxFile.readAll(); + vxFile.close(); + + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); + if (parseError.error != QJsonParseError::NoError) { + return QString(); + } + + QJsonObject obj = doc.object(); + QString signature; + + if (obj.contains("files") && obj["files"].isArray()) { + QJsonArray filesArray = obj["files"].toArray(); + for (const QJsonValue &fileVal : filesArray) { + QJsonObject fileObj = fileVal.toObject(); + if (fileObj["name"].toString() == currentFileName) { + signature = fileObj["signature"].toString(); + return signature; + } } + } + + if (signature.isEmpty() && obj.contains("signature")) { + signature = obj["signature"].toString(); + } - QFile vxFile(vxJsonPath); + return signature; +} + +QString VxUrlUtils::getFilePathFromSignature(const QString &p_startPath, + const QString &p_signature) { + // Find the file with the specified signature in all vx.json files under the specified directory + QDirIterator it(p_startPath, {"vx.json"}, QDir::Files | QDir::NoDotAndDotDot, + QDirIterator::Subdirectories); + + const QString rootPath = + VNoteX::getInst().getNotebookMgr().getCurrentNotebook()->getRootFolderAbsolutePath(); + const QString recycleBinPath = PathUtils::concatenateFilePath(rootPath, "vx_recycle_bin"); + + while (it.hasNext()) { + const QString vxPath = it.next(); + + // skip vx.json in recycle bin + if (vxPath.endsWith("vx_recycle_bin/vx.json") || vxPath.startsWith(recycleBinPath)) { + continue; + } + + QFile vxFile(vxPath); if (!vxFile.open(QIODevice::ReadOnly)) { - return QString(); + continue; } - QByteArray data = vxFile.readAll(); + const QByteArray data = vxFile.readAll(); vxFile.close(); QJsonParseError parseError; - QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); + const QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); if (parseError.error != QJsonParseError::NoError) { - return QString(); + continue; } - QJsonObject obj = doc.object(); + const QJsonObject json = doc.object(); QString signature; - - if (obj.contains("files") && obj["files"].isArray()) { - QJsonArray filesArray = obj["files"].toArray(); - for (const QJsonValue &fileVal : filesArray) { - QJsonObject fileObj = fileVal.toObject(); - if (fileObj["name"].toString() == currentFileName) { - signature = fileObj["signature"].toString(); - return signature; - } - } + QString fileName; + + // Find signature in files array + const auto filesArray = json.value("files").toArray(); + for (const auto &fileItem : filesArray) { + const auto fileObj = fileItem.toObject(); + if (fileObj["signature"].toString() == p_signature) { + fileName = fileObj["name"].toString(); + signature = p_signature; + break; + } } - - if (signature.isEmpty() && obj.contains("signature")) { - signature = obj["signature"].toString(); + // If not found in files array, use directory signature + if (signature.isEmpty()) { + signature = json.value("signature").toString(); } - return signature; -} - -QString VxUrlUtils::getFilePathFromSignature(const QString &p_startPath, const QString &p_signature) -{ - // Find the file with the specified signature in all vx.json files under the specified directory - QDirIterator it(p_startPath, {"vx.json"}, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); - - const QString rootPath = VNoteX::getInst().getNotebookMgr().getCurrentNotebook()->getRootFolderAbsolutePath(); - const QString recycleBinPath = PathUtils::concatenateFilePath(rootPath, "vx_recycle_bin"); - - while (it.hasNext()) { - const QString vxPath = it.next(); - - // skip vx.json in recycle bin - if (vxPath.endsWith("vx_recycle_bin/vx.json") || vxPath.startsWith(recycleBinPath)) { - continue; - } - - QFile vxFile(vxPath); - if (!vxFile.open(QIODevice::ReadOnly)) { - continue; - } - - const QByteArray data = vxFile.readAll(); - vxFile.close(); - - QJsonParseError parseError; - const QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); - if (parseError.error != QJsonParseError::NoError) { - continue; - } - - const QJsonObject json = doc.object(); - QString signature; - QString fileName; - - // Find signature in files array - const auto filesArray = json.value("files").toArray(); - for (const auto &fileItem : filesArray) { - const auto fileObj = fileItem.toObject(); - if (fileObj["signature"].toString() == p_signature) { - fileName = fileObj["name"].toString(); - signature = p_signature; - break; - } - } - // If not found in files array, use directory signature - if (signature.isEmpty()) { - signature = json.value("signature").toString(); - } - - if (!signature.isEmpty() && signature == p_signature) { - const QString dirPath = QFileInfo(vxPath).absolutePath(); - const QString fullPath = PathUtils::concatenateFilePath(dirPath, fileName); - return fullPath; - } + if (!signature.isEmpty() && signature == p_signature) { + const QString dirPath = QFileInfo(vxPath).absolutePath(); + const QString fullPath = PathUtils::concatenateFilePath(dirPath, fileName); + return fullPath; } + } - return QString(); + return QString(); } diff --git a/src/utils/vxurlutils.h b/src/utils/vxurlutils.h index 35b2e1c1f9..a6ae488d11 100644 --- a/src/utils/vxurlutils.h +++ b/src/utils/vxurlutils.h @@ -2,37 +2,35 @@ #define VXURLUTILS_H #include -#include -#include #include +#include +#include class QTemporaryFile; -namespace vnotex -{ - class VxUrlUtils - { - public: - VxUrlUtils() = delete; +namespace vnotex { +class VxUrlUtils { +public: + VxUrlUtils() = delete; - // Generate vxUrl. - static QString generateVxURL(const QString &p_signature, const QString &p_filePath); + // Generate vxUrl. + static QString generateVxURL(const QString &p_signature, const QString &p_filePath); - // Get signature from vxUrl. - static QString getSignatureFromVxURL(const QString &p_vxUrl); + // Get signature from vxUrl. + static QString getSignatureFromVxURL(const QString &p_vxUrl); - // Get file name from vxUrl. - static QString getFileNameFromVxURL(const QString &p_vxUrl); + // Get file name from vxUrl. + static QString getFileNameFromVxURL(const QString &p_vxUrl); - // Get file path from vxUrl. - static QString getFilePathFromVxURL(const QString &p_vxUrl); + // Get file path from vxUrl. + static QString getFilePathFromVxURL(const QString &p_vxUrl); - // Get signature from file path. - static QString getSignatureFromFilePath(const QString &p_filePath); + // Get signature from file path. + static QString getSignatureFromFilePath(const QString &p_filePath); - // Get file path from signature. - static QString getFilePathFromSignature(const QString &p_startPath, const QString &p_signature); - }; -} // ns vnotex + // Get file path from signature. + static QString getFilePathFromSignature(const QString &p_startPath, const QString &p_signature); +}; +} // namespace vnotex #endif // VXURLUTILS_H diff --git a/src/utils/webutils.cpp b/src/utils/webutils.cpp index 0d45d75207..a9ca9d529b 100644 --- a/src/utils/webutils.cpp +++ b/src/utils/webutils.cpp @@ -1,104 +1,102 @@ #include "webutils.h" -#include #include #include +#include #include "fileutils.h" #include "pathutils.h" -#include #include +#include using namespace vnotex; -QString WebUtils::purifyUrl(const QString &p_url) -{ - int idx = p_url.indexOf('?'); - if (idx > -1) { - return p_url.left(idx); - } +QString WebUtils::purifyUrl(const QString &p_url) { + int idx = p_url.indexOf('?'); + if (idx > -1) { + return p_url.left(idx); + } - return p_url; + return p_url; } -QString WebUtils::toDataUri(const QUrl &p_url, bool p_keepTitle) -{ - QString uri; - Q_ASSERT(!p_url.isRelative()); - QString file = p_url.isLocalFile() ? p_url.toLocalFile() : p_url.toString(); - const auto filePath = purifyUrl(file); - const QFileInfo finfo(filePath); - const QString suffix(finfo.suffix().toLower()); - if (!QImageReader::supportedImageFormats().contains(suffix.toLatin1())) { - return uri; - } +QString WebUtils::toDataUri(const QUrl &p_url, bool p_keepTitle) { + QString uri; + Q_ASSERT(!p_url.isRelative()); + QString file = p_url.isLocalFile() ? p_url.toLocalFile() : p_url.toString(); + const auto filePath = purifyUrl(file); + const QFileInfo finfo(filePath); + const QString suffix(finfo.suffix().toLower()); + if (!QImageReader::supportedImageFormats().contains(suffix.toLatin1())) { + return uri; + } - QByteArray data; - if (p_url.scheme() == "https" || p_url.scheme() == "http") { - // Download it. - data = vte::NetworkAccess::request(p_url).m_data; - } else if (finfo.exists()) { - data = FileUtils::readFile(filePath); - } + QByteArray data; + if (p_url.scheme() == "https" || p_url.scheme() == "http") { + // Download it. + data = vte::NetworkAccess::request(p_url).m_data; + } else if (finfo.exists()) { + data = FileUtils::readFile(filePath); + } - if (data.isEmpty()) { - return uri; - } + if (data.isEmpty()) { + return uri; + } + + if (suffix == "svg") { + uri = QStringLiteral("data:image/svg+xml;utf8,%1").arg(QString::fromUtf8(data)); + uri.replace('\r', "").replace('\n', ""); + + // Using unescaped '#' characters in a data URI body is deprecated and + // will be removed in M68, around July 2018. Please use '%23' instead. + uri.replace("#", "%23"); + + // Escape "'" to avoid conflict with src='...' attribute. + uri.replace("'", "%27"); - if (suffix == "svg") { - uri = QStringLiteral("data:image/svg+xml;utf8,%1").arg(QString::fromUtf8(data)); - uri.replace('\r', "").replace('\n', ""); - - // Using unescaped '#' characters in a data URI body is deprecated and - // will be removed in M68, around July 2018. Please use '%23' instead. - uri.replace("#", "%23"); - - // Escape "'" to avoid conflict with src='...' attribute. - uri.replace("'", "%27"); - - if (!p_keepTitle) { - // Remove .... - QRegularExpression reg(".*"); - reg.setPatternOptions(QRegularExpression::CaseInsensitiveOption); - uri.remove(reg); - } - } else { - uri = QStringLiteral("data:image/%1;base64,%2").arg(suffix, QString::fromUtf8(data.toBase64())); + if (!p_keepTitle) { + // Remove .... + QRegularExpression reg(".*"); + reg.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + uri.remove(reg); } + } else { + uri = QStringLiteral("data:image/%1;base64,%2").arg(suffix, QString::fromUtf8(data.toBase64())); + } - return uri; + return uri; } -QString WebUtils::copyResource(const QUrl &p_url, const QString &p_folder) -{ - Q_ASSERT(!p_url.isRelative()); +QString WebUtils::copyResource(const QUrl &p_url, const QString &p_folder) { + Q_ASSERT(!p_url.isRelative()); - QDir dir(p_folder); - if (!dir.exists()) { - dir.mkpath(p_folder); - } + QDir dir(p_folder); + if (!dir.exists()) { + dir.mkpath(p_folder); + } + + QString file = p_url.isLocalFile() ? p_url.toLocalFile() : p_url.toString(); + QFileInfo finfo(file); + auto fileName = + FileUtils::generateFileNameWithSequence(p_folder, finfo.completeBaseName(), finfo.suffix()); + QString targetFile = dir.absoluteFilePath(fileName); - QString file = p_url.isLocalFile() ? p_url.toLocalFile() : p_url.toString(); - QFileInfo finfo(file); - auto fileName = FileUtils::generateFileNameWithSequence(p_folder, finfo.completeBaseName(), finfo.suffix()); - QString targetFile = dir.absoluteFilePath(fileName); - - bool succ = true; - try { - if (p_url.scheme() == "https" || p_url.scheme() == "http") { - // Download it. - auto data = vte::NetworkAccess::request(p_url).m_data; - if (!data.isEmpty()) { - FileUtils::writeFile(targetFile, data); - } - } else if (finfo.exists()) { - // Do a copy. - FileUtils::copyFile(file, targetFile, false); - } - } catch (Exception &p_e) { - Q_UNUSED(p_e); - succ = false; + bool succ = true; + try { + if (p_url.scheme() == "https" || p_url.scheme() == "http") { + // Download it. + auto data = vte::NetworkAccess::request(p_url).m_data; + if (!data.isEmpty()) { + FileUtils::writeFile(targetFile, data); + } + } else if (finfo.exists()) { + // Do a copy. + FileUtils::copyFile(file, targetFile, false); } + } catch (Exception &p_e) { + Q_UNUSED(p_e); + succ = false; + } - return succ ? targetFile : QString(); + return succ ? targetFile : QString(); } diff --git a/src/utils/webutils.h b/src/utils/webutils.h index 9e20cf6c71..4bdc8ea11e 100644 --- a/src/utils/webutils.h +++ b/src/utils/webutils.h @@ -5,20 +5,18 @@ class QUrl; -namespace vnotex -{ - class WebUtils - { - public: - WebUtils() = delete; +namespace vnotex { +class WebUtils { +public: + WebUtils() = delete; - // Remove query in the url (?xxx). - static QString purifyUrl(const QString &p_url); + // Remove query in the url (?xxx). + static QString purifyUrl(const QString &p_url); - static QString toDataUri(const QUrl &p_url, bool p_keepTitle); + static QString toDataUri(const QUrl &p_url, bool p_keepTitle); - static QString copyResource(const QUrl &p_url, const QString &p_folder); - }; -} + static QString copyResource(const QUrl &p_url, const QString &p_folder); +}; +} // namespace vnotex #endif // WEBUTILS_H diff --git a/src/utils/widgetutils.cpp b/src/utils/widgetutils.cpp index 3414af5c3c..aae6c704be 100644 --- a/src/utils/widgetutils.cpp +++ b/src/utils/widgetutils.cpp @@ -1,505 +1,454 @@ #include "widgetutils.h" -#include -#include -#include -#include #include -#include +#include +#include #include +#include #include +#include +#include +#include +#include #include -#include -#include #include -#include -#include -#include +#include +#include #include -#include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include #include -#include -#include +#include +#include +#include #include -#include #include +#include using namespace vnotex; -void WidgetUtils::setPropertyDynamically(QWidget *p_widget, - const char *p_prop, - const QVariant &p_val) -{ - p_widget->setProperty(p_prop, p_val); - updateStyle(p_widget); +void WidgetUtils::setPropertyDynamically(QWidget *p_widget, const char *p_prop, + const QVariant &p_val) { + p_widget->setProperty(p_prop, p_val); + updateStyle(p_widget); } -void WidgetUtils::updateStyle(QWidget *p_widget) -{ - p_widget->style()->unpolish(p_widget); - p_widget->style()->polish(p_widget); - p_widget->update(); +void WidgetUtils::updateStyle(QWidget *p_widget) { + p_widget->style()->unpolish(p_widget); + p_widget->style()->polish(p_widget); + p_widget->update(); } -qreal WidgetUtils::calculateScaleFactor(const QScreen *p_screen) -{ - static qreal factor = -1; +qreal WidgetUtils::calculateScaleFactor(const QScreen *p_screen) { + static qreal factor = -1; - if (factor < 0 || p_screen) { - auto screen = p_screen ? p_screen : QGuiApplication::primaryScreen(); - factor = screen->devicePixelRatio(); - qDebug() << screen->name() << "dpi" << factor; - } + if (factor < 0 || p_screen) { + auto screen = p_screen ? p_screen : QGuiApplication::primaryScreen(); + factor = screen->devicePixelRatio(); + qDebug() << screen->name() << "dpi" << factor; + } - return factor; + return factor; } -bool WidgetUtils::isScrollBarVisible(QAbstractScrollArea *p_widget, bool p_horizontal) -{ - auto scrollBar = p_horizontal ? p_widget->horizontalScrollBar() : p_widget->verticalScrollBar(); - if (scrollBar && scrollBar->isVisible() && scrollBar->minimum() != scrollBar->maximum()) { - return true; - } +bool WidgetUtils::isScrollBarVisible(QAbstractScrollArea *p_widget, bool p_horizontal) { + auto scrollBar = p_horizontal ? p_widget->horizontalScrollBar() : p_widget->verticalScrollBar(); + if (scrollBar && scrollBar->isVisible() && scrollBar->minimum() != scrollBar->maximum()) { + return true; + } - return false; + return false; } -QSize WidgetUtils::availableScreenSize(QWidget *p_widget) -{ - return p_widget->screen()->availableGeometry().size(); +QSize WidgetUtils::availableScreenSize(QWidget *p_widget) { + return p_widget->screen()->availableGeometry().size(); } -void WidgetUtils::openUrlByDesktop(const QUrl &p_url) -{ - const auto scheme = p_url.scheme(); - if (scheme != "http" && scheme != "https" && - !(p_url.isLocalFile() && QFileInfo(p_url.toLocalFile()).isDir())) { - // Prompt for user. - int ret = MessageBoxHelper::questionYesNo(MessageBoxHelper::Warning, - MainWindow::tr("Are you sure to open link (%1)?").arg(p_url.toString()), - MainWindow::tr("Malicious link might do harm to your device."), - QString(), - nullptr); - if (ret == QMessageBox::No) { - return; - } - } - - QDesktopServices::openUrl(p_url); +void WidgetUtils::openUrlByDesktop(const QUrl &p_url) { + const auto scheme = p_url.scheme(); + if (scheme != "http" && scheme != "https" && + !(p_url.isLocalFile() && QFileInfo(p_url.toLocalFile()).isDir())) { + // Prompt for user. + int ret = MessageBoxHelper::questionYesNo( + MessageBoxHelper::Warning, + MainWindow::tr("Are you sure to open link (%1)?").arg(p_url.toString()), + MainWindow::tr("Malicious link might do harm to your device."), QString(), nullptr); + if (ret == QMessageBox::No) { + return; + } + } + + QDesktopServices::openUrl(p_url); } -bool WidgetUtils::processKeyEventLikeVi(QWidget *p_widget, - QKeyEvent *p_event, - QWidget *p_escTargetWidget) -{ - Q_ASSERT(p_widget); - - bool eventHandled = false; - int key = p_event->key(); - int modifiers = p_event->modifiers(); - if (!p_escTargetWidget) { - p_escTargetWidget = p_widget; - } +bool WidgetUtils::processKeyEventLikeVi(QWidget *p_widget, QKeyEvent *p_event, + QWidget *p_escTargetWidget) { + Q_ASSERT(p_widget); - switch (key) { - case Qt::Key_BracketLeft: - { - if (isViControlModifier(modifiers)) { - auto escEvent = new QKeyEvent(QEvent::KeyPress, - Qt::Key_Escape, - Qt::NoModifier); - QCoreApplication::postEvent(p_escTargetWidget, escEvent); - eventHandled = true; - } + bool eventHandled = false; + int key = p_event->key(); + int modifiers = p_event->modifiers(); + if (!p_escTargetWidget) { + p_escTargetWidget = p_widget; + } - break; + switch (key) { + case Qt::Key_BracketLeft: { + if (isViControlModifier(modifiers)) { + auto escEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); + QCoreApplication::postEvent(p_escTargetWidget, escEvent); + eventHandled = true; } - case Qt::Key_J: - { - if (isViControlModifier(modifiers)) { - // The event must be allocated on the heap since the post event queue will take ownership - // of the event and delete it once it has been posted. - auto downEvent = new QKeyEvent(QEvent::KeyPress, - Qt::Key_Down, - Qt::NoModifier); - QCoreApplication::postEvent(p_widget, downEvent); - eventHandled = true; - } + break; + } - break; + case Qt::Key_J: { + if (isViControlModifier(modifiers)) { + // The event must be allocated on the heap since the post event queue will take ownership + // of the event and delete it once it has been posted. + auto downEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, downEvent); + eventHandled = true; } - case Qt::Key_K: - { - if (isViControlModifier(modifiers)) { - auto upEvent = new QKeyEvent(QEvent::KeyPress, - Qt::Key_Up, - Qt::NoModifier); - QCoreApplication::postEvent(p_widget, upEvent); - eventHandled = true; - } + break; + } - break; + case Qt::Key_K: { + if (isViControlModifier(modifiers)) { + auto upEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, upEvent); + eventHandled = true; } - case Qt::Key_H: - { - if (isViControlModifier(modifiers)) { - auto upEvent = new QKeyEvent(QEvent::KeyPress, - Qt::Key_Left, - Qt::NoModifier); - QCoreApplication::postEvent(p_widget, upEvent); - eventHandled = true; - } + break; + } - break; + case Qt::Key_H: { + if (isViControlModifier(modifiers)) { + auto upEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, upEvent); + eventHandled = true; } - case Qt::Key_L: - { - if (isViControlModifier(modifiers)) { - auto upEvent = new QKeyEvent(QEvent::KeyPress, - Qt::Key_Right, - Qt::NoModifier); - QCoreApplication::postEvent(p_widget, upEvent); - eventHandled = true; - } + break; + } - break; + case Qt::Key_L: { + if (isViControlModifier(modifiers)) { + auto upEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); + QCoreApplication::postEvent(p_widget, upEvent); + eventHandled = true; } - default: - break; - } + break; + } - if (eventHandled) { - p_event->accept(); - } + default: + break; + } + + if (eventHandled) { + p_event->accept(); + } - return eventHandled; + return eventHandled; } -bool WidgetUtils::isViControlModifier(int p_modifiers) -{ +bool WidgetUtils::isViControlModifier(int p_modifiers) { #if defined(Q_OS_MACOS) || defined(Q_OS_MAC) - return p_modifiers == Qt::MetaModifier; + return p_modifiers == Qt::MetaModifier; #else - return p_modifiers == Qt::ControlModifier; + return p_modifiers == Qt::ControlModifier; #endif } -void WidgetUtils::clearActionGroup(QActionGroup *p_actGroup) -{ - auto actions = p_actGroup->actions(); - for (auto action : actions) { - p_actGroup->removeAction(action); - } +void WidgetUtils::clearActionGroup(QActionGroup *p_actGroup) { + auto actions = p_actGroup->actions(); + for (auto action : actions) { + p_actGroup->removeAction(action); + } } -void WidgetUtils::addActionShortcut(QAction *p_action, - const QString &p_shortcut, - Qt::ShortcutContext p_context) -{ - QKeySequence kseq(p_shortcut); - if (kseq.isEmpty()) { - return; - } - - p_action->setShortcut(kseq); - p_action->setShortcutContext(p_context); - p_action->setText(QStringLiteral("%1\t%2").arg(p_action->text(), kseq.toString(QKeySequence::NativeText))); +void WidgetUtils::addActionShortcut(QAction *p_action, const QString &p_shortcut, + Qt::ShortcutContext p_context) { + QKeySequence kseq(p_shortcut); + if (kseq.isEmpty()) { + return; + } + + p_action->setShortcut(kseq); + p_action->setShortcutContext(p_context); + p_action->setText( + QStringLiteral("%1\t%2").arg(p_action->text(), kseq.toString(QKeySequence::NativeText))); } -void WidgetUtils::addActionShortcutText(QAction *p_action, const QString &p_shortcut) -{ - if (p_shortcut.isEmpty()) { - return; - } +void WidgetUtils::addActionShortcutText(QAction *p_action, const QString &p_shortcut) { + if (p_shortcut.isEmpty()) { + return; + } - QKeySequence kseq(p_shortcut); - if (kseq.isEmpty()) { - return; - } + QKeySequence kseq(p_shortcut); + if (kseq.isEmpty()) { + return; + } - p_action->setText(QStringLiteral("%1\t%2").arg(p_action->text(), kseq.toString(QKeySequence::NativeText))); + p_action->setText( + QStringLiteral("%1\t%2").arg(p_action->text(), kseq.toString(QKeySequence::NativeText))); } -void WidgetUtils::addButtonShortcutText(QPushButton *p_button, const QString &p_shortcut) -{ - if (p_shortcut.isEmpty()) { - return; - } +void WidgetUtils::addButtonShortcutText(QPushButton *p_button, const QString &p_shortcut) { + if (p_shortcut.isEmpty()) { + return; + } - QKeySequence kseq(p_shortcut); - if (kseq.isEmpty()) { - return; - } + QKeySequence kseq(p_shortcut); + if (kseq.isEmpty()) { + return; + } - p_button->setText(QStringLiteral("%1 (%2)").arg(p_button->text(), kseq.toString(QKeySequence::NativeText))); + p_button->setText( + QStringLiteral("%1 (%2)").arg(p_button->text(), kseq.toString(QKeySequence::NativeText))); } -void WidgetUtils::updateSize(QWidget *p_widget) -{ - p_widget->adjustSize(); - p_widget->updateGeometry(); +void WidgetUtils::updateSize(QWidget *p_widget) { + p_widget->adjustSize(); + p_widget->updateGeometry(); } -void WidgetUtils::resizeToHideScrollBarLater(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal) -{ - QTimer::singleShot(200, p_scroll, [p_scroll, p_vertical, p_horizontal]() { - WidgetUtils::resizeToHideScrollBar(p_scroll, p_vertical, p_horizontal); - }); +void WidgetUtils::resizeToHideScrollBarLater(QScrollArea *p_scroll, bool p_vertical, + bool p_horizontal) { + QTimer::singleShot(200, p_scroll, [p_scroll, p_vertical, p_horizontal]() { + WidgetUtils::resizeToHideScrollBar(p_scroll, p_vertical, p_horizontal); + }); } -void WidgetUtils::resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal) -{ - bool changed = false; - auto parentWidget = p_scroll->parentWidget(); - - if (p_horizontal && WidgetUtils::isScrollBarVisible(p_scroll, true)) { - auto scrollBar = p_scroll->horizontalScrollBar(); - auto delta = scrollBar->maximum() - scrollBar->minimum(); - auto availableSize = WidgetUtils::availableScreenSize(p_scroll); - - if (parentWidget) { - int newWidth = parentWidget->width() + delta; - if (newWidth <= availableSize.width()) { - changed = true; - p_scroll->resize(p_scroll->width() + delta, p_scroll->height()); - auto geo = parentWidget->geometry(); - parentWidget->setGeometry(geo.x() - delta / 2, - geo.y(), - newWidth, - geo.height()); - } - } else { - int newWidth = p_scroll->width() + delta; - if (newWidth <= availableSize.width()) { - changed = true; - p_scroll->resize(newWidth, p_scroll->height()); - } - } - } - - if (p_vertical && WidgetUtils::isScrollBarVisible(p_scroll, false)) { - auto scrollBar = p_scroll->verticalScrollBar(); - auto delta = scrollBar->maximum() - scrollBar->minimum(); - auto availableSize = WidgetUtils::availableScreenSize(p_scroll); - - if (parentWidget) { - int newHeight = parentWidget->height() + delta; - if (newHeight <= availableSize.height()) { - changed = true; - p_scroll->resize(p_scroll->width(), p_scroll->height() + delta); - auto geo = parentWidget->geometry(); - parentWidget->setGeometry(geo.x(), - geo.y() - delta / 2, - geo.width(), - newHeight); - } - } else { - int newHeight = p_scroll->height() + delta; - if (newHeight <= availableSize.height()) { - changed = true; - p_scroll->resize(p_scroll->width(), newHeight); - } - } - } - - if (changed) { - p_scroll->updateGeometry(); - } +void WidgetUtils::resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal) { + bool changed = false; + auto parentWidget = p_scroll->parentWidget(); + + if (p_horizontal && WidgetUtils::isScrollBarVisible(p_scroll, true)) { + auto scrollBar = p_scroll->horizontalScrollBar(); + auto delta = scrollBar->maximum() - scrollBar->minimum(); + auto availableSize = WidgetUtils::availableScreenSize(p_scroll); + + if (parentWidget) { + int newWidth = parentWidget->width() + delta; + if (newWidth <= availableSize.width()) { + changed = true; + p_scroll->resize(p_scroll->width() + delta, p_scroll->height()); + auto geo = parentWidget->geometry(); + parentWidget->setGeometry(geo.x() - delta / 2, geo.y(), newWidth, geo.height()); + } + } else { + int newWidth = p_scroll->width() + delta; + if (newWidth <= availableSize.width()) { + changed = true; + p_scroll->resize(newWidth, p_scroll->height()); + } + } + } + + if (p_vertical && WidgetUtils::isScrollBarVisible(p_scroll, false)) { + auto scrollBar = p_scroll->verticalScrollBar(); + auto delta = scrollBar->maximum() - scrollBar->minimum(); + auto availableSize = WidgetUtils::availableScreenSize(p_scroll); + + if (parentWidget) { + int newHeight = parentWidget->height() + delta; + if (newHeight <= availableSize.height()) { + changed = true; + p_scroll->resize(p_scroll->width(), p_scroll->height() + delta); + auto geo = parentWidget->geometry(); + parentWidget->setGeometry(geo.x(), geo.y() - delta / 2, geo.width(), newHeight); + } + } else { + int newHeight = p_scroll->height() + delta; + if (newHeight <= availableSize.height()) { + changed = true; + p_scroll->resize(p_scroll->width(), newHeight); + } + } + } + + if (changed) { + p_scroll->updateGeometry(); + } } -QShortcut *WidgetUtils::createShortcut(const QString &p_shortcut, - QWidget *p_widget, - Qt::ShortcutContext p_context) -{ - QKeySequence kseq(p_shortcut); - if (kseq.isEmpty()) { - return nullptr; - } +QShortcut *WidgetUtils::createShortcut(const QString &p_shortcut, QWidget *p_widget, + Qt::ShortcutContext p_context) { + QKeySequence kseq(p_shortcut); + if (kseq.isEmpty()) { + return nullptr; + } - auto shortcut = new QShortcut(kseq, p_widget, nullptr, nullptr, p_context); - if (shortcut->key().isEmpty()) { - delete shortcut; - return nullptr; - } - return shortcut; + auto shortcut = new QShortcut(kseq, p_widget, nullptr, nullptr, p_context); + if (shortcut->key().isEmpty()) { + delete shortcut; + return nullptr; + } + return shortcut; } -bool WidgetUtils::isMetaKey(int p_key) -{ - return p_key == Qt::Key_Control - || p_key == Qt::Key_Shift - || p_key == Qt::Key_Meta +bool WidgetUtils::isMetaKey(int p_key) { + return p_key == Qt::Key_Control || p_key == Qt::Key_Shift || + p_key == Qt::Key_Meta #if defined(Q_OS_LINUX) - // For mapping Caps as Ctrl in KDE. - || p_key == Qt::Key_CapsLock + // For mapping Caps as Ctrl in KDE. + || p_key == Qt::Key_CapsLock #endif - || p_key == Qt::Key_Alt; + || p_key == Qt::Key_Alt; } -QVector WidgetUtils::getVisibleIndexes(const QListView *p_view) -{ - QVector indexes; +QVector WidgetUtils::getVisibleIndexes(const QListView *p_view) { + QVector indexes; - auto firstItem = p_view->indexAt(QPoint(0, 0)); - if (!firstItem.isValid()) { - return indexes; - } + auto firstItem = p_view->indexAt(QPoint(0, 0)); + if (!firstItem.isValid()) { + return indexes; + } - auto lastItem = p_view->indexAt(p_view->viewport()->rect().bottomLeft()); + auto lastItem = p_view->indexAt(p_view->viewport()->rect().bottomLeft()); - int firstRow = firstItem.row(); - int lastRow = lastItem.isValid() ? lastItem.row() : (p_view->model()->rowCount() - 1); - for (int i = firstRow; i <= lastRow; ++i) { - if (p_view->isRowHidden(i)) { - continue; - } - auto item = firstItem.siblingAtRow(i); - if (item.isValid()) { - indexes.append(item); - } + int firstRow = firstItem.row(); + int lastRow = lastItem.isValid() ? lastItem.row() : (p_view->model()->rowCount() - 1); + for (int i = firstRow; i <= lastRow; ++i) { + if (p_view->isRowHidden(i)) { + continue; } + auto item = firstItem.siblingAtRow(i); + if (item.isValid()) { + indexes.append(item); + } + } - return indexes; + return indexes; } -QString WidgetUtils::getMonospaceFont() -{ - static QString font; - if (font.isNull()) { - QStringList candidates; - candidates << QStringLiteral("YaHei Consolas Hybrid") - << QStringLiteral("Consolas") - << QStringLiteral("Monaco") - << QStringLiteral("Andale Mono") - << QStringLiteral("Monospace") - << QStringLiteral("Courier New"); - auto availFamilies = QFontDatabase().families(); - for (const auto &candidate : candidates) { - QString family = candidate.trimmed().toLower(); - for (auto availFamily : availFamilies) { - availFamily.remove(QRegularExpression("\\[.*\\]")); - if (family == availFamily.trimmed().toLower()) { - font = availFamily; - return font; - } - } +QString WidgetUtils::getMonospaceFont() { + static QString font; + if (font.isNull()) { + QStringList candidates; + candidates << QStringLiteral("YaHei Consolas Hybrid") << QStringLiteral("Consolas") + << QStringLiteral("Monaco") << QStringLiteral("Andale Mono") + << QStringLiteral("Monospace") << QStringLiteral("Courier New"); + auto availFamilies = QFontDatabase().families(); + for (const auto &candidate : candidates) { + QString family = candidate.trimmed().toLower(); + for (auto availFamily : availFamilies) { + availFamily.remove(QRegularExpression("\\[.*\\]")); + if (family == availFamily.trimmed().toLower()) { + font = availFamily; + return font; } - - // Fallback to current font. - font = QFont().family(); + } } - return font; + // Fallback to current font. + font = QFont().family(); + } + + return font; } -QAction *WidgetUtils::findActionByObjectName(const QList &p_actions, const QString &p_objName) -{ - for (auto act : p_actions) { - if (act->objectName() == p_objName) { - return act; - } +QAction *WidgetUtils::findActionByObjectName(const QList &p_actions, + const QString &p_objName) { + for (auto act : p_actions) { + if (act->objectName() == p_objName) { + return act; } + } - return nullptr; + return nullptr; } // Insert @p_action into @p_menu after action @p_after. -void WidgetUtils::insertActionAfter(QMenu *p_menu, QAction *p_after, QAction *p_action) -{ - p_menu->insertAction(p_after, p_action); - if (p_after) { - p_menu->removeAction(p_after); - p_menu->insertAction(p_action, p_after); - } +void WidgetUtils::insertActionAfter(QMenu *p_menu, QAction *p_after, QAction *p_action) { + p_menu->insertAction(p_after, p_action); + if (p_after) { + p_menu->removeAction(p_after); + p_menu->insertAction(p_action, p_after); + } } -void WidgetUtils::selectBaseName(QLineEdit *p_lineEdit) -{ - auto text = p_lineEdit->text(); - int dotIndex = text.lastIndexOf(QLatin1Char('.')); - p_lineEdit->setSelection(0, (dotIndex == -1) ? text.size() : dotIndex); +void WidgetUtils::selectBaseName(QLineEdit *p_lineEdit) { + auto text = p_lineEdit->text(); + int dotIndex = text.lastIndexOf(QLatin1Char('.')); + p_lineEdit->setSelection(0, (dotIndex == -1) ? text.size() : dotIndex); } -void WidgetUtils::setContentsMargins(QLayout *p_layout) -{ - // Use 0 bottom margin to align dock widgets with the content area. - p_layout->setContentsMargins(CONTENTS_MARGIN, CONTENTS_MARGIN, CONTENTS_MARGIN, 0); +void WidgetUtils::setContentsMargins(QLayout *p_layout) { + // Use 0 bottom margin to align dock widgets with the content area. + p_layout->setContentsMargins(CONTENTS_MARGIN, CONTENTS_MARGIN, CONTENTS_MARGIN, 0); } -bool WidgetUtils::distributeWidgetsOfSplitter(QSplitter *p_splitter) -{ - if (!p_splitter) { - return false; - } - - if (p_splitter->count() == 0) { - return false; - } else if (p_splitter->count() == 1) { - return true; - } - - auto sizes = p_splitter->sizes(); - int totalWidth = 0; - for (auto sz : sizes) { - totalWidth += sz; - } +bool WidgetUtils::distributeWidgetsOfSplitter(QSplitter *p_splitter) { + if (!p_splitter) { + return false; + } - int newWidth = totalWidth / sizes.size(); - if (newWidth == 0) { - return false; - } + if (p_splitter->count() == 0) { + return false; + } else if (p_splitter->count() == 1) { + return true; + } + + auto sizes = p_splitter->sizes(); + int totalWidth = 0; + for (auto sz : sizes) { + totalWidth += sz; + } + + int newWidth = totalWidth / sizes.size(); + if (newWidth == 0) { + return false; + } - bool changed = false; - for (int i = 0; i < sizes.size(); ++i) { - if (sizes[i] != newWidth) { - sizes[i] = newWidth; - changed = true; - } + bool changed = false; + for (int i = 0; i < sizes.size(); ++i) { + if (sizes[i] != newWidth) { + sizes[i] = newWidth; + changed = true; } + } - if (changed) { - p_splitter->setSizes(sizes); - return true; - } + if (changed) { + p_splitter->setSizes(sizes); + return true; + } - return false; + return false; } -void WidgetUtils::clearLayout(QFormLayout *p_layout) -{ - for (int i = p_layout->rowCount() - 1; i >= 0; --i) { - p_layout->removeRow(i); - } +void WidgetUtils::clearLayout(QFormLayout *p_layout) { + for (int i = p_layout->rowCount() - 1; i >= 0; --i) { + p_layout->removeRow(i); + } } // Different from QWidget::isAncestorOf(): unnecessary to be within the same window. -bool WidgetUtils::isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child) -{ - Q_ASSERT(p_widget); +bool WidgetUtils::isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child) { + Q_ASSERT(p_widget); - if (!p_child) { - return false; - } + if (!p_child) { + return false; + } - const QWidget *pa = p_child; - while (pa) { - if (pa == p_widget) { - return true; - } - pa = pa->parentWidget(); + const QWidget *pa = p_child; + while (pa) { + if (pa == p_widget) { + return true; } + pa = pa->parentWidget(); + } - return false; + return false; } diff --git a/src/utils/widgetutils.h b/src/utils/widgetutils.h index 21b4959aa1..422f576a02 100644 --- a/src/utils/widgetutils.h +++ b/src/utils/widgetutils.h @@ -1,12 +1,12 @@ #ifndef WIDGETUTILS_H #define WIDGETUTILS_H -#include -#include +#include #include -#include #include -#include +#include +#include +#include class QWidget; class QAbstractScrollArea; @@ -24,80 +24,75 @@ class QSplitter; class QScreen; class QFormLayout; -namespace vnotex -{ - class WidgetUtils - { - public: - WidgetUtils() = delete; +namespace vnotex { +class WidgetUtils { +public: + WidgetUtils() = delete; - static void setPropertyDynamically(QWidget *p_widget, - const char *p_prop, - const QVariant &p_val = QVariant()); + static void setPropertyDynamically(QWidget *p_widget, const char *p_prop, + const QVariant &p_val = QVariant()); - static void updateStyle(QWidget *p_widget); + static void updateStyle(QWidget *p_widget); - static qreal calculateScaleFactor(const QScreen *p_screen = nullptr); + static qreal calculateScaleFactor(const QScreen *p_screen = nullptr); - static bool isScrollBarVisible(QAbstractScrollArea *p_widget, bool p_horizontal); + static bool isScrollBarVisible(QAbstractScrollArea *p_widget, bool p_horizontal); - static QSize availableScreenSize(QWidget *p_widget); + static QSize availableScreenSize(QWidget *p_widget); - static void openUrlByDesktop(const QUrl &p_url); + static void openUrlByDesktop(const QUrl &p_url); - // Given @p_event, try to process it by injecting proper event instead if it - // triggers Vi operation. - // Return true if @p_event is handled properly. - // @p_escTargetWidget: the widget to accept the ESC event. - static bool processKeyEventLikeVi(QWidget *p_widget, - QKeyEvent *p_event, - QWidget *p_escTargetWidget = nullptr); + // Given @p_event, try to process it by injecting proper event instead if it + // triggers Vi operation. + // Return true if @p_event is handled properly. + // @p_escTargetWidget: the widget to accept the ESC event. + static bool processKeyEventLikeVi(QWidget *p_widget, QKeyEvent *p_event, + QWidget *p_escTargetWidget = nullptr); - static bool isViControlModifier(int p_modifiers); + static bool isViControlModifier(int p_modifiers); - static bool isMetaKey(int p_key); + static bool isMetaKey(int p_key); - static void clearActionGroup(QActionGroup *p_actGroup); + static void clearActionGroup(QActionGroup *p_actGroup); - static void addActionShortcut(QAction *p_action, - const QString &p_shortcut, - Qt::ShortcutContext p_context = Qt::WindowShortcut); + static void addActionShortcut(QAction *p_action, const QString &p_shortcut, + Qt::ShortcutContext p_context = Qt::WindowShortcut); - // Just add a shortcut text hint to the action. - static void addActionShortcutText(QAction *p_action, const QString &p_shortcut); + // Just add a shortcut text hint to the action. + static void addActionShortcutText(QAction *p_action, const QString &p_shortcut); - static void addButtonShortcutText(QPushButton *p_button, const QString &p_shortcut); + static void addButtonShortcutText(QPushButton *p_button, const QString &p_shortcut); - static QShortcut *createShortcut(const QString &p_shortcut, - QWidget *p_widget, - Qt::ShortcutContext p_context = Qt::WindowShortcut); + static QShortcut *createShortcut(const QString &p_shortcut, QWidget *p_widget, + Qt::ShortcutContext p_context = Qt::WindowShortcut); - static void updateSize(QWidget *p_widget); + static void updateSize(QWidget *p_widget); - static void resizeToHideScrollBarLater(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal); + static void resizeToHideScrollBarLater(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal); - static QVector getVisibleIndexes(const QListView *p_view); + static QVector getVisibleIndexes(const QListView *p_view); - static QString getMonospaceFont(); + static QString getMonospaceFont(); - static QAction *findActionByObjectName(const QList &p_actions, const QString &p_objName); + static QAction *findActionByObjectName(const QList &p_actions, + const QString &p_objName); - static void insertActionAfter(QMenu *p_menu, QAction *p_after, QAction *p_action); + static void insertActionAfter(QMenu *p_menu, QAction *p_after, QAction *p_action); - // Select the base name part of the line edit content. - static void selectBaseName(QLineEdit *p_lineEdit); + // Select the base name part of the line edit content. + static void selectBaseName(QLineEdit *p_lineEdit); - static void setContentsMargins(QLayout *p_layout); + static void setContentsMargins(QLayout *p_layout); - static bool distributeWidgetsOfSplitter(QSplitter *p_splitter); + static bool distributeWidgetsOfSplitter(QSplitter *p_splitter); - static void clearLayout(QFormLayout *p_layout); + static void clearLayout(QFormLayout *p_layout); - static bool isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child); + static bool isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child); - private: - static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal); - }; -} // ns vnotex +private: + static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal); +}; +} // namespace vnotex #endif // WIDGETUTILS_H diff --git a/src/widgets/attachmentdragdropareaindicator.cpp b/src/widgets/attachmentdragdropareaindicator.cpp index 5156b7222c..0df3e5156a 100644 --- a/src/widgets/attachmentdragdropareaindicator.cpp +++ b/src/widgets/attachmentdragdropareaindicator.cpp @@ -2,8 +2,8 @@ #include #include -#include #include +#include #include "viewwindow.h" #include @@ -14,33 +14,28 @@ using namespace vnotex; AttachmentDragDropAreaIndicator::AttachmentDragDropAreaIndicator(ViewWindow *p_viewWindow) - : m_viewWindow(p_viewWindow) -{ -} + : m_viewWindow(p_viewWindow) {} -bool AttachmentDragDropAreaIndicator::handleDragEnterEvent(QDragEnterEvent *p_event) -{ - if (isAccepted(p_event)) { - p_event->acceptProposedAction(); - return true; - } - return false; +bool AttachmentDragDropAreaIndicator::handleDragEnterEvent(QDragEnterEvent *p_event) { + if (isAccepted(p_event)) { + p_event->acceptProposedAction(); + return true; + } + return false; } -bool AttachmentDragDropAreaIndicator::handleDropEvent(QDropEvent *p_event) -{ - return UrlDragDropUtils::handleDropEvent(p_event, [this](const QStringList &p_files) { - auto buffer = m_viewWindow->getBuffer(); - Q_ASSERT(buffer && buffer->isAttachmentSupported()); - auto files = buffer->addAttachment(QString(), p_files); - if (!files.isEmpty()) { - VNoteX::getInst().showStatusMessageShort( - ViewWindow::tr("Attached %n file(s)", "", files.size())); - } - }); +bool AttachmentDragDropAreaIndicator::handleDropEvent(QDropEvent *p_event) { + return UrlDragDropUtils::handleDropEvent(p_event, [this](const QStringList &p_files) { + auto buffer = m_viewWindow->getBuffer(); + Q_ASSERT(buffer && buffer->isAttachmentSupported()); + auto files = buffer->addAttachment(QString(), p_files); + if (!files.isEmpty()) { + VNoteX::getInst().showStatusMessageShort( + ViewWindow::tr("Attached %n file(s)", "", files.size())); + } + }); } -bool AttachmentDragDropAreaIndicator::isAccepted(const QDragEnterEvent *p_event) -{ - return p_event->mimeData()->hasFormat(QStringLiteral("text/uri-list")); +bool AttachmentDragDropAreaIndicator::isAccepted(const QDragEnterEvent *p_event) { + return p_event->mimeData()->hasFormat(QStringLiteral("text/uri-list")); } diff --git a/src/widgets/attachmentdragdropareaindicator.h b/src/widgets/attachmentdragdropareaindicator.h index 71a53b64be..d004e13bbb 100644 --- a/src/widgets/attachmentdragdropareaindicator.h +++ b/src/widgets/attachmentdragdropareaindicator.h @@ -3,24 +3,22 @@ #include "dragdropareaindicator.h" -namespace vnotex -{ - class ViewWindow; +namespace vnotex { +class ViewWindow; - class AttachmentDragDropAreaIndicator : public DragDropAreaIndicatorInterface - { - public: - AttachmentDragDropAreaIndicator(ViewWindow *p_viewWindow); +class AttachmentDragDropAreaIndicator : public DragDropAreaIndicatorInterface { +public: + AttachmentDragDropAreaIndicator(ViewWindow *p_viewWindow); - bool handleDragEnterEvent(QDragEnterEvent *p_event) Q_DECL_OVERRIDE; + bool handleDragEnterEvent(QDragEnterEvent *p_event) Q_DECL_OVERRIDE; - bool handleDropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE; + bool handleDropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE; - static bool isAccepted(const QDragEnterEvent *p_event); + static bool isAccepted(const QDragEnterEvent *p_event); - private: - ViewWindow *m_viewWindow = nullptr; - }; -} +private: + ViewWindow *m_viewWindow = nullptr; +}; +} // namespace vnotex #endif // ATTACHMENTDRAGDROPAREAINDICATOR_H diff --git a/src/widgets/attachmentpopup.cpp b/src/widgets/attachmentpopup.cpp index a51e4658d3..d7de4337e5 100644 --- a/src/widgets/attachmentpopup.cpp +++ b/src/widgets/attachmentpopup.cpp @@ -1,358 +1,331 @@ #include "attachmentpopup.h" +#include #include -#include +#include +#include #include #include #include -#include -#include -#include +#include #include #include "propertydefs.h" +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include +#include +#include "dialogs/filepropertiesdialog.h" +#include "fileopenparameters.h" #include "filesystemviewer.h" #include "messageboxhelper.h" -#include "fileopenparameters.h" +#include #include #include -#include -#include "dialogs/filepropertiesdialog.h" using namespace vnotex; AttachmentPopup::AttachmentPopup(QToolButton *p_btn, QWidget *p_parent) - : ButtonPopup(p_btn, p_parent) -{ - setupUI(); - - connect(this, &QMenu::aboutToShow, - this, [this]() { - Q_ASSERT(m_buffer); - if (m_needUpdateAttachmentFolder) { - setRootFolder(m_buffer->getAttachmentFolderPath()); - } - - m_viewer->setFocus(); - }); -} + : ButtonPopup(p_btn, p_parent) { + setupUI(); -void AttachmentPopup::setupUI() -{ - QWidget *widget = new QWidget{}; - auto mainLayout = new QVBoxLayout(widget); - - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - - auto buttonsLayout = new QHBoxLayout(); - - { - // Add. - auto addBtn = createButton(); - - auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("add.svg"))), - tr("Add"), - addBtn); - connect(act, &QAction::triggered, - this, [this]() { - if (checkRootFolderAndSingleSelection()) { - // Get dest folder path before other dialogs. - const auto destFolderPath = getDestFolderPath(); - - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - auto files = QFileDialog::getOpenFileNames(nullptr, - tr("Select Files As Attachments"), - sessionConfig.getExternalMediaDefaultPath()); - if (files.isEmpty()) { - return; - } - - sessionConfig.setExternalMediaDefaultPath(QFileInfo(files[0]).path()); - - addAttachments(destFolderPath, files); - } - }); - addBtn->setDefaultAction(act); - buttonsLayout->addWidget(addBtn); + connect(this, &QMenu::aboutToShow, this, [this]() { + Q_ASSERT(m_buffer); + if (m_needUpdateAttachmentFolder) { + setRootFolder(m_buffer->getAttachmentFolderPath()); } - { - // New File. - auto newFileBtn = createButton(); - - auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("new_file.svg"))), - tr("New File"), - newFileBtn); - connect(act, &QAction::triggered, - this, [this]() { - if (checkRootFolderAndSingleSelection()) { - // Get dest folder path before other dialogs. - const auto destFolderPath = getDestFolderPath(); - auto name = QInputDialog::getText(this, - tr("New Attachment"), - tr("File name:")); - if (!name.isEmpty()) { - newAttachmentFile(destFolderPath, name); - } - } - }); - newFileBtn->setDefaultAction(act); - buttonsLayout->addWidget(newFileBtn); - } + m_viewer->setFocus(); + }); +} - { - // New Folder. - auto newFolderBtn = createButton(); - - auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("new_folder.svg"))), - tr("New Folder"), - newFolderBtn); - connect(act, &QAction::triggered, - this, [this]() { - if (checkRootFolderAndSingleSelection()) { - // Get dest folder path before other dialogs. - const auto destFolderPath = getDestFolderPath(); - auto name = QInputDialog::getText(this, - tr("New Attachment"), - tr("Folder name:")); - if (!name.isEmpty()) { - newAttachmentFolder(destFolderPath, name); - } - } - }); - newFolderBtn->setDefaultAction(act); - buttonsLayout->addWidget(newFolderBtn); - } +void AttachmentPopup::setupUI() { + QWidget *widget = new QWidget{}; + auto mainLayout = new QVBoxLayout(widget); - { - // Open folder. - auto openFolderBtn = createButton(); - - auto act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("open_folder.svg"))), - tr("Open Folder"), - openFolderBtn); - connect(act, &QAction::triggered, - this, [this]() { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(m_viewer->rootPath())); - }); - openFolderBtn->setDefaultAction(act); - buttonsLayout->addWidget(openFolderBtn); - } + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - buttonsLayout->addStretch(); - - { - // 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::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); - } + auto buttonsLayout = new QHBoxLayout(); - { - // 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; - } - } - - if (!skip) { - paths << selectedPaths[i]; - } - } - - m_buffer->removeAttachment(paths); - }); - m_deleteBtn->setDefaultAction(act); - buttonsLayout->addWidget(m_deleteBtn); - } + { + // Add. + auto addBtn = createButton(); - { - // 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); - } + auto act = new QAction( + IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("add.svg"))), + tr("Add"), addBtn); + connect(act, &QAction::triggered, this, [this]() { + if (checkRootFolderAndSingleSelection()) { + // Get dest folder path before other dialogs. + const auto destFolderPath = getDestFolderPath(); - { - // 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); - } + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + auto files = QFileDialog::getOpenFileNames(nullptr, tr("Select Files As Attachments"), + sessionConfig.getExternalMediaDefaultPath()); + if (files.isEmpty()) { + return; + } + + sessionConfig.setExternalMediaDefaultPath(QFileInfo(files[0]).path()); + + addAttachments(destFolderPath, files); + } + }); + addBtn->setDefaultAction(act); + buttonsLayout->addWidget(addBtn); + } + + { + // New File. + auto newFileBtn = createButton(); + + auto act = new QAction( + IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile(QStringLiteral("new_file.svg"))), + tr("New File"), newFileBtn); + connect(act, &QAction::triggered, this, [this]() { + if (checkRootFolderAndSingleSelection()) { + // Get dest folder path before other dialogs. + const auto destFolderPath = getDestFolderPath(); + auto name = QInputDialog::getText(this, tr("New Attachment"), tr("File name:")); + if (!name.isEmpty()) { + newAttachmentFile(destFolderPath, name); + } + } + }); + newFileBtn->setDefaultAction(act); + buttonsLayout->addWidget(newFileBtn); + } + + { + // New Folder. + auto newFolderBtn = createButton(); + + auto act = new QAction(IconUtils::fetchIconWithDisabledState( + themeMgr.getIconFile(QStringLiteral("new_folder.svg"))), + tr("New Folder"), newFolderBtn); + connect(act, &QAction::triggered, this, [this]() { + if (checkRootFolderAndSingleSelection()) { + // Get dest folder path before other dialogs. + const auto destFolderPath = getDestFolderPath(); + auto name = QInputDialog::getText(this, tr("New Attachment"), tr("Folder name:")); + if (!name.isEmpty()) { + newAttachmentFolder(destFolderPath, name); + } + } + }); + newFolderBtn->setDefaultAction(act); + buttonsLayout->addWidget(newFolderBtn); + } + + { + // Open folder. + auto openFolderBtn = createButton(); + + auto act = new QAction(IconUtils::fetchIconWithDisabledState( + themeMgr.getIconFile(QStringLiteral("open_folder.svg"))), + tr("Open Folder"), openFolderBtn); + connect(act, &QAction::triggered, this, + [this]() { WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(m_viewer->rootPath())); }); + openFolderBtn->setDefaultAction(act); + buttonsLayout->addWidget(openFolderBtn); + } + + buttonsLayout->addStretch(); + + { + // 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::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); + } + + { + // 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; + } + } + + if (!skip) { + paths << selectedPaths[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); + mainLayout->addLayout(buttonsLayout); - m_viewer = new FileSystemViewer(this); - connect(m_viewer, &FileSystemViewer::selectionChanged, - this, &AttachmentPopup::updateButtonsState); + m_viewer = new FileSystemViewer(this); + connect(m_viewer, &FileSystemViewer::selectionChanged, this, + &AttachmentPopup::updateButtonsState); - updateButtonsState(); + updateButtonsState(); - mainLayout->addWidget(m_viewer); + mainLayout->addWidget(m_viewer); - widget->setMinimumSize(320, 384); + widget->setMinimumSize(320, 384); - addWidget(widget); + addWidget(widget); } -QToolButton *AttachmentPopup::createButton() -{ - auto btn = new QToolButton(this); - btn->setProperty(PropertyDefs::c_actionToolButton, true); - return btn; +QToolButton *AttachmentPopup::createButton() { + auto btn = new QToolButton(this); + btn->setProperty(PropertyDefs::c_actionToolButton, true); + return btn; } -bool AttachmentPopup::checkRootFolderAndSingleSelection() -{ - const auto rootPath = m_viewer->rootPath(); - bool ret = !rootPath.isEmpty() && m_viewer->selectedCount() <= 1; - if (!ret) { - MessageBoxHelper::notify(MessageBoxHelper::Information, - tr("Please select one directory to continue."), - this); - } - return ret; +bool AttachmentPopup::checkRootFolderAndSingleSelection() { + const auto rootPath = m_viewer->rootPath(); + bool ret = !rootPath.isEmpty() && m_viewer->selectedCount() <= 1; + if (!ret) { + MessageBoxHelper::notify(MessageBoxHelper::Information, + tr("Please select one directory to continue."), this); + } + return ret; } -void AttachmentPopup::setRootFolder(const QString &p_folderPath) -{ - m_viewer->setRootPath(p_folderPath); - m_needUpdateAttachmentFolder = false; +void AttachmentPopup::setRootFolder(const QString &p_folderPath) { + m_viewer->setRootPath(p_folderPath); + m_needUpdateAttachmentFolder = false; } -void AttachmentPopup::setBuffer(Buffer *p_buffer) -{ - if (m_buffer == p_buffer) { - return; - } +void AttachmentPopup::setBuffer(Buffer *p_buffer) { + if (m_buffer == p_buffer) { + return; + } - m_buffer = p_buffer; - m_needUpdateAttachmentFolder = true; + m_buffer = p_buffer; + m_needUpdateAttachmentFolder = true; } -QString AttachmentPopup::getDestFolderPath() const -{ - const auto selectedPaths = m_viewer->getSelectedPaths(); - Q_ASSERT(selectedPaths.size() <= 1); - QString destFolderPath; - if (selectedPaths.isEmpty()) { - destFolderPath = m_viewer->rootPath(); - } else { - destFolderPath = PathUtils::dirOrParentDirPath(selectedPaths[0]); - } - return destFolderPath; +QString AttachmentPopup::getDestFolderPath() const { + const auto selectedPaths = m_viewer->getSelectedPaths(); + Q_ASSERT(selectedPaths.size() <= 1); + QString destFolderPath; + if (selectedPaths.isEmpty()) { + destFolderPath = m_viewer->rootPath(); + } else { + destFolderPath = PathUtils::dirOrParentDirPath(selectedPaths[0]); + } + return destFolderPath; } -void AttachmentPopup::addAttachments(const QString &p_destFolderPath, const QStringList &p_files) -{ - auto files = m_buffer->addAttachment(p_destFolderPath, p_files); - showPopupLater(files); +void AttachmentPopup::addAttachments(const QString &p_destFolderPath, const QStringList &p_files) { + auto files = m_buffer->addAttachment(p_destFolderPath, p_files); + showPopupLater(files); } -void AttachmentPopup::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) -{ - auto file = m_buffer->newAttachmentFile(p_destFolderPath, p_name); - showPopupLater(QStringList() << file); +void AttachmentPopup::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) { + auto file = m_buffer->newAttachmentFile(p_destFolderPath, p_name); + showPopupLater(QStringList() << file); } -void AttachmentPopup::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) -{ - auto folder = m_buffer->newAttachmentFolder(p_destFolderPath, p_name); - showPopupLater(QStringList() << folder); +void AttachmentPopup::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) { + auto folder = m_buffer->newAttachmentFolder(p_destFolderPath, p_name); + showPopupLater(QStringList() << folder); } -void AttachmentPopup::showPopupLater(const QStringList &p_pathsToSelect) -{ - QTimer::singleShot(250, this, [this, p_pathsToSelect]() { - m_viewer->scrollToAndSelect(p_pathsToSelect); - m_button->showMenu(); - }); +void AttachmentPopup::showPopupLater(const QStringList &p_pathsToSelect) { + QTimer::singleShot(250, this, [this, p_pathsToSelect]() { + m_viewer->scrollToAndSelect(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); +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); } diff --git a/src/widgets/attachmentpopup.h b/src/widgets/attachmentpopup.h index a90edb56e3..cb8b32acfb 100644 --- a/src/widgets/attachmentpopup.h +++ b/src/widgets/attachmentpopup.h @@ -3,53 +3,51 @@ #include "buttonpopup.h" -namespace vnotex -{ - class FileSystemViewer; - class Buffer; +namespace vnotex { +class FileSystemViewer; +class Buffer; - class AttachmentPopup : public ButtonPopup - { - Q_OBJECT - public: - AttachmentPopup(QToolButton *p_btn, QWidget *p_parent = nullptr); +class AttachmentPopup : public ButtonPopup { + Q_OBJECT +public: + AttachmentPopup(QToolButton *p_btn, QWidget *p_parent = nullptr); - void setBuffer(Buffer *p_buffer); + void setBuffer(Buffer *p_buffer); - private slots: - void updateButtonsState(); +private slots: + void updateButtonsState(); - private: - void setupUI(); +private: + void setupUI(); - QToolButton *createButton(); + QToolButton *createButton(); - bool checkRootFolderAndSingleSelection(); + bool checkRootFolderAndSingleSelection(); - void addAttachments(const QString &p_destFolderPath, const QStringList &p_files); + void addAttachments(const QString &p_destFolderPath, const QStringList &p_files); - void setRootFolder(const QString &p_folderPath); + void setRootFolder(const QString &p_folderPath); - QString getDestFolderPath() const; + QString getDestFolderPath() const; - void newAttachmentFile(const QString &p_destFolderPath, const QString &p_name); + void newAttachmentFile(const QString &p_destFolderPath, const QString &p_name); - void newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name); + void newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name); - void showPopupLater(const QStringList &p_pathsToSelect = QStringList()); + void showPopupLater(const QStringList &p_pathsToSelect = QStringList()); - Buffer *m_buffer = nullptr; + Buffer *m_buffer = nullptr; - // Managed by QObject. - FileSystemViewer *m_viewer = nullptr; + // Managed by QObject. + FileSystemViewer *m_viewer = nullptr; - QToolButton *m_openBtn = nullptr; - QToolButton *m_deleteBtn = nullptr; - QToolButton *m_copyPathBtn = nullptr; - QToolButton *m_propertiesBtn = nullptr; + QToolButton *m_openBtn = nullptr; + QToolButton *m_deleteBtn = nullptr; + QToolButton *m_copyPathBtn = nullptr; + QToolButton *m_propertiesBtn = nullptr; - bool m_needUpdateAttachmentFolder = true; - }; -} + bool m_needUpdateAttachmentFolder = true; +}; +} // namespace vnotex #endif // ATTACHMENTPOPUP_H diff --git a/src/widgets/biaction.cpp b/src/widgets/biaction.cpp index e2b81ba656..92ea57a55e 100644 --- a/src/widgets/biaction.cpp +++ b/src/widgets/biaction.cpp @@ -1,102 +1,83 @@ #include "biaction.h" -#include #include +#include #include #include using namespace vnotex; -BiAction::BiAction(const QIcon &p_icon, - const QString &p_text, - const QIcon &p_altIcon, - const QString &p_altText, - QObject *p_parent) - : QAction(p_icon, p_text, p_parent) -{ - m_resources[State::Default].m_icon = p_icon; - m_resources[State::Default].m_text = p_text; - - m_resources[State::Alternative].m_icon = p_altIcon; - m_resources[State::Alternative].m_text = p_altText; - - connect(this, &QAction::triggered, - this, [this]() { - toggleState(); - }); -} +BiAction::BiAction(const QIcon &p_icon, const QString &p_text, const QIcon &p_altIcon, + const QString &p_altText, QObject *p_parent) + : QAction(p_icon, p_text, p_parent) { + m_resources[State::Default].m_icon = p_icon; + m_resources[State::Default].m_text = p_text; -BiAction::State BiAction::previousState() const -{ - if (m_state == State::Default) { - return State::Alternative; - } else { - return State::Default; - } + m_resources[State::Alternative].m_icon = p_altIcon; + m_resources[State::Alternative].m_text = p_altText; + + connect(this, &QAction::triggered, this, [this]() { toggleState(); }); } -BiAction::State BiAction::state() const -{ - return m_state; +BiAction::State BiAction::previousState() const { + if (m_state == State::Default) { + return State::Alternative; + } else { + return State::Default; + } } -void BiAction::setState(BiAction::State p_state) -{ - if (p_state == m_state) { - return; - } +BiAction::State BiAction::state() const { return m_state; } - const QString preText = m_resources[m_state].m_text; - auto preMenu = m_resources[m_state].m_menu; +void BiAction::setState(BiAction::State p_state) { + if (p_state == m_state) { + return; + } - m_state = p_state; + const QString preText = m_resources[m_state].m_text; + auto preMenu = m_resources[m_state].m_menu; - auto &resource = m_resources[m_state]; - if (!resource.m_icon.isNull()) { - setIcon(resource.m_icon); - } + m_state = p_state; - // Use replacement instead since there may exist shortcut text. - setText(text().replace(preText, resource.m_text)); + auto &resource = m_resources[m_state]; + if (!resource.m_icon.isNull()) { + setIcon(resource.m_icon); + } - setMenu(resource.m_menu); - if (resource.m_menu) { - resource.m_menu->setEnabled(true); - } + // Use replacement instead since there may exist shortcut text. + setText(text().replace(preText, resource.m_text)); - if (preMenu) { - preMenu->setEnabled(false); - } + setMenu(resource.m_menu); + if (resource.m_menu) { + resource.m_menu->setEnabled(true); + } - updateToolButtonPopupMode(); -} + if (preMenu) { + preMenu->setEnabled(false); + } -void BiAction::setStateMenu(BiAction::State p_state, QMenu *p_menu) -{ - m_resources[p_state].m_menu = p_menu; - if (m_state == p_state) { - setMenu(m_resources[m_state].m_menu); - updateToolButtonPopupMode(); - } + updateToolButtonPopupMode(); } -void BiAction::toggleState() -{ - setState(previousState()); +void BiAction::setStateMenu(BiAction::State p_state, QMenu *p_menu) { + m_resources[p_state].m_menu = p_menu; + if (m_state == p_state) { + setMenu(m_resources[m_state].m_menu); + updateToolButtonPopupMode(); + } } -void BiAction::setToolButtonForAction(QToolButton *p_btn) -{ - m_toolBtn = p_btn; - updateToolButtonPopupMode(); +void BiAction::toggleState() { setState(previousState()); } + +void BiAction::setToolButtonForAction(QToolButton *p_btn) { + m_toolBtn = p_btn; + updateToolButtonPopupMode(); } -void BiAction::updateToolButtonPopupMode() -{ - if (m_toolBtn) { - m_toolBtn->setPopupMode(menu() ? QToolButton::MenuButtonPopup - : QToolButton::DelayedPopup); - WidgetUtils::updateStyle(m_toolBtn); - } +void BiAction::updateToolButtonPopupMode() { + if (m_toolBtn) { + m_toolBtn->setPopupMode(menu() ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup); + WidgetUtils::updateStyle(m_toolBtn); + } } diff --git a/src/widgets/biaction.h b/src/widgets/biaction.h index f379859cbe..7c3246ec12 100644 --- a/src/widgets/biaction.h +++ b/src/widgets/biaction.h @@ -5,56 +5,45 @@ class QToolButton; -namespace vnotex -{ - // Action with two states. - class BiAction : public QAction - { - Q_OBJECT - public: - enum State - { - Default, - Alternative, - Max - }; +namespace vnotex { +// Action with two states. +class BiAction : public QAction { + Q_OBJECT +public: + enum State { Default, Alternative, Max }; - BiAction(const QIcon &p_icon, - const QString &p_text, - const QIcon &p_altIcon, - const QString &p_altText, - QObject *p_parent = nullptr); + BiAction(const QIcon &p_icon, const QString &p_text, const QIcon &p_altIcon, + const QString &p_altText, QObject *p_parent = nullptr); - BiAction::State previousState() const; - BiAction::State state() const; - void setState(BiAction::State p_state); + BiAction::State previousState() const; + BiAction::State state() const; + void setState(BiAction::State p_state); - void toggleState(); + void toggleState(); - void setStateMenu(BiAction::State p_state, QMenu *p_menu); + void setStateMenu(BiAction::State p_state, QMenu *p_menu); - void setToolButtonForAction(QToolButton *p_btn); + void setToolButtonForAction(QToolButton *p_btn); - private: - struct StateResource - { - QIcon m_icon; +private: + struct StateResource { + QIcon m_icon; - QString m_text; + QString m_text; - QMenu *m_menu = nullptr; - }; + QMenu *m_menu = nullptr; + }; - void updateToolButtonPopupMode(); + void updateToolButtonPopupMode(); - State m_state = State::Default; + State m_state = State::Default; - StateResource m_resources[State::Max]; + StateResource m_resources[State::Max]; - // Managed by QObject. - // We will use this to control the menu indicator of the button. - QToolButton *m_toolBtn = nullptr; - }; -} + // Managed by QObject. + // We will use this to control the menu indicator of the button. + QToolButton *m_toolBtn = nullptr; +}; +} // namespace vnotex #endif // BIACTION_H diff --git a/src/widgets/buttonpopup.cpp b/src/widgets/buttonpopup.cpp index 5527de72eb..7fedc06646 100644 --- a/src/widgets/buttonpopup.cpp +++ b/src/widgets/buttonpopup.cpp @@ -1,38 +1,33 @@ #include "buttonpopup.h" -#include #include +#include #include using namespace vnotex; -ButtonPopup::ButtonPopup(QToolButton *p_btn, QWidget *p_parent) - : QMenu(p_parent), - m_button(p_btn) -{ +ButtonPopup::ButtonPopup(QToolButton *p_btn, QWidget *p_parent) : QMenu(p_parent), m_button(p_btn) { #if defined(Q_OS_MACOS) || defined(Q_OS_MAC) - // Qt::Popup on macOS does not work well with input method. - setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); - setWindowModality(Qt::ApplicationModal); + // Qt::Popup on macOS does not work well with input method. + setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); + setWindowModality(Qt::ApplicationModal); #endif } -void ButtonPopup::keyPressEvent(QKeyEvent *p_event) -{ - const int key = p_event->key(); - if (key == Qt::Key_Return || key == Qt::Key_Enter) { - // Swallow Enter/Return key here to avoid hiding the popup. - p_event->accept(); - return; - } - QMenu::keyPressEvent(p_event); +void ButtonPopup::keyPressEvent(QKeyEvent *p_event) { + const int key = p_event->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter) { + // Swallow Enter/Return key here to avoid hiding the popup. + p_event->accept(); + return; + } + QMenu::keyPressEvent(p_event); } -void ButtonPopup::addWidget(QWidget *p_widget) -{ - auto act = new QWidgetAction(this); - // @act will own @p_widget. - act->setDefaultWidget(p_widget); - addAction(act); +void ButtonPopup::addWidget(QWidget *p_widget) { + auto act = new QWidgetAction(this); + // @act will own @p_widget. + act->setDefaultWidget(p_widget); + addAction(act); } diff --git a/src/widgets/buttonpopup.h b/src/widgets/buttonpopup.h index 4417080371..cf0b406690 100644 --- a/src/widgets/buttonpopup.h +++ b/src/widgets/buttonpopup.h @@ -5,23 +5,21 @@ class QToolButton; -namespace vnotex -{ - // Base class for the popup of a QToolButton. - class ButtonPopup : public QMenu - { - Q_OBJECT - public: - ButtonPopup(QToolButton *p_btn, QWidget *p_parent = nullptr); +namespace vnotex { +// Base class for the popup of a QToolButton. +class ButtonPopup : public QMenu { + Q_OBJECT +public: + ButtonPopup(QToolButton *p_btn, QWidget *p_parent = nullptr); - protected: - void keyPressEvent(QKeyEvent *p_event) override; +protected: + void keyPressEvent(QKeyEvent *p_event) override; - void addWidget(QWidget *p_widget); + void addWidget(QWidget *p_widget); - // Button for this menu. - QToolButton *m_button = nullptr; - }; -} + // Button for this menu. + QToolButton *m_button = nullptr; +}; +} // namespace vnotex #endif // BUTTONPOPUP_H diff --git a/src/widgets/combobox.cpp b/src/widgets/combobox.cpp index 430de197c6..6cc5b2d6f4 100644 --- a/src/widgets/combobox.cpp +++ b/src/widgets/combobox.cpp @@ -5,23 +5,19 @@ using namespace vnotex; -ComboBox::ComboBox(QWidget *p_parent) - : QComboBox(p_parent) -{ -} +ComboBox::ComboBox(QWidget *p_parent) : QComboBox(p_parent) {} -void ComboBox::showPopup() -{ - QComboBox::showPopup(); +void ComboBox::showPopup() { + QComboBox::showPopup(); #if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) - auto vw = view(); - if (count() > 0) { - int cnt = qMin(count(), maxVisibleItems()); - int height = 20 + cnt * vw->visualRect(vw->model()->index(0, 0)).height(); - if (height > vw->height()) { - vw->setMinimumHeight(height); - } + auto vw = view(); + if (count() > 0) { + int cnt = qMin(count(), maxVisibleItems()); + int height = 20 + cnt * vw->visualRect(vw->model()->index(0, 0)).height(); + if (height > vw->height()) { + vw->setMinimumHeight(height); } + } #endif } diff --git a/src/widgets/combobox.h b/src/widgets/combobox.h index b8334f4834..beb2479644 100644 --- a/src/widgets/combobox.h +++ b/src/widgets/combobox.h @@ -3,16 +3,14 @@ #include -namespace vnotex -{ - class ComboBox : public QComboBox - { - Q_OBJECT - public: - explicit ComboBox(QWidget *p_parent = nullptr); +namespace vnotex { +class ComboBox : public QComboBox { + Q_OBJECT +public: + explicit ComboBox(QWidget *p_parent = nullptr); - void showPopup() Q_DECL_OVERRIDE; - }; -} + void showPopup() Q_DECL_OVERRIDE; +}; +} // namespace vnotex #endif // COMBOBOX_H diff --git a/src/widgets/consoleviewer.cpp b/src/widgets/consoleviewer.cpp index 312e363374..63965638a8 100644 --- a/src/widgets/consoleviewer.cpp +++ b/src/widgets/consoleviewer.cpp @@ -1,62 +1,51 @@ #include "consoleviewer.h" -#include #include #include #include +#include #include -#include "widgetsfactory.h" #include "titlebar.h" +#include "widgetsfactory.h" using namespace vnotex; -ConsoleViewer::ConsoleViewer(QWidget *p_parent) - : QFrame(p_parent) -{ - setupUI(); -} +ConsoleViewer::ConsoleViewer(QWidget *p_parent) : QFrame(p_parent) { setupUI(); } -void ConsoleViewer::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - WidgetUtils::setContentsMargins(mainLayout); +void ConsoleViewer::setupUI() { + auto mainLayout = new QVBoxLayout(this); + WidgetUtils::setContentsMargins(mainLayout); - { - setupTitleBar(QString(), this); - mainLayout->addWidget(m_titleBar); - } + { + setupTitleBar(QString(), this); + mainLayout->addWidget(m_titleBar); + } - m_consoleEdit = new QPlainTextEdit(this); - m_consoleEdit->setReadOnly(true); - mainLayout->addWidget(m_consoleEdit); + m_consoleEdit = new QPlainTextEdit(this); + m_consoleEdit->setReadOnly(true); + mainLayout->addWidget(m_consoleEdit); - setFocusProxy(m_consoleEdit); + setFocusProxy(m_consoleEdit); } -void ConsoleViewer::setupTitleBar(const QString &p_title, QWidget *p_parent) -{ - m_titleBar = new TitleBar(p_title, true, TitleBar::Action::None, p_parent); - m_titleBar->setActionButtonsAlwaysShown(true); +void ConsoleViewer::setupTitleBar(const QString &p_title, QWidget *p_parent) { + m_titleBar = new TitleBar(p_title, true, TitleBar::Action::None, p_parent); + m_titleBar->setActionButtonsAlwaysShown(true); - { - auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear")); - connect(clearBtn, &QToolButton::triggered, - this, &ConsoleViewer::clear); - } + { + auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear")); + connect(clearBtn, &QToolButton::triggered, this, &ConsoleViewer::clear); + } } -void ConsoleViewer::append(const QString &p_text) -{ - m_consoleEdit->appendPlainText(p_text); - auto scrollBar = m_consoleEdit->verticalScrollBar(); - if (scrollBar) { - scrollBar->setValue(scrollBar->maximum()); - } +void ConsoleViewer::append(const QString &p_text) { + m_consoleEdit->appendPlainText(p_text); + auto scrollBar = m_consoleEdit->verticalScrollBar(); + if (scrollBar) { + scrollBar->setValue(scrollBar->maximum()); + } } -void ConsoleViewer::clear() -{ - m_consoleEdit->clear(); -} +void ConsoleViewer::clear() { m_consoleEdit->clear(); } diff --git a/src/widgets/consoleviewer.h b/src/widgets/consoleviewer.h index 6f2dd3db18..505915354a 100644 --- a/src/widgets/consoleviewer.h +++ b/src/widgets/consoleviewer.h @@ -5,29 +5,27 @@ class QPlainTextEdit; -namespace vnotex -{ - class TitleBar; +namespace vnotex { +class TitleBar; - class ConsoleViewer : public QFrame - { - Q_OBJECT - public: - explicit ConsoleViewer(QWidget *p_parent = nullptr); +class ConsoleViewer : public QFrame { + Q_OBJECT +public: + explicit ConsoleViewer(QWidget *p_parent = nullptr); - void append(const QString &p_text); + void append(const QString &p_text); - void clear(); + void clear(); - private: - void setupUI(); +private: + void setupUI(); - void setupTitleBar(const QString &p_title, QWidget *p_parent = nullptr); + void setupTitleBar(const QString &p_title, QWidget *p_parent = nullptr); - TitleBar *m_titleBar = nullptr; + TitleBar *m_titleBar = nullptr; - QPlainTextEdit *m_consoleEdit = nullptr; - }; -} + QPlainTextEdit *m_consoleEdit = nullptr; +}; +} // namespace vnotex #endif // CONSOLEVIEWER_H diff --git a/src/widgets/dialogs/deleteconfirmdialog.cpp b/src/widgets/dialogs/deleteconfirmdialog.cpp index d45170cd12..b735daddf7 100644 --- a/src/widgets/dialogs/deleteconfirmdialog.cpp +++ b/src/widgets/dialogs/deleteconfirmdialog.cpp @@ -1,211 +1,195 @@ #include "deleteconfirmdialog.h" -#include +#include #include #include #include #include -#include -#include #include +#include +#include #include "global.h" -#include #include "selectionitemwidget.h" +#include using namespace vnotex; -DeleteConfirmDialog::DeleteConfirmDialog(const QString &p_title, - const QString &p_text, +DeleteConfirmDialog::DeleteConfirmDialog(const QString &p_title, const QString &p_text, const QString &p_info, const QVector &p_items, DeleteConfirmDialog::Flags p_flags, - bool p_noAskAgainChecked, - QWidget *p_parent) - : ScrollDialog(p_parent), - m_items(p_items) -{ - setupUI(p_title, p_text, p_info, p_flags, p_noAskAgainChecked); + bool p_noAskAgainChecked, QWidget *p_parent) + : ScrollDialog(p_parent), m_items(p_items) { + setupUI(p_title, p_text, p_info, p_flags, p_noAskAgainChecked); - updateItemsList(); + updateItemsList(); - updateCountLabel(); + updateCountLabel(); } -void DeleteConfirmDialog::setupUI(const QString &p_title, - const QString &p_text, - const QString &p_info, - DeleteConfirmDialog::Flags p_flags, - bool p_noAskAgainChecked) -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); - - auto mainLayout = new QVBoxLayout(mainWidget); - - // Text. - if (!p_text.isEmpty()) { - auto textLabel = new QLabel(p_text, mainWidget); - textLabel->setWordWrap(true); - mainLayout->addWidget(textLabel); - } - - // Info. - if (!p_info.isEmpty()) { - auto infoLabel = new QLabel(p_info, mainWidget); - infoLabel->setWordWrap(true); - mainLayout->addWidget(infoLabel); +void DeleteConfirmDialog::setupUI(const QString &p_title, const QString &p_text, + const QString &p_info, DeleteConfirmDialog::Flags p_flags, + bool p_noAskAgainChecked) { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); + + auto mainLayout = new QVBoxLayout(mainWidget); + + // Text. + if (!p_text.isEmpty()) { + auto textLabel = new QLabel(p_text, mainWidget); + textLabel->setWordWrap(true); + mainLayout->addWidget(textLabel); + } + + // Info. + if (!p_info.isEmpty()) { + auto infoLabel = new QLabel(p_info, mainWidget); + infoLabel->setWordWrap(true); + mainLayout->addWidget(infoLabel); + } + + // Ask again. + if (p_flags & Flag::AskAgain) { + m_noAskCB = new QCheckBox(tr("Do not ask again"), mainWidget); + m_noAskCB->setChecked(p_noAskAgainChecked); + mainLayout->addWidget(m_noAskCB); + } + + // Count. + { + QHBoxLayout *labelLayout = new QHBoxLayout(); + + m_countLabel = new QLabel("Items", mainWidget); + + labelLayout->addWidget(m_countLabel); + labelLayout->addStretch(); + labelLayout->setContentsMargins(0, 0, 0, 0); + + mainLayout->addLayout(labelLayout); + } + + // List and preview. + { + auto listLayout = new QHBoxLayout(); + + m_listWidget = new QListWidget(mainWidget); + connect(m_listWidget, &QListWidget::currentRowChanged, this, + &DeleteConfirmDialog::currentFileChanged); + connect(m_listWidget, &QListWidget::itemActivated, this, [this](QListWidgetItem *p_item) { + if (!p_item) { + return; + } + + auto widget = getItemWidget(p_item); + Q_ASSERT(widget); + QString filePath = m_items[widget->getData().toInt()].m_path; + if (!filePath.isEmpty()) { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(filePath)); + } + }); + + listLayout->addWidget(m_listWidget); + + if (p_flags & Flag::Preview) { + m_previewer = new QLabel(mainWidget); + m_previewer->setScaledContents(true); + + m_previewArea = new QScrollArea(mainWidget); + m_previewArea->setBackgroundRole(QPalette::Dark); + m_previewArea->setWidget(m_previewer); + m_previewArea->setMinimumSize(256, 256); + + listLayout->addWidget(m_previewArea); } - // Ask again. - if (p_flags & Flag::AskAgain) { - m_noAskCB = new QCheckBox(tr("Do not ask again"), mainWidget); - m_noAskCB->setChecked(p_noAskAgainChecked); - mainLayout->addWidget(m_noAskCB); - } + mainLayout->addLayout(listLayout); + } - // Count. - { - QHBoxLayout *labelLayout = new QHBoxLayout(); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - m_countLabel = new QLabel("Items", mainWidget); - - labelLayout->addWidget(m_countLabel); - labelLayout->addStretch(); - labelLayout->setContentsMargins(0, 0, 0, 0); - - mainLayout->addLayout(labelLayout); - } - - // List and preview. - { - auto listLayout = new QHBoxLayout(); - - m_listWidget = new QListWidget(mainWidget); - connect(m_listWidget, &QListWidget::currentRowChanged, - this, &DeleteConfirmDialog::currentFileChanged); - connect(m_listWidget, &QListWidget::itemActivated, - this, [this](QListWidgetItem *p_item) { - if (!p_item) { - return; - } - - auto widget = getItemWidget(p_item); - Q_ASSERT(widget); - QString filePath = m_items[widget->getData().toInt()].m_path; - if (!filePath.isEmpty()) { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(filePath)); - } - }); - - listLayout->addWidget(m_listWidget); - - if (p_flags & Flag::Preview) { - m_previewer = new QLabel(mainWidget); - m_previewer->setScaledContents(true); - - m_previewArea = new QScrollArea(mainWidget); - m_previewArea->setBackgroundRole(QPalette::Dark); - m_previewArea->setWidget(m_previewer); - m_previewArea->setMinimumSize(256, 256); - - listLayout->addWidget(m_previewArea); - } - - mainLayout->addLayout(listLayout); - } - - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - - setWindowTitle(p_title); + setWindowTitle(p_title); } -QVector DeleteConfirmDialog::getConfirmedItems() const -{ - QVector confirmedItems; +QVector DeleteConfirmDialog::getConfirmedItems() const { + QVector confirmedItems; - for (int i = 0; i < m_listWidget->count(); ++i) { - SelectionItemWidget *widget = getItemWidget(m_listWidget->item(i)); - if (widget->isChecked()) { - confirmedItems.push_back(m_items[widget->getData().toInt()]); - } + for (int i = 0; i < m_listWidget->count(); ++i) { + SelectionItemWidget *widget = getItemWidget(m_listWidget->item(i)); + if (widget->isChecked()) { + confirmedItems.push_back(m_items[widget->getData().toInt()]); } + } - return confirmedItems; + return confirmedItems; } -void DeleteConfirmDialog::updateItemsList() -{ - m_listWidget->clear(); +void DeleteConfirmDialog::updateItemsList() { + m_listWidget->clear(); - for (int i = 0; i < m_items.size(); ++i) { - auto itemWidget = new SelectionItemWidget(m_items[i].m_icon, m_items[i].m_name, this); - itemWidget->setChecked(true); - itemWidget->setData(i); - itemWidget->setToolTip(m_items[i].m_tip); - connect(itemWidget, &SelectionItemWidget::checkStateChanged, - this, &DeleteConfirmDialog::updateCountLabel); + for (int i = 0; i < m_items.size(); ++i) { + auto itemWidget = new SelectionItemWidget(m_items[i].m_icon, m_items[i].m_name, this); + itemWidget->setChecked(true); + itemWidget->setData(i); + itemWidget->setToolTip(m_items[i].m_tip); + connect(itemWidget, &SelectionItemWidget::checkStateChanged, this, + &DeleteConfirmDialog::updateCountLabel); - QListWidgetItem *item = new QListWidgetItem(m_listWidget); - QSize size = itemWidget->sizeHint(); - size.setHeight(size.height() * 2); - item->setSizeHint(size); + QListWidgetItem *item = new QListWidgetItem(m_listWidget); + QSize size = itemWidget->sizeHint(); + size.setHeight(size.height() * 2); + item->setSizeHint(size); - m_listWidget->setItemWidget(item, itemWidget); - } - - m_listWidget->setMinimumSize(m_listWidget->sizeHint()); - m_listWidget->setCurrentRow(-1); - m_listWidget->setCurrentRow(0); -} + m_listWidget->setItemWidget(item, itemWidget); + } -bool DeleteConfirmDialog::isNoAskChecked() const -{ - return m_noAskCB->isChecked(); + m_listWidget->setMinimumSize(m_listWidget->sizeHint()); + m_listWidget->setCurrentRow(-1); + m_listWidget->setCurrentRow(0); } -void DeleteConfirmDialog::currentFileChanged(int p_row) -{ - if (m_previewer) { - bool succeed = false; - if (p_row > -1) { - SelectionItemWidget *widget = getItemWidget(m_listWidget->item(p_row)); - if (widget) { - int idx = widget->getData().toInt(); - Q_ASSERT(idx < m_items.size()); - QPixmap image(m_items[idx].m_path); - if (!image.isNull()) { - m_previewer->setPixmap(image); - m_previewer->adjustSize(); - succeed = true; - } - } +bool DeleteConfirmDialog::isNoAskChecked() const { return m_noAskCB->isChecked(); } + +void DeleteConfirmDialog::currentFileChanged(int p_row) { + if (m_previewer) { + bool succeed = false; + if (p_row > -1) { + SelectionItemWidget *widget = getItemWidget(m_listWidget->item(p_row)); + if (widget) { + int idx = widget->getData().toInt(); + Q_ASSERT(idx < m_items.size()); + QPixmap image(m_items[idx].m_path); + if (!image.isNull()) { + m_previewer->setPixmap(image); + m_previewer->adjustSize(); + succeed = true; } + } + } - m_previewArea->setVisible(succeed); - if (succeed) { - resizeToHideScrollBarLater(true, true); - } + m_previewArea->setVisible(succeed); + if (succeed) { + resizeToHideScrollBarLater(true, true); } + } } -SelectionItemWidget *DeleteConfirmDialog::getItemWidget(QListWidgetItem *p_item) const -{ - QWidget *wid = m_listWidget->itemWidget(p_item); - return static_cast(wid); +SelectionItemWidget *DeleteConfirmDialog::getItemWidget(QListWidgetItem *p_item) const { + QWidget *wid = m_listWidget->itemWidget(p_item); + return static_cast(wid); } -void DeleteConfirmDialog::updateCountLabel() -{ - int total = m_listWidget->count(); - int checked = 0; +void DeleteConfirmDialog::updateCountLabel() { + int total = m_listWidget->count(); + int checked = 0; - for (int i = 0; i < total; ++i) { - SelectionItemWidget *widget = getItemWidget(m_listWidget->item(i)); - if (widget->isChecked()) { - ++checked; - } + for (int i = 0; i < total; ++i) { + SelectionItemWidget *widget = getItemWidget(m_listWidget->item(i)); + if (widget->isChecked()) { + ++checked; } + } - m_countLabel->setText(tr("%1/%2 Items").arg(checked).arg(total)); + m_countLabel->setText(tr("%1/%2 Items").arg(checked).arg(total)); } diff --git a/src/widgets/dialogs/deleteconfirmdialog.h b/src/widgets/dialogs/deleteconfirmdialog.h index e348336371..d4f36c2d97 100644 --- a/src/widgets/dialogs/deleteconfirmdialog.h +++ b/src/widgets/dialogs/deleteconfirmdialog.h @@ -11,101 +11,67 @@ class QListWidgetItem; class QCheckBox; class QScrollArea; -namespace vnotex -{ - class SelectionItemWidget; - - // Information about a deletion item needed to confirm. - struct ConfirmItemInfo - { - ConfirmItemInfo() - { - } - - ConfirmItemInfo(const QString &p_name, - const QString &p_tip, - const QString &p_path, - void *p_data) - : m_name(p_name), - m_tip(p_tip), - m_path(p_path), - m_data(p_data) - { - } - - ConfirmItemInfo(const QIcon &p_icon, - const QString &p_name, - const QString &p_tip, - const QString &p_path, - void *p_data) - : m_icon(p_icon), - m_name(p_name), - m_tip(p_tip), - m_path(p_path), - m_data(p_data) - { - } - - QIcon m_icon; - QString m_name; - QString m_tip; - QString m_path; - void *m_data = nullptr; - }; - - - class DeleteConfirmDialog : public ScrollDialog - { - Q_OBJECT - public: - enum Flag { - None = 0, - AskAgain = 0x1, - Preview = 0x2 - }; - Q_DECLARE_FLAGS(Flags, Flag) - - DeleteConfirmDialog(const QString &p_title, - const QString &p_text, - const QString &p_info, - const QVector &p_items, - DeleteConfirmDialog::Flags p_flags, - bool p_noAskAgainChecked, - QWidget *p_parent = nullptr); - - QVector getConfirmedItems() const; - - bool isNoAskChecked() const; - - private slots: - void currentFileChanged(int p_row); - - void updateCountLabel(); - - private: - void setupUI(const QString &p_title, - const QString &p_text, - const QString &p_info, - DeleteConfirmDialog::Flags p_flags, - bool p_noAskAgainChecked); - - void updateItemsList(); - - SelectionItemWidget *getItemWidget(QListWidgetItem *p_item) const; - - QVector m_items; - - QLabel *m_countLabel = nullptr; - QListWidget *m_listWidget = nullptr; - - QLabel *m_previewer = nullptr; - - QScrollArea *m_previewArea = nullptr; - - QCheckBox *m_noAskCB = nullptr; - }; - - Q_DECLARE_OPERATORS_FOR_FLAGS(DeleteConfirmDialog::Flags) -} // ns vnotex +namespace vnotex { +class SelectionItemWidget; + +// Information about a deletion item needed to confirm. +struct ConfirmItemInfo { + ConfirmItemInfo() {} + + ConfirmItemInfo(const QString &p_name, const QString &p_tip, const QString &p_path, void *p_data) + : m_name(p_name), m_tip(p_tip), m_path(p_path), m_data(p_data) {} + + ConfirmItemInfo(const QIcon &p_icon, const QString &p_name, const QString &p_tip, + const QString &p_path, void *p_data) + : m_icon(p_icon), m_name(p_name), m_tip(p_tip), m_path(p_path), m_data(p_data) {} + + QIcon m_icon; + QString m_name; + QString m_tip; + QString m_path; + void *m_data = nullptr; +}; + +class DeleteConfirmDialog : public ScrollDialog { + Q_OBJECT +public: + enum Flag { None = 0, AskAgain = 0x1, Preview = 0x2 }; + Q_DECLARE_FLAGS(Flags, Flag) + + DeleteConfirmDialog(const QString &p_title, const QString &p_text, const QString &p_info, + const QVector &p_items, DeleteConfirmDialog::Flags p_flags, + bool p_noAskAgainChecked, QWidget *p_parent = nullptr); + + QVector getConfirmedItems() const; + + bool isNoAskChecked() const; + +private slots: + void currentFileChanged(int p_row); + + void updateCountLabel(); + +private: + void setupUI(const QString &p_title, const QString &p_text, const QString &p_info, + DeleteConfirmDialog::Flags p_flags, bool p_noAskAgainChecked); + + void updateItemsList(); + + SelectionItemWidget *getItemWidget(QListWidgetItem *p_item) const; + + QVector m_items; + + QLabel *m_countLabel = nullptr; + QListWidget *m_listWidget = nullptr; + + QLabel *m_previewer = nullptr; + + QScrollArea *m_previewArea = nullptr; + + QCheckBox *m_noAskCB = nullptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(DeleteConfirmDialog::Flags) +} // namespace vnotex #endif // DELETECONFIRMDIALOG_H diff --git a/src/widgets/dialogs/dialog.cpp b/src/widgets/dialogs/dialog.cpp index 6c8cc1146f..6244c128c5 100644 --- a/src/widgets/dialogs/dialog.cpp +++ b/src/widgets/dialogs/dialog.cpp @@ -1,183 +1,153 @@ #include "dialog.h" -#include -#include #include -#include -#include +#include +#include #include #include -#include +#include +#include +#include -#include #include "../propertydefs.h" #include "../widgetsfactory.h" +#include using namespace vnotex; -Dialog::Dialog(QWidget *p_parent, Qt::WindowFlags p_flags) - : QDialog(p_parent, p_flags) -{ - m_layout = new QVBoxLayout(this); +Dialog::Dialog(QWidget *p_parent, Qt::WindowFlags p_flags) : QDialog(p_parent, p_flags) { + m_layout = new QVBoxLayout(this); } -void Dialog::setCentralWidget(QWidget *p_widget) -{ - Q_ASSERT(!m_centralWidget && p_widget); - m_centralWidget = p_widget; - m_centralWidget->setProperty(PropertyDefs::c_dialogCentralWidget, true); - m_layout->addWidget(m_centralWidget); +void Dialog::setCentralWidget(QWidget *p_widget) { + Q_ASSERT(!m_centralWidget && p_widget); + m_centralWidget = p_widget; + m_centralWidget->setProperty(PropertyDefs::c_dialogCentralWidget, true); + m_layout->addWidget(m_centralWidget); } -void Dialog::addBottomWidget(QWidget *p_widget) -{ - m_layout->insertWidget(m_layout->indexOf(m_centralWidget) + 1, p_widget); +void Dialog::addBottomWidget(QWidget *p_widget) { + m_layout->insertWidget(m_layout->indexOf(m_centralWidget) + 1, p_widget); } void Dialog::setDialogButtonBox(QDialogButtonBox::StandardButtons p_buttons, - QDialogButtonBox::StandardButton p_defaultButton) -{ - if (m_dialogButtonBox) { - m_dialogButtonBox->setStandardButtons(p_buttons); - } else { - m_dialogButtonBox = new QDialogButtonBox(p_buttons, this); - connect(m_dialogButtonBox, &QDialogButtonBox::accepted, - this, &Dialog::acceptedButtonClicked); - connect(m_dialogButtonBox, &QDialogButtonBox::rejected, - this, &Dialog::rejectedButtonClicked); - connect(m_dialogButtonBox, &QDialogButtonBox::clicked, - this, [this](QAbstractButton *p_button) { - switch (m_dialogButtonBox->buttonRole(p_button)) { - case QDialogButtonBox::ResetRole: - resetButtonClicked(); - break; - - case QDialogButtonBox::ApplyRole: - appliedButtonClicked(); - break; - - default: - break; - } - }); - - m_layout->addWidget(m_dialogButtonBox); - } - - // If default button is not set, the first button with the accept role is made - // the default button when the dialog is shown. - if (p_defaultButton != QDialogButtonBox::NoButton) { - auto btn = m_dialogButtonBox->button(p_defaultButton); - if (btn) { - btn->setDefault(true); - } - } -} - -QDialogButtonBox *Dialog::getDialogButtonBox() const -{ - return m_dialogButtonBox; -} - -void Dialog::setInformationText(const QString &p_text, InformationLevel p_level) -{ - if (!m_infoTextEdit) { - if (p_text.isEmpty()) { - return; - } - - m_infoTextEdit = WidgetsFactory::createPlainTextConsole(this); - m_infoTextEdit->setMaximumHeight(m_infoTextEdit->minimumSizeHint().height()); - m_layout->insertWidget(m_layout->count() - 1, m_infoTextEdit); - } - - m_infoTextEdit->setPlainText(p_text); - m_infoTextEdit->ensureCursorVisible(); - - const bool visible = !p_text.isEmpty(); - const bool needResize = visible != m_infoTextEdit->isVisible(); - m_infoTextEdit->setVisible(visible); - - // Change the style. - const char *level = ""; - switch (p_level) { - case InformationLevel::Info: - level = "info"; + QDialogButtonBox::StandardButton p_defaultButton) { + if (m_dialogButtonBox) { + m_dialogButtonBox->setStandardButtons(p_buttons); + } else { + m_dialogButtonBox = new QDialogButtonBox(p_buttons, this); + connect(m_dialogButtonBox, &QDialogButtonBox::accepted, this, &Dialog::acceptedButtonClicked); + connect(m_dialogButtonBox, &QDialogButtonBox::rejected, this, &Dialog::rejectedButtonClicked); + connect(m_dialogButtonBox, &QDialogButtonBox::clicked, this, [this](QAbstractButton *p_button) { + switch (m_dialogButtonBox->buttonRole(p_button)) { + case QDialogButtonBox::ResetRole: + resetButtonClicked(); break; - case InformationLevel::Warning: - level = "warning"; + case QDialogButtonBox::ApplyRole: + appliedButtonClicked(); break; - case InformationLevel::Error: - level = "error"; + default: break; + } + }); + + m_layout->addWidget(m_dialogButtonBox); + } + + // If default button is not set, the first button with the accept role is made + // the default button when the dialog is shown. + if (p_defaultButton != QDialogButtonBox::NoButton) { + auto btn = m_dialogButtonBox->button(p_defaultButton); + if (btn) { + btn->setDefault(true); } - - WidgetUtils::setPropertyDynamically(m_infoTextEdit, PropertyDefs::c_state, level); - if (needResize) { - WidgetUtils::updateSize(this); - } + } } -void Dialog::appendInformationText(const QString &p_text) -{ - if (!m_infoTextEdit) { - setInformationText(p_text); - } else { - m_infoTextEdit->appendPlainText(p_text); - m_infoTextEdit->moveCursor(QTextCursor::End); - m_infoTextEdit->ensureCursorVisible(); - } -} +QDialogButtonBox *Dialog::getDialogButtonBox() const { return m_dialogButtonBox; } -void Dialog::clearInformationText() -{ - if (m_infoTextEdit) { - m_infoTextEdit->clear(); +void Dialog::setInformationText(const QString &p_text, InformationLevel p_level) { + if (!m_infoTextEdit) { + if (p_text.isEmpty()) { + return; } -} -void Dialog::acceptedButtonClicked() -{ - QDialog::accept(); + m_infoTextEdit = WidgetsFactory::createPlainTextConsole(this); + m_infoTextEdit->setMaximumHeight(m_infoTextEdit->minimumSizeHint().height()); + m_layout->insertWidget(m_layout->count() - 1, m_infoTextEdit); + } + + m_infoTextEdit->setPlainText(p_text); + m_infoTextEdit->ensureCursorVisible(); + + const bool visible = !p_text.isEmpty(); + const bool needResize = visible != m_infoTextEdit->isVisible(); + m_infoTextEdit->setVisible(visible); + + // Change the style. + const char *level = ""; + switch (p_level) { + case InformationLevel::Info: + level = "info"; + break; + + case InformationLevel::Warning: + level = "warning"; + break; + + case InformationLevel::Error: + level = "error"; + break; + } + + WidgetUtils::setPropertyDynamically(m_infoTextEdit, PropertyDefs::c_state, level); + if (needResize) { + WidgetUtils::updateSize(this); + } +} + +void Dialog::appendInformationText(const QString &p_text) { + if (!m_infoTextEdit) { + setInformationText(p_text); + } else { + m_infoTextEdit->appendPlainText(p_text); + m_infoTextEdit->moveCursor(QTextCursor::End); + m_infoTextEdit->ensureCursorVisible(); + } } -void Dialog::rejectedButtonClicked() -{ - QDialog::reject(); +void Dialog::clearInformationText() { + if (m_infoTextEdit) { + m_infoTextEdit->clear(); + } } -void Dialog::resetButtonClicked() -{ -} +void Dialog::acceptedButtonClicked() { QDialog::accept(); } -void Dialog::appliedButtonClicked() -{ -} +void Dialog::rejectedButtonClicked() { QDialog::reject(); } -void Dialog::setButtonEnabled(QDialogButtonBox::StandardButton p_button, bool p_enabled) -{ - QPushButton *button = getDialogButtonBox()->button(p_button); - if (button) { - button->setEnabled(p_enabled); - } -} +void Dialog::resetButtonClicked() {} -void Dialog::completeButStay() -{ - Q_ASSERT(m_centralWidget); - m_centralWidget->setEnabled(false); - m_completed = true; +void Dialog::appliedButtonClicked() {} + +void Dialog::setButtonEnabled(QDialogButtonBox::StandardButton p_button, bool p_enabled) { + QPushButton *button = getDialogButtonBox()->button(p_button); + if (button) { + button->setEnabled(p_enabled); + } } -bool Dialog::isCompleted() const -{ - return m_completed; +void Dialog::completeButStay() { + Q_ASSERT(m_centralWidget); + m_centralWidget->setEnabled(false); + m_completed = true; } -QSize Dialog::sizeHint() const -{ - auto sz = QDialog::sizeHint(); - return sz * 1.2; +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 5f07d0a483..4489c5d882 100644 --- a/src/widgets/dialogs/dialog.h +++ b/src/widgets/dialogs/dialog.h @@ -7,66 +7,60 @@ class QBoxLayout; class QPlainTextEdit; -namespace vnotex -{ - class Dialog : public QDialog - { - Q_OBJECT - public: - explicit Dialog(QWidget *p_parent = nullptr, Qt::WindowFlags p_flags = Qt::WindowFlags()); +namespace vnotex { +class Dialog : public QDialog { + Q_OBJECT +public: + explicit Dialog(QWidget *p_parent = nullptr, Qt::WindowFlags p_flags = Qt::WindowFlags()); - void setDialogButtonBox(QDialogButtonBox::StandardButtons p_buttons, - QDialogButtonBox::StandardButton p_defaultButton = QDialogButtonBox::NoButton); + void + setDialogButtonBox(QDialogButtonBox::StandardButtons p_buttons, + QDialogButtonBox::StandardButton p_defaultButton = QDialogButtonBox::NoButton); - QDialogButtonBox *getDialogButtonBox() const; + QDialogButtonBox *getDialogButtonBox() const; - enum class InformationLevel - { - Info, - Warning, - Error - }; + enum class InformationLevel { Info, Warning, Error }; - void setInformationText(const QString &p_text, InformationLevel p_level = InformationLevel::Info); + void setInformationText(const QString &p_text, InformationLevel p_level = InformationLevel::Info); - void appendInformationText(const QString &p_text); + void appendInformationText(const QString &p_text); - void clearInformationText(); + void clearInformationText(); - void setButtonEnabled(QDialogButtonBox::StandardButton p_button, bool p_enabled); + void setButtonEnabled(QDialogButtonBox::StandardButton p_button, bool p_enabled); - // Dialog has completed but just stay the GUI to let user know information. - void completeButStay(); + // Dialog has completed but just stay the GUI to let user know information. + void completeButStay(); - bool isCompleted() const; + bool isCompleted() const; - QSize sizeHint() const Q_DECL_OVERRIDE; + QSize sizeHint() const Q_DECL_OVERRIDE; - protected: - virtual void acceptedButtonClicked(); +protected: + virtual void acceptedButtonClicked(); - virtual void rejectedButtonClicked(); + virtual void rejectedButtonClicked(); - virtual void resetButtonClicked(); + virtual void resetButtonClicked(); - virtual void appliedButtonClicked(); + virtual void appliedButtonClicked(); - virtual void setCentralWidget(QWidget *p_widget); + virtual void setCentralWidget(QWidget *p_widget); - // Add @p_widget below the central widget. - virtual void addBottomWidget(QWidget *p_widget); + // Add @p_widget below the central widget. + virtual void addBottomWidget(QWidget *p_widget); - QBoxLayout *m_layout = nullptr; + QBoxLayout *m_layout = nullptr; - QWidget *m_centralWidget = nullptr; + QWidget *m_centralWidget = nullptr; - private: - QPlainTextEdit *m_infoTextEdit = nullptr; +private: + QPlainTextEdit *m_infoTextEdit = nullptr; - QDialogButtonBox *m_dialogButtonBox = nullptr; + QDialogButtonBox *m_dialogButtonBox = nullptr; - bool m_completed = false; - }; -} // ns vnotex + bool m_completed = false; +}; +} // namespace vnotex #endif // DIALOG_H diff --git a/src/widgets/dialogs/exportdialog.cpp b/src/widgets/dialogs/exportdialog.cpp index 3ff1e95edc..f57dd5b07f 100644 --- a/src/widgets/dialogs/exportdialog.cpp +++ b/src/widgets/dialogs/exportdialog.cpp @@ -1,988 +1,926 @@ #include "exportdialog.h" -#include +#include +#include +#include +#include #include -#include +#include #include +#include #include -#include -#include #include -#include -#include -#include -#include +#include +#include #include -#include #include -#include -#include -#include +#include +#include +#include +#include -#include -#include #include -#include -#include #include #include +#include #include -#include +#include +#include +#include +#include #include #include -#include -#include +#include +#include #include #include -#include +#include using namespace vnotex; -ExportDialog::ExportDialog(Notebook *p_notebook, - Node *p_folder, - Node *p_note, - Buffer *p_buffer, +ExportDialog::ExportDialog(Notebook *p_notebook, Node *p_folder, Node *p_note, Buffer *p_buffer, QWidget *p_parent) - : ScrollDialog(p_parent), - m_notebook(p_notebook), - m_folder(p_folder), - m_note(p_note), - m_buffer(p_buffer) -{ - setupUI(); + : ScrollDialog(p_parent), m_notebook(p_notebook), m_folder(p_folder), m_note(p_note), + m_buffer(p_buffer) { + setupUI(); - initOptions(); + initOptions(); - restoreFields(m_option); + restoreFields(m_option); - setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint); + setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint); - connect(this, &QDialog::finished, - this, [this]() { - saveFields(m_option); - ConfigMgr::getInst().getSessionConfig().setExportOption(m_option); - }); + connect(this, &QDialog::finished, this, [this]() { + saveFields(m_option); + ConfigMgr::getInst().getSessionConfig().setExportOption(m_option); + }); } -void ExportDialog::setupUI() -{ - auto widget = new QWidget(this); - setCentralWidget(widget); +void ExportDialog::setupUI() { + auto widget = new QWidget(this); + setCentralWidget(widget); - auto mainLayout = new QVBoxLayout(widget); + auto mainLayout = new QVBoxLayout(widget); - auto sourceBox = setupSourceGroup(widget); - mainLayout->addWidget(sourceBox); + auto sourceBox = setupSourceGroup(widget); + mainLayout->addWidget(sourceBox); - auto targetBox = setupTargetGroup(widget); - mainLayout->addWidget(targetBox); + auto targetBox = setupTargetGroup(widget); + mainLayout->addWidget(targetBox); - m_advancedGroupBox = setupAdvancedGroup(widget); - mainLayout->addWidget(m_advancedGroupBox); + m_advancedGroupBox = setupAdvancedGroup(widget); + mainLayout->addWidget(m_advancedGroupBox); - m_progressBar = new QProgressBar(widget); - m_progressBar->setRange(0, 0); - m_progressBar->hide(); - addBottomWidget(m_progressBar); + m_progressBar = new QProgressBar(widget); + m_progressBar->setRange(0, 0); + m_progressBar->hide(); + addBottomWidget(m_progressBar); - setupButtonBox(); + setupButtonBox(); - setWindowTitle(tr("Export")); + setWindowTitle(tr("Export")); } -QGroupBox *ExportDialog::setupSourceGroup(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("Source"), p_parent); - auto layout = WidgetsFactory::createFormLayout(box); +QGroupBox *ExportDialog::setupSourceGroup(QWidget *p_parent) { + auto box = new QGroupBox(tr("Source"), p_parent); + auto layout = WidgetsFactory::createFormLayout(box); - { - m_sourceComboBox = WidgetsFactory::createComboBox(box); - if (m_buffer) { - m_sourceComboBox->addItem(tr("Current Buffer (%1)").arg(m_buffer->getName()), - static_cast(ExportSource::CurrentBuffer)); - } - if (m_note && m_note->hasContent()) { - m_sourceComboBox->addItem(tr("Current Note (%1)").arg(m_note->getName()), - static_cast(ExportSource::CurrentNote)); - } - if (m_folder && m_folder->isContainer()) { - m_sourceComboBox->addItem(tr("Current Folder (%1)").arg(m_folder->getName()), - static_cast(ExportSource::CurrentFolder)); - } - if (m_notebook) { - m_sourceComboBox->addItem(tr("Current Notebook (%1)").arg(m_notebook->getName()), - static_cast(ExportSource::CurrentNotebook)); - } - layout->addRow(tr("Source:"), m_sourceComboBox); + { + m_sourceComboBox = WidgetsFactory::createComboBox(box); + if (m_buffer) { + m_sourceComboBox->addItem(tr("Current Buffer (%1)").arg(m_buffer->getName()), + static_cast(ExportSource::CurrentBuffer)); } - - { - // TODO: Source format filtering. + if (m_note && m_note->hasContent()) { + m_sourceComboBox->addItem(tr("Current Note (%1)").arg(m_note->getName()), + static_cast(ExportSource::CurrentNote)); + } + if (m_folder && m_folder->isContainer()) { + m_sourceComboBox->addItem(tr("Current Folder (%1)").arg(m_folder->getName()), + static_cast(ExportSource::CurrentFolder)); } + if (m_notebook) { + m_sourceComboBox->addItem(tr("Current Notebook (%1)").arg(m_notebook->getName()), + static_cast(ExportSource::CurrentNotebook)); + } + layout->addRow(tr("Source:"), m_sourceComboBox); + } + + { + // TODO: Source format filtering. + } - return box; + return box; } -QString ExportDialog::getDefaultOutputDir() const -{ - return PathUtils::concatenateFilePath(ConfigMgr::getDocumentOrHomePath(), tr("vnote_exports")); +QString ExportDialog::getDefaultOutputDir() const { + return PathUtils::concatenateFilePath(ConfigMgr::getDocumentOrHomePath(), tr("vnote_exports")); } -QGroupBox *ExportDialog::setupTargetGroup(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("Target"), p_parent); - auto layout = WidgetsFactory::createFormLayout(box); +QGroupBox *ExportDialog::setupTargetGroup(QWidget *p_parent) { + auto box = new QGroupBox(tr("Target"), p_parent); + auto layout = WidgetsFactory::createFormLayout(box); - { - m_targetFormatComboBox = WidgetsFactory::createComboBox(box); - m_targetFormatComboBox->addItem(tr("Markdown"), - static_cast(ExportFormat::Markdown)); - m_targetFormatComboBox->addItem(tr("HTML"), - static_cast(ExportFormat::HTML)); - m_targetFormatComboBox->addItem(tr("PDF"), - static_cast(ExportFormat::PDF)); - m_targetFormatComboBox->addItem(tr("Custom"), - static_cast(ExportFormat::Custom)); - connect(m_targetFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this]() { - AdvancedSettings settings = AdvancedSettings::Max; - int format = m_targetFormatComboBox->currentData().toInt(); - switch (format) { - case static_cast(ExportFormat::HTML): - settings = AdvancedSettings::HTML; - break; - - case static_cast(ExportFormat::PDF): - settings = AdvancedSettings::PDF; - break; - - case static_cast(ExportFormat::Custom): - settings = AdvancedSettings::Custom; - break; - - default: - break; - } - showAdvancedSettings(settings); - }); - layout->addRow(tr("Format:"), m_targetFormatComboBox); - } + { + m_targetFormatComboBox = WidgetsFactory::createComboBox(box); + m_targetFormatComboBox->addItem(tr("Markdown"), static_cast(ExportFormat::Markdown)); + m_targetFormatComboBox->addItem(tr("HTML"), static_cast(ExportFormat::HTML)); + m_targetFormatComboBox->addItem(tr("PDF"), static_cast(ExportFormat::PDF)); + m_targetFormatComboBox->addItem(tr("Custom"), static_cast(ExportFormat::Custom)); + connect(m_targetFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this]() { + AdvancedSettings settings = AdvancedSettings::Max; + int format = m_targetFormatComboBox->currentData().toInt(); + switch (format) { + case static_cast(ExportFormat::HTML): + settings = AdvancedSettings::HTML; + break; - { - m_transparentBgCheckBox = WidgetsFactory::createCheckBox(tr("Use transparent background"), box); - layout->addRow(m_transparentBgCheckBox); - } + case static_cast(ExportFormat::PDF): + settings = AdvancedSettings::PDF; + break; - { - const auto webStyles = VNoteX::getInst().getThemeMgr().getWebStyles(); + case static_cast(ExportFormat::Custom): + settings = AdvancedSettings::Custom; + break; - m_renderingStyleComboBox = WidgetsFactory::createComboBox(box); - layout->addRow(tr("Rendering style:"), m_renderingStyleComboBox); - for (const auto &pa : webStyles) { - m_renderingStyleComboBox->addItem(pa.first, pa.second); - } + default: + break; + } + showAdvancedSettings(settings); + }); + layout->addRow(tr("Format:"), m_targetFormatComboBox); + } - m_syntaxHighlightStyleComboBox = WidgetsFactory::createComboBox(box); - layout->addRow(tr("Syntax highlighting style:"), m_syntaxHighlightStyleComboBox); - for (const auto &pa : webStyles) { - m_syntaxHighlightStyleComboBox->addItem(pa.first, pa.second); - } - } + { + m_transparentBgCheckBox = WidgetsFactory::createCheckBox(tr("Use transparent background"), box); + layout->addRow(m_transparentBgCheckBox); + } - { - m_outputDirInput = new LocationInputWithBrowseButton(box); - layout->addRow(tr("Output directory:"), m_outputDirInput); - connect(m_outputDirInput, &LocationInputWithBrowseButton::clicked, - this, [this]() { - QString initPath = getOutputDir(); - if (!QFileInfo::exists(initPath)) { - initPath = getDefaultOutputDir(); - } + { + const auto webStyles = VNoteX::getInst().getThemeMgr().getWebStyles(); - QString dirPath = QFileDialog::getExistingDirectory(this, - tr("Select Export Output Directory"), - initPath, - QFileDialog::ShowDirsOnly - | QFileDialog::DontResolveSymlinks); + m_renderingStyleComboBox = WidgetsFactory::createComboBox(box); + layout->addRow(tr("Rendering style:"), m_renderingStyleComboBox); + for (const auto &pa : webStyles) { + m_renderingStyleComboBox->addItem(pa.first, pa.second); + } - if (!dirPath.isEmpty()) { - m_outputDirInput->setText(dirPath); - } - }); + m_syntaxHighlightStyleComboBox = WidgetsFactory::createComboBox(box); + layout->addRow(tr("Syntax highlighting style:"), m_syntaxHighlightStyleComboBox); + for (const auto &pa : webStyles) { + m_syntaxHighlightStyleComboBox->addItem(pa.first, pa.second); } + } + + { + m_outputDirInput = new LocationInputWithBrowseButton(box); + layout->addRow(tr("Output directory:"), m_outputDirInput); + connect(m_outputDirInput, &LocationInputWithBrowseButton::clicked, this, [this]() { + QString initPath = getOutputDir(); + if (!QFileInfo::exists(initPath)) { + initPath = getDefaultOutputDir(); + } - return box; + QString dirPath = QFileDialog::getExistingDirectory( + this, tr("Select Export Output Directory"), initPath, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + if (!dirPath.isEmpty()) { + m_outputDirInput->setText(dirPath); + } + }); + } + + return box; } -QGroupBox *ExportDialog::setupAdvancedGroup(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("Advanced"), p_parent); - auto layout = new QVBoxLayout(box); +QGroupBox *ExportDialog::setupAdvancedGroup(QWidget *p_parent) { + auto box = new QGroupBox(tr("Advanced"), p_parent); + auto layout = new QVBoxLayout(box); - m_advancedSettings.resize(AdvancedSettings::Max); + m_advancedSettings.resize(AdvancedSettings::Max); - m_advancedSettings[AdvancedSettings::General] = setupGeneralAdvancedSettings(box); - layout->addWidget(m_advancedSettings[AdvancedSettings::General]); + m_advancedSettings[AdvancedSettings::General] = setupGeneralAdvancedSettings(box); + layout->addWidget(m_advancedSettings[AdvancedSettings::General]); - return box; + return box; } -QWidget *ExportDialog::setupGeneralAdvancedSettings(QWidget *p_parent) -{ - QWidget *widget = new QWidget(p_parent); - auto layout = WidgetsFactory::createFormLayout(widget); - layout->setContentsMargins(0, 0, 0, 0); +QWidget *ExportDialog::setupGeneralAdvancedSettings(QWidget *p_parent) { + QWidget *widget = new QWidget(p_parent); + auto layout = WidgetsFactory::createFormLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); - { - m_recursiveCheckBox = WidgetsFactory::createCheckBox(tr("Process sub-folders"), widget); - layout->addRow(m_recursiveCheckBox); - } + { + m_recursiveCheckBox = WidgetsFactory::createCheckBox(tr("Process sub-folders"), widget); + layout->addRow(m_recursiveCheckBox); + } - { - m_exportAttachmentsCheckBox = WidgetsFactory::createCheckBox(tr("Export attachments"), widget); - layout->addRow(m_exportAttachmentsCheckBox); - } + { + m_exportAttachmentsCheckBox = WidgetsFactory::createCheckBox(tr("Export attachments"), widget); + layout->addRow(m_exportAttachmentsCheckBox); + } - return widget; + return widget; } -void ExportDialog::setupButtonBox() -{ - setDialogButtonBox(QDialogButtonBox::Close); +void ExportDialog::setupButtonBox() { + setDialogButtonBox(QDialogButtonBox::Close); - auto box = getDialogButtonBox(); + auto box = getDialogButtonBox(); - m_exportBtn = box->addButton(tr("Export"), QDialogButtonBox::ActionRole); - connect(m_exportBtn, &QPushButton::clicked, - this, &ExportDialog::startExport); + m_exportBtn = box->addButton(tr("Export"), QDialogButtonBox::ActionRole); + connect(m_exportBtn, &QPushButton::clicked, this, &ExportDialog::startExport); - m_openDirBtn = box->addButton(tr("Open Directory"), QDialogButtonBox::ActionRole); - connect(m_openDirBtn, &QPushButton::clicked, - this, [this]() { - auto dir = getOutputDir(); - if (!dir.isEmpty()) { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(dir)); - } - }); + m_openDirBtn = box->addButton(tr("Open Directory"), QDialogButtonBox::ActionRole); + connect(m_openDirBtn, &QPushButton::clicked, this, [this]() { + auto dir = getOutputDir(); + if (!dir.isEmpty()) { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(dir)); + } + }); - m_copyContentBtn = box->addButton(tr("Copy Content"), QDialogButtonBox::ActionRole); - m_copyContentBtn->setToolTip(tr("Copy exported file content")); - m_copyContentBtn->setEnabled(false); - connect(m_copyContentBtn, &QPushButton::clicked, - this, [this]() { - if (m_exportedFile.isEmpty()) { - return; - } - - const auto content = FileUtils::readTextFile(m_exportedFile); - if (!content.isEmpty()) { - ClipboardUtils::setTextToClipboard(content); - } - }); -} + m_copyContentBtn = box->addButton(tr("Copy Content"), QDialogButtonBox::ActionRole); + m_copyContentBtn->setToolTip(tr("Copy exported file content")); + m_copyContentBtn->setEnabled(false); + connect(m_copyContentBtn, &QPushButton::clicked, this, [this]() { + if (m_exportedFile.isEmpty()) { + return; + } -QString ExportDialog::getOutputDir() const -{ - return m_outputDirInput->text(); + const auto content = FileUtils::readTextFile(m_exportedFile); + if (!content.isEmpty()) { + ClipboardUtils::setTextToClipboard(content); + } + }); } -void ExportDialog::initOptions() -{ - // Read it from config. - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - m_option = sessionConfig.getExportOption(); - m_customOptions = sessionConfig.getCustomExportOptions(); +QString ExportDialog::getOutputDir() const { return m_outputDirInput->text(); } - const auto &theme = VNoteX::getInst().getThemeMgr().getCurrentTheme(); - m_option.m_renderingStyleFile = theme.getFile(Theme::File::WebStyleSheet); - m_option.m_syntaxHighlightStyleFile = theme.getFile(Theme::File::HighlightStyleSheet); +void ExportDialog::initOptions() { + // Read it from config. + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + m_option = sessionConfig.getExportOption(); + m_customOptions = sessionConfig.getCustomExportOptions(); - if (m_option.m_outputDir.isEmpty()) { - m_option.m_outputDir = getDefaultOutputDir(); - } + const auto &theme = VNoteX::getInst().getThemeMgr().getCurrentTheme(); + m_option.m_renderingStyleFile = theme.getFile(Theme::File::WebStyleSheet); + m_option.m_syntaxHighlightStyleFile = theme.getFile(Theme::File::HighlightStyleSheet); - if (findCustomOption(m_option.m_customExport) == -1) { - m_option.m_customExport = m_customOptions.isEmpty() ? QString() : m_customOptions[0].m_name; - } + if (m_option.m_outputDir.isEmpty()) { + m_option.m_outputDir = getDefaultOutputDir(); + } + + if (findCustomOption(m_option.m_customExport) == -1) { + m_option.m_customExport = m_customOptions.isEmpty() ? QString() : m_customOptions[0].m_name; + } } -void ExportDialog::restoreFields(const ExportOption &p_option) -{ - { - int idx = m_sourceComboBox->findData(static_cast(p_option.m_source)); - if (idx != -1) { - m_sourceComboBox->setCurrentIndex(idx); - } +void ExportDialog::restoreFields(const ExportOption &p_option) { + { + int idx = m_sourceComboBox->findData(static_cast(p_option.m_source)); + if (idx != -1) { + m_sourceComboBox->setCurrentIndex(idx); } + } - { - int idx = m_targetFormatComboBox->findData(static_cast(p_option.m_targetFormat)); - if (idx != -1) { - m_targetFormatComboBox->setCurrentIndex(idx); - } + { + int idx = m_targetFormatComboBox->findData(static_cast(p_option.m_targetFormat)); + if (idx != -1) { + m_targetFormatComboBox->setCurrentIndex(idx); } + } - m_transparentBgCheckBox->setChecked(p_option.m_useTransparentBg); + m_transparentBgCheckBox->setChecked(p_option.m_useTransparentBg); - { - int idx = m_renderingStyleComboBox->findData(p_option.m_renderingStyleFile); - if (idx != -1) { - m_renderingStyleComboBox->setCurrentIndex(idx); - } + { + int idx = m_renderingStyleComboBox->findData(p_option.m_renderingStyleFile); + if (idx != -1) { + m_renderingStyleComboBox->setCurrentIndex(idx); } + } - { - int idx = m_syntaxHighlightStyleComboBox->findData(p_option.m_syntaxHighlightStyleFile); - if (idx != -1) { - m_syntaxHighlightStyleComboBox->setCurrentIndex(idx); - } + { + int idx = m_syntaxHighlightStyleComboBox->findData(p_option.m_syntaxHighlightStyleFile); + if (idx != -1) { + m_syntaxHighlightStyleComboBox->setCurrentIndex(idx); } + } - m_outputDirInput->setText(p_option.m_outputDir); + m_outputDirInput->setText(p_option.m_outputDir); - m_recursiveCheckBox->setChecked(p_option.m_recursive); + m_recursiveCheckBox->setChecked(p_option.m_recursive); - m_exportAttachmentsCheckBox->setChecked(p_option.m_exportAttachments); + m_exportAttachmentsCheckBox->setChecked(p_option.m_exportAttachments); } -void ExportDialog::saveFields(ExportOption &p_option) -{ - p_option.m_source = static_cast(m_sourceComboBox->currentData().toInt()); - p_option.m_targetFormat = static_cast(m_targetFormatComboBox->currentData().toInt()); - p_option.m_useTransparentBg = m_transparentBgCheckBox->isChecked(); - p_option.m_renderingStyleFile = m_renderingStyleComboBox->currentData().toString(); - p_option.m_syntaxHighlightStyleFile = m_syntaxHighlightStyleComboBox->currentData().toString(); - p_option.m_outputDir = getOutputDir(); - p_option.m_recursive = m_recursiveCheckBox->isChecked(); - p_option.m_exportAttachments = m_exportAttachmentsCheckBox->isChecked(); +void ExportDialog::saveFields(ExportOption &p_option) { + p_option.m_source = static_cast(m_sourceComboBox->currentData().toInt()); + p_option.m_targetFormat = + static_cast(m_targetFormatComboBox->currentData().toInt()); + p_option.m_useTransparentBg = m_transparentBgCheckBox->isChecked(); + p_option.m_renderingStyleFile = m_renderingStyleComboBox->currentData().toString(); + p_option.m_syntaxHighlightStyleFile = m_syntaxHighlightStyleComboBox->currentData().toString(); + p_option.m_outputDir = getOutputDir(); + p_option.m_recursive = m_recursiveCheckBox->isChecked(); + p_option.m_exportAttachments = m_exportAttachmentsCheckBox->isChecked(); - if (m_advancedSettings[AdvancedSettings::HTML]) { - saveFields(p_option.m_htmlOption); - } + if (m_advancedSettings[AdvancedSettings::HTML]) { + saveFields(p_option.m_htmlOption); + } - if (m_advancedSettings[AdvancedSettings::PDF]) { - saveFields(p_option.m_pdfOption); - } + if (m_advancedSettings[AdvancedSettings::PDF]) { + saveFields(p_option.m_pdfOption); + } - if (m_advancedSettings[AdvancedSettings::Custom]) { - saveCustomFields(p_option); - } + if (m_advancedSettings[AdvancedSettings::Custom]) { + saveCustomFields(p_option); + } } -void ExportDialog::startExport() -{ - if (m_exportOngoing) { - return; - } +void ExportDialog::startExport() { + if (m_exportOngoing) { + return; + } - // On start. - { - clearInformationText(); - m_exportedFile.clear(); - m_exportOngoing = true; - updateUIOnExport(); - } + // On start. + { + clearInformationText(); + m_exportedFile.clear(); + m_exportOngoing = true; + updateUIOnExport(); + } - saveFields(m_option); + saveFields(m_option); - int ret = doExport(m_option); - appendLog(tr("%n file(s) exported", "", ret)); + int ret = doExport(m_option); + appendLog(tr("%n file(s) exported", "", ret)); - // On end. - { - m_exportOngoing = false; - updateUIOnExport(); - } + // On end. + { + m_exportOngoing = false; + updateUIOnExport(); + } } -void ExportDialog::rejectedButtonClicked() -{ - if (m_exportOngoing) { - // Just cancel the export. - appendLog(tr("Cancelling the export")); - getExporter()->stop(); - } else { - Dialog::rejectedButtonClicked(); - } +void ExportDialog::rejectedButtonClicked() { + if (m_exportOngoing) { + // Just cancel the export. + appendLog(tr("Cancelling the export")); + getExporter()->stop(); + } else { + Dialog::rejectedButtonClicked(); + } } -void ExportDialog::appendLog(const QString &p_log) -{ - appendInformationText(">>> " + p_log); - QCoreApplication::sendPostedEvents(); +void ExportDialog::appendLog(const QString &p_log) { + appendInformationText(">>> " + p_log); + QCoreApplication::sendPostedEvents(); } -void ExportDialog::updateUIOnExport() -{ - m_exportBtn->setEnabled(!m_exportOngoing); - if (m_exportOngoing) { - m_progressBar->setMaximum(0); - m_progressBar->show(); - } else { - m_progressBar->hide(); - } - m_copyContentBtn->setEnabled(!m_exportedFile.isEmpty()); -} - -int ExportDialog::doExport(ExportOption p_option) -{ - if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf) { - // Check wkhtmltopdf executable. - const auto &wkExePath = p_option.m_pdfOption.m_wkhtmltopdfExePath; - if (wkExePath.isEmpty() || !QFileInfo::exists(wkExePath)) { - appendLog(tr("Please specify a valid wkhtmltopdf executable file (%1)").arg(wkExePath)); - return 0; - } - - p_option.m_transformSvgToPngEnabled = true; - p_option.m_removeCodeToolBarEnabled = true; - } else if (p_option.m_targetFormat == ExportFormat::Custom) { - int optIdx = findCustomOption(p_option.m_customExport); - if (optIdx == -1) { - appendLog(tr("Please specify a valid scheme")); - return 0; - } - - p_option.m_customOption = &m_customOptions[optIdx]; - } - - int exportedFilesCount = 0; +void ExportDialog::updateUIOnExport() { + m_exportBtn->setEnabled(!m_exportOngoing); + if (m_exportOngoing) { + m_progressBar->setMaximum(0); + m_progressBar->show(); + } else { + m_progressBar->hide(); + } + m_copyContentBtn->setEnabled(!m_exportedFile.isEmpty()); +} + +int ExportDialog::doExport(ExportOption p_option) { + if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf) { + // Check wkhtmltopdf executable. + const auto &wkExePath = p_option.m_pdfOption.m_wkhtmltopdfExePath; + if (wkExePath.isEmpty() || !QFileInfo::exists(wkExePath)) { + appendLog(tr("Please specify a valid wkhtmltopdf executable file (%1)").arg(wkExePath)); + return 0; + } + + p_option.m_transformSvgToPngEnabled = true; + p_option.m_removeCodeToolBarEnabled = true; + } else if (p_option.m_targetFormat == ExportFormat::Custom) { + int optIdx = findCustomOption(p_option.m_customExport); + if (optIdx == -1) { + appendLog(tr("Please specify a valid scheme")); + return 0; + } + + p_option.m_customOption = &m_customOptions[optIdx]; + } + + int exportedFilesCount = 0; + + switch (p_option.m_source) { + case ExportSource::CurrentBuffer: { + Q_ASSERT(m_buffer); + const auto outputFile = getExporter()->doExport(p_option, m_buffer); + exportedFilesCount = outputFile.isEmpty() ? 0 : 1; + if (exportedFilesCount == 1 && p_option.m_targetFormat == ExportFormat::HTML) { + m_exportedFile = outputFile; + } + break; + } + + case ExportSource::CurrentNote: { + Q_ASSERT(m_note); + const auto outputFile = getExporter()->doExport(p_option, m_note); + exportedFilesCount = outputFile.isEmpty() ? 0 : 1; + if (exportedFilesCount == 1 && p_option.m_targetFormat == ExportFormat::HTML) { + m_exportedFile = outputFile; + } + break; + } + + case ExportSource::CurrentFolder: { + Q_ASSERT(m_folder); + const auto outputFiles = getExporter()->doExportFolder(p_option, m_folder); + exportedFilesCount = outputFiles.size(); + break; + } + + case ExportSource::CurrentNotebook: { + Q_ASSERT(m_notebook); + const auto outputFiles = getExporter()->doExport(p_option, m_notebook); + exportedFilesCount = outputFiles.size(); + break; + } + } + + return exportedFilesCount; +} + +Exporter *ExportDialog::getExporter() { + if (!m_exporter) { + m_exporter = new Exporter(this); + connect(m_exporter, &Exporter::progressUpdated, this, &ExportDialog::updateProgress); + connect(m_exporter, &Exporter::logRequested, this, &ExportDialog::appendLog); + } + return m_exporter; +} + +void ExportDialog::updateProgress(int p_val, int p_maximum) { + if (p_maximum < m_progressBar->value()) { + m_progressBar->setValue(p_val); + m_progressBar->setMaximum(p_maximum); + } else { + m_progressBar->setMaximum(p_maximum); + m_progressBar->setValue(p_val); + } +} + +QWidget *ExportDialog::getHtmlAdvancedSettings() { + if (!m_advancedSettings[AdvancedSettings::HTML]) { + // Setup HTML advanced settings. + QWidget *widget = new QWidget(m_advancedGroupBox); + auto layout = WidgetsFactory::createFormLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); - switch (p_option.m_source) { - case ExportSource::CurrentBuffer: { - Q_ASSERT(m_buffer); - const auto outputFile = getExporter()->doExport(p_option, m_buffer); - exportedFilesCount = outputFile.isEmpty() ? 0 : 1; - if (exportedFilesCount == 1 && p_option.m_targetFormat == ExportFormat::HTML) { - m_exportedFile = outputFile; - } - break; + m_embedStylesCheckBox = WidgetsFactory::createCheckBox(tr("Embed styles"), widget); + layout->addRow(m_embedStylesCheckBox); } - case ExportSource::CurrentNote: { - Q_ASSERT(m_note); - const auto outputFile = getExporter()->doExport(p_option, m_note); - exportedFilesCount = outputFile.isEmpty() ? 0 : 1; - if (exportedFilesCount == 1 && p_option.m_targetFormat == ExportFormat::HTML) { - m_exportedFile = outputFile; - } - break; + m_embedImagesCheckBox = WidgetsFactory::createCheckBox(tr("Embed images"), widget); + layout->addRow(m_embedImagesCheckBox); } - case ExportSource::CurrentFolder: { - Q_ASSERT(m_folder); - const auto outputFiles = getExporter()->doExportFolder(p_option, m_folder); - exportedFilesCount = outputFiles.size(); - break; + m_completePageCheckBox = WidgetsFactory::createCheckBox(tr("Complete page"), widget); + m_completePageCheckBox->setToolTip( + tr("Export the whole page along with images which may change the links structure")); + connect(m_completePageCheckBox, &QCheckBox::stateChanged, this, [this](int p_state) { + bool checked = p_state == Qt::Checked; + m_embedImagesCheckBox->setEnabled(checked); + }); + layout->addRow(m_completePageCheckBox); } - case ExportSource::CurrentNotebook: { - Q_ASSERT(m_notebook); - const auto outputFiles = getExporter()->doExport(p_option, m_notebook); - exportedFilesCount = outputFiles.size(); - break; - } + m_useMimeHtmlFormatCheckBox = WidgetsFactory::createCheckBox(tr("Mime HTML format"), widget); + connect(m_useMimeHtmlFormatCheckBox, &QCheckBox::stateChanged, this, [this](int p_state) { + bool checked = p_state == Qt::Checked; + m_embedStylesCheckBox->setEnabled(!checked); + m_completePageCheckBox->setEnabled(!checked); + }); + // TODO: do not support MHTML for now. + m_useMimeHtmlFormatCheckBox->setEnabled(false); + m_useMimeHtmlFormatCheckBox->hide(); + layout->addRow(m_useMimeHtmlFormatCheckBox); } - return exportedFilesCount; -} - -Exporter *ExportDialog::getExporter() -{ - if (!m_exporter) { - m_exporter = new Exporter(this); - connect(m_exporter, &Exporter::progressUpdated, - this, &ExportDialog::updateProgress); - connect(m_exporter, &Exporter::logRequested, - this, &ExportDialog::appendLog); - } - return m_exporter; -} - -void ExportDialog::updateProgress(int p_val, int p_maximum) -{ - if (p_maximum < m_progressBar->value()) { - m_progressBar->setValue(p_val); - m_progressBar->setMaximum(p_maximum); - } else { - m_progressBar->setMaximum(p_maximum); - m_progressBar->setValue(p_val); + { + m_addOutlinePanelCheckBox = WidgetsFactory::createCheckBox(tr("Add outline panel"), widget); + layout->addRow(m_addOutlinePanelCheckBox); } -} - -QWidget *ExportDialog::getHtmlAdvancedSettings() -{ - if (!m_advancedSettings[AdvancedSettings::HTML]) { - // Setup HTML advanced settings. - QWidget *widget = new QWidget(m_advancedGroupBox); - auto layout = WidgetsFactory::createFormLayout(widget); - layout->setContentsMargins(0, 0, 0, 0); - - { - m_embedStylesCheckBox = WidgetsFactory::createCheckBox(tr("Embed styles"), widget); - layout->addRow(m_embedStylesCheckBox); - } - - { - m_embedImagesCheckBox = WidgetsFactory::createCheckBox(tr("Embed images"), widget); - layout->addRow(m_embedImagesCheckBox); - } - - { - m_completePageCheckBox = WidgetsFactory::createCheckBox(tr("Complete page"), widget); - m_completePageCheckBox->setToolTip(tr("Export the whole page along with images which may change the links structure")); - connect(m_completePageCheckBox, &QCheckBox::stateChanged, - this, [this](int p_state) { - bool checked = p_state == Qt::Checked; - m_embedImagesCheckBox->setEnabled(checked); - }); - layout->addRow(m_completePageCheckBox); - } - - { - m_useMimeHtmlFormatCheckBox = WidgetsFactory::createCheckBox(tr("Mime HTML format"), widget); - connect(m_useMimeHtmlFormatCheckBox, &QCheckBox::stateChanged, - this, [this](int p_state) { - bool checked = p_state == Qt::Checked; - m_embedStylesCheckBox->setEnabled(!checked); - m_completePageCheckBox->setEnabled(!checked); - }); - // TODO: do not support MHTML for now. - m_useMimeHtmlFormatCheckBox->setEnabled(false); - m_useMimeHtmlFormatCheckBox->hide(); - layout->addRow(m_useMimeHtmlFormatCheckBox); - } - - { - m_addOutlinePanelCheckBox = WidgetsFactory::createCheckBox(tr("Add outline panel"), widget); - layout->addRow(m_addOutlinePanelCheckBox); - } - m_advancedGroupBox->layout()->addWidget(widget); + m_advancedGroupBox->layout()->addWidget(widget); - m_advancedSettings[AdvancedSettings::HTML] = widget; + m_advancedSettings[AdvancedSettings::HTML] = widget; - restoreFields(m_option.m_htmlOption); - } + restoreFields(m_option.m_htmlOption); + } - return m_advancedSettings[AdvancedSettings::HTML]; + return m_advancedSettings[AdvancedSettings::HTML]; } -void ExportDialog::showAdvancedSettings(AdvancedSettings p_settings) -{ - for (int i = AdvancedSettings::General + 1; i < m_advancedSettings.size(); ++i) { - if (m_advancedSettings[i]) { - m_advancedSettings[i]->hide(); - } +void ExportDialog::showAdvancedSettings(AdvancedSettings p_settings) { + for (int i = AdvancedSettings::General + 1; i < m_advancedSettings.size(); ++i) { + if (m_advancedSettings[i]) { + m_advancedSettings[i]->hide(); } + } - QWidget *widget = nullptr; - switch (p_settings) { - case AdvancedSettings::HTML: - widget = getHtmlAdvancedSettings(); - break; + QWidget *widget = nullptr; + switch (p_settings) { + case AdvancedSettings::HTML: + widget = getHtmlAdvancedSettings(); + break; - case AdvancedSettings::PDF: - widget = getPdfAdvancedSettings(); - break; + case AdvancedSettings::PDF: + widget = getPdfAdvancedSettings(); + break; - case AdvancedSettings::Custom: - widget = getCustomAdvancedSettings(); - break; + case AdvancedSettings::Custom: + widget = getCustomAdvancedSettings(); + break; - default: - break; - } + default: + break; + } - if (widget) { - widget->show(); - } + if (widget) { + widget->show(); + } } -void ExportDialog::restoreFields(const ExportHtmlOption &p_option) -{ - m_embedStylesCheckBox->setChecked(p_option.m_embedStyles); - m_embedImagesCheckBox->setChecked(p_option.m_embedImages); - m_completePageCheckBox->setChecked(p_option.m_completePage); - m_useMimeHtmlFormatCheckBox->setChecked(p_option.m_useMimeHtmlFormat); - m_addOutlinePanelCheckBox->setChecked(p_option.m_addOutlinePanel); +void ExportDialog::restoreFields(const ExportHtmlOption &p_option) { + m_embedStylesCheckBox->setChecked(p_option.m_embedStyles); + m_embedImagesCheckBox->setChecked(p_option.m_embedImages); + m_completePageCheckBox->setChecked(p_option.m_completePage); + m_useMimeHtmlFormatCheckBox->setChecked(p_option.m_useMimeHtmlFormat); + m_addOutlinePanelCheckBox->setChecked(p_option.m_addOutlinePanel); } -void ExportDialog::saveFields(ExportHtmlOption &p_option) -{ - p_option.m_embedStyles = m_embedStylesCheckBox->isChecked(); - p_option.m_embedImages = m_embedImagesCheckBox->isChecked(); - p_option.m_completePage = m_completePageCheckBox->isChecked(); - p_option.m_useMimeHtmlFormat = m_useMimeHtmlFormatCheckBox->isChecked(); - p_option.m_addOutlinePanel = m_addOutlinePanelCheckBox->isChecked(); +void ExportDialog::saveFields(ExportHtmlOption &p_option) { + p_option.m_embedStyles = m_embedStylesCheckBox->isChecked(); + p_option.m_embedImages = m_embedImagesCheckBox->isChecked(); + p_option.m_completePage = m_completePageCheckBox->isChecked(); + p_option.m_useMimeHtmlFormat = m_useMimeHtmlFormatCheckBox->isChecked(); + p_option.m_addOutlinePanel = m_addOutlinePanelCheckBox->isChecked(); } -QWidget *ExportDialog::getPdfAdvancedSettings() -{ - if (!m_advancedSettings[AdvancedSettings::PDF]) { - QWidget *widget = new QWidget(m_advancedGroupBox); - auto layout = WidgetsFactory::createFormLayout(widget); - layout->setContentsMargins(0, 0, 0, 0); - - { - m_pageLayoutBtn = new QPushButton(tr("Settings"), widget); - connect(m_pageLayoutBtn, &QPushButton::clicked, - this, [this]() { - QPrinter printer; - printer.setPageLayout(*m_pageLayout); - - QPageSetupDialog dlg(&printer, this); - if (dlg.exec() != QDialog::Accepted) { - return; - } +QWidget *ExportDialog::getPdfAdvancedSettings() { + if (!m_advancedSettings[AdvancedSettings::PDF]) { + QWidget *widget = new QWidget(m_advancedGroupBox); + auto layout = WidgetsFactory::createFormLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); - m_pageLayout->setUnits(QPageLayout::Millimeter); - m_pageLayout->setPageSize(printer.pageLayout().pageSize()); - m_pageLayout->setMargins(printer.pageLayout().margins(QPageLayout::Millimeter)); - m_pageLayout->setOrientation(printer.pageLayout().orientation()); + { + m_pageLayoutBtn = new QPushButton(tr("Settings"), widget); + connect(m_pageLayoutBtn, &QPushButton::clicked, this, [this]() { + QPrinter printer; + printer.setPageLayout(*m_pageLayout); - updatePageLayoutButtonLabel(); - }); - layout->addRow(tr("Page layout:"), m_pageLayoutBtn); + QPageSetupDialog dlg(&printer, this); + if (dlg.exec() != QDialog::Accepted) { + return; } - { - m_addTableOfContentsCheckBox = WidgetsFactory::createCheckBox(tr("Add Table-of-Contents"), widget); - layout->addRow(m_addTableOfContentsCheckBox); - } + m_pageLayout->setUnits(QPageLayout::Millimeter); + m_pageLayout->setPageSize(printer.pageLayout().pageSize()); + m_pageLayout->setMargins(printer.pageLayout().margins(QPageLayout::Millimeter)); + m_pageLayout->setOrientation(printer.pageLayout().orientation()); - { - auto useLayout = new QHBoxLayout(); + updatePageLayoutButtonLabel(); + }); + layout->addRow(tr("Page layout:"), m_pageLayoutBtn); + } - m_useWkhtmltopdfCheckBox = WidgetsFactory::createCheckBox(tr("Use wkhtmltopdf (outline supported)"), widget); - useLayout->addWidget(m_useWkhtmltopdfCheckBox); + { + m_addTableOfContentsCheckBox = + WidgetsFactory::createCheckBox(tr("Add Table-of-Contents"), widget); + layout->addRow(m_addTableOfContentsCheckBox); + } - auto downloadBtn = new QPushButton(tr("Download"), widget); - connect(downloadBtn, &QPushButton::clicked, - this, []() { - WidgetUtils::openUrlByDesktop(QUrl("https://wkhtmltopdf.org/downloads.html")); - }); - useLayout->addWidget(downloadBtn); + { + auto useLayout = new QHBoxLayout(); - layout->addRow(useLayout); - } + m_useWkhtmltopdfCheckBox = + WidgetsFactory::createCheckBox(tr("Use wkhtmltopdf (outline supported)"), widget); + useLayout->addWidget(m_useWkhtmltopdfCheckBox); - { - m_allInOneCheckBox = WidgetsFactory::createCheckBox(tr("All-in-One"), widget); - m_allInOneCheckBox->setToolTip(tr("Export all source files into one file")); - m_allInOneCheckBox->setEnabled(false); - connect(m_useWkhtmltopdfCheckBox, &QCheckBox::stateChanged, - this, [this](int p_state) { - m_allInOneCheckBox->setEnabled(p_state == Qt::Checked); - }); - layout->addRow(m_allInOneCheckBox); - } + auto downloadBtn = new QPushButton(tr("Download"), widget); + connect(downloadBtn, &QPushButton::clicked, this, []() { + WidgetUtils::openUrlByDesktop(QUrl("https://wkhtmltopdf.org/downloads.html")); + }); + useLayout->addWidget(downloadBtn); - { - auto pathLayout = new QHBoxLayout(); + layout->addRow(useLayout); + } - m_wkhtmltopdfExePathLineEdit = WidgetsFactory::createLineEdit(widget); - pathLayout->addWidget(m_wkhtmltopdfExePathLineEdit); + { + m_allInOneCheckBox = WidgetsFactory::createCheckBox(tr("All-in-One"), widget); + m_allInOneCheckBox->setToolTip(tr("Export all source files into one file")); + m_allInOneCheckBox->setEnabled(false); + connect(m_useWkhtmltopdfCheckBox, &QCheckBox::stateChanged, this, + [this](int p_state) { m_allInOneCheckBox->setEnabled(p_state == Qt::Checked); }); + layout->addRow(m_allInOneCheckBox); + } - auto browseBtn = new QPushButton(tr("Browse"), widget); - pathLayout->addWidget(browseBtn); - connect(browseBtn, &QPushButton::clicked, - this, [this]() { - QString filePath = QFileDialog::getOpenFileName(this, - tr("Select wkhtmltopdf Executable"), - QCoreApplication::applicationDirPath()); + { + auto pathLayout = new QHBoxLayout(); - if (!filePath.isEmpty()) { - m_wkhtmltopdfExePathLineEdit->setText(filePath); - } - }); + m_wkhtmltopdfExePathLineEdit = WidgetsFactory::createLineEdit(widget); + pathLayout->addWidget(m_wkhtmltopdfExePathLineEdit); - layout->addRow(tr("Wkhtmltopdf path:"), pathLayout); - } + auto browseBtn = new QPushButton(tr("Browse"), widget); + pathLayout->addWidget(browseBtn); + connect(browseBtn, &QPushButton::clicked, this, [this]() { + QString filePath = QFileDialog::getOpenFileName(this, tr("Select wkhtmltopdf Executable"), + QCoreApplication::applicationDirPath()); - { - m_wkhtmltopdfArgsLineEdit = WidgetsFactory::createLineEdit(widget); - layout->addRow(tr("Wkhtmltopdf arguments:"), m_wkhtmltopdfArgsLineEdit); + if (!filePath.isEmpty()) { + m_wkhtmltopdfExePathLineEdit->setText(filePath); } + }); - m_advancedGroupBox->layout()->addWidget(widget); - - m_advancedSettings[AdvancedSettings::PDF] = widget; + layout->addRow(tr("Wkhtmltopdf path:"), pathLayout); + } - restoreFields(m_option.m_pdfOption); + { + m_wkhtmltopdfArgsLineEdit = WidgetsFactory::createLineEdit(widget); + layout->addRow(tr("Wkhtmltopdf arguments:"), m_wkhtmltopdfArgsLineEdit); } - return m_advancedSettings[AdvancedSettings::PDF]; + m_advancedGroupBox->layout()->addWidget(widget); + + m_advancedSettings[AdvancedSettings::PDF] = widget; + + restoreFields(m_option.m_pdfOption); + } + + return m_advancedSettings[AdvancedSettings::PDF]; } -QWidget *ExportDialog::getCustomAdvancedSettings() -{ - if (!m_advancedSettings[AdvancedSettings::Custom]) { - QWidget *widget = new QWidget(m_advancedGroupBox); - auto layout = WidgetsFactory::createFormLayout(widget); - layout->setContentsMargins(0, 0, 0, 0); +QWidget *ExportDialog::getCustomAdvancedSettings() { + if (!m_advancedSettings[AdvancedSettings::Custom]) { + QWidget *widget = new QWidget(m_advancedGroupBox); + auto layout = WidgetsFactory::createFormLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); - { - auto schemeLayout = new QHBoxLayout(); - layout->addRow(tr("Scheme:"), schemeLayout); + { + auto schemeLayout = new QHBoxLayout(); + layout->addRow(tr("Scheme:"), schemeLayout); - m_customExportComboBox = WidgetsFactory::createComboBox(widget); - m_customExportComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - schemeLayout->addWidget(m_customExportComboBox, 1); + m_customExportComboBox = WidgetsFactory::createComboBox(widget); + m_customExportComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + schemeLayout->addWidget(m_customExportComboBox, 1); - auto addBtn = new QPushButton(tr("New"), widget); - addBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - connect(addBtn, &QPushButton::clicked, - this, &ExportDialog::addCustomExportScheme); - schemeLayout->addWidget(addBtn); + auto addBtn = new QPushButton(tr("New"), widget); + addBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + connect(addBtn, &QPushButton::clicked, this, &ExportDialog::addCustomExportScheme); + schemeLayout->addWidget(addBtn); - auto delBtn = new QPushButton(tr("Delete"), widget); - delBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - connect(delBtn, &QPushButton::clicked, - this, &ExportDialog::removeCustomExportScheme); - schemeLayout->addWidget(delBtn); - } + auto delBtn = new QPushButton(tr("Delete"), widget); + delBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + connect(delBtn, &QPushButton::clicked, this, &ExportDialog::removeCustomExportScheme); + schemeLayout->addWidget(delBtn); + } - { - m_targetSuffixLineEdit = WidgetsFactory::createLineEdit(widget); - m_targetSuffixLineEdit->setToolTip(tr("Suffix of the target file like docs/pdf/epub")); - m_targetSuffixLineEdit->setEnabled(false); - layout->addRow(tr("Target file suffix:"), m_targetSuffixLineEdit); - } + { + m_targetSuffixLineEdit = WidgetsFactory::createLineEdit(widget); + m_targetSuffixLineEdit->setToolTip(tr("Suffix of the target file like docs/pdf/epub")); + m_targetSuffixLineEdit->setEnabled(false); + layout->addRow(tr("Target file suffix:"), m_targetSuffixLineEdit); + } - { - m_resourcePathSeparatorLineEdit = WidgetsFactory::createLineEdit(widget); - m_resourcePathSeparatorLineEdit->setToolTip(tr("Separator used to concatenate resource folder paths")); - m_resourcePathSeparatorLineEdit->setEnabled(false); - layout->addRow(tr("Resource path separator:"), m_resourcePathSeparatorLineEdit); - } + { + m_resourcePathSeparatorLineEdit = WidgetsFactory::createLineEdit(widget); + m_resourcePathSeparatorLineEdit->setToolTip( + tr("Separator used to concatenate resource folder paths")); + m_resourcePathSeparatorLineEdit->setEnabled(false); + layout->addRow(tr("Resource path separator:"), m_resourcePathSeparatorLineEdit); + } - { - m_useHtmlInputCheckBox = WidgetsFactory::createCheckBox(tr("Use HTML format as input"), widget); - m_useHtmlInputCheckBox->setToolTip(tr("Convert to HTMl format first as the input of the custom export command")); - m_useHtmlInputCheckBox->setEnabled(false); - layout->addRow(m_useHtmlInputCheckBox); - } + { + m_useHtmlInputCheckBox = + WidgetsFactory::createCheckBox(tr("Use HTML format as input"), widget); + m_useHtmlInputCheckBox->setToolTip( + tr("Convert to HTMl format first as the input of the custom export command")); + m_useHtmlInputCheckBox->setEnabled(false); + layout->addRow(m_useHtmlInputCheckBox); + } - { - m_allInOneCheckBox = WidgetsFactory::createCheckBox(tr("All-in-One"), widget); - m_allInOneCheckBox->setToolTip(tr("Export all source files into one file")); - m_allInOneCheckBox->setEnabled(false); - layout->addRow(m_allInOneCheckBox); - } + { + m_allInOneCheckBox = WidgetsFactory::createCheckBox(tr("All-in-One"), widget); + m_allInOneCheckBox->setToolTip(tr("Export all source files into one file")); + m_allInOneCheckBox->setEnabled(false); + layout->addRow(m_allInOneCheckBox); + } - { - m_targetPageScrollableCheckBox = WidgetsFactory::createCheckBox(tr("Target page scrollable"), widget); - m_targetPageScrollableCheckBox->setToolTip(tr("Whether the page of the target file is scrollable")); - m_targetPageScrollableCheckBox->setEnabled(false); - layout->addRow(m_targetPageScrollableCheckBox); - } + { + m_targetPageScrollableCheckBox = + WidgetsFactory::createCheckBox(tr("Target page scrollable"), widget); + m_targetPageScrollableCheckBox->setToolTip( + tr("Whether the page of the target file is scrollable")); + m_targetPageScrollableCheckBox->setEnabled(false); + layout->addRow(m_targetPageScrollableCheckBox); + } - { - auto usage = tr("Command:\n" - "\t%1: List of input files.\n" - "\t%2: List of paths to search for images and other resources.\n" - "\t%3: Path of rendering CSS style sheet.\n" - "\t%4: Path of syntax highlighting CSS style sheet.\n" - "\t%5: Path of output file."); - layout->addRow(new QLabel(usage, widget)); - } + { + auto usage = tr("Command:\n" + "\t%1: List of input files.\n" + "\t%2: List of paths to search for images and other resources.\n" + "\t%3: Path of rendering CSS style sheet.\n" + "\t%4: Path of syntax highlighting CSS style sheet.\n" + "\t%5: Path of output file."); + layout->addRow(new QLabel(usage, widget)); + } - { - m_commandTextEdit = WidgetsFactory::createPlainTextEdit(widget); + { + m_commandTextEdit = WidgetsFactory::createPlainTextEdit(widget); #if defined(Q_OS_WIN) - m_commandTextEdit->setPlaceholderText("pandoc.exe --resource-path=.;%2 --css=%3 --css=%4 -s -o %5 %1"); + m_commandTextEdit->setPlaceholderText( + "pandoc.exe --resource-path=.;%2 --css=%3 --css=%4 -s -o %5 %1"); #else - m_commandTextEdit->setPlaceholderText("pandoc --resource-path=.:%2 --css=%3 --css=%4 -s -o %5 %1"); + m_commandTextEdit->setPlaceholderText( + "pandoc --resource-path=.:%2 --css=%3 --css=%4 -s -o %5 %1"); #endif - m_commandTextEdit->setMaximumHeight(m_commandTextEdit->minimumSizeHint().height()); - m_commandTextEdit->setEnabled(false); - layout->addRow(m_commandTextEdit); - } + m_commandTextEdit->setMaximumHeight(m_commandTextEdit->minimumSizeHint().height()); + m_commandTextEdit->setEnabled(false); + layout->addRow(m_commandTextEdit); + } - connect(m_customExportComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &ExportDialog::customExportCurrentSchemeChanged); + connect(m_customExportComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ExportDialog::customExportCurrentSchemeChanged); - m_advancedGroupBox->layout()->addWidget(widget); + m_advancedGroupBox->layout()->addWidget(widget); - m_advancedSettings[AdvancedSettings::Custom] = widget; + m_advancedSettings[AdvancedSettings::Custom] = widget; - restoreCustomFields(m_option); - } + restoreCustomFields(m_option); + } - return m_advancedSettings[AdvancedSettings::Custom]; + return m_advancedSettings[AdvancedSettings::Custom]; } -void ExportDialog::restoreFields(const ExportPdfOption &p_option) -{ - m_pageLayout = p_option.m_layout; - updatePageLayoutButtonLabel(); +void ExportDialog::restoreFields(const ExportPdfOption &p_option) { + m_pageLayout = p_option.m_layout; + updatePageLayoutButtonLabel(); - m_addTableOfContentsCheckBox->setChecked(p_option.m_addTableOfContents); - m_useWkhtmltopdfCheckBox->setChecked(p_option.m_useWkhtmltopdf); - m_allInOneCheckBox->setChecked(p_option.m_allInOne); - m_wkhtmltopdfExePathLineEdit->setText(p_option.m_wkhtmltopdfExePath); - m_wkhtmltopdfArgsLineEdit->setText(p_option.m_wkhtmltopdfArgs); + m_addTableOfContentsCheckBox->setChecked(p_option.m_addTableOfContents); + m_useWkhtmltopdfCheckBox->setChecked(p_option.m_useWkhtmltopdf); + m_allInOneCheckBox->setChecked(p_option.m_allInOne); + m_wkhtmltopdfExePathLineEdit->setText(p_option.m_wkhtmltopdfExePath); + m_wkhtmltopdfArgsLineEdit->setText(p_option.m_wkhtmltopdfArgs); } -void ExportDialog::saveFields(ExportPdfOption &p_option) -{ - p_option.m_layout = m_pageLayout; - p_option.m_addTableOfContents = m_addTableOfContentsCheckBox->isChecked(); - p_option.m_useWkhtmltopdf = m_useWkhtmltopdfCheckBox->isChecked(); - p_option.m_allInOne = m_allInOneCheckBox->isChecked(); - p_option.m_wkhtmltopdfExePath = m_wkhtmltopdfExePathLineEdit->text(); - p_option.m_wkhtmltopdfArgs = m_wkhtmltopdfArgsLineEdit->text(); +void ExportDialog::saveFields(ExportPdfOption &p_option) { + p_option.m_layout = m_pageLayout; + p_option.m_addTableOfContents = m_addTableOfContentsCheckBox->isChecked(); + p_option.m_useWkhtmltopdf = m_useWkhtmltopdfCheckBox->isChecked(); + p_option.m_allInOne = m_allInOneCheckBox->isChecked(); + p_option.m_wkhtmltopdfExePath = m_wkhtmltopdfExePathLineEdit->text(); + p_option.m_wkhtmltopdfArgs = m_wkhtmltopdfArgsLineEdit->text(); } -void ExportDialog::restoreCustomFields(const ExportOption &p_option) -{ - m_customExportComboBox->clear(); - int curIndex = -1; - for (int i = 0; i < m_customOptions.size(); ++i) { - m_customExportComboBox->addItem(m_customOptions[i].m_name, m_customOptions[i].m_name); - if (m_customOptions[i].m_name == p_option.m_customExport) { - curIndex = i; - } +void ExportDialog::restoreCustomFields(const ExportOption &p_option) { + m_customExportComboBox->clear(); + int curIndex = -1; + for (int i = 0; i < m_customOptions.size(); ++i) { + m_customExportComboBox->addItem(m_customOptions[i].m_name, m_customOptions[i].m_name); + if (m_customOptions[i].m_name == p_option.m_customExport) { + curIndex = i; } - m_customExportComboBox->setCurrentIndex(curIndex); + } + m_customExportComboBox->setCurrentIndex(curIndex); } -void ExportDialog::saveCustomFields(ExportOption &p_option) -{ - p_option.m_customExport = m_customExportComboBox->currentData().toString(); +void ExportDialog::saveCustomFields(ExportOption &p_option) { + p_option.m_customExport = m_customExportComboBox->currentData().toString(); - int idx = findCustomOption(p_option.m_customExport); - if (idx > -1) { - auto &opt = m_customOptions[idx]; - opt.m_targetSuffix = m_targetSuffixLineEdit->text(); - opt.m_resourcePathSeparator = m_resourcePathSeparatorLineEdit->text(); - opt.m_useHtmlInput = m_useHtmlInputCheckBox->isChecked(); - opt.m_allInOne = m_allInOneCheckBox->isChecked(); - opt.m_targetPageScrollable = m_targetPageScrollableCheckBox->isChecked(); - - opt.m_command = m_commandTextEdit->toPlainText().trimmed(); - int lineIdx = opt.m_command.indexOf(QLatin1Char('\n')); - if (lineIdx > -1) { - opt.m_command = opt.m_command.left(lineIdx); - } + int idx = findCustomOption(p_option.m_customExport); + if (idx > -1) { + auto &opt = m_customOptions[idx]; + opt.m_targetSuffix = m_targetSuffixLineEdit->text(); + opt.m_resourcePathSeparator = m_resourcePathSeparatorLineEdit->text(); + opt.m_useHtmlInput = m_useHtmlInputCheckBox->isChecked(); + opt.m_allInOne = m_allInOneCheckBox->isChecked(); + opt.m_targetPageScrollable = m_targetPageScrollableCheckBox->isChecked(); - ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); + opt.m_command = m_commandTextEdit->toPlainText().trimmed(); + int lineIdx = opt.m_command.indexOf(QLatin1Char('\n')); + if (lineIdx > -1) { + opt.m_command = opt.m_command.left(lineIdx); } -} -void ExportDialog::updatePageLayoutButtonLabel() -{ - Q_ASSERT(m_pageLayout); - m_pageLayoutBtn->setText( - QStringLiteral("%1, %2").arg(m_pageLayout->pageSize().name(), - m_pageLayout->orientation() == QPageLayout::Portrait ? tr("Portrait") : tr("Landscape"))); + ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); + } } -int ExportDialog::findCustomOption(const QString &p_name) const -{ - if (p_name.isEmpty()) { - return -1; - } - - for (int i = 0; i < m_customOptions.size(); ++i) { - if (m_customOptions[i].m_name == p_name) { - return i; - } - } - - return -1; +void ExportDialog::updatePageLayoutButtonLabel() { + Q_ASSERT(m_pageLayout); + m_pageLayoutBtn->setText(QStringLiteral("%1, %2").arg( + m_pageLayout->pageSize().name(), + m_pageLayout->orientation() == QPageLayout::Portrait ? tr("Portrait") : tr("Landscape"))); } -void ExportDialog::addCustomExportScheme() -{ - QString name; - while (true) { - name = QInputDialog::getText(this, tr("New Custom Export Scheme"), tr("Scheme name:")); - if (name.isEmpty()) { - return; - } - - if (findCustomOption(name) != -1) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Name conflicts with existing scheme."), - this); - } else { - break; - } - } - - // Based on current scheme. - ExportCustomOption newOption; +int ExportDialog::findCustomOption(const QString &p_name) const { + if (p_name.isEmpty()) { + return -1; + } - { - int curIndex = findCustomOption(m_customExportComboBox->currentData().toString()); - if (curIndex > -1) { - newOption = m_customOptions[curIndex]; - } + for (int i = 0; i < m_customOptions.size(); ++i) { + if (m_customOptions[i].m_name == p_name) { + return i; } + } - newOption.m_name = name; - m_customOptions.append(newOption); - ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); - - // Add it to combo box. - m_customExportComboBox->addItem(name, name); - m_customExportComboBox->setCurrentIndex(m_customExportComboBox->findData(name)); + return -1; } -void ExportDialog::removeCustomExportScheme() -{ - auto name = m_customExportComboBox->currentData().toString(); +void ExportDialog::addCustomExportScheme() { + QString name; + while (true) { + name = QInputDialog::getText(this, tr("New Custom Export Scheme"), tr("Scheme name:")); if (name.isEmpty()) { - return; - } - - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, - tr("Delete scheme (%1)?").arg(name), - QString(), - QString(), - this); - if (ret != QMessageBox::Ok) { - return; + return; } - int idx = findCustomOption(name); - Q_ASSERT(idx > -1); - m_customOptions.remove(idx); - ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); - - m_customExportComboBox->removeItem(m_customExportComboBox->currentIndex()); -} - -void ExportDialog::customExportCurrentSchemeChanged(int p_comboIdx) -{ - const bool enabled = p_comboIdx >= 0; - m_targetSuffixLineEdit->setEnabled(enabled); - m_resourcePathSeparatorLineEdit->setEnabled(enabled); - m_useHtmlInputCheckBox->setEnabled(enabled); - m_allInOneCheckBox->setEnabled(enabled); - m_targetPageScrollableCheckBox->setEnabled(enabled); - m_commandTextEdit->setEnabled(enabled); - - if (p_comboIdx < 0) { - m_option.m_customExport.clear(); - return; - } - - auto name = m_customExportComboBox->currentData().toString(); - m_option.m_customExport = name; - int curIndex = findCustomOption(name); - Q_ASSERT(curIndex > -1); - const auto &opt = m_customOptions[curIndex]; - m_targetSuffixLineEdit->setText(opt.m_targetSuffix); - m_resourcePathSeparatorLineEdit->setText(opt.m_resourcePathSeparator); - m_useHtmlInputCheckBox->setChecked(opt.m_useHtmlInput); - m_allInOneCheckBox->setChecked(opt.m_allInOne); - m_targetPageScrollableCheckBox->setChecked(opt.m_targetPageScrollable); - m_commandTextEdit->setPlainText(opt.m_command); + if (findCustomOption(name) != -1) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("Name conflicts with existing scheme."), this); + } else { + break; + } + } + + // Based on current scheme. + ExportCustomOption newOption; + + { + int curIndex = findCustomOption(m_customExportComboBox->currentData().toString()); + if (curIndex > -1) { + newOption = m_customOptions[curIndex]; + } + } + + newOption.m_name = name; + m_customOptions.append(newOption); + ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); + + // Add it to combo box. + m_customExportComboBox->addItem(name, name); + m_customExportComboBox->setCurrentIndex(m_customExportComboBox->findData(name)); +} + +void ExportDialog::removeCustomExportScheme() { + auto name = m_customExportComboBox->currentData().toString(); + if (name.isEmpty()) { + return; + } + + int ret = MessageBoxHelper::questionOkCancel( + MessageBoxHelper::Warning, tr("Delete scheme (%1)?").arg(name), QString(), QString(), this); + if (ret != QMessageBox::Ok) { + return; + } + + int idx = findCustomOption(name); + Q_ASSERT(idx > -1); + m_customOptions.remove(idx); + ConfigMgr::getInst().getSessionConfig().setCustomExportOptions(m_customOptions); + + m_customExportComboBox->removeItem(m_customExportComboBox->currentIndex()); +} + +void ExportDialog::customExportCurrentSchemeChanged(int p_comboIdx) { + const bool enabled = p_comboIdx >= 0; + m_targetSuffixLineEdit->setEnabled(enabled); + m_resourcePathSeparatorLineEdit->setEnabled(enabled); + m_useHtmlInputCheckBox->setEnabled(enabled); + m_allInOneCheckBox->setEnabled(enabled); + m_targetPageScrollableCheckBox->setEnabled(enabled); + m_commandTextEdit->setEnabled(enabled); + + if (p_comboIdx < 0) { + m_option.m_customExport.clear(); + return; + } + + auto name = m_customExportComboBox->currentData().toString(); + m_option.m_customExport = name; + int curIndex = findCustomOption(name); + Q_ASSERT(curIndex > -1); + const auto &opt = m_customOptions[curIndex]; + m_targetSuffixLineEdit->setText(opt.m_targetSuffix); + m_resourcePathSeparatorLineEdit->setText(opt.m_resourcePathSeparator); + m_useHtmlInputCheckBox->setChecked(opt.m_useHtmlInput); + m_allInOneCheckBox->setChecked(opt.m_allInOne); + m_targetPageScrollableCheckBox->setChecked(opt.m_targetPageScrollable); + m_commandTextEdit->setPlainText(opt.m_command); } diff --git a/src/widgets/dialogs/exportdialog.h b/src/widgets/dialogs/exportdialog.h index 659ced9413..1fea0e1a33 100644 --- a/src/widgets/dialogs/exportdialog.h +++ b/src/widgets/dialogs/exportdialog.h @@ -16,194 +16,182 @@ class QProgressBar; class QPlainTextEdit; class QPageLayout; -namespace vnotex -{ - class Notebook; - class Node; - class Buffer; - class Exporter; - class LocationInputWithBrowseButton; +namespace vnotex { +class Notebook; +class Node; +class Buffer; +class Exporter; +class LocationInputWithBrowseButton; - class ExportDialog : public ScrollDialog - { - Q_OBJECT - public: - // Current notebook/folder/buffer. - ExportDialog(Notebook *p_notebook, - Node *p_folder, - Node *p_note, - Buffer *p_buffer, - QWidget *p_parent = nullptr); +class ExportDialog : public ScrollDialog { + Q_OBJECT +public: + // Current notebook/folder/buffer. + ExportDialog(Notebook *p_notebook, Node *p_folder, Node *p_note, Buffer *p_buffer, + QWidget *p_parent = nullptr); - protected: - void rejectedButtonClicked() Q_DECL_OVERRIDE; +protected: + void rejectedButtonClicked() Q_DECL_OVERRIDE; - private slots: - void updateProgress(int p_val, int p_maximum); +private slots: + void updateProgress(int p_val, int p_maximum); - void appendLog(const QString &p_log); + void appendLog(const QString &p_log); - void customExportCurrentSchemeChanged(int p_comboIdx); + void customExportCurrentSchemeChanged(int p_comboIdx); - private: - enum AdvancedSettings - { - General, - HTML, - PDF, - Custom, - Max - }; +private: + enum AdvancedSettings { General, HTML, PDF, Custom, Max }; - void setupUI(); + void setupUI(); - QGroupBox *setupSourceGroup(QWidget *p_parent); + QGroupBox *setupSourceGroup(QWidget *p_parent); - QGroupBox *setupTargetGroup(QWidget *p_parent); + QGroupBox *setupTargetGroup(QWidget *p_parent); - QGroupBox *setupAdvancedGroup(QWidget *p_parent); + QGroupBox *setupAdvancedGroup(QWidget *p_parent); - QWidget *setupGeneralAdvancedSettings(QWidget *p_parent); + QWidget *setupGeneralAdvancedSettings(QWidget *p_parent); - QWidget *getHtmlAdvancedSettings(); + QWidget *getHtmlAdvancedSettings(); - QWidget *getPdfAdvancedSettings(); + QWidget *getPdfAdvancedSettings(); - QWidget *getCustomAdvancedSettings(); + QWidget *getCustomAdvancedSettings(); - void showAdvancedSettings(AdvancedSettings p_settings); + void showAdvancedSettings(AdvancedSettings p_settings); - void setupButtonBox(); + void setupButtonBox(); - QString getOutputDir() const; + QString getOutputDir() const; - void initOptions(); + void initOptions(); - void restoreFields(const ExportOption &p_option); + void restoreFields(const ExportOption &p_option); - void saveFields(ExportOption &p_option); + void saveFields(ExportOption &p_option); - void restoreFields(const ExportHtmlOption &p_option); + void restoreFields(const ExportHtmlOption &p_option); - void saveFields(ExportHtmlOption &p_option); + void saveFields(ExportHtmlOption &p_option); - void restoreFields(const ExportPdfOption &p_option); + void restoreFields(const ExportPdfOption &p_option); - void saveFields(ExportPdfOption &p_option); + void saveFields(ExportPdfOption &p_option); - void restoreCustomFields(const ExportOption &p_option); + void restoreCustomFields(const ExportOption &p_option); - void saveCustomFields(ExportOption &p_option); + void saveCustomFields(ExportOption &p_option); - void startExport(); + void startExport(); - void updateUIOnExport(); + void updateUIOnExport(); - // Return exported files count. - int doExport(ExportOption p_option); + // Return exported files count. + int doExport(ExportOption p_option); - Exporter *getExporter(); + Exporter *getExporter(); - QString getDefaultOutputDir() const; + QString getDefaultOutputDir() const; - void updatePageLayoutButtonLabel(); + void updatePageLayoutButtonLabel(); - int findCustomOption(const QString &p_name) const; + int findCustomOption(const QString &p_name) const; - void addCustomExportScheme(); + void addCustomExportScheme(); - void removeCustomExportScheme(); + void removeCustomExportScheme(); - // Managed by QObject. - Exporter *m_exporter = nullptr; + // Managed by QObject. + Exporter *m_exporter = nullptr; - Notebook *m_notebook = nullptr; + Notebook *m_notebook = nullptr; - Node *m_folder = nullptr; + Node *m_folder = nullptr; - Node *m_note = nullptr; + Node *m_note = nullptr; - Buffer *m_buffer = nullptr; + Buffer *m_buffer = nullptr; - // Last exported single file. - QString m_exportedFile; + // Last exported single file. + QString m_exportedFile; - bool m_exportOngoing = false; + bool m_exportOngoing = false; - QPushButton *m_exportBtn = nullptr; + QPushButton *m_exportBtn = nullptr; - QPushButton *m_openDirBtn = nullptr; + QPushButton *m_openDirBtn = nullptr; - QPushButton *m_copyContentBtn = nullptr; + QPushButton *m_copyContentBtn = nullptr; - QComboBox *m_sourceComboBox = nullptr; + QComboBox *m_sourceComboBox = nullptr; - QComboBox *m_targetFormatComboBox = nullptr; + QComboBox *m_targetFormatComboBox = nullptr; - QCheckBox *m_transparentBgCheckBox = nullptr; + QCheckBox *m_transparentBgCheckBox = nullptr; - QComboBox *m_renderingStyleComboBox = nullptr; + QComboBox *m_renderingStyleComboBox = nullptr; - QComboBox *m_syntaxHighlightStyleComboBox = nullptr; + QComboBox *m_syntaxHighlightStyleComboBox = nullptr; - LocationInputWithBrowseButton *m_outputDirInput = nullptr; + LocationInputWithBrowseButton *m_outputDirInput = nullptr; - QProgressBar *m_progressBar = nullptr; + QProgressBar *m_progressBar = nullptr; - QGroupBox *m_advancedGroupBox = nullptr; + QGroupBox *m_advancedGroupBox = nullptr; - QVector m_advancedSettings; + QVector m_advancedSettings; - // General settings. - QCheckBox *m_recursiveCheckBox = nullptr; + // General settings. + QCheckBox *m_recursiveCheckBox = nullptr; - QCheckBox *m_exportAttachmentsCheckBox = nullptr; + QCheckBox *m_exportAttachmentsCheckBox = nullptr; - // HTML settings. - QCheckBox *m_embedStylesCheckBox = nullptr; + // HTML settings. + QCheckBox *m_embedStylesCheckBox = nullptr; - QCheckBox *m_embedImagesCheckBox = nullptr; + QCheckBox *m_embedImagesCheckBox = nullptr; - QCheckBox *m_completePageCheckBox = nullptr; + QCheckBox *m_completePageCheckBox = nullptr; - QCheckBox *m_useMimeHtmlFormatCheckBox = nullptr; + QCheckBox *m_useMimeHtmlFormatCheckBox = nullptr; - QCheckBox *m_addOutlinePanelCheckBox = nullptr; + QCheckBox *m_addOutlinePanelCheckBox = nullptr; - // PDF settings. - QPushButton *m_pageLayoutBtn = nullptr; + // PDF settings. + QPushButton *m_pageLayoutBtn = nullptr; - QCheckBox *m_addTableOfContentsCheckBox = nullptr; + QCheckBox *m_addTableOfContentsCheckBox = nullptr; - QCheckBox *m_useWkhtmltopdfCheckBox = nullptr; + QCheckBox *m_useWkhtmltopdfCheckBox = nullptr; - QCheckBox *m_allInOneCheckBox = nullptr; + QCheckBox *m_allInOneCheckBox = nullptr; - QLineEdit *m_wkhtmltopdfExePathLineEdit = nullptr; + QLineEdit *m_wkhtmltopdfExePathLineEdit = nullptr; - QLineEdit *m_wkhtmltopdfArgsLineEdit = nullptr; + QLineEdit *m_wkhtmltopdfArgsLineEdit = nullptr; - QSharedPointer m_pageLayout; + QSharedPointer m_pageLayout; - // Custom settings. - QComboBox *m_customExportComboBox = nullptr; + // Custom settings. + QComboBox *m_customExportComboBox = nullptr; - QLineEdit *m_targetSuffixLineEdit = nullptr; + QLineEdit *m_targetSuffixLineEdit = nullptr; - QLineEdit *m_resourcePathSeparatorLineEdit = nullptr; + QLineEdit *m_resourcePathSeparatorLineEdit = nullptr; - QCheckBox *m_useHtmlInputCheckBox = nullptr; + QCheckBox *m_useHtmlInputCheckBox = nullptr; - QCheckBox *m_customAllInOneCheckBox = nullptr; + QCheckBox *m_customAllInOneCheckBox = nullptr; - QCheckBox *m_targetPageScrollableCheckBox = nullptr; + QCheckBox *m_targetPageScrollableCheckBox = nullptr; - QPlainTextEdit *m_commandTextEdit = nullptr; + QPlainTextEdit *m_commandTextEdit = nullptr; - ExportOption m_option; + ExportOption m_option; - QVector m_customOptions; - }; -} + QVector m_customOptions; +}; +} // namespace vnotex #endif // EXPORTDIALOG_H diff --git a/src/widgets/dialogs/filepropertiesdialog.cpp b/src/widgets/dialogs/filepropertiesdialog.cpp index 705b25ccb9..af7db769b6 100644 --- a/src/widgets/dialogs/filepropertiesdialog.cpp +++ b/src/widgets/dialogs/filepropertiesdialog.cpp @@ -1,8 +1,8 @@ #include "filepropertiesdialog.h" +#include #include #include -#include #include #include "../lineedit.h" @@ -10,53 +10,45 @@ #include #include - using namespace vnotex; FilePropertiesDialog::FilePropertiesDialog(const QString &p_path, QWidget *p_parent) - : ScrollDialog(p_parent), - m_path(p_path) -{ - Q_ASSERT(!p_path.isEmpty()); - setupUI(); + : ScrollDialog(p_parent), m_path(p_path) { + Q_ASSERT(!p_path.isEmpty()); + setupUI(); - LineEdit::selectBaseName(m_nameLineEdit); + LineEdit::selectBaseName(m_nameLineEdit); - m_nameLineEdit->setFocus(); + m_nameLineEdit->setFocus(); } -void FilePropertiesDialog::setupUI() -{ - auto widget = new QWidget(this); - setCentralWidget(widget); +void FilePropertiesDialog::setupUI() { + auto widget = new QWidget(this); + setCentralWidget(widget); - auto mainLayout = WidgetsFactory::createFormLayout(widget); - mainLayout->setContentsMargins(0, 0, 0, 0); + auto mainLayout = WidgetsFactory::createFormLayout(widget); + mainLayout->setContentsMargins(0, 0, 0, 0); - const QFileInfo info(m_path); + const QFileInfo info(m_path); - mainLayout->addRow(tr("Location:"), new QLabel(info.absolutePath(), widget)); + mainLayout->addRow(tr("Location:"), new QLabel(info.absolutePath(), widget)); - setupNameLineEdit(widget); - m_nameLineEdit->setText(info.fileName()); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); + setupNameLineEdit(widget); + m_nameLineEdit->setText(info.fileName()); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); - mainLayout->addRow(tr("Size:"), new QLabel(tr("%1 Bytes").arg(info.size()), widget)); + mainLayout->addRow(tr("Size:"), new QLabel(tr("%1 Bytes").arg(info.size()), widget)); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("Properties")); + setWindowTitle(tr("Properties")); } -void FilePropertiesDialog::setupNameLineEdit(QWidget *p_parent) -{ - m_nameLineEdit = WidgetsFactory::createLineEdit(p_parent); - auto validator = new QRegularExpressionValidator(QRegularExpression(PathUtils::c_fileNameRegularExpression), - m_nameLineEdit); - m_nameLineEdit->setValidator(validator); +void FilePropertiesDialog::setupNameLineEdit(QWidget *p_parent) { + m_nameLineEdit = WidgetsFactory::createLineEdit(p_parent); + auto validator = new QRegularExpressionValidator( + QRegularExpression(PathUtils::c_fileNameRegularExpression), m_nameLineEdit); + m_nameLineEdit->setValidator(validator); } -QString FilePropertiesDialog::getFileName() const -{ - return m_nameLineEdit->text(); -} +QString FilePropertiesDialog::getFileName() const { return m_nameLineEdit->text(); } diff --git a/src/widgets/dialogs/filepropertiesdialog.h b/src/widgets/dialogs/filepropertiesdialog.h index 6e166f78c7..fe435539ee 100644 --- a/src/widgets/dialogs/filepropertiesdialog.h +++ b/src/widgets/dialogs/filepropertiesdialog.h @@ -5,25 +5,23 @@ class QLineEdit; -namespace vnotex -{ - class FilePropertiesDialog : public ScrollDialog - { - Q_OBJECT - public: - FilePropertiesDialog(const QString &p_path, QWidget *p_parent = nullptr); +namespace vnotex { +class FilePropertiesDialog : public ScrollDialog { + Q_OBJECT +public: + FilePropertiesDialog(const QString &p_path, QWidget *p_parent = nullptr); - QString getFileName() const; + QString getFileName() const; - private: - void setupUI(); +private: + void setupUI(); - void setupNameLineEdit(QWidget *p_parent); + void setupNameLineEdit(QWidget *p_parent); - QString m_path; + QString m_path; - QLineEdit *m_nameLineEdit = nullptr; - }; -} + QLineEdit *m_nameLineEdit = nullptr; +}; +} // namespace vnotex #endif // FILEPROPERTIESDIALOG_H diff --git a/src/widgets/dialogs/folderfilesfilterwidget.cpp b/src/widgets/dialogs/folderfilesfilterwidget.cpp index e9084788c3..5b70746393 100644 --- a/src/widgets/dialogs/folderfilesfilterwidget.cpp +++ b/src/widgets/dialogs/folderfilesfilterwidget.cpp @@ -1,204 +1,179 @@ #include "folderfilesfilterwidget.h" -#include -#include +#include +#include +#include #include +#include #include -#include #include -#include -#include -#include #include +#include #include -#include +#include +#include -#include "../widgetsfactory.h" #include "../lineedit.h" +#include "../widgetsfactory.h" +#include "selectionitemwidget.h" #include #include -#include "selectionitemwidget.h" using namespace vnotex; -FolderFilesFilterWidget::FolderFilesFilterWidget(QWidget *p_parent) - : QWidget(p_parent) -{ - m_scanTimer = new QTimer(this); - m_scanTimer->setSingleShot(true); - m_scanTimer->setInterval(2000); - connect(m_scanTimer, &QTimer::timeout, - this, &FolderFilesFilterWidget::scanSuffixes); +FolderFilesFilterWidget::FolderFilesFilterWidget(QWidget *p_parent) : QWidget(p_parent) { + m_scanTimer = new QTimer(this); + m_scanTimer->setSingleShot(true); + m_scanTimer->setInterval(2000); + connect(m_scanTimer, &QTimer::timeout, this, &FolderFilesFilterWidget::scanSuffixes); - setupUI(); + setupUI(); } -void FolderFilesFilterWidget::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); - - { - auto pathLayout = new QHBoxLayout(); - pathLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addRow(tr("Folder:"), pathLayout); - - m_folderPathEdit = WidgetsFactory::createLineEdit(this); - pathLayout->addWidget(m_folderPathEdit); - connect(m_folderPathEdit, &QLineEdit::textChanged, - this, [this]() { - m_ready = false; - m_scanTimer->start(); - }); - - auto browseBtn = new QPushButton(tr("Browse"), this); - pathLayout->addWidget(browseBtn); - connect(browseBtn, &QPushButton::clicked, - this, [this]() { - static QString lastBrowsePath = QDir::homePath(); - auto folderPath = QFileDialog::getExistingDirectory(this, - tr("Select Notebook Root Folder"), - lastBrowsePath, - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - if (!folderPath.isEmpty()) { - lastBrowsePath = PathUtils::parentDirPath(folderPath); - m_folderPathEdit->setText(folderPath); - } - }); - } - - { - auto layout = new QHBoxLayout(); - mainLayout->addRow(tr("Select files:"), layout); - layout->setContentsMargins(0, 0, 0, 0); - - m_suffixList = new QListWidget(this); - layout->addWidget(m_suffixList); - - auto btnLayout = new QVBoxLayout(); - layout->addLayout(btnLayout); - btnLayout->setContentsMargins(0, 0, 0, 0); - - auto selectAllBtn = new QPushButton(tr("Select All"), this); - btnLayout->addWidget(selectAllBtn); - connect(selectAllBtn, &QPushButton::clicked, - this, [this]() { - for (int i = 0; i < m_suffixList->count(); ++i) { - SelectionItemWidget *widget = getItemWidget(m_suffixList->item(i)); - widget->setChecked(true); - } - }); - - auto clearBtn = new QPushButton(tr("Clear"), this); - btnLayout->addWidget(clearBtn); - connect(clearBtn, &QPushButton::clicked, - this, [this]() { - for (int i = 0; i < m_suffixList->count(); ++i) { - SelectionItemWidget *widget = getItemWidget(m_suffixList->item(i)); - widget->setChecked(false); - } - }); - - btnLayout->addStretch(); - } +void FolderFilesFilterWidget::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + + { + auto pathLayout = new QHBoxLayout(); + pathLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addRow(tr("Folder:"), pathLayout); + + m_folderPathEdit = WidgetsFactory::createLineEdit(this); + pathLayout->addWidget(m_folderPathEdit); + connect(m_folderPathEdit, &QLineEdit::textChanged, this, [this]() { + m_ready = false; + m_scanTimer->start(); + }); + + auto browseBtn = new QPushButton(tr("Browse"), this); + pathLayout->addWidget(browseBtn); + connect(browseBtn, &QPushButton::clicked, this, [this]() { + static QString lastBrowsePath = QDir::homePath(); + auto folderPath = QFileDialog::getExistingDirectory( + this, tr("Select Notebook Root Folder"), lastBrowsePath, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (!folderPath.isEmpty()) { + lastBrowsePath = PathUtils::parentDirPath(folderPath); + m_folderPathEdit->setText(folderPath); + } + }); + } + + { + auto layout = new QHBoxLayout(); + mainLayout->addRow(tr("Select files:"), layout); + layout->setContentsMargins(0, 0, 0, 0); + + m_suffixList = new QListWidget(this); + layout->addWidget(m_suffixList); + + auto btnLayout = new QVBoxLayout(); + layout->addLayout(btnLayout); + btnLayout->setContentsMargins(0, 0, 0, 0); + + auto selectAllBtn = new QPushButton(tr("Select All"), this); + btnLayout->addWidget(selectAllBtn); + connect(selectAllBtn, &QPushButton::clicked, this, [this]() { + for (int i = 0; i < m_suffixList->count(); ++i) { + SelectionItemWidget *widget = getItemWidget(m_suffixList->item(i)); + widget->setChecked(true); + } + }); + + auto clearBtn = new QPushButton(tr("Clear"), this); + btnLayout->addWidget(clearBtn); + connect(clearBtn, &QPushButton::clicked, this, [this]() { + for (int i = 0; i < m_suffixList->count(); ++i) { + SelectionItemWidget *widget = getItemWidget(m_suffixList->item(i)); + widget->setChecked(false); + } + }); + + btnLayout->addStretch(); + } } -QString FolderFilesFilterWidget::getFolderPath() const -{ - Q_ASSERT(m_ready); - return m_folderPathEdit->text(); +QString FolderFilesFilterWidget::getFolderPath() const { + Q_ASSERT(m_ready); + return m_folderPathEdit->text(); } -QStringList FolderFilesFilterWidget::getSuffixes() const -{ - Q_ASSERT(m_ready); - QStringList suffixes; - for (int i = 0; i < m_suffixList->count(); ++i) { - auto widget = getItemWidget(m_suffixList->item(i)); - if (widget->isChecked()) { - suffixes << widget->getData().toString(); - } +QStringList FolderFilesFilterWidget::getSuffixes() const { + Q_ASSERT(m_ready); + QStringList suffixes; + for (int i = 0; i < m_suffixList->count(); ++i) { + auto widget = getItemWidget(m_suffixList->item(i)); + if (widget->isChecked()) { + suffixes << widget->getData().toString(); } + } - return suffixes; + return suffixes; } -static void scanDir(const QString &p_path, QSet &p_suffixes) -{ - QDir dir(p_path); - auto children = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); - for (const auto &child : children) { - if (child.isDir()) { - scanDir(child.filePath(), p_suffixes); - } else { - if (!child.suffix().isEmpty()) { - p_suffixes.insert(child.suffix()); - } - } +static void scanDir(const QString &p_path, QSet &p_suffixes) { + QDir dir(p_path); + auto children = + dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); + for (const auto &child : children) { + if (child.isDir()) { + scanDir(child.filePath(), p_suffixes); + } else { + if (!child.suffix().isEmpty()) { + p_suffixes.insert(child.suffix()); + } } + } } -static bool shouldSuffixBeChecked(const QString &p_suffix) -{ - QStringList suffixes = {QStringLiteral("md"), - QStringLiteral("markdown"), - QStringLiteral("cpp"), - QStringLiteral("py"), - QStringLiteral("js"), - QStringLiteral("css"), - QStringLiteral("html"), - QStringLiteral("txt")}; - auto suf = p_suffix.toLower(); - return suffixes.contains(suf); +static bool shouldSuffixBeChecked(const QString &p_suffix) { + QStringList suffixes = {QStringLiteral("md"), QStringLiteral("markdown"), QStringLiteral("cpp"), + QStringLiteral("py"), QStringLiteral("js"), QStringLiteral("css"), + QStringLiteral("html"), QStringLiteral("txt")}; + auto suf = p_suffix.toLower(); + return suffixes.contains(suf); } -void FolderFilesFilterWidget::scanSuffixes() -{ - m_suffixList->clear(); +void FolderFilesFilterWidget::scanSuffixes() { + m_suffixList->clear(); - auto folderPath = m_folderPathEdit->text(); - bool validFolderPath = QFileInfo::exists(folderPath) && PathUtils::isLegalPath(folderPath); - if (validFolderPath) { - WidgetUtils::setPropertyDynamically(m_folderPathEdit, "State"); + auto folderPath = m_folderPathEdit->text(); + bool validFolderPath = QFileInfo::exists(folderPath) && PathUtils::isLegalPath(folderPath); + if (validFolderPath) { + WidgetUtils::setPropertyDynamically(m_folderPathEdit, "State"); - QSet suffixes; - scanDir(folderPath, suffixes); + QSet suffixes; + scanDir(folderPath, suffixes); - for (const auto &suffix : suffixes) { - auto itemWidget = new SelectionItemWidget(suffix, this); - itemWidget->setChecked(shouldSuffixBeChecked(suffix)); - itemWidget->setData(suffix); + for (const auto &suffix : suffixes) { + auto itemWidget = new SelectionItemWidget(suffix, this); + itemWidget->setChecked(shouldSuffixBeChecked(suffix)); + itemWidget->setData(suffix); - QListWidgetItem *item = new QListWidgetItem(m_suffixList); - QSize size = itemWidget->sizeHint(); - size.setHeight(size.height() * 2); - item->setSizeHint(size); + QListWidgetItem *item = new QListWidgetItem(m_suffixList); + QSize size = itemWidget->sizeHint(); + size.setHeight(size.height() * 2); + item->setSizeHint(size); - m_suffixList->setItemWidget(item, itemWidget); - } - } else { - WidgetUtils::setPropertyDynamically(m_folderPathEdit, "State", "error"); - qWarning() << "invalid folder path" << folderPath; + m_suffixList->setItemWidget(item, itemWidget); } + } else { + WidgetUtils::setPropertyDynamically(m_folderPathEdit, "State", "error"); + qWarning() << "invalid folder path" << folderPath; + } - WidgetUtils::updateSize(m_suffixList); + WidgetUtils::updateSize(m_suffixList); - m_ready = true; - emit filesChanged(); + m_ready = true; + emit filesChanged(); } -SelectionItemWidget *FolderFilesFilterWidget::getItemWidget(QListWidgetItem *p_item) const -{ - QWidget *wid = m_suffixList->itemWidget(p_item); - return static_cast(wid); +SelectionItemWidget *FolderFilesFilterWidget::getItemWidget(QListWidgetItem *p_item) const { + QWidget *wid = m_suffixList->itemWidget(p_item); + return static_cast(wid); } -bool FolderFilesFilterWidget::isReady() const -{ - return m_ready; -} +bool FolderFilesFilterWidget::isReady() const { return m_ready; } -QLineEdit *FolderFilesFilterWidget::getFolderPathEdit() const -{ - return m_folderPathEdit; -} +QLineEdit *FolderFilesFilterWidget::getFolderPathEdit() const { return m_folderPathEdit; } diff --git a/src/widgets/dialogs/folderfilesfilterwidget.h b/src/widgets/dialogs/folderfilesfilterwidget.h index 204324bbd3..a06d646d04 100644 --- a/src/widgets/dialogs/folderfilesfilterwidget.h +++ b/src/widgets/dialogs/folderfilesfilterwidget.h @@ -1,55 +1,53 @@ #ifndef FOLDERFILESFILTERWIDGET_H #define FOLDERFILESFILTERWIDGET_H -#include #include +#include class QTimer; class QLineEdit; class QListWidget; class QListWidgetItem; -namespace vnotex -{ - class SelectionItemWidget; +namespace vnotex { +class SelectionItemWidget; - // Filter files within a folder by suffix. - class FolderFilesFilterWidget : public QWidget - { - Q_OBJECT - public: - explicit FolderFilesFilterWidget(QWidget *p_parent = nullptr); +// Filter files within a folder by suffix. +class FolderFilesFilterWidget : public QWidget { + Q_OBJECT +public: + explicit FolderFilesFilterWidget(QWidget *p_parent = nullptr); - QLineEdit *getFolderPathEdit() const; + QLineEdit *getFolderPathEdit() const; - QString getFolderPath() const; + QString getFolderPath() const; - QStringList getSuffixes() const; + QStringList getSuffixes() const; - // Whether complete scanning files. - bool isReady() const; + // Whether complete scanning files. + bool isReady() const; - signals: - // Folder path or selected suffixes changed. - void filesChanged(); +signals: + // Folder path or selected suffixes changed. + void filesChanged(); - private slots: - void scanSuffixes(); +private slots: + void scanSuffixes(); - private: - void setupUI(); +private: + void setupUI(); - SelectionItemWidget *getItemWidget(QListWidgetItem *p_item) const; + SelectionItemWidget *getItemWidget(QListWidgetItem *p_item) const; - // Managed by QObject. - QTimer *m_scanTimer = nullptr; + // Managed by QObject. + QTimer *m_scanTimer = nullptr; - QLineEdit *m_folderPathEdit = nullptr; + QLineEdit *m_folderPathEdit = nullptr; - QListWidget *m_suffixList = nullptr; + QListWidget *m_suffixList = nullptr; - bool m_ready = false; - }; -} + bool m_ready = false; +}; +} // namespace vnotex #endif // FOLDERFILESFILTERWIDGET_H diff --git a/src/widgets/dialogs/folderpropertiesdialog.cpp b/src/widgets/dialogs/folderpropertiesdialog.cpp index e947d8fdaa..f405991968 100644 --- a/src/widgets/dialogs/folderpropertiesdialog.cpp +++ b/src/widgets/dialogs/folderpropertiesdialog.cpp @@ -2,101 +2,92 @@ #include -#include "notebook/notebook.h" -#include "notebook/node.h" #include "../widgetsfactory.h" -#include #include "exception.h" #include "nodeinfowidget.h" +#include "notebook/node.h" +#include "notebook/notebook.h" #include #include +#include using namespace vnotex; FolderPropertiesDialog::FolderPropertiesDialog(Node *p_node, QWidget *p_parent) - : ScrollDialog(p_parent), - m_node(p_node) -{ - Q_ASSERT(m_node); - setupUI(); - - m_infoWidget->getNameLineEdit()->selectAll(); - m_infoWidget->getNameLineEdit()->setFocus(); + : ScrollDialog(p_parent), m_node(p_node) { + Q_ASSERT(m_node); + setupUI(); + + m_infoWidget->getNameLineEdit()->selectAll(); + m_infoWidget->getNameLineEdit()->setFocus(); } -void FolderPropertiesDialog::setupUI() -{ - setupNodeInfoWidget(this); - setCentralWidget(m_infoWidget); +void FolderPropertiesDialog::setupUI() { + setupNodeInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(m_node->getName() + QStringLiteral(" ") + tr("Properties")); + setWindowTitle(m_node->getName() + QStringLiteral(" ") + tr("Properties")); } -void FolderPropertiesDialog::setupNodeInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new NodeInfoWidget(m_node, p_parent); +void FolderPropertiesDialog::setupNodeInfoWidget(QWidget *p_parent) { + m_infoWidget = new NodeInfoWidget(m_node, p_parent); } -bool FolderPropertiesDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool FolderPropertiesDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool FolderPropertiesDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool FolderPropertiesDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - auto name = m_infoWidget->getName(); - if (name.isEmpty()) { - p_msg = tr("Please specify a name for the folder."); - return false; - } + auto name = m_infoWidget->getName(); + if (name.isEmpty()) { + p_msg = tr("Please specify a name for the folder."); + return false; + } - Q_ASSERT(m_infoWidget->getParentNode() == m_node->getParent()); - if (!m_node->canRename(name)) { - p_msg = tr("Name conflicts with existing folder."); - return false; - } + Q_ASSERT(m_infoWidget->getParentNode() == m_node->getParent()); + if (!m_node->canRename(name)) { + p_msg = tr("Name conflicts with existing folder."); + return false; + } - return true; + return true; } -void FolderPropertiesDialog::acceptedButtonClicked() -{ - if (validateInputs() && saveFolderProperties()) { - accept(); - } +void FolderPropertiesDialog::acceptedButtonClicked() { + if (validateInputs() && saveFolderProperties()) { + accept(); + } } -bool FolderPropertiesDialog::saveFolderProperties() -{ - try { - if (m_infoWidget->getName() != m_node->getName()) { - // Close the node first. - auto event = QSharedPointer::create(); - emit VNoteX::getInst().nodeAboutToRename(m_node, event); - if (!event->m_response.toBool()) { - return false; - } - - m_node->updateName(m_infoWidget->getName()); - } - } catch (Exception &p_e) { - QString msg = tr("Failed to save folder (%1) in (%2) (%3).").arg(m_node->getName(), - m_node->getNotebook()->getName(), - p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); +bool FolderPropertiesDialog::saveFolderProperties() { + try { + if (m_infoWidget->getName() != m_node->getName()) { + // Close the node first. + auto event = QSharedPointer::create(); + emit VNoteX::getInst().nodeAboutToRename(m_node, event); + if (!event->m_response.toBool()) { return false; - } + } - return true; + m_node->updateName(m_infoWidget->getName()); + } + } catch (Exception &p_e) { + QString msg = tr("Failed to save folder (%1) in (%2) (%3).") + .arg(m_node->getName(), m_node->getNotebook()->getName(), p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } diff --git a/src/widgets/dialogs/folderpropertiesdialog.h b/src/widgets/dialogs/folderpropertiesdialog.h index 68aa55b304..3e78c45e72 100644 --- a/src/widgets/dialogs/folderpropertiesdialog.h +++ b/src/widgets/dialogs/folderpropertiesdialog.h @@ -3,35 +3,33 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Node; - class NodeInfoWidget; +namespace vnotex { +class Node; +class NodeInfoWidget; - class FolderPropertiesDialog : public ScrollDialog - { - Q_OBJECT - public: - FolderPropertiesDialog(Node *p_node, QWidget *p_parent = nullptr); +class FolderPropertiesDialog : public ScrollDialog { + Q_OBJECT +public: + FolderPropertiesDialog(Node *p_node, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupNodeInfoWidget(QWidget *p_parent); + void setupNodeInfoWidget(QWidget *p_parent); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool saveFolderProperties(); + bool saveFolderProperties(); - bool validateInputs(); + bool validateInputs(); - NodeInfoWidget *m_infoWidget = nullptr; + NodeInfoWidget *m_infoWidget = nullptr; - Node *m_node = nullptr; - }; -} // ns vnotex + Node *m_node = nullptr; +}; +} // namespace vnotex #endif // FOLDERPROPERTIESDIALOG_H diff --git a/src/widgets/dialogs/imageinsertdialog.cpp b/src/widgets/dialogs/imageinsertdialog.cpp index c75d2f09a5..1dbe43eb4f 100644 --- a/src/widgets/dialogs/imageinsertdialog.cpp +++ b/src/widgets/dialogs/imageinsertdialog.cpp @@ -1,31 +1,31 @@ #include "imageinsertdialog.h" +#include +#include +#include +#include #include -#include -#include -#include #include #include +#include #include -#include -#include #include -#include -#include -#include -#include +#include +#include #include -#include +#include +#include +#include #include #include -#include -#include +#include +#include #include #include -#include -#include +#include +#include using namespace vnotex; @@ -35,333 +35,292 @@ int ImageInsertDialog::s_lastScaleWidth = -1; bool ImageInsertDialog::s_fixedScaleWidth = false; -ImageInsertDialog::ImageInsertDialog(const QString &p_title, - const QString &p_imageTitle, - const QString &p_imageAlt, - const QString &p_imagePath, - bool p_browserEnabled, - QWidget *p_parent) - : Dialog(p_parent), - m_browserEnabled(p_browserEnabled) -{ - m_imagePathCheckTimer = new QTimer(this); - m_imagePathCheckTimer->setSingleShot(true); - m_imagePathCheckTimer->setInterval(500); - connect(m_imagePathCheckTimer, &QTimer::timeout, - this, &ImageInsertDialog::checkImagePathInput); - - setupUI(p_title, p_imageTitle, p_imageAlt, p_imagePath); - - checkInput(); -} - -void ImageInsertDialog::setupUI(const QString &p_title, - const QString &p_imageTitle, - const QString &p_imageAlt, - const QString &p_imagePath) -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); - - auto mainLayout = new QVBoxLayout(mainWidget); - - auto gridLayout = new QGridLayout(); - mainLayout->addLayout(gridLayout); - - mainLayout->addStretch(); - - // Image Path. - m_imagePathEdit = WidgetsFactory::createLineEdit(p_imagePath, mainWidget); - m_imagePathEdit->setReadOnly(!m_browserEnabled); - gridLayout->addWidget(new QLabel(tr("From:"), mainWidget), 0, 0, 1, 1); - gridLayout->addWidget(m_imagePathEdit, 0, 1, 1, 3); - connect(m_imagePathEdit, &QLineEdit::textChanged, - this, [this]() { - m_imagePathCheckTimer->start(); - }); - - m_browseBtn = new QPushButton(tr("&Browse"), mainWidget); - m_browseBtn->setEnabled(m_browserEnabled); - gridLayout->addWidget(m_browseBtn, 0, 4, 1, 1); - connect(m_browseBtn, &QPushButton::clicked, - this, &ImageInsertDialog::browseFile); - - // Image Title. - m_imageTitleEdit = WidgetsFactory::createLineEdit(p_imageTitle, mainWidget); - auto titleValidator = new QRegularExpressionValidator(QRegularExpression(vte::MarkdownUtils::c_imageTitleRegExp), m_imageTitleEdit); - m_imageTitleEdit->setValidator(titleValidator); - gridLayout->addWidget(new QLabel(tr("Title:"), mainWidget), 1, 0, 1, 1); - gridLayout->addWidget(m_imageTitleEdit, 1, 1, 1, 3); - connect(m_imageTitleEdit, &QLineEdit::textChanged, - this, &ImageInsertDialog::checkInput); - - // Image Alt. - m_imageAltEdit = WidgetsFactory::createLineEdit(p_imageAlt, mainWidget); - auto altValidator = new QRegularExpressionValidator(QRegularExpression(vte::MarkdownUtils::c_imageAltRegExp), m_imageAltEdit); - m_imageAltEdit->setValidator(altValidator); - gridLayout->addWidget(new QLabel(tr("Alt text:"), mainWidget), 2, 0, 1, 1); - gridLayout->addWidget(m_imageAltEdit, 2, 1, 1, 3); - - // Scale. - m_widthSpin = WidgetsFactory::createSpinBox(mainWidget); - m_widthSpin->setMinimum(1); - m_widthSpin->setSingleStep(10); - m_widthSpin->setSuffix(" px"); - connect(m_widthSpin, static_cast(&QSpinBox::valueChanged), - this, [this](int p_val) { - if (m_image.isNull()) { - return; - } - - int height = m_image.height() * (1.0 * p_val / m_image.width()); - m_imageLabel->resize(p_val, height); - - s_lastScaleWidth = p_val; - }); - // 0.1 to 2.0 -> 1 to 20. - m_scaleSlider = new QSlider(mainWidget); - m_scaleSlider->setOrientation(Qt::Horizontal); - m_scaleSlider->setMinimum(1); - m_scaleSlider->setMaximum(50); - m_scaleSlider->setValue(s_lastScaleSliderValue); - m_scaleSlider->setSingleStep(1); - m_scaleSlider->setPageStep(5); - connect(m_scaleSlider, &QSlider::valueChanged, - this, &ImageInsertDialog::handleScaleSliderValueChanged); - m_sliderLabel = new QLabel("1x", mainWidget); - gridLayout->addWidget(new QLabel(tr("Scaling width:"), mainWidget), 3, 0, 1, 1); - gridLayout->addWidget(m_widthSpin, 3, 1, 1, 1); - gridLayout->addWidget(m_scaleSlider, 3, 2, 1, 2); - gridLayout->addWidget(m_sliderLabel, 3, 4, 1, 1); - - { - auto fixedWidthCheckBox = WidgetsFactory::createCheckBox(tr("Fixed scaling width"), mainWidget); - fixedWidthCheckBox->setChecked(s_fixedScaleWidth); - connect(fixedWidthCheckBox, &QCheckBox::stateChanged, - this, [](int p_state) { - s_fixedScaleWidth = p_state == Qt::Checked; - }); - gridLayout->addWidget(fixedWidthCheckBox, 4, 1, 1, 1); - } - - // Preview area. - m_imageLabel = new QLabel(mainWidget); - m_imageLabel->setScaledContents(true); - m_previewArea = new QScrollArea(mainWidget); - m_previewArea->setBackgroundRole(QPalette::Dark); - m_previewArea->setWidget(m_imageLabel); - m_previewArea->setMinimumSize(256, 256); - gridLayout->addWidget(m_previewArea, 5, 0, 1, 5); - - setImageControlsVisible(false); - - gridLayout->setColumnStretch(0, 0); - gridLayout->setColumnStretch(1, 0); - gridLayout->setColumnStretch(2, 1); - gridLayout->setColumnStretch(3, 1); - gridLayout->setColumnStretch(4, 0); +ImageInsertDialog::ImageInsertDialog(const QString &p_title, const QString &p_imageTitle, + const QString &p_imageAlt, const QString &p_imagePath, + bool p_browserEnabled, QWidget *p_parent) + : Dialog(p_parent), m_browserEnabled(p_browserEnabled) { + m_imagePathCheckTimer = new QTimer(this); + m_imagePathCheckTimer->setSingleShot(true); + m_imagePathCheckTimer->setInterval(500); + connect(m_imagePathCheckTimer, &QTimer::timeout, this, &ImageInsertDialog::checkImagePathInput); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setupUI(p_title, p_imageTitle, p_imageAlt, p_imagePath); - setWindowTitle(p_title); + checkInput(); } -void ImageInsertDialog::setImageControlsVisible(bool p_visible) -{ - m_widthSpin->setEnabled(p_visible); - m_scaleSlider->setEnabled(p_visible); - m_sliderLabel->setEnabled(p_visible); +void ImageInsertDialog::setupUI(const QString &p_title, const QString &p_imageTitle, + const QString &p_imageAlt, const QString &p_imagePath) { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); + + auto mainLayout = new QVBoxLayout(mainWidget); + + auto gridLayout = new QGridLayout(); + mainLayout->addLayout(gridLayout); + + mainLayout->addStretch(); + + // Image Path. + m_imagePathEdit = WidgetsFactory::createLineEdit(p_imagePath, mainWidget); + m_imagePathEdit->setReadOnly(!m_browserEnabled); + gridLayout->addWidget(new QLabel(tr("From:"), mainWidget), 0, 0, 1, 1); + gridLayout->addWidget(m_imagePathEdit, 0, 1, 1, 3); + connect(m_imagePathEdit, &QLineEdit::textChanged, this, + [this]() { m_imagePathCheckTimer->start(); }); + + m_browseBtn = new QPushButton(tr("&Browse"), mainWidget); + m_browseBtn->setEnabled(m_browserEnabled); + gridLayout->addWidget(m_browseBtn, 0, 4, 1, 1); + connect(m_browseBtn, &QPushButton::clicked, this, &ImageInsertDialog::browseFile); + + // Image Title. + m_imageTitleEdit = WidgetsFactory::createLineEdit(p_imageTitle, mainWidget); + auto titleValidator = new QRegularExpressionValidator( + QRegularExpression(vte::MarkdownUtils::c_imageTitleRegExp), m_imageTitleEdit); + m_imageTitleEdit->setValidator(titleValidator); + gridLayout->addWidget(new QLabel(tr("Title:"), mainWidget), 1, 0, 1, 1); + gridLayout->addWidget(m_imageTitleEdit, 1, 1, 1, 3); + connect(m_imageTitleEdit, &QLineEdit::textChanged, this, &ImageInsertDialog::checkInput); + + // Image Alt. + m_imageAltEdit = WidgetsFactory::createLineEdit(p_imageAlt, mainWidget); + auto altValidator = new QRegularExpressionValidator( + QRegularExpression(vte::MarkdownUtils::c_imageAltRegExp), m_imageAltEdit); + m_imageAltEdit->setValidator(altValidator); + gridLayout->addWidget(new QLabel(tr("Alt text:"), mainWidget), 2, 0, 1, 1); + gridLayout->addWidget(m_imageAltEdit, 2, 1, 1, 3); + + // Scale. + m_widthSpin = WidgetsFactory::createSpinBox(mainWidget); + m_widthSpin->setMinimum(1); + m_widthSpin->setSingleStep(10); + m_widthSpin->setSuffix(" px"); + connect(m_widthSpin, static_cast(&QSpinBox::valueChanged), this, + [this](int p_val) { + if (m_image.isNull()) { + return; + } - m_previewArea->setVisible(p_visible); + int height = m_image.height() * (1.0 * p_val / m_image.width()); + m_imageLabel->resize(p_val, height); + + s_lastScaleWidth = p_val; + }); + // 0.1 to 2.0 -> 1 to 20. + m_scaleSlider = new QSlider(mainWidget); + m_scaleSlider->setOrientation(Qt::Horizontal); + m_scaleSlider->setMinimum(1); + m_scaleSlider->setMaximum(50); + m_scaleSlider->setValue(s_lastScaleSliderValue); + m_scaleSlider->setSingleStep(1); + m_scaleSlider->setPageStep(5); + connect(m_scaleSlider, &QSlider::valueChanged, this, + &ImageInsertDialog::handleScaleSliderValueChanged); + m_sliderLabel = new QLabel("1x", mainWidget); + gridLayout->addWidget(new QLabel(tr("Scaling width:"), mainWidget), 3, 0, 1, 1); + gridLayout->addWidget(m_widthSpin, 3, 1, 1, 1); + gridLayout->addWidget(m_scaleSlider, 3, 2, 1, 2); + gridLayout->addWidget(m_sliderLabel, 3, 4, 1, 1); + + { + auto fixedWidthCheckBox = WidgetsFactory::createCheckBox(tr("Fixed scaling width"), mainWidget); + fixedWidthCheckBox->setChecked(s_fixedScaleWidth); + connect(fixedWidthCheckBox, &QCheckBox::stateChanged, this, + [](int p_state) { s_fixedScaleWidth = p_state == Qt::Checked; }); + gridLayout->addWidget(fixedWidthCheckBox, 4, 1, 1, 1); + } + + // Preview area. + m_imageLabel = new QLabel(mainWidget); + m_imageLabel->setScaledContents(true); + m_previewArea = new QScrollArea(mainWidget); + m_previewArea->setBackgroundRole(QPalette::Dark); + m_previewArea->setWidget(m_imageLabel); + m_previewArea->setMinimumSize(256, 256); + gridLayout->addWidget(m_previewArea, 5, 0, 1, 5); + + setImageControlsVisible(false); + + gridLayout->setColumnStretch(0, 0); + gridLayout->setColumnStretch(1, 0); + gridLayout->setColumnStretch(2, 1); + gridLayout->setColumnStretch(3, 1); + gridLayout->setColumnStretch(4, 0); + + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + setWindowTitle(p_title); } -void ImageInsertDialog::showEvent(QShowEvent *p_event) -{ - Dialog::showEvent(p_event); +void ImageInsertDialog::setImageControlsVisible(bool p_visible) { + m_widthSpin->setEnabled(p_visible); + m_scaleSlider->setEnabled(p_visible); + m_sliderLabel->setEnabled(p_visible); - m_imageTitleEdit->selectAll(); - m_imageTitleEdit->setFocus(); + m_previewArea->setVisible(p_visible); } -void ImageInsertDialog::checkImagePathInput() -{ - const QString text = m_imagePathEdit->text(); - QUrl url = QUrl::fromUserInput(text); - if (text.isEmpty() || !url.isValid()) { - setImage(QImage()); - return; - } +void ImageInsertDialog::showEvent(QShowEvent *p_event) { + Dialog::showEvent(p_event); - if (url.isLocalFile()) { - const auto localFile = url.toLocalFile(); - if (QFileInfo::exists(localFile)) { - setImage(FileUtils::imageFromFile(localFile)); - } else { - setImage(QImage()); - } + m_imageTitleEdit->selectAll(); + m_imageTitleEdit->setFocus(); +} - m_source = Source::LocalFile; +void ImageInsertDialog::checkImagePathInput() { + const QString text = m_imagePathEdit->text(); + QUrl url = QUrl::fromUserInput(text); + if (text.isEmpty() || !url.isValid()) { + setImage(QImage()); + return; + } + + if (url.isLocalFile()) { + const auto localFile = url.toLocalFile(); + if (QFileInfo::exists(localFile)) { + setImage(FileUtils::imageFromFile(localFile)); } else { - setImage(QImage()); - m_source = Source::ImageData; - - if (!m_downloader) { - m_downloader = new vte::NetworkAccess(this); - connect(m_downloader, &vte::NetworkAccess::requestFinished, - this, &ImageInsertDialog::handleImageDownloaded); - } + setImage(QImage()); + } - m_downloader->requestAsync(url); + m_source = Source::LocalFile; + } else { + setImage(QImage()); + m_source = Source::ImageData; + + if (!m_downloader) { + m_downloader = new vte::NetworkAccess(this); + connect(m_downloader, &vte::NetworkAccess::requestFinished, this, + &ImageInsertDialog::handleImageDownloaded); } - m_imageTitleEdit->setText(QFileInfo(text).baseName()); + m_downloader->requestAsync(url); + } - checkInput(); -} + m_imageTitleEdit->setText(QFileInfo(text).baseName()); -void ImageInsertDialog::checkInput() -{ - setButtonEnabled(QDialogButtonBox::Ok, !m_image.isNull()); + checkInput(); } -void ImageInsertDialog::browseFile() -{ - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - QString filePath = QFileDialog::getOpenFileName(this, - tr("Select Image To Insert"), - sessionConfig.getExternalMediaDefaultPath(), - tr("Images (*.png *.xpm *.jpg *.bmp *.gif *.svg *.webp);;All (*.*)")); - if (filePath.isEmpty()) { - return; - } +void ImageInsertDialog::checkInput() { setButtonEnabled(QDialogButtonBox::Ok, !m_image.isNull()); } - sessionConfig.setExternalMediaDefaultPath(PathUtils::parentDirPath(filePath)); +void ImageInsertDialog::browseFile() { + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + QString filePath = QFileDialog::getOpenFileName( + this, tr("Select Image To Insert"), sessionConfig.getExternalMediaDefaultPath(), + tr("Images (*.png *.xpm *.jpg *.bmp *.gif *.svg *.webp);;All (*.*)")); + if (filePath.isEmpty()) { + return; + } - m_source = Source::LocalFile; + sessionConfig.setExternalMediaDefaultPath(PathUtils::parentDirPath(filePath)); - setImagePath(filePath); + m_source = Source::LocalFile; - m_imageTitleEdit->selectAll(); - m_imageTitleEdit->setFocus(); -} + setImagePath(filePath); -QString ImageInsertDialog::getImageTitle() const -{ - return m_imageTitleEdit->text(); + m_imageTitleEdit->selectAll(); + m_imageTitleEdit->setFocus(); } -QString ImageInsertDialog::getImageAltText() const -{ - return m_imageAltEdit->text(); -} +QString ImageInsertDialog::getImageTitle() const { return m_imageTitleEdit->text(); } -QString ImageInsertDialog::getImagePath() const -{ - if (m_tempFile.isNull()) { - return m_imagePathEdit->text(); - } else { - return m_tempFile->fileName(); - } -} +QString ImageInsertDialog::getImageAltText() const { return m_imageAltEdit->text(); } -ImageInsertDialog::Source ImageInsertDialog::getImageSource() const -{ - return m_source; +QString ImageInsertDialog::getImagePath() const { + if (m_tempFile.isNull()) { + return m_imagePathEdit->text(); + } else { + return m_tempFile->fileName(); + } } -void ImageInsertDialog::setImageSource(ImageInsertDialog::Source p_source) -{ - m_source = p_source; -} +ImageInsertDialog::Source ImageInsertDialog::getImageSource() const { return m_source; } -const QImage &ImageInsertDialog::getImage() const -{ - return m_image; -} +void ImageInsertDialog::setImageSource(ImageInsertDialog::Source p_source) { m_source = p_source; } -void ImageInsertDialog::setImage(const QImage &p_image) -{ - m_image = p_image; - if (m_image.isNull()) { - m_imageLabel->clear(); - setImageControlsVisible(false); - } else { - m_imageLabel->setPixmap(QPixmap::fromImage(m_image)); +const QImage &ImageInsertDialog::getImage() const { return m_image; } - m_imageLabel->adjustSize(); +void ImageInsertDialog::setImage(const QImage &p_image) { + m_image = p_image; + if (m_image.isNull()) { + m_imageLabel->clear(); + setImageControlsVisible(false); + } else { + m_imageLabel->setPixmap(QPixmap::fromImage(m_image)); - m_widthSpin->setMaximum(m_image.width() * 5); + m_imageLabel->adjustSize(); - if (s_fixedScaleWidth) { - m_widthSpin->setValue(s_lastScaleWidth); - } else { - // Set the scaling widgets. - if (m_scaleSlider->value() == s_lastScaleSliderValue) { - // Trigger it manually. - handleScaleSliderValueChanged(s_lastScaleSliderValue); - } else { - m_scaleSlider->setValue(s_lastScaleSliderValue); - } - } + m_widthSpin->setMaximum(m_image.width() * 5); - setImageControlsVisible(true); + if (s_fixedScaleWidth) { + m_widthSpin->setValue(s_lastScaleWidth); + } else { + // Set the scaling widgets. + if (m_scaleSlider->value() == s_lastScaleSliderValue) { + // Trigger it manually. + handleScaleSliderValueChanged(s_lastScaleSliderValue); + } else { + m_scaleSlider->setValue(s_lastScaleSliderValue); + } } - checkInput(); + setImageControlsVisible(true); + } + + checkInput(); } -void ImageInsertDialog::setImagePath(const QString &p_path) -{ - m_tempFile.reset(); - m_imagePathEdit->setText(p_path); +void ImageInsertDialog::setImagePath(const QString &p_path) { + m_tempFile.reset(); + m_imagePathEdit->setText(p_path); } -int ImageInsertDialog::getScaledWidth() const -{ - if (m_image.isNull()) { - return 0; - } +int ImageInsertDialog::getScaledWidth() const { + if (m_image.isNull()) { + return 0; + } - int val = m_widthSpin->value(); - return val == m_image.width() ? 0 : val; + int val = m_widthSpin->value(); + return val == m_image.width() ? 0 : val; } -void ImageInsertDialog::handleImageDownloaded(const vte::NetworkReply &p_data, const QString &p_url) -{ - setImage(QImage::fromData(p_data.m_data)); - - // Save it to a temp file to avoid potential data loss via QImage. - bool savedToFile = false; - if (!p_data.m_data.isEmpty()) { - auto format = QFileInfo(PathUtils::removeUrlParameters(p_url)).suffix(); - m_tempFile.reset(FileUtils::createTemporaryFile(format)); - if (m_tempFile->open()) { - savedToFile = -1 != m_tempFile->write(p_data.m_data); - m_tempFile->close(); - } +void ImageInsertDialog::handleImageDownloaded(const vte::NetworkReply &p_data, + const QString &p_url) { + setImage(QImage::fromData(p_data.m_data)); + + // Save it to a temp file to avoid potential data loss via QImage. + bool savedToFile = false; + if (!p_data.m_data.isEmpty()) { + auto format = QFileInfo(PathUtils::removeUrlParameters(p_url)).suffix(); + m_tempFile.reset(FileUtils::createTemporaryFile(format)); + if (m_tempFile->open()) { + savedToFile = -1 != m_tempFile->write(p_data.m_data); + m_tempFile->close(); } + } - m_source = savedToFile ? Source::LocalFile : Source::ImageData; - if (!savedToFile) { - m_tempFile.reset(); - } + m_source = savedToFile ? Source::LocalFile : Source::ImageData; + if (!savedToFile) { + m_tempFile.reset(); + } } -void ImageInsertDialog::handleScaleSliderValueChanged(int p_val) -{ - if (m_image.isNull()) { - return; - } +void ImageInsertDialog::handleScaleSliderValueChanged(int p_val) { + if (m_image.isNull()) { + return; + } - int width = m_image.width(); - qreal factor = 1.0; - if (p_val != 10) { - factor = p_val / 10.0; - width = m_image.width() * factor; - } + int width = m_image.width(); + qreal factor = 1.0; + if (p_val != 10) { + factor = p_val / 10.0; + width = m_image.width() * factor; + } - m_widthSpin->setValue(width); - m_sliderLabel->setText(QString::number(factor) + "x"); + m_widthSpin->setValue(width); + m_sliderLabel->setText(QString::number(factor) + "x"); - s_lastScaleSliderValue = p_val; + s_lastScaleSliderValue = p_val; } diff --git a/src/widgets/dialogs/imageinsertdialog.h b/src/widgets/dialogs/imageinsertdialog.h index 08fe4e9227..e400f858fa 100644 --- a/src/widgets/dialogs/imageinsertdialog.h +++ b/src/widgets/dialogs/imageinsertdialog.h @@ -3,8 +3,8 @@ #include "dialog.h" -#include #include +#include class QLineEdit; class QPushButton; @@ -15,108 +15,96 @@ class QTimer; class QTemporaryFile; class QScrollArea; -namespace vte -{ - class NetworkAccess; - struct NetworkReply; -} +namespace vte { +class NetworkAccess; +struct NetworkReply; +} // namespace vte -namespace vnotex -{ - class ImageInsertDialog : public Dialog - { - Q_OBJECT - public: - enum Source - { - LocalFile, - ImageData - }; +namespace vnotex { +class ImageInsertDialog : public Dialog { + Q_OBJECT +public: + enum Source { LocalFile, ImageData }; - ImageInsertDialog(const QString &p_title, - const QString &p_imageTitle, - const QString &p_imageAlt, - const QString &p_imagePath, - bool p_browserEnabled = true, - QWidget *p_parent = nullptr); + ImageInsertDialog(const QString &p_title, const QString &p_imageTitle, const QString &p_imageAlt, + const QString &p_imagePath, bool p_browserEnabled = true, + QWidget *p_parent = nullptr); - QString getImageTitle() const; + QString getImageTitle() const; - QString getImageAltText() const; + QString getImageAltText() const; - QString getImagePath() const; - void setImagePath(const QString &p_path); + QString getImagePath() const; + void setImagePath(const QString &p_path); - ImageInsertDialog::Source getImageSource() const; - void setImageSource(ImageInsertDialog::Source p_source); + ImageInsertDialog::Source getImageSource() const; + void setImageSource(ImageInsertDialog::Source p_source); - const QImage &getImage() const; - void setImage(const QImage &p_image); + const QImage &getImage() const; + void setImage(const QImage &p_image); - // Return 0 if no scaling. - int getScaledWidth() const; + // Return 0 if no scaling. + int getScaledWidth() const; - protected: - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; +protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void checkImagePathInput(); +private slots: + void checkImagePathInput(); - void checkInput(); + void checkInput(); - void browseFile(); + void browseFile(); - void handleImageDownloaded(const vte::NetworkReply &p_data, const QString &p_url); + void handleImageDownloaded(const vte::NetworkReply &p_data, const QString &p_url); - void handleScaleSliderValueChanged(int p_val); + void handleScaleSliderValueChanged(int p_val); - private: - void setupUI(const QString &p_title, - const QString &p_imageTitle, - const QString &p_imageAlt, - const QString &p_imagePath); +private: + void setupUI(const QString &p_title, const QString &p_imageTitle, const QString &p_imageAlt, + const QString &p_imagePath); - void setImageControlsVisible(bool p_visible); + void setImageControlsVisible(bool p_visible); - bool m_browserEnabled = true; + bool m_browserEnabled = true; - Source m_source = Source::LocalFile; + Source m_source = Source::LocalFile; - QLineEdit *m_imagePathEdit = nullptr; + QLineEdit *m_imagePathEdit = nullptr; - QPushButton *m_browseBtn = nullptr; + QPushButton *m_browseBtn = nullptr; - QLineEdit *m_imageTitleEdit = nullptr; + QLineEdit *m_imageTitleEdit = nullptr; - QLineEdit *m_imageAltEdit = nullptr; + QLineEdit *m_imageAltEdit = nullptr; - QSpinBox *m_widthSpin = nullptr; + QSpinBox *m_widthSpin = nullptr; - QSlider *m_scaleSlider = nullptr; + QSlider *m_scaleSlider = nullptr; - QLabel *m_sliderLabel = nullptr; + QLabel *m_sliderLabel = nullptr; - QLabel *m_imageLabel = nullptr; + QLabel *m_imageLabel = nullptr; - QScrollArea *m_previewArea = nullptr; + QScrollArea *m_previewArea = nullptr; - QImage m_image; + QImage m_image; - // Managed by QObject. - vte::NetworkAccess *m_downloader = nullptr; + // Managed by QObject. + vte::NetworkAccess *m_downloader = nullptr; - // Managed by QObject. - QTimer *m_imagePathCheckTimer = nullptr; + // Managed by QObject. + QTimer *m_imagePathCheckTimer = nullptr; - // Used to hold downloaded image, to avoid data loss via QImage. - QSharedPointer m_tempFile; + // Used to hold downloaded image, to avoid data loss via QImage. + QSharedPointer m_tempFile; - static int s_lastScaleSliderValue; + static int s_lastScaleSliderValue; - static int s_lastScaleWidth; + static int s_lastScaleWidth; - static bool s_fixedScaleWidth; - }; -} + static bool s_fixedScaleWidth; +}; +} // namespace vnotex #endif // IMAGEINSERTDIALOG_H diff --git a/src/widgets/dialogs/importfolderdialog.cpp b/src/widgets/dialogs/importfolderdialog.cpp index d9c1535db7..93927e7b03 100644 --- a/src/widgets/dialogs/importfolderdialog.cpp +++ b/src/widgets/dialogs/importfolderdialog.cpp @@ -1,122 +1,109 @@ #include "importfolderdialog.h" -#include #include -#include #include +#include +#include +#include "exception.h" #include "folderfilesfilterwidget.h" +#include "importfolderutils.h" #include "vnotex.h" -#include "exception.h" -#include #include #include -#include "importfolderutils.h" +#include using namespace vnotex; ImportFolderDialog::ImportFolderDialog(Node *p_node, QWidget *p_parent) - : ScrollDialog(p_parent), - m_parentNode(p_node) -{ - setupUI(); + : ScrollDialog(p_parent), m_parentNode(p_node) { + setupUI(); - m_filterWidget->getFolderPathEdit()->setFocus(); + m_filterWidget->getFolderPathEdit()->setFocus(); } -void ImportFolderDialog::setupUI() -{ - auto widget = new QWidget(this); - auto mainLayout = new QVBoxLayout(widget); - setCentralWidget(widget); +void ImportFolderDialog::setupUI() { + auto widget = new QWidget(this); + auto mainLayout = new QVBoxLayout(widget); + setCentralWidget(widget); - auto label = new QLabel(tr("Import folder into (%1).").arg(m_parentNode->fetchAbsolutePath()), widget); - label->setWordWrap(true); - mainLayout->addWidget(label); + auto label = + new QLabel(tr("Import folder into (%1).").arg(m_parentNode->fetchAbsolutePath()), widget); + label->setWordWrap(true); + mainLayout->addWidget(label); - setupFolderFilesFilterWidget(widget); - mainLayout->addWidget(m_filterWidget); + setupFolderFilesFilterWidget(widget); + mainLayout->addWidget(m_filterWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setButtonEnabled(QDialogButtonBox::Ok, false); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setButtonEnabled(QDialogButtonBox::Ok, false); - setWindowTitle(tr("Import Folder")); + setWindowTitle(tr("Import Folder")); } -void ImportFolderDialog::setupFolderFilesFilterWidget(QWidget *p_parent) -{ - m_filterWidget = new FolderFilesFilterWidget(p_parent); - connect(m_filterWidget, &FolderFilesFilterWidget::filesChanged, - this, [this]() { - validateInputs(); - }); +void ImportFolderDialog::setupFolderFilesFilterWidget(QWidget *p_parent) { + m_filterWidget = new FolderFilesFilterWidget(p_parent); + connect(m_filterWidget, &FolderFilesFilterWidget::filesChanged, this, + [this]() { validateInputs(); }); } -const QSharedPointer &ImportFolderDialog::getNewNode() const -{ - return m_newNode; -} +const QSharedPointer &ImportFolderDialog::getNewNode() const { return m_newNode; } -void ImportFolderDialog::acceptedButtonClicked() -{ - if (isCompleted() || importFolder()) { - accept(); - } +void ImportFolderDialog::acceptedButtonClicked() { + if (isCompleted() || importFolder()) { + accept(); + } } -void ImportFolderDialog::validateInputs() -{ - bool valid = true; - QString msg; +void ImportFolderDialog::validateInputs() { + bool valid = true; + QString msg; - auto folder = m_filterWidget->getFolderPath(); - if (!QFileInfo::exists(folder) || !PathUtils::isLegalPath(folder)) { - msg = tr("Please specify a valid folder to import."); - valid = false; - } + auto folder = m_filterWidget->getFolderPath(); + if (!QFileInfo::exists(folder) || !PathUtils::isLegalPath(folder)) { + msg = tr("Please specify a valid folder to import."); + valid = false; + } - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - setButtonEnabled(QDialogButtonBox::Ok, valid); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + setButtonEnabled(QDialogButtonBox::Ok, valid); } -bool ImportFolderDialog::importFolder() -{ - const auto folder = m_filterWidget->getFolderPath(); - auto nb = m_parentNode->getNotebook(); - if (PathUtils::pathContains(folder, m_parentNode->fetchAbsolutePath())) - { - // Avoid recursive import. - auto msg = tr("Failed to add folder (%1) as node under (%2).").arg(folder, m_parentNode->fetchAbsolutePath()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - m_newNode = nullptr; - try { - m_newNode = nb->copyAsNode(m_parentNode, Node::Flag::Container, folder); - } catch (Exception &p_e) { - auto msg = tr("Failed to add folder (%1) as node (%2).").arg(folder, p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - QString errMsg; - ImportFolderUtils::importFolderContents(nb, - m_newNode.data(), - m_filterWidget->getSuffixes(), - errMsg); - - emit nb->nodeUpdated(m_parentNode); - - if (!errMsg.isEmpty()) { - qWarning() << errMsg; - setInformationText(errMsg, ScrollDialog::InformationLevel::Error); - completeButStay(); - return false; - } - - return true; +bool ImportFolderDialog::importFolder() { + const auto folder = m_filterWidget->getFolderPath(); + auto nb = m_parentNode->getNotebook(); + if (PathUtils::pathContains(folder, m_parentNode->fetchAbsolutePath())) { + // Avoid recursive import. + auto msg = tr("Failed to add folder (%1) as node under (%2).") + .arg(folder, m_parentNode->fetchAbsolutePath()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + m_newNode = nullptr; + try { + m_newNode = nb->copyAsNode(m_parentNode, Node::Flag::Container, folder); + } catch (Exception &p_e) { + auto msg = tr("Failed to add folder (%1) as node (%2).").arg(folder, p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + QString errMsg; + ImportFolderUtils::importFolderContents(nb, m_newNode.data(), m_filterWidget->getSuffixes(), + errMsg); + + emit nb->nodeUpdated(m_parentNode); + + if (!errMsg.isEmpty()) { + qWarning() << errMsg; + setInformationText(errMsg, ScrollDialog::InformationLevel::Error); + completeButStay(); + return false; + } + + return true; } diff --git a/src/widgets/dialogs/importfolderdialog.h b/src/widgets/dialogs/importfolderdialog.h index b2067ab06a..2a113de65f 100644 --- a/src/widgets/dialogs/importfolderdialog.h +++ b/src/widgets/dialogs/importfolderdialog.h @@ -3,39 +3,37 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Node; - class FolderFilesFilterWidget; +namespace vnotex { +class Node; +class FolderFilesFilterWidget; - class ImportFolderDialog : public ScrollDialog - { - Q_OBJECT - public: - // Import a folder under @p_node. - ImportFolderDialog(Node *p_node, QWidget *p_parent = nullptr); +class ImportFolderDialog : public ScrollDialog { + Q_OBJECT +public: + // Import a folder under @p_node. + ImportFolderDialog(Node *p_node, QWidget *p_parent = nullptr); - const QSharedPointer &getNewNode() const; + const QSharedPointer &getNewNode() const; - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private slots: - void validateInputs(); +private slots: + void validateInputs(); - private: - void setupUI(); +private: + void setupUI(); - void setupFolderFilesFilterWidget(QWidget *p_parent = nullptr); + void setupFolderFilesFilterWidget(QWidget *p_parent = nullptr); - bool importFolder(); + bool importFolder(); - Node *m_parentNode = nullptr; + Node *m_parentNode = nullptr; - QSharedPointer m_newNode; + QSharedPointer m_newNode; - FolderFilesFilterWidget *m_filterWidget = nullptr; - }; -} + FolderFilesFilterWidget *m_filterWidget = nullptr; +}; +} // namespace vnotex #endif // IMPORTFOLDERDIALOG_H diff --git a/src/widgets/dialogs/importfolderutils.cpp b/src/widgets/dialogs/importfolderutils.cpp index b87d393ae1..40ad361c93 100644 --- a/src/widgets/dialogs/importfolderutils.cpp +++ b/src/widgets/dialogs/importfolderutils.cpp @@ -1,113 +1,129 @@ #include "importfolderutils.h" -#include -#include -#include -#include #include "legacynotebookutils.h" +#include +#include +#include +#include #include using namespace vnotex; -void ImportFolderUtils::importFolderContents(Notebook *p_notebook, - Node *p_node, - const QStringList &p_suffixes, - QString &p_errMsg) -{ - auto rootDir = p_node->toDir(); - auto children = rootDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); - for (const auto &child : children) { - if (child.isDir()) { - if (p_notebook->isBuiltInFolder(p_node, child.fileName())) { - continue; - } +void ImportFolderUtils::importFolderContents(Notebook *p_notebook, Node *p_node, + const QStringList &p_suffixes, QString &p_errMsg) { + auto rootDir = p_node->toDir(); + auto children = + rootDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); + for (const auto &child : children) { + if (child.isDir()) { + if (p_notebook->isBuiltInFolder(p_node, child.fileName())) { + continue; + } - QSharedPointer node; - try { - node = p_notebook->addAsNode(p_node, Node::Flag::Container, child.fileName(), NodeParameters()); - } catch (Exception &p_e) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(child.fileName(), p_e.what())); - continue; - } + QSharedPointer node; + try { + node = p_notebook->addAsNode(p_node, Node::Flag::Container, child.fileName(), + NodeParameters()); + } catch (Exception &p_e) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).") + .arg(child.fileName(), p_e.what())); + continue; + } - importFolderContents(p_notebook, node.data(), p_suffixes, p_errMsg); - } else if (!p_notebook->isBuiltInFile(p_node, child.fileName())) { - if (p_suffixes.contains(child.suffix())) { - try { - p_notebook->addAsNode(p_node, Node::Flag::Content, child.fileName(), NodeParameters()); - } catch (Exception &p_e) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(child.filePath(), p_e.what())); - } - } + importFolderContents(p_notebook, node.data(), p_suffixes, p_errMsg); + } else if (!p_notebook->isBuiltInFile(p_node, child.fileName())) { + if (p_suffixes.contains(child.suffix())) { + try { + p_notebook->addAsNode(p_node, Node::Flag::Content, child.fileName(), NodeParameters()); + } catch (Exception &p_e) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).") + .arg(child.filePath(), p_e.what())); } + } } + } } -void ImportFolderUtils::importFolderContentsByLegacyConfig(Notebook *p_notebook, - Node *p_node, - QString &p_errMsg) -{ - auto rootDir = p_node->toDir(); +void ImportFolderUtils::importFolderContentsByLegacyConfig(Notebook *p_notebook, Node *p_node, + QString &p_errMsg) { + auto rootDir = p_node->toDir(); - QJsonObject config; - try { - config = LegacyNotebookUtils::getFolderConfig(rootDir.absolutePath()); - } catch (Exception &p_e) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to read folder config (%1) (%2).").arg(rootDir.absolutePath(), p_e.what())); - return; - } + QJsonObject config; + try { + config = LegacyNotebookUtils::getFolderConfig(rootDir.absolutePath()); + } catch (Exception &p_e) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Failed to read folder config (%1) (%2).") + .arg(rootDir.absolutePath(), p_e.what())); + return; + } - // Remove the config file. - LegacyNotebookUtils::removeFolderConfigFile(rootDir.absolutePath()); + // Remove the config file. + LegacyNotebookUtils::removeFolderConfigFile(rootDir.absolutePath()); - // Folders. - LegacyNotebookUtils::forEachFolder(config, [&rootDir, p_notebook, p_node, &p_errMsg](const QString &name) { - if (!rootDir.exists(name)) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Folder (%1) does not exist.").arg(name)); - return; - } + // Folders. + LegacyNotebookUtils::forEachFolder(config, [&rootDir, p_notebook, p_node, + &p_errMsg](const QString &name) { + if (!rootDir.exists(name)) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Folder (%1) does not exist.").arg(name)); + return; + } - if (p_notebook->isBuiltInFolder(p_node, name)) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Folder (%1) conflicts with built-in folder.").arg(name)); - return; - } + if (p_notebook->isBuiltInFolder(p_node, name)) { + Utils::appendMsg( + p_errMsg, + ImportFolderUtilsTranslate::tr("Folder (%1) conflicts with built-in folder.").arg(name)); + return; + } - QSharedPointer node; - try { - NodeParameters paras; - paras.m_createdTimeUtc = LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootDir.filePath(name)); - node = p_notebook->addAsNode(p_node, Node::Flag::Container, name, paras); - } catch (Exception &p_e) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(name, p_e.what())); - return; - } + QSharedPointer node; + try { + NodeParameters paras; + paras.m_createdTimeUtc = + LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootDir.filePath(name)); + node = p_notebook->addAsNode(p_node, Node::Flag::Container, name, paras); + } catch (Exception &p_e) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).") + .arg(name, p_e.what())); + return; + } - ImportFolderUtils::importFolderContentsByLegacyConfig(p_notebook, node.data(), p_errMsg); - }); + ImportFolderUtils::importFolderContentsByLegacyConfig(p_notebook, node.data(), p_errMsg); + }); - // Files. - LegacyNotebookUtils::forEachFile(config, [&rootDir, p_notebook, p_node, &p_errMsg](const LegacyNotebookUtils::FileInfo &info) { - if (!rootDir.exists(info.m_name)) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("File (%1) does not exist.").arg(info.m_name)); - return; - } + // Files. + LegacyNotebookUtils::forEachFile(config, [&rootDir, p_notebook, p_node, + &p_errMsg](const LegacyNotebookUtils::FileInfo &info) { + if (!rootDir.exists(info.m_name)) { + Utils::appendMsg( + p_errMsg, ImportFolderUtilsTranslate::tr("File (%1) does not exist.").arg(info.m_name)); + return; + } - if (p_notebook->isBuiltInFile(p_node, info.m_name)) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("File (%1) conflicts with built-in file.").arg(info.m_name)); - return; - } + if (p_notebook->isBuiltInFile(p_node, info.m_name)) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("File (%1) conflicts with built-in file.") + .arg(info.m_name)); + return; + } - QSharedPointer node; - try { - NodeParameters paras; - paras.m_createdTimeUtc = info.m_createdTimeUtc; - paras.m_modifiedTimeUtc = info.m_modifiedTimeUtc; - paras.m_attachmentFolder = info.m_attachmentFolder; - paras.m_tags = info.m_tags; - node = p_notebook->addAsNode(p_node, Node::Flag::Content, info.m_name, paras); - } catch (Exception &p_e) { - Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(info.m_name, p_e.what())); - return; - } - }); + QSharedPointer node; + try { + NodeParameters paras; + paras.m_createdTimeUtc = info.m_createdTimeUtc; + paras.m_modifiedTimeUtc = info.m_modifiedTimeUtc; + paras.m_attachmentFolder = info.m_attachmentFolder; + paras.m_tags = info.m_tags; + node = p_notebook->addAsNode(p_node, Node::Flag::Content, info.m_name, paras); + } catch (Exception &p_e) { + Utils::appendMsg(p_errMsg, + ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).") + .arg(info.m_name, p_e.what())); + return; + } + }); } diff --git a/src/widgets/dialogs/importfolderutils.h b/src/widgets/dialogs/importfolderutils.h index 69e4d1bc53..2cffb02c6b 100644 --- a/src/widgets/dialogs/importfolderutils.h +++ b/src/widgets/dialogs/importfolderutils.h @@ -5,35 +5,29 @@ #include -namespace vnotex -{ - class Notebook; - class Node; - - // A dummy class used to do translations. - class ImportFolderUtilsTranslate : public QObject - { - Q_OBJECT - }; - - class ImportFolderUtils - { - public: - ImportFolderUtils() = delete; - - // Process folder @p_node. - // @p_node has already been added. - static void importFolderContents(Notebook *p_notebook, - Node *p_node, - const QStringList &p_suffixes, - QString &p_errMsg); - - // Process folder @p_node by legacy notebook config. - // @p_node has already been added. - static void importFolderContentsByLegacyConfig(Notebook *p_notebook, - Node *p_node, - QString &p_errMsg); - }; -} +namespace vnotex { +class Notebook; +class Node; + +// A dummy class used to do translations. +class ImportFolderUtilsTranslate : public QObject { + Q_OBJECT +}; + +class ImportFolderUtils { +public: + ImportFolderUtils() = delete; + + // Process folder @p_node. + // @p_node has already been added. + static void importFolderContents(Notebook *p_notebook, Node *p_node, + const QStringList &p_suffixes, QString &p_errMsg); + + // Process folder @p_node by legacy notebook config. + // @p_node has already been added. + static void importFolderContentsByLegacyConfig(Notebook *p_notebook, Node *p_node, + QString &p_errMsg); +}; +} // namespace vnotex #endif // IMPORTFOLDERUTILS_H diff --git a/src/widgets/dialogs/importlegacynotebookdialog.cpp b/src/widgets/dialogs/importlegacynotebookdialog.cpp index 0a459bfb69..00cde8948d 100644 --- a/src/widgets/dialogs/importlegacynotebookdialog.cpp +++ b/src/widgets/dialogs/importlegacynotebookdialog.cpp @@ -1,159 +1,149 @@ #include "importlegacynotebookdialog.h" -#include #include +#include +#include "../messageboxhelper.h" +#include "importfolderutils.h" +#include "legacynotebookutils.h" #include "notebookinfowidget.h" -#include -#include -#include -#include "vnotex.h" #include "notebookmgr.h" -#include "legacynotebookutils.h" -#include "../messageboxhelper.h" +#include "vnotex.h" #include -#include "importfolderutils.h" +#include +#include +#include using namespace vnotex; ImportLegacyNotebookDialog::ImportLegacyNotebookDialog(QWidget *p_parent) - : NewNotebookDialog(p_parent) -{ - setWindowTitle(tr("Open Legacy Notebook")); + : NewNotebookDialog(p_parent) { + setWindowTitle(tr("Open Legacy Notebook")); - m_infoWidget->setMode(NotebookInfoWidget::Mode::CreateFromLegacy); - m_infoWidget->getRootFolderPathLineEdit()->setFocus(); + m_infoWidget->setMode(NotebookInfoWidget::Mode::CreateFromLegacy); + m_infoWidget->getRootFolderPathLineEdit()->setFocus(); } -void ImportLegacyNotebookDialog::acceptedButtonClicked() -{ - if (isCompleted()) { - accept(); - return; - } - - // Warn user about the transformation. - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, - 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()) { - accept(); - return; - } +void ImportLegacyNotebookDialog::acceptedButtonClicked() { + if (isCompleted()) { + accept(); + return; + } + + // Warn user about the transformation. + int ret = MessageBoxHelper::questionOkCancel( + MessageBoxHelper::Warning, + 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()) { + accept(); + return; + } } -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 open.")); - return false; - } +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 open.")); + return false; + } - if (!LegacyNotebookUtils::isLegacyNotebookRootFolder(rootFolderPath)) { - Utils::appendMsg(p_msg, tr("Failed to recognize a legacy notebook from the root folder.")); - return false; - } + if (!LegacyNotebookUtils::isLegacyNotebookRootFolder(rootFolderPath)) { + Utils::appendMsg(p_msg, tr("Failed to recognize a legacy notebook from the root folder.")); + return false; + } - // Check if there already exists one notebook with the same root folder. - { - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); - if (notebook) { - Utils::appendMsg(p_msg, - tr("There already exists a notebook (%1) with the same root folder.").arg(notebook->getName())); - return false; - } + // Check if there already exists one notebook with the same root folder. + { + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); + if (notebook) { + Utils::appendMsg(p_msg, tr("There already exists a notebook (%1) with the same root folder.") + .arg(notebook->getName())); + return false; } + } - return true; + return true; } -bool ImportLegacyNotebookDialog::importLegacyNotebook() -{ - const auto rootFolderPath = m_infoWidget->getRootFolderPath(); +bool ImportLegacyNotebookDialog::importLegacyNotebook() { + const auto rootFolderPath = m_infoWidget->getRootFolderPath(); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - 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; + QString imageFolder; + QString attachmentFolder; + QDateTime createdTimeUtc; + + try { + imageFolder = LegacyNotebookUtils::getImageFolderOfNotebook(rootFolderPath); + if (imageFolder.isEmpty()) { + imageFolder = Notebook::c_defaultImageFolder; } - auto paras = NotebookParameters::createNotebookParameters(notebookMgr, - m_infoWidget->getType(), - m_infoWidget->getName(), - m_infoWidget->getDescription(), - rootFolderPath, - m_infoWidget->getIcon(), - imageFolder, - attachmentFolder, - createdTimeUtc, - m_infoWidget->getBackend(), - m_infoWidget->getVersionController(), - m_infoWidget->getConfigMgr()); - paras->m_ensureEmptyRootFolder = false; - QSharedPointer nb; - try { - nb = notebookMgr.newNotebook(paras); - } catch (Exception &p_e) { - QString msg = tr("Failed to create notebook in (%1) (%2).").arg(rootFolderPath, p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; + attachmentFolder = LegacyNotebookUtils::getAttachmentFolderOfNotebook(rootFolderPath); + if (attachmentFolder.isEmpty()) { + attachmentFolder = Notebook::c_defaultAttachmentFolder; } - QString errMsg; - - // Copy legacy recycle bin folder into new one or just delete it if it is empty. - { - auto legacyBinFolder = LegacyNotebookUtils::getRecycleBinFolderOfNotebook(rootFolderPath); - if (!legacyBinFolder.isEmpty()) { - auto binFolderPath = PathUtils::concatenateFilePath(rootFolderPath, legacyBinFolder); - if (PathUtils::isEmptyDir(binFolderPath)) { - FileUtils::removeDir(binFolderPath); - } else { - nb->moveDirToRecycleBin(binFolderPath); - } - } + 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(), m_infoWidget->getDescription(), + rootFolderPath, m_infoWidget->getIcon(), imageFolder, attachmentFolder, createdTimeUtc, + m_infoWidget->getBackend(), m_infoWidget->getVersionController(), + m_infoWidget->getConfigMgr()); + paras->m_ensureEmptyRootFolder = false; + QSharedPointer nb; + try { + nb = notebookMgr.newNotebook(paras); + } catch (Exception &p_e) { + QString msg = tr("Failed to create notebook in (%1) (%2).").arg(rootFolderPath, p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + QString errMsg; + + // Copy legacy recycle bin folder into new one or just delete it if it is empty. + { + auto legacyBinFolder = LegacyNotebookUtils::getRecycleBinFolderOfNotebook(rootFolderPath); + if (!legacyBinFolder.isEmpty()) { + auto binFolderPath = PathUtils::concatenateFilePath(rootFolderPath, legacyBinFolder); + if (PathUtils::isEmptyDir(binFolderPath)) { + FileUtils::removeDir(binFolderPath); + } else { + nb->moveDirToRecycleBin(binFolderPath); + } } + } - auto rootNode = nb->getRootNode(); + auto rootNode = nb->getRootNode(); - 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()); - } + 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()); + emit nb->nodeUpdated(rootNode.data()); - if (!errMsg.isEmpty()) { - qWarning() << errMsg; - setInformationText(errMsg, ScrollDialog::InformationLevel::Error); - completeButStay(); - return false; - } + if (!errMsg.isEmpty()) { + qWarning() << errMsg; + setInformationText(errMsg, ScrollDialog::InformationLevel::Error); + completeButStay(); + return false; + } - return true; + return true; } diff --git a/src/widgets/dialogs/importlegacynotebookdialog.h b/src/widgets/dialogs/importlegacynotebookdialog.h index 730d3263b1..4317ebcd6d 100644 --- a/src/widgets/dialogs/importlegacynotebookdialog.h +++ b/src/widgets/dialogs/importlegacynotebookdialog.h @@ -3,22 +3,20 @@ #include "newnotebookdialog.h" -namespace vnotex -{ - class ImportLegacyNotebookDialog : public NewNotebookDialog - { - Q_OBJECT - public: - explicit ImportLegacyNotebookDialog(QWidget *p_parent = nullptr); +namespace vnotex { +class ImportLegacyNotebookDialog : public NewNotebookDialog { + Q_OBJECT +public: + explicit ImportLegacyNotebookDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - bool validateRootFolderInput(QString &p_msg) Q_DECL_OVERRIDE; + bool validateRootFolderInput(QString &p_msg) Q_DECL_OVERRIDE; - private: - bool importLegacyNotebook(); - }; -} +private: + bool importLegacyNotebook(); +}; +} // namespace vnotex #endif // IMPORTLEGACYNOTEBOOKDIALOG_H diff --git a/src/widgets/dialogs/importnotebookdialog.cpp b/src/widgets/dialogs/importnotebookdialog.cpp index 5b311c2b97..ea2886ac16 100644 --- a/src/widgets/dialogs/importnotebookdialog.cpp +++ b/src/widgets/dialogs/importnotebookdialog.cpp @@ -3,152 +3,143 @@ #include #include "../widgetsfactory.h" -#include "vnotex.h" -#include "notebookmgr.h" +#include "configmgr.h" +#include "exception.h" #include "notebook/inotebookfactory.h" #include "notebook/notebookparameters.h" -#include "versioncontroller/iversioncontrollerfactory.h" -#include "notebookconfigmgr/inotebookconfigmgrfactory.h" #include "notebookbackend/inotebookbackendfactory.h" -#include "configmgr.h" +#include "notebookconfigmgr/inotebookconfigmgrfactory.h" +#include "notebookinfowidget.h" +#include "notebookmgr.h" +#include "versioncontroller/iversioncontrollerfactory.h" +#include "vnotex.h" #include #include -#include "exception.h" -#include "notebookinfowidget.h" using namespace vnotex; -ImportNotebookDialog::ImportNotebookDialog(QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(); +ImportNotebookDialog::ImportNotebookDialog(QWidget *p_parent) : ScrollDialog(p_parent) { + setupUI(); - m_infoWidget->getRootFolderPathLineEdit()->setFocus(); + m_infoWidget->getRootFolderPathLineEdit()->setFocus(); } -void ImportNotebookDialog::setupUI() -{ - setupNotebookInfoWidget(this); - setCentralWidget(m_infoWidget); +void ImportNotebookDialog::setupUI() { + setupNotebookInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setButtonEnabled(QDialogButtonBox::Ok, false); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setButtonEnabled(QDialogButtonBox::Ok, false); - setWindowTitle(tr("Open Notebook")); + setWindowTitle(tr("Open Notebook")); } -void ImportNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::Import, p_parent); - connect(m_infoWidget, &NotebookInfoWidget::basicInfoEdited, - this, &ImportNotebookDialog::validateInputs); - connect(m_infoWidget, &NotebookInfoWidget::notebookBackendEdited, - this, &ImportNotebookDialog::validateInputs); +void ImportNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent) { + m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::Import, p_parent); + connect(m_infoWidget, &NotebookInfoWidget::basicInfoEdited, this, + &ImportNotebookDialog::validateInputs); + connect(m_infoWidget, &NotebookInfoWidget::notebookBackendEdited, this, + &ImportNotebookDialog::validateInputs); } -void ImportNotebookDialog::acceptedButtonClicked() -{ - if (importNotebook()) { - accept(); - } +void ImportNotebookDialog::acceptedButtonClicked() { + if (importNotebook()) { + accept(); + } } -void ImportNotebookDialog::validateInputs() -{ - bool valid = true; - QString msg; +void ImportNotebookDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateRootFolderInput(msg); + valid = valid && validateRootFolderInput(msg); - if (valid) { - valid = createNotebookToImport(msg); - } else { - m_notebookToImport.clear(); - } + if (valid) { + valid = createNotebookToImport(msg); + } else { + m_notebookToImport.clear(); + } - m_infoWidget->setNotebook(m_notebookToImport.data()); + m_infoWidget->setNotebook(m_notebookToImport.data()); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - setButtonEnabled(QDialogButtonBox::Ok, valid); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + setButtonEnabled(QDialogButtonBox::Ok, valid); } -bool ImportNotebookDialog::validateRootFolderInput(QString &p_msg) -{ - auto rootFolderPath = m_infoWidget->getRootFolderPath(); - if (rootFolderPath.isEmpty() || !QFileInfo::exists(rootFolderPath)) { - Utils::appendMsg(p_msg, tr("The root folder specified does not exist.")); - return false; +bool ImportNotebookDialog::validateRootFolderInput(QString &p_msg) { + auto rootFolderPath = m_infoWidget->getRootFolderPath(); + if (rootFolderPath.isEmpty() || !QFileInfo::exists(rootFolderPath)) { + Utils::appendMsg(p_msg, tr("The root folder specified does not exist.")); + return false; + } + + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + + // Check if there already exists one notebook with the same root folder. + { + auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); + if (notebook) { + Utils::appendMsg(p_msg, tr("There already exists a notebook (%1) with the same root folder.") + .arg(notebook->getName())); + return false; } + } - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - - // Check if there already exists one notebook with the same root folder. - { - auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); - if (notebook) { - Utils::appendMsg(p_msg, - tr("There already exists a notebook (%1) with the same root folder.").arg(notebook->getName())); - return false; - } - } - - // Check if it is a valid bundle notebook root folder. - { - auto factory = notebookMgr.getBundleNotebookFactory(); - auto backendName = m_infoWidget->getBackend(); - auto backend = notebookMgr.createNotebookBackend(backendName, rootFolderPath); - if (!factory->checkRootFolder(backend)) { - Utils::appendMsg(p_msg, - tr("Not a valid (%1) root folder (%2).").arg(factory->getDisplayName(), rootFolderPath)); - return false; - } + // Check if it is a valid bundle notebook root folder. + { + auto factory = notebookMgr.getBundleNotebookFactory(); + auto backendName = m_infoWidget->getBackend(); + auto backend = notebookMgr.createNotebookBackend(backendName, rootFolderPath); + if (!factory->checkRootFolder(backend)) { + Utils::appendMsg( + p_msg, + tr("Not a valid (%1) root folder (%2).").arg(factory->getDisplayName(), rootFolderPath)); + return false; } + } - return true; + return true; } -bool ImportNotebookDialog::createNotebookToImport(QString &p_msg) -{ - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - auto factory = notebookMgr.getBundleNotebookFactory(); +bool ImportNotebookDialog::createNotebookToImport(QString &p_msg) { + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto factory = notebookMgr.getBundleNotebookFactory(); - auto rootFolderPath = m_infoWidget->getRootFolderPath(); + auto rootFolderPath = m_infoWidget->getRootFolderPath(); - auto backendName = m_infoWidget->getBackend(); - auto backend = notebookMgr.createNotebookBackend(backendName, rootFolderPath); + auto backendName = m_infoWidget->getBackend(); + auto backend = notebookMgr.createNotebookBackend(backendName, rootFolderPath); - try { - m_notebookToImport = factory->createNotebook(notebookMgr, - rootFolderPath, - backend); - } catch (Exception &p_e) { - Utils::appendMsg(p_msg, tr("Failed to create notebook from root folder (%1) (%2).").arg(rootFolderPath, p_e.what())); - return false; - } + try { + m_notebookToImport = factory->createNotebook(notebookMgr, rootFolderPath, backend); + } catch (Exception &p_e) { + Utils::appendMsg(p_msg, tr("Failed to create notebook from root folder (%1) (%2).") + .arg(rootFolderPath, p_e.what())); + return false; + } - Q_ASSERT(m_notebookToImport); - return true; + Q_ASSERT(m_notebookToImport); + return true; } -bool ImportNotebookDialog::importNotebook() -{ - if (!m_notebookToImport) { - QString msg = tr("Failed to open notebook."); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - try { - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - notebookMgr.importNotebook(m_notebookToImport); - } catch (Exception &p_e) { - QString msg = tr("Failed to open notebook (%1).").arg(p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } +bool ImportNotebookDialog::importNotebook() { + if (!m_notebookToImport) { + QString msg = tr("Failed to open notebook."); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } - return true; + try { + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + notebookMgr.importNotebook(m_notebookToImport); + } catch (Exception &p_e) { + QString msg = tr("Failed to open notebook (%1).").arg(p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } diff --git a/src/widgets/dialogs/importnotebookdialog.h b/src/widgets/dialogs/importnotebookdialog.h index c5e695289b..97c5aed15f 100644 --- a/src/widgets/dialogs/importnotebookdialog.h +++ b/src/widgets/dialogs/importnotebookdialog.h @@ -6,38 +6,36 @@ class QGroupBox; class QComboBox; -namespace vnotex -{ - class NotebookInfoWidget; - class Notebook; +namespace vnotex { +class NotebookInfoWidget; +class Notebook; - class ImportNotebookDialog : public ScrollDialog - { - Q_OBJECT - public: - explicit ImportNotebookDialog(QWidget *p_parent = nullptr); +class ImportNotebookDialog : public ScrollDialog { + Q_OBJECT +public: + explicit ImportNotebookDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private slots: - void validateInputs(); +private slots: + void validateInputs(); - private: - void setupUI(); +private: + void setupUI(); - void setupNotebookInfoWidget(QWidget *p_parent = nullptr); + void setupNotebookInfoWidget(QWidget *p_parent = nullptr); - bool validateRootFolderInput(QString &p_msg); + bool validateRootFolderInput(QString &p_msg); - bool createNotebookToImport(QString &p_msg); + bool createNotebookToImport(QString &p_msg); - bool importNotebook(); + bool importNotebook(); - NotebookInfoWidget *m_infoWidget = nullptr; + NotebookInfoWidget *m_infoWidget = nullptr; - QSharedPointer m_notebookToImport; - }; -} // ns vnotex + QSharedPointer m_notebookToImport; +}; +} // namespace vnotex #endif // IMPORTNOTEBOOKDIALOG_H diff --git a/src/widgets/dialogs/legacynotebookutils.cpp b/src/widgets/dialogs/legacynotebookutils.cpp index 1dbc643405..9677f4e8bc 100644 --- a/src/widgets/dialogs/legacynotebookutils.cpp +++ b/src/widgets/dialogs/legacynotebookutils.cpp @@ -1,98 +1,90 @@ #include "legacynotebookutils.h" -#include #include +#include -#include #include +#include #include using namespace vnotex; const QString LegacyNotebookUtils::c_legacyFolderConfigFile = "_vnote.json"; -static QDateTime stringToDateTime(const QString &p_str) -{ - if (p_str.isEmpty()) { - return QDateTime::currentDateTimeUtc(); - } - return Utils::dateTimeFromStringUniform(p_str); +static QDateTime stringToDateTime(const QString &p_str) { + if (p_str.isEmpty()) { + return QDateTime::currentDateTimeUtc(); + } + return Utils::dateTimeFromStringUniform(p_str); } -bool LegacyNotebookUtils::isLegacyNotebookRootFolder(const QString &p_folderPath) -{ - return QFileInfo::exists(getFolderConfigFile(p_folderPath)); +bool LegacyNotebookUtils::isLegacyNotebookRootFolder(const QString &p_folderPath) { + return QFileInfo::exists(getFolderConfigFile(p_folderPath)); } -QDateTime LegacyNotebookUtils::getCreatedTimeUtcOfFolder(const QString &p_folderPath) -{ - auto ti = getFolderConfig(p_folderPath).value(QStringLiteral("created_time")).toString(); - return stringToDateTime(ti); +QDateTime LegacyNotebookUtils::getCreatedTimeUtcOfFolder(const QString &p_folderPath) { + auto ti = getFolderConfig(p_folderPath).value(QStringLiteral("created_time")).toString(); + return stringToDateTime(ti); } -QString LegacyNotebookUtils::getAttachmentFolderOfNotebook(const QString &p_folderPath) -{ - return getFolderConfig(p_folderPath).value(QStringLiteral("attachment_folder")).toString(); +QString LegacyNotebookUtils::getAttachmentFolderOfNotebook(const QString &p_folderPath) { + return getFolderConfig(p_folderPath).value(QStringLiteral("attachment_folder")).toString(); } -QString LegacyNotebookUtils::getImageFolderOfNotebook(const QString &p_folderPath) -{ - return getFolderConfig(p_folderPath).value(QStringLiteral("image_folder")).toString(); +QString LegacyNotebookUtils::getImageFolderOfNotebook(const QString &p_folderPath) { + return getFolderConfig(p_folderPath).value(QStringLiteral("image_folder")).toString(); } -QString LegacyNotebookUtils::getRecycleBinFolderOfNotebook(const QString &p_folderPath) -{ - return getFolderConfig(p_folderPath).value(QStringLiteral("recycle_bin_folder")).toString(); +QString LegacyNotebookUtils::getRecycleBinFolderOfNotebook(const QString &p_folderPath) { + return getFolderConfig(p_folderPath).value(QStringLiteral("recycle_bin_folder")).toString(); } -QString LegacyNotebookUtils::getFolderConfigFile(const QString &p_folderPath) -{ - return PathUtils::concatenateFilePath(p_folderPath, c_legacyFolderConfigFile); +QString LegacyNotebookUtils::getFolderConfigFile(const QString &p_folderPath) { + return PathUtils::concatenateFilePath(p_folderPath, c_legacyFolderConfigFile); } -QJsonObject LegacyNotebookUtils::getFolderConfig(const QString &p_folderPath) -{ - auto configFile = getFolderConfigFile(p_folderPath); - return QJsonDocument::fromJson(FileUtils::readFile(configFile)).object(); +QJsonObject LegacyNotebookUtils::getFolderConfig(const QString &p_folderPath) { + auto configFile = getFolderConfigFile(p_folderPath); + return QJsonDocument::fromJson(FileUtils::readFile(configFile)).object(); } -void LegacyNotebookUtils::removeFolderConfigFile(const QString &p_folderPath) -{ - auto configFile = getFolderConfigFile(p_folderPath); - FileUtils::removeFile(configFile); +void LegacyNotebookUtils::removeFolderConfigFile(const QString &p_folderPath) { + auto configFile = getFolderConfigFile(p_folderPath); + FileUtils::removeFile(configFile); } -void LegacyNotebookUtils::forEachFolder(const QJsonObject &p_config, std::function p_func) -{ - auto folderArray = p_config.value(QStringLiteral("sub_directories")).toArray(); - for (int i = 0; i < folderArray.size(); ++i) { - const auto name = folderArray[i].toObject().value(QStringLiteral("name")).toString(); - p_func(name); - } +void LegacyNotebookUtils::forEachFolder(const QJsonObject &p_config, + std::function p_func) { + auto folderArray = p_config.value(QStringLiteral("sub_directories")).toArray(); + for (int i = 0; i < folderArray.size(); ++i) { + const auto name = folderArray[i].toObject().value(QStringLiteral("name")).toString(); + p_func(name); + } } -void LegacyNotebookUtils::forEachFile(const QJsonObject &p_config, std::function p_func) -{ - auto fileArray = p_config.value(QStringLiteral("files")).toArray(); - for (int i = 0; i < fileArray.size(); ++i) { - const auto obj = fileArray[i].toObject(); - FileInfo info; - info.m_name = obj.value(QStringLiteral("name")).toString(); - { - auto ti = obj.value(QStringLiteral("created_time")).toString(); - info.m_createdTimeUtc = stringToDateTime(ti); - } - { - auto ti = obj.value(QStringLiteral("created_time")).toString(); - info.m_modifiedTimeUtc = stringToDateTime(ti); - } - info.m_attachmentFolder = obj.value(QStringLiteral("attachment_folder")).toString(); - { - auto arr = obj.value(QStringLiteral("tags")).toArray(); - for (int i = 0; i < arr.size(); ++i) { - info.m_tags << arr[i].toString(); - } - } - p_func(info); +void LegacyNotebookUtils::forEachFile( + const QJsonObject &p_config, + std::function p_func) { + auto fileArray = p_config.value(QStringLiteral("files")).toArray(); + for (int i = 0; i < fileArray.size(); ++i) { + const auto obj = fileArray[i].toObject(); + FileInfo info; + info.m_name = obj.value(QStringLiteral("name")).toString(); + { + auto ti = obj.value(QStringLiteral("created_time")).toString(); + info.m_createdTimeUtc = stringToDateTime(ti); + } + { + auto ti = obj.value(QStringLiteral("created_time")).toString(); + info.m_modifiedTimeUtc = stringToDateTime(ti); + } + info.m_attachmentFolder = obj.value(QStringLiteral("attachment_folder")).toString(); + { + auto arr = obj.value(QStringLiteral("tags")).toArray(); + for (int i = 0; i < arr.size(); ++i) { + info.m_tags << arr[i].toString(); + } } + p_func(info); + } } diff --git a/src/widgets/dialogs/legacynotebookutils.h b/src/widgets/dialogs/legacynotebookutils.h index 501b07c5d9..bbeb9ea827 100644 --- a/src/widgets/dialogs/legacynotebookutils.h +++ b/src/widgets/dialogs/legacynotebookutils.h @@ -1,55 +1,54 @@ #ifndef LEGACYNOTEBOOKUTILS_H #define LEGACYNOTEBOOKUTILS_H -#include #include #include +#include #include -namespace vnotex -{ - class LegacyNotebookUtils - { - public: - struct FileInfo - { - QString m_name; +namespace vnotex { +class LegacyNotebookUtils { +public: + struct FileInfo { + QString m_name; - QDateTime m_createdTimeUtc = QDateTime::currentDateTimeUtc(); + QDateTime m_createdTimeUtc = QDateTime::currentDateTimeUtc(); - QDateTime m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); + QDateTime m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); - QString m_attachmentFolder; + QString m_attachmentFolder; - QStringList m_tags; - }; + QStringList m_tags; + }; - LegacyNotebookUtils() = delete; + LegacyNotebookUtils() = delete; - static bool isLegacyNotebookRootFolder(const QString &p_folderPath); + static bool isLegacyNotebookRootFolder(const QString &p_folderPath); - static QDateTime getCreatedTimeUtcOfFolder(const QString &p_folderPath); + static QDateTime getCreatedTimeUtcOfFolder(const QString &p_folderPath); - static QString getAttachmentFolderOfNotebook(const QString &p_folderPath); + static QString getAttachmentFolderOfNotebook(const QString &p_folderPath); - static QString getImageFolderOfNotebook(const QString &p_folderPath); + static QString getImageFolderOfNotebook(const QString &p_folderPath); - static QString getRecycleBinFolderOfNotebook(const QString &p_folderPath); + static QString getRecycleBinFolderOfNotebook(const QString &p_folderPath); - static QJsonObject getFolderConfig(const QString &p_folderPath); + static QJsonObject getFolderConfig(const QString &p_folderPath); - static void removeFolderConfigFile(const QString &p_folderPath); + static void removeFolderConfigFile(const QString &p_folderPath); - static void forEachFolder(const QJsonObject &p_config, std::function p_func); + static void forEachFolder(const QJsonObject &p_config, + std::function p_func); - static void forEachFile(const QJsonObject &p_config, std::function p_func); + static void forEachFile(const QJsonObject &p_config, + std::function p_func); - private: - static QString getFolderConfigFile(const QString &p_folderPath); +private: + static QString getFolderConfigFile(const QString &p_folderPath); - static const QString c_legacyFolderConfigFile; - }; -} + static const QString c_legacyFolderConfigFile; +}; +} // namespace vnotex #endif // LEGACYNOTEBOOKUTILS_H diff --git a/src/widgets/dialogs/levellabelwithupbutton.cpp b/src/widgets/dialogs/levellabelwithupbutton.cpp index 3c7df606a6..5dd506ae0a 100644 --- a/src/widgets/dialogs/levellabelwithupbutton.cpp +++ b/src/widgets/dialogs/levellabelwithupbutton.cpp @@ -1,80 +1,68 @@ #include "levellabelwithupbutton.h" -#include -#include #include +#include +#include -#include #include +#include using namespace vnotex; -LevelLabelWithUpButton::LevelLabelWithUpButton(QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(); -} +LevelLabelWithUpButton::LevelLabelWithUpButton(QWidget *p_parent) : QWidget(p_parent) { setupUI(); } -void LevelLabelWithUpButton::setupUI() -{ - auto mainLayout = new QHBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); +void LevelLabelWithUpButton::setupUI() { + auto mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); - m_label = new QLabel(this); - mainLayout->addWidget(m_label, 1); + m_label = new QLabel(this); + mainLayout->addWidget(m_label, 1); - const auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile("up_level.svg"); - m_upButton = new QPushButton(IconUtils::fetchIconWithDisabledState(iconFile), - tr("Up"), - this); - m_upButton->setToolTip(tr("Go one level up")); - connect(m_upButton, &QPushButton::clicked, - this, [this]() { - if (m_levelIdx < m_levels.size() - 1) { - ++m_levelIdx; - updateLabelAndButton(); - emit levelChanged(); - } - }); - mainLayout->addWidget(m_upButton, 0); + const auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile("up_level.svg"); + m_upButton = new QPushButton(IconUtils::fetchIconWithDisabledState(iconFile), tr("Up"), this); + m_upButton->setToolTip(tr("Go one level up")); + connect(m_upButton, &QPushButton::clicked, this, [this]() { + if (m_levelIdx < m_levels.size() - 1) { + ++m_levelIdx; + updateLabelAndButton(); + emit levelChanged(); + } + }); + mainLayout->addWidget(m_upButton, 0); - updateLabelAndButton(); + updateLabelAndButton(); } -void LevelLabelWithUpButton::updateLabelAndButton() -{ - if (m_levels.isEmpty()) { - m_label->clear(); - } else { - Q_ASSERT(m_levelIdx < m_levels.size()); - m_label->setText(m_levels[m_levelIdx].m_name); - } +void LevelLabelWithUpButton::updateLabelAndButton() { + if (m_levels.isEmpty()) { + m_label->clear(); + } else { + Q_ASSERT(m_levelIdx < m_levels.size()); + m_label->setText(m_levels[m_levelIdx].m_name); + } - m_upButton->setVisible(!m_readOnly && (m_levelIdx < m_levels.size() - 1)); + m_upButton->setVisible(!m_readOnly && (m_levelIdx < m_levels.size() - 1)); } -const LevelLabelWithUpButton::Level &LevelLabelWithUpButton::getLevel() const -{ - Q_ASSERT(m_levelIdx < m_levels.size()); - return m_levels[m_levelIdx]; +const LevelLabelWithUpButton::Level &LevelLabelWithUpButton::getLevel() const { + Q_ASSERT(m_levelIdx < m_levels.size()); + return m_levels[m_levelIdx]; } -void LevelLabelWithUpButton::setLevels(const QVector &p_levels) -{ - m_levels = p_levels; - Q_ASSERT(!m_levels.isEmpty()); - m_levelIdx = 0; +void LevelLabelWithUpButton::setLevels(const QVector &p_levels) { + m_levels = p_levels; + Q_ASSERT(!m_levels.isEmpty()); + m_levelIdx = 0; - updateLabelAndButton(); - emit levelChanged(); + updateLabelAndButton(); + emit levelChanged(); } -void LevelLabelWithUpButton::setReadOnly(bool p_readonly) -{ - if (m_readOnly == p_readonly) { - return; - } +void LevelLabelWithUpButton::setReadOnly(bool p_readonly) { + if (m_readOnly == p_readonly) { + return; + } - m_readOnly = p_readonly; - updateLabelAndButton(); + m_readOnly = p_readonly; + updateLabelAndButton(); } diff --git a/src/widgets/dialogs/levellabelwithupbutton.h b/src/widgets/dialogs/levellabelwithupbutton.h index eac59e6c01..a575f56b4d 100644 --- a/src/widgets/dialogs/levellabelwithupbutton.h +++ b/src/widgets/dialogs/levellabelwithupbutton.h @@ -6,47 +6,44 @@ class QLabel; class QPushButton; -namespace vnotex -{ - // Used to navigate through a series of levels. - class LevelLabelWithUpButton : public QWidget - { - Q_OBJECT - public: - struct Level - { - QString m_name; +namespace vnotex { +// Used to navigate through a series of levels. +class LevelLabelWithUpButton : public QWidget { + Q_OBJECT +public: + struct Level { + QString m_name; - const void *m_data = nullptr; - }; + const void *m_data = nullptr; + }; - LevelLabelWithUpButton(QWidget *p_parent = nullptr); + LevelLabelWithUpButton(QWidget *p_parent = nullptr); - const Level &getLevel() const; + const Level &getLevel() const; - // From bottom to up. - void setLevels(const QVector &p_levels); + // From bottom to up. + void setLevels(const QVector &p_levels); - void setReadOnly(bool p_readonly); + void setReadOnly(bool p_readonly); - signals: - void levelChanged(); +signals: + void levelChanged(); - private: - void setupUI(); +private: + void setupUI(); - void updateLabelAndButton(); + void updateLabelAndButton(); - QLabel *m_label = nullptr; + QLabel *m_label = nullptr; - QPushButton *m_upButton = nullptr; + QPushButton *m_upButton = nullptr; - QVector m_levels; + QVector m_levels; - int m_levelIdx = -1; + int m_levelIdx = -1; - bool m_readOnly = false; - }; -} // ns vnotex + bool m_readOnly = false; +}; +} // namespace vnotex #endif // LEVELLABELWITHUPBUTTON_H diff --git a/src/widgets/dialogs/linkinsertdialog.cpp b/src/widgets/dialogs/linkinsertdialog.cpp index d03f417966..e10cad0bb1 100644 --- a/src/widgets/dialogs/linkinsertdialog.cpp +++ b/src/widgets/dialogs/linkinsertdialog.cpp @@ -1,112 +1,94 @@ #include "linkinsertdialog.h" #include -#include #include +#include -#include -#include #include +#include +#include using namespace vnotex; -LinkInsertDialog::LinkInsertDialog(const QString &p_title, - const QString &p_linkText, - const QString &p_linkUrl, - bool p_linkTextOptional, +LinkInsertDialog::LinkInsertDialog(const QString &p_title, const QString &p_linkText, + const QString &p_linkUrl, bool p_linkTextOptional, QWidget *p_parent) - : ScrollDialog(p_parent), - m_linkTextOptional(p_linkTextOptional) -{ - setupUI(p_title, p_linkText, p_linkUrl); + : ScrollDialog(p_parent), m_linkTextOptional(p_linkTextOptional) { + setupUI(p_title, p_linkText, p_linkUrl); - checkInput(); + checkInput(); } -void LinkInsertDialog::setupUI(const QString &p_title, - const QString &p_linkText, - const QString &p_linkUrl) -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); +void LinkInsertDialog::setupUI(const QString &p_title, const QString &p_linkText, + const QString &p_linkUrl) { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); - auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); + auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); - m_linkTextEdit = WidgetsFactory::createLineEdit(p_linkText, mainWidget); - mainLayout->addRow(tr("&Text:"), m_linkTextEdit); - connect(m_linkTextEdit, &QLineEdit::textChanged, - this, [this]() { - checkInput(false); - }); + m_linkTextEdit = WidgetsFactory::createLineEdit(p_linkText, mainWidget); + mainLayout->addRow(tr("&Text:"), m_linkTextEdit); + connect(m_linkTextEdit, &QLineEdit::textChanged, this, [this]() { checkInput(false); }); - m_linkUrlEdit = WidgetsFactory::createLineEdit(p_linkUrl, mainWidget); - mainLayout->addRow(tr("&Url:"), m_linkUrlEdit); - connect(m_linkUrlEdit, &QLineEdit::textChanged, - this, [this]() { - checkInput(true); - }); + m_linkUrlEdit = WidgetsFactory::createLineEdit(p_linkUrl, mainWidget); + mainLayout->addRow(tr("&Url:"), m_linkUrlEdit); + connect(m_linkUrlEdit, &QLineEdit::textChanged, this, [this]() { checkInput(true); }); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(p_title); + setWindowTitle(p_title); } -void LinkInsertDialog::checkInput(bool p_autoCompleteText) -{ - bool ok = true; - - const auto linkUrl = m_linkUrlEdit->text(); - if (linkUrl.isEmpty()) { - ok = false; - } else { - const auto linkText = m_linkTextEdit->text(); - if (linkText.isEmpty()) { - // Try to guess the text from url. - if (p_autoCompleteText) { - int idx = linkUrl.lastIndexOf(QRegularExpression(QStringLiteral("[/\\\\]"))); - if (idx != -1 && idx != linkUrl.size() - 1) { - m_linkTextEdit->setText(linkUrl.mid(idx + 1)); - } else { - ok = m_linkTextOptional; - } - } else { - ok = m_linkTextOptional; - } +void LinkInsertDialog::checkInput(bool p_autoCompleteText) { + bool ok = true; + + const auto linkUrl = m_linkUrlEdit->text(); + if (linkUrl.isEmpty()) { + ok = false; + } else { + const auto linkText = m_linkTextEdit->text(); + if (linkText.isEmpty()) { + // Try to guess the text from url. + if (p_autoCompleteText) { + int idx = linkUrl.lastIndexOf(QRegularExpression(QStringLiteral("[/\\\\]"))); + if (idx != -1 && idx != linkUrl.size() - 1) { + m_linkTextEdit->setText(linkUrl.mid(idx + 1)); + } else { + ok = m_linkTextOptional; } + } else { + ok = m_linkTextOptional; + } } + } - setButtonEnabled(QDialogButtonBox::Ok, ok); + setButtonEnabled(QDialogButtonBox::Ok, ok); } -QString LinkInsertDialog::getLinkText() const -{ - return m_linkTextEdit->text(); -} - -QString LinkInsertDialog::getLinkUrl() const -{ - // For local file, translate to URL without spaces. - auto text = m_linkUrlEdit->text(); - if (text.isEmpty()) { - return text; - } +QString LinkInsertDialog::getLinkText() const { return m_linkTextEdit->text(); } - auto url = QUrl::fromUserInput(text); - if (url.isLocalFile()) { - return url.toString(QUrl::EncodeSpaces); - } +QString LinkInsertDialog::getLinkUrl() const { + // For local file, translate to URL without spaces. + auto text = m_linkUrlEdit->text(); + if (text.isEmpty()) { return text; + } + + auto url = QUrl::fromUserInput(text); + if (url.isLocalFile()) { + return url.toString(QUrl::EncodeSpaces); + } + return text; } -void LinkInsertDialog::showEvent(QShowEvent *p_event) -{ - ScrollDialog::showEvent(p_event); +void LinkInsertDialog::showEvent(QShowEvent *p_event) { + ScrollDialog::showEvent(p_event); - if (!m_linkUrlEdit->text().isEmpty() || m_linkTextEdit->text().isEmpty()) { - m_linkTextEdit->setFocus(); - m_linkTextEdit->selectAll(); - } else { - m_linkUrlEdit->setFocus(); - m_linkUrlEdit->selectAll(); - } + if (!m_linkUrlEdit->text().isEmpty() || m_linkTextEdit->text().isEmpty()) { + m_linkTextEdit->setFocus(); + m_linkTextEdit->selectAll(); + } else { + m_linkUrlEdit->setFocus(); + m_linkUrlEdit->selectAll(); + } } diff --git a/src/widgets/dialogs/linkinsertdialog.h b/src/widgets/dialogs/linkinsertdialog.h index 6bb54ac1b2..68ba0b070a 100644 --- a/src/widgets/dialogs/linkinsertdialog.h +++ b/src/widgets/dialogs/linkinsertdialog.h @@ -5,39 +5,32 @@ class QLineEdit; -namespace vnotex -{ - class LinkInsertDialog : public ScrollDialog - { - Q_OBJECT - public: - LinkInsertDialog(const QString &p_title, - const QString &p_linkText, - const QString &p_linkUrl, - bool p_linkTextOptional, - QWidget *p_parent = nullptr); +namespace vnotex { +class LinkInsertDialog : public ScrollDialog { + Q_OBJECT +public: + LinkInsertDialog(const QString &p_title, const QString &p_linkText, const QString &p_linkUrl, + bool p_linkTextOptional, QWidget *p_parent = nullptr); - QString getLinkText() const; + QString getLinkText() const; - QString getLinkUrl() const; + QString getLinkUrl() const; - protected: - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; +protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void checkInput(bool p_autoCompleteText = true); +private slots: + void checkInput(bool p_autoCompleteText = true); - private: - void setupUI(const QString &p_title, - const QString &p_linkText, - const QString &p_linkUrl); +private: + void setupUI(const QString &p_title, const QString &p_linkText, const QString &p_linkUrl); - bool m_linkTextOptional = false; + bool m_linkTextOptional = false; - QLineEdit *m_linkTextEdit = nullptr; + QLineEdit *m_linkTextEdit = nullptr; - QLineEdit *m_linkUrlEdit = nullptr; - }; -} + QLineEdit *m_linkUrlEdit = nullptr; +}; +} // namespace vnotex #endif // LINKINSERTDIALOG_H diff --git a/src/widgets/dialogs/managenotebooksdialog.cpp b/src/widgets/dialogs/managenotebooksdialog.cpp index 6731cf3cf2..1a211e4049 100644 --- a/src/widgets/dialogs/managenotebooksdialog.cpp +++ b/src/widgets/dialogs/managenotebooksdialog.cpp @@ -1,315 +1,287 @@ #include "managenotebooksdialog.h" #include -#include -#include #include #include -#include #include +#include +#include #include +#include +#include "../listwidget.h" +#include "../messageboxhelper.h" +#include "../propertydefs.h" +#include "../widgetsfactory.h" +#include "exception.h" #include "notebook/notebook.h" #include "notebookinfowidget.h" -#include "vnotex.h" #include "notebookmgr.h" -#include "../messageboxhelper.h" +#include "vnotex.h" +#include #include #include #include -#include "../widgetsfactory.h" -#include "exception.h" -#include "../propertydefs.h" -#include "../listwidget.h" -#include using namespace vnotex; ManageNotebooksDialog::ManageNotebooksDialog(const Notebook *p_notebook, QWidget *p_parent) - : Dialog(p_parent) -{ - setupUI(); + : Dialog(p_parent) { + setupUI(); - loadNotebooks(p_notebook); + loadNotebooks(p_notebook); } -void ManageNotebooksDialog::setupUI() -{ - auto widget = new QWidget(this); - setCentralWidget(widget); - - auto mainLayout = new QHBoxLayout(widget); - - setupNotebookList(widget); - mainLayout->addWidget(m_notebookList); - mainLayout->setStretchFactor(m_notebookList, 1); - - { - m_infoScrollArea = new QScrollArea(widget); - m_infoScrollArea->setWidgetResizable(true); - mainLayout->addWidget(m_infoScrollArea); - mainLayout->setStretchFactor(m_infoScrollArea, 3); - - auto infoWidget = new QWidget(widget); - m_infoScrollArea->setWidget(infoWidget); - - auto infoLayout = new QVBoxLayout(infoWidget); - - setupNotebookInfoWidget(infoWidget); - infoLayout->addWidget(m_notebookInfoWidget); - - auto btnLayout = new QHBoxLayout(); - infoLayout->addLayout(btnLayout); - - m_closeNotebookBtn = new QPushButton(tr("Close Noteboook"), infoWidget); - btnLayout->addStretch(); - btnLayout->addWidget(m_closeNotebookBtn); - connect(m_closeNotebookBtn, &QPushButton::clicked, - this, [this]() { - if (checkUnsavedChanges()) { - return; - } - closeNotebook(m_notebookInfoWidget->getNotebook()); - }); - - m_deleteNotebookBtn = new QPushButton(tr("Delete"), infoWidget); - WidgetUtils::setPropertyDynamically(m_deleteNotebookBtn, PropertyDefs::c_dangerButton, true); - btnLayout->addWidget(m_deleteNotebookBtn); - connect(m_deleteNotebookBtn, &QPushButton::clicked, - this, [this]() { - if (checkUnsavedChanges()) { - return; - } - removeNotebook(m_notebookInfoWidget->getNotebook()); - }); - } +void ManageNotebooksDialog::setupUI() { + auto widget = new QWidget(this); + setCentralWidget(widget); + + auto mainLayout = new QHBoxLayout(widget); + + setupNotebookList(widget); + mainLayout->addWidget(m_notebookList); + mainLayout->setStretchFactor(m_notebookList, 1); + + { + m_infoScrollArea = new QScrollArea(widget); + m_infoScrollArea->setWidgetResizable(true); + mainLayout->addWidget(m_infoScrollArea); + mainLayout->setStretchFactor(m_infoScrollArea, 3); - setDialogButtonBox(QDialogButtonBox::Ok - | QDialogButtonBox::Apply - | QDialogButtonBox::Reset - | QDialogButtonBox::Cancel); + auto infoWidget = new QWidget(widget); + m_infoScrollArea->setWidget(infoWidget); - setWindowTitle(tr("Manage Notebooks")); + auto infoLayout = new QVBoxLayout(infoWidget); + + setupNotebookInfoWidget(infoWidget); + infoLayout->addWidget(m_notebookInfoWidget); + + auto btnLayout = new QHBoxLayout(); + infoLayout->addLayout(btnLayout); + + m_closeNotebookBtn = new QPushButton(tr("Close Noteboook"), infoWidget); + btnLayout->addStretch(); + btnLayout->addWidget(m_closeNotebookBtn); + connect(m_closeNotebookBtn, &QPushButton::clicked, this, [this]() { + if (checkUnsavedChanges()) { + return; + } + closeNotebook(m_notebookInfoWidget->getNotebook()); + }); + + m_deleteNotebookBtn = new QPushButton(tr("Delete"), infoWidget); + WidgetUtils::setPropertyDynamically(m_deleteNotebookBtn, PropertyDefs::c_dangerButton, true); + btnLayout->addWidget(m_deleteNotebookBtn); + connect(m_deleteNotebookBtn, &QPushButton::clicked, this, [this]() { + if (checkUnsavedChanges()) { + return; + } + removeNotebook(m_notebookInfoWidget->getNotebook()); + }); + } + + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Reset | + QDialogButtonBox::Cancel); + + setWindowTitle(tr("Manage Notebooks")); } -Notebook *ManageNotebooksDialog::getNotebookFromItem(const QListWidgetItem *p_item) const -{ - Notebook *notebook = nullptr; - if (p_item) { - auto id = static_cast(p_item->data(Qt::UserRole).toULongLong()); - notebook = VNoteX::getInst().getNotebookMgr().findNotebookById(id).data(); - } +Notebook *ManageNotebooksDialog::getNotebookFromItem(const QListWidgetItem *p_item) const { + Notebook *notebook = nullptr; + if (p_item) { + auto id = static_cast(p_item->data(Qt::UserRole).toULongLong()); + notebook = VNoteX::getInst().getNotebookMgr().findNotebookById(id).data(); + } - return notebook; + return notebook; } -void ManageNotebooksDialog::setupNotebookList(QWidget *p_parent) -{ - m_notebookList = new ListWidget(p_parent); - connect(m_notebookList, &QListWidget::currentItemChanged, - this, [this](QListWidgetItem *p_item, QListWidgetItem *p_previous) { - auto notebook = getNotebookFromItem(p_item); - if (m_changesUnsaved) { - // Have unsaved changes. - if (m_notebook != notebook) { - checkUnsavedChanges(); - - QTimer::singleShot(50, this, [this, p_previous]() { - m_notebookList->setCurrentItem(p_previous); - }); - } - - return; - } - - m_notebook = notebook; - selectNotebook(m_notebook); - }); +void ManageNotebooksDialog::setupNotebookList(QWidget *p_parent) { + m_notebookList = new ListWidget(p_parent); + connect(m_notebookList, &QListWidget::currentItemChanged, this, + [this](QListWidgetItem *p_item, QListWidgetItem *p_previous) { + auto notebook = getNotebookFromItem(p_item); + if (m_changesUnsaved) { + // Have unsaved changes. + if (m_notebook != notebook) { + checkUnsavedChanges(); + + QTimer::singleShot( + 50, this, [this, p_previous]() { m_notebookList->setCurrentItem(p_previous); }); + } + + return; + } + + m_notebook = notebook; + selectNotebook(m_notebook); + }); } -void ManageNotebooksDialog::setupNotebookInfoWidget(QWidget *p_parent) -{ - m_notebookInfoWidget = new NotebookInfoWidget(NotebookInfoWidget::Edit, p_parent); - connect(m_notebookInfoWidget, &NotebookInfoWidget::basicInfoEdited, - this, [this]() { - bool unsaved = false; - if (m_notebook) { - if (m_notebook->getName() != m_notebookInfoWidget->getName() - || m_notebook->getDescription() != m_notebookInfoWidget->getDescription()) { - unsaved = true; - } - } - - setChangesUnsaved(unsaved); - }); +void ManageNotebooksDialog::setupNotebookInfoWidget(QWidget *p_parent) { + m_notebookInfoWidget = new NotebookInfoWidget(NotebookInfoWidget::Edit, p_parent); + connect(m_notebookInfoWidget, &NotebookInfoWidget::basicInfoEdited, this, [this]() { + bool unsaved = false; + if (m_notebook) { + if (m_notebook->getName() != m_notebookInfoWidget->getName() || + m_notebook->getDescription() != m_notebookInfoWidget->getDescription()) { + unsaved = true; + } + } + + setChangesUnsaved(unsaved); + }); } -void ManageNotebooksDialog::loadNotebooks(const Notebook *p_notebook) -{ - setChangesUnsaved(false); - - m_notebookList->clear(); - - bool hasCurrentItem = false; - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - const auto ¬ebooks = notebookMgr.getNotebooks(); - for (auto &nb : notebooks) { - auto item = new QListWidgetItem(nb->getName()); - item->setData(Qt::UserRole, nb->getId()); - item->setToolTip(nb->getName()); - m_notebookList->addItem(item); - - if (nb.data() == p_notebook) { - hasCurrentItem = true; - m_notebookList->setCurrentItem(item, QItemSelectionModel::ClearAndSelect); - } +void ManageNotebooksDialog::loadNotebooks(const Notebook *p_notebook) { + setChangesUnsaved(false); + + m_notebookList->clear(); + + bool hasCurrentItem = false; + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + const auto ¬ebooks = notebookMgr.getNotebooks(); + for (auto &nb : notebooks) { + auto item = new QListWidgetItem(nb->getName()); + item->setData(Qt::UserRole, nb->getId()); + item->setToolTip(nb->getName()); + m_notebookList->addItem(item); + + if (nb.data() == p_notebook) { + hasCurrentItem = true; + m_notebookList->setCurrentItem(item, QItemSelectionModel::ClearAndSelect); } + } - if (!hasCurrentItem) { - if (notebooks.isEmpty()) { - selectNotebook(nullptr); - } else { - m_notebookList->setCurrentRow(0); - } + if (!hasCurrentItem) { + if (notebooks.isEmpty()) { + selectNotebook(nullptr); + } else { + m_notebookList->setCurrentRow(0); } + } } -void ManageNotebooksDialog::selectNotebook(Notebook *p_notebook) -{ - m_notebookInfoWidget->setNotebook(p_notebook); - setChangesUnsaved(false); +void ManageNotebooksDialog::selectNotebook(Notebook *p_notebook) { + m_notebookInfoWidget->setNotebook(p_notebook); + setChangesUnsaved(false); - // Update buttons. - m_closeNotebookBtn->setEnabled(p_notebook); - m_deleteNotebookBtn->setEnabled(p_notebook); + // Update buttons. + m_closeNotebookBtn->setEnabled(p_notebook); + m_deleteNotebookBtn->setEnabled(p_notebook); - WidgetUtils::resizeToHideScrollBarLater(m_infoScrollArea, false, true); + WidgetUtils::resizeToHideScrollBarLater(m_infoScrollArea, false, true); } -void ManageNotebooksDialog::acceptedButtonClicked() -{ - if (saveChangesToNotebook()) { - accept(); - } +void ManageNotebooksDialog::acceptedButtonClicked() { + if (saveChangesToNotebook()) { + accept(); + } } -void ManageNotebooksDialog::resetButtonClicked() -{ - m_notebookInfoWidget->clear(); - selectNotebook(m_notebook); +void ManageNotebooksDialog::resetButtonClicked() { + m_notebookInfoWidget->clear(); + selectNotebook(m_notebook); } -void ManageNotebooksDialog::appliedButtonClicked() -{ - Q_ASSERT(m_changesUnsaved); - if (saveChangesToNotebook()) { - loadNotebooks(m_notebook); - } +void ManageNotebooksDialog::appliedButtonClicked() { + Q_ASSERT(m_changesUnsaved); + if (saveChangesToNotebook()) { + loadNotebooks(m_notebook); + } } -void ManageNotebooksDialog::setChangesUnsaved(bool p_unsaved) -{ - m_changesUnsaved = p_unsaved; - setButtonEnabled(QDialogButtonBox::Apply, m_changesUnsaved); - setButtonEnabled(QDialogButtonBox::Reset, m_changesUnsaved); +void ManageNotebooksDialog::setChangesUnsaved(bool p_unsaved) { + m_changesUnsaved = p_unsaved; + setButtonEnabled(QDialogButtonBox::Apply, m_changesUnsaved); + setButtonEnabled(QDialogButtonBox::Reset, m_changesUnsaved); } -bool ManageNotebooksDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool ManageNotebooksDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); + valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? Dialog::InformationLevel::Info - : Dialog::InformationLevel::Error); - return valid; + setInformationText(msg, valid ? Dialog::InformationLevel::Info : Dialog::InformationLevel::Error); + return valid; } -bool ManageNotebooksDialog::validateNameInput(QString &p_msg) -{ - if (m_notebookInfoWidget->getName().isEmpty()) { - Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); - return false; - } +bool ManageNotebooksDialog::validateNameInput(QString &p_msg) { + if (m_notebookInfoWidget->getName().isEmpty()) { + Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); + return false; + } - return true; + return true; } -bool ManageNotebooksDialog::saveChangesToNotebook() -{ - if (!m_changesUnsaved || !m_notebook) { - return true; - } +bool ManageNotebooksDialog::saveChangesToNotebook() { + if (!m_changesUnsaved || !m_notebook) { + return true; + } - if (!validateInputs()) { - return false; - } + if (!validateInputs()) { + return false; + } - m_notebook->updateName(m_notebookInfoWidget->getName()); - m_notebook->updateDescription(m_notebookInfoWidget->getDescription()); - return true; + m_notebook->updateName(m_notebookInfoWidget->getName()); + m_notebook->updateDescription(m_notebookInfoWidget->getDescription()); + return true; } -bool ManageNotebooksDialog::closeNotebook(const Notebook *p_notebook) -{ - if (!p_notebook) { - return false; - } +bool ManageNotebooksDialog::closeNotebook(const Notebook *p_notebook) { + if (!p_notebook) { + return false; + } - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Question, - tr("Close notebook (%1)?") - .arg(p_notebook->getName()), - tr("The notebook could be opened by VNote again via \"Open Other Notebooks\" operation."), - tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), - this); - if (ret != QMessageBox::Ok) { - return false; - } + int ret = MessageBoxHelper::questionOkCancel( + MessageBoxHelper::Question, tr("Close notebook (%1)?").arg(p_notebook->getName()), + tr("The notebook could be opened by VNote again via \"Open Other Notebooks\" operation."), + tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), this); + if (ret != QMessageBox::Ok) { + return false; + } - try - { - VNoteX::getInst().getNotebookMgr().closeNotebook(p_notebook->getId()); - } catch (Exception &p_e) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to close notebook (%1)").arg(p_e.what()), - this); - } + try { + VNoteX::getInst().getNotebookMgr().closeNotebook(p_notebook->getId()); + } catch (Exception &p_e) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("Failed to close notebook (%1)").arg(p_e.what()), this); + } - loadNotebooks(nullptr); - return true; + loadNotebooks(nullptr); + return true; } -void ManageNotebooksDialog::removeNotebook(const Notebook *p_notebook) -{ - if (!p_notebook) { - return; - } - - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, - tr("Please close the notebook in VNote first and delete the notebook root folder files manually."), - tr("Press \"Ok\" to close the notebook and open the location of the notebook root folder."), - tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), - this); - if (ret != QMessageBox::Ok) { - return; - } - - const auto rootFolder = p_notebook->getRootFolderAbsolutePath(); - - if (closeNotebook(p_notebook)) { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(rootFolder)); - } +void ManageNotebooksDialog::removeNotebook(const Notebook *p_notebook) { + if (!p_notebook) { + return; + } + + int ret = MessageBoxHelper::questionOkCancel( + MessageBoxHelper::Warning, + tr("Please close the notebook in VNote first and delete the notebook root folder files " + "manually."), + tr("Press \"Ok\" to close the notebook and open the location of the notebook root folder."), + tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), this); + if (ret != QMessageBox::Ok) { + return; + } + + const auto rootFolder = p_notebook->getRootFolderAbsolutePath(); + + if (closeNotebook(p_notebook)) { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(rootFolder)); + } } -bool ManageNotebooksDialog::checkUnsavedChanges() -{ - if (m_changesUnsaved) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("There are unsaved changes to current notebook."), - this); - return true; - } +bool ManageNotebooksDialog::checkUnsavedChanges() { + if (m_changesUnsaved) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("There are unsaved changes to current notebook."), this); + return true; + } - return false; + return false; } diff --git a/src/widgets/dialogs/managenotebooksdialog.h b/src/widgets/dialogs/managenotebooksdialog.h index 60b9a7d505..c9bbce6235 100644 --- a/src/widgets/dialogs/managenotebooksdialog.h +++ b/src/widgets/dialogs/managenotebooksdialog.h @@ -9,66 +9,64 @@ class QMenu; class QPushButton; class QScrollArea; -namespace vnotex -{ - class Notebook; - class NotebookInfoWidget; +namespace vnotex { +class Notebook; +class NotebookInfoWidget; - class ManageNotebooksDialog : public Dialog - { - Q_OBJECT - public: - ManageNotebooksDialog(const Notebook *p_notebook, QWidget *p_parent = nullptr); +class ManageNotebooksDialog : public Dialog { + Q_OBJECT +public: + ManageNotebooksDialog(const Notebook *p_notebook, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - void resetButtonClicked() Q_DECL_OVERRIDE; + void resetButtonClicked() Q_DECL_OVERRIDE; - void appliedButtonClicked() Q_DECL_OVERRIDE; + void appliedButtonClicked() Q_DECL_OVERRIDE; - private slots: - void selectNotebook(Notebook *p_notebook); +private slots: + void selectNotebook(Notebook *p_notebook); - private: - void setupUI(); +private: + void setupUI(); - void setupNotebookList(QWidget *p_parent = nullptr); + void setupNotebookList(QWidget *p_parent = nullptr); - void setupNotebookInfoWidget(QWidget *p_parent = nullptr); + void setupNotebookInfoWidget(QWidget *p_parent = nullptr); - void loadNotebooks(const Notebook *p_notebook); + void loadNotebooks(const Notebook *p_notebook); - void setChangesUnsaved(bool p_unsaved); + void setChangesUnsaved(bool p_unsaved); - bool saveChangesToNotebook(); + bool saveChangesToNotebook(); - Notebook *getNotebookFromItem(const QListWidgetItem *p_item) const; + Notebook *getNotebookFromItem(const QListWidgetItem *p_item) const; - bool closeNotebook(const Notebook *p_notebook); + bool closeNotebook(const Notebook *p_notebook); - void removeNotebook(const Notebook *p_notebook); + void removeNotebook(const Notebook *p_notebook); - bool checkUnsavedChanges(); + bool checkUnsavedChanges(); - bool validateInputs(); + bool validateInputs(); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - QListWidget *m_notebookList = nullptr; + QListWidget *m_notebookList = nullptr; - NotebookInfoWidget *m_notebookInfoWidget = nullptr; + NotebookInfoWidget *m_notebookInfoWidget = nullptr; - bool m_changesUnsaved = false; + bool m_changesUnsaved = false; - Notebook *m_notebook = nullptr; + Notebook *m_notebook = nullptr; - QScrollArea *m_infoScrollArea = nullptr; + QScrollArea *m_infoScrollArea = nullptr; - QPushButton *m_closeNotebookBtn = nullptr; + QPushButton *m_closeNotebookBtn = nullptr; - QPushButton *m_deleteNotebookBtn = nullptr; - }; -} // ns vnotex + QPushButton *m_deleteNotebookBtn = nullptr; +}; +} // namespace vnotex #endif // MANAGENOTEBOOKSDIALOG_H diff --git a/src/widgets/dialogs/newfolderdialog.cpp b/src/widgets/dialogs/newfolderdialog.cpp index b8c601c22c..8eb4679799 100644 --- a/src/widgets/dialogs/newfolderdialog.cpp +++ b/src/widgets/dialogs/newfolderdialog.cpp @@ -2,98 +2,86 @@ #include -#include +#include #include +#include #include -#include #include "../widgetsfactory.h" #include "nodeinfowidget.h" using namespace vnotex; -NewFolderDialog::NewFolderDialog(Node *p_node, QWidget *p_parent) - : ScrollDialog(p_parent) -{ - Q_ASSERT(p_node && p_node->isLoaded()); - setupUI(p_node); +NewFolderDialog::NewFolderDialog(Node *p_node, QWidget *p_parent) : ScrollDialog(p_parent) { + Q_ASSERT(p_node && p_node->isLoaded()); + setupUI(p_node); - m_infoWidget->getNameLineEdit()->setFocus(); + m_infoWidget->getNameLineEdit()->setFocus(); } -void NewFolderDialog::setupUI(const Node *p_node) -{ - setupNodeInfoWidget(p_node, this); - setCentralWidget(m_infoWidget); +void NewFolderDialog::setupUI(const Node *p_node) { + setupNodeInfoWidget(p_node, this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Folder")); + setWindowTitle(tr("New Folder")); } -void NewFolderDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) -{ - m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Container, p_parent); +void NewFolderDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) { + m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Container, p_parent); } -bool NewFolderDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool NewFolderDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool NewFolderDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool NewFolderDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - auto name = m_infoWidget->getName(); - if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { - p_msg = tr("Please specify a name for the folder."); - return false; - } + auto name = m_infoWidget->getName(); + if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { + p_msg = tr("Please specify a name for the folder."); + return false; + } - if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) { - p_msg = tr("Name conflicts with existing or built-in folder."); - return false; - } + if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) { + p_msg = tr("Name conflicts with existing or built-in folder."); + return false; + } - return true; + return true; } -void NewFolderDialog::acceptedButtonClicked() -{ - if (validateInputs() && newFolder()) { - accept(); - } +void NewFolderDialog::acceptedButtonClicked() { + if (validateInputs() && newFolder()) { + accept(); + } } -bool NewFolderDialog::newFolder() -{ - m_newNode.clear(); - - Notebook *notebook = const_cast(m_infoWidget->getNotebook()); - Node *parentNode = const_cast(m_infoWidget->getParentNode()); - try { - m_newNode = notebook->newNode(parentNode, Node::Flag::Container, m_infoWidget->getName()); - } catch (Exception &p_e) { - QString msg = tr("Failed to create folder under (%1) in (%2) (%3).").arg(parentNode->getName(), - notebook->getName(), - p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - emit notebook->nodeUpdated(parentNode); - return true; +bool NewFolderDialog::newFolder() { + m_newNode.clear(); + + Notebook *notebook = const_cast(m_infoWidget->getNotebook()); + Node *parentNode = const_cast(m_infoWidget->getParentNode()); + try { + m_newNode = notebook->newNode(parentNode, Node::Flag::Container, m_infoWidget->getName()); + } catch (Exception &p_e) { + QString msg = tr("Failed to create folder under (%1) in (%2) (%3).") + .arg(parentNode->getName(), notebook->getName(), p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + emit notebook->nodeUpdated(parentNode); + return true; } -const QSharedPointer &NewFolderDialog::getNewNode() const -{ - return m_newNode; -} +const QSharedPointer &NewFolderDialog::getNewNode() const { return m_newNode; } diff --git a/src/widgets/dialogs/newfolderdialog.h b/src/widgets/dialogs/newfolderdialog.h index 352714c5e8..18b0f7f461 100644 --- a/src/widgets/dialogs/newfolderdialog.h +++ b/src/widgets/dialogs/newfolderdialog.h @@ -3,38 +3,36 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Node; - class NodeInfoWidget; +namespace vnotex { +class Node; +class NodeInfoWidget; - class NewFolderDialog : public ScrollDialog - { - Q_OBJECT - public: - // New a folder under @p_node. - NewFolderDialog(Node *p_node, QWidget *p_parent = nullptr); +class NewFolderDialog : public ScrollDialog { + Q_OBJECT +public: + // New a folder under @p_node. + NewFolderDialog(Node *p_node, QWidget *p_parent = nullptr); - const QSharedPointer &getNewNode() const; + const QSharedPointer &getNewNode() const; - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(const Node *p_node); +private: + void setupUI(const Node *p_node); - void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent); + void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool newFolder(); + bool newFolder(); - bool validateInputs(); + bool validateInputs(); - NodeInfoWidget *m_infoWidget = nullptr; + NodeInfoWidget *m_infoWidget = nullptr; - QSharedPointer m_newNode; - }; -} // ns vnotex + QSharedPointer m_newNode; +}; +} // namespace vnotex #endif // NEWFOLDERDIALOG_H diff --git a/src/widgets/dialogs/newnotebookdialog.cpp b/src/widgets/dialogs/newnotebookdialog.cpp index 01672d78a0..d5f1f1bbaf 100644 --- a/src/widgets/dialogs/newnotebookdialog.cpp +++ b/src/widgets/dialogs/newnotebookdialog.cpp @@ -3,150 +3,135 @@ #include #include "../widgetsfactory.h" -#include "vnotex.h" -#include "notebookmgr.h" +#include "configmgr.h" +#include "exception.h" #include "notebook/inotebookfactory.h" #include "notebook/notebookparameters.h" -#include "configmgr.h" +#include "notebookinfowidget.h" +#include "notebookmgr.h" +#include "vnotex.h" #include #include -#include "exception.h" -#include "notebookinfowidget.h" using namespace vnotex; -NewNotebookDialog::NewNotebookDialog(QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(); +NewNotebookDialog::NewNotebookDialog(QWidget *p_parent) : ScrollDialog(p_parent) { + setupUI(); - m_infoWidget->getNameLineEdit()->setFocus(); + m_infoWidget->getNameLineEdit()->setFocus(); } -void NewNotebookDialog::setupUI() -{ - setupNotebookInfoWidget(this); - setCentralWidget(m_infoWidget); +void NewNotebookDialog::setupUI() { + setupNotebookInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Notebook")); + setWindowTitle(tr("New Notebook")); } -void NewNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::Create, p_parent); - connect(m_infoWidget, &NotebookInfoWidget::rootFolderEdited, - this, &NewNotebookDialog::handleRootFolderPathChanged); - - { - auto whatsThis = tr("
Both absolute and relative paths are supported. ~ and environment variable are not supported now."); - auto rootFolderEdit = m_infoWidget->getRootFolderPathLineEdit(); - rootFolderEdit->setWhatsThis(rootFolderEdit->whatsThis() + whatsThis); - } +void NewNotebookDialog::setupNotebookInfoWidget(QWidget *p_parent) { + m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::Create, p_parent); + connect(m_infoWidget, &NotebookInfoWidget::rootFolderEdited, this, + &NewNotebookDialog::handleRootFolderPathChanged); + + { + auto whatsThis = tr("
Both absolute and relative paths are supported. ~ and environment " + "variable are not supported now."); + auto rootFolderEdit = m_infoWidget->getRootFolderPathLineEdit(); + rootFolderEdit->setWhatsThis(rootFolderEdit->whatsThis() + whatsThis); + } } -bool NewNotebookDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool NewNotebookDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - valid = valid && validateRootFolderInput(msg); + valid = valid && validateNameInput(msg); + valid = valid && validateRootFolderInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool NewNotebookDialog::validateNameInput(QString &p_msg) -{ - if (m_infoWidget->getName().isEmpty()) { - Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); - return false; - } +bool NewNotebookDialog::validateNameInput(QString &p_msg) { + if (m_infoWidget->getName().isEmpty()) { + Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); + return false; + } - return true; + return true; } -bool NewNotebookDialog::validateRootFolderInput(QString &p_msg) -{ - auto rootFolderPath = m_infoWidget->getRootFolderPath(); - if (!PathUtils::isLegalPath(rootFolderPath)) { - Utils::appendMsg(p_msg, tr("Please specify a valid root folder for the notebook.")); - return false; - } - - { - QFileInfo finfo(rootFolderPath); - if (finfo.exists()) { - if (finfo.isDir()) { - if (!QDir(rootFolderPath).isEmpty()) { - Utils::appendMsg(p_msg, - tr("Root folder of the notebook must be empty. " - "If you want to import existing data, please try other operations.")); - return false; - } - } else { - Utils::appendMsg(p_msg, tr("Root folder should be a directory.")); - return false; - } +bool NewNotebookDialog::validateRootFolderInput(QString &p_msg) { + auto rootFolderPath = m_infoWidget->getRootFolderPath(); + if (!PathUtils::isLegalPath(rootFolderPath)) { + Utils::appendMsg(p_msg, tr("Please specify a valid root folder for the notebook.")); + return false; + } + + { + QFileInfo finfo(rootFolderPath); + if (finfo.exists()) { + if (finfo.isDir()) { + if (!QDir(rootFolderPath).isEmpty()) { + Utils::appendMsg(p_msg, + tr("Root folder of the notebook must be empty. " + "If you want to import existing data, please try other operations.")); + return false; } + } else { + Utils::appendMsg(p_msg, tr("Root folder should be a directory.")); + return false; + } } + } - // Check if there already exists one notebook with the same root folder. - { - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); - if (notebook) { - Utils::appendMsg(p_msg, - tr("There already exists a notebook (%1) with the same root folder.").arg(notebook->getName())); - return false; - } + // Check if there already exists one notebook with the same root folder. + { + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); + if (notebook) { + Utils::appendMsg(p_msg, tr("There already exists a notebook (%1) with the same root folder.") + .arg(notebook->getName())); + return false; } + } - return true; + return true; } -void NewNotebookDialog::acceptedButtonClicked() -{ - if (validateInputs() && newNotebook()) { - accept(); - } +void NewNotebookDialog::acceptedButtonClicked() { + if (validateInputs() && newNotebook()) { + accept(); + } } -bool NewNotebookDialog::newNotebook() -{ - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - auto paras = NotebookParameters::createNotebookParameters(notebookMgr, - m_infoWidget->getType(), - m_infoWidget->getName(), - m_infoWidget->getDescription(), - m_infoWidget->getRootFolderPath(), - m_infoWidget->getIcon(), - Notebook::c_defaultImageFolder, - Notebook::c_defaultAttachmentFolder, - QDateTime::currentDateTimeUtc(), - m_infoWidget->getBackend(), - m_infoWidget->getVersionController(), - m_infoWidget->getConfigMgr()); - try { - notebookMgr.newNotebook(paras); - } catch (Exception &p_e) { - QString msg = tr("Failed to create notebook in (%1) (%2).") - .arg(m_infoWidget->getRootFolderPath(), p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - return true; +bool NewNotebookDialog::newNotebook() { + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto paras = NotebookParameters::createNotebookParameters( + notebookMgr, m_infoWidget->getType(), m_infoWidget->getName(), m_infoWidget->getDescription(), + m_infoWidget->getRootFolderPath(), m_infoWidget->getIcon(), Notebook::c_defaultImageFolder, + Notebook::c_defaultAttachmentFolder, QDateTime::currentDateTimeUtc(), + m_infoWidget->getBackend(), m_infoWidget->getVersionController(), + m_infoWidget->getConfigMgr()); + try { + notebookMgr.newNotebook(paras); + } catch (Exception &p_e) { + QString msg = tr("Failed to create notebook in (%1) (%2).") + .arg(m_infoWidget->getRootFolderPath(), p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } -void NewNotebookDialog::handleRootFolderPathChanged() -{ - auto nameEdit = m_infoWidget->getNameLineEdit(); - if (nameEdit->text().isEmpty()) { - nameEdit->setText(PathUtils::dirName(m_infoWidget->getRootFolderPath())); - } +void NewNotebookDialog::handleRootFolderPathChanged() { + auto nameEdit = m_infoWidget->getNameLineEdit(); + if (nameEdit->text().isEmpty()) { + nameEdit->setText(PathUtils::dirName(m_infoWidget->getRootFolderPath())); + } } diff --git a/src/widgets/dialogs/newnotebookdialog.h b/src/widgets/dialogs/newnotebookdialog.h index 9065988401..bcd90b419b 100644 --- a/src/widgets/dialogs/newnotebookdialog.h +++ b/src/widgets/dialogs/newnotebookdialog.h @@ -3,38 +3,36 @@ #include "scrolldialog.h" -namespace vnotex -{ - class NotebookInfoWidget; +namespace vnotex { +class NotebookInfoWidget; - class NewNotebookDialog : public ScrollDialog - { - Q_OBJECT - public: - explicit NewNotebookDialog(QWidget *p_parent = nullptr); +class NewNotebookDialog : public ScrollDialog { + Q_OBJECT +public: + explicit NewNotebookDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - virtual bool validateRootFolderInput(QString &p_msg); + virtual bool validateRootFolderInput(QString &p_msg); - virtual void handleRootFolderPathChanged(); + virtual void handleRootFolderPathChanged(); - NotebookInfoWidget *m_infoWidget = nullptr; + NotebookInfoWidget *m_infoWidget = nullptr; - private: - void setupUI(); +private: + void setupUI(); - void setupNotebookInfoWidget(QWidget *p_parent = nullptr); + void setupNotebookInfoWidget(QWidget *p_parent = nullptr); - bool validateInputs(); + bool validateInputs(); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - // Create a new notebook. - // Return true if succeeded. - bool newNotebook(); - }; -} // ns vnotex + // Create a new notebook. + // Return true if succeeded. + bool newNotebook(); +}; +} // namespace vnotex #endif // NEWNOTEBOOKDIALOG_H diff --git a/src/widgets/dialogs/newnotebookfromfolderdialog.cpp b/src/widgets/dialogs/newnotebookfromfolderdialog.cpp index ab2310d052..22cbfbe827 100644 --- a/src/widgets/dialogs/newnotebookfromfolderdialog.cpp +++ b/src/widgets/dialogs/newnotebookfromfolderdialog.cpp @@ -1,179 +1,165 @@ #include "newnotebookfromfolderdialog.h" +#include #include #include -#include #include "../widgetsfactory.h" +#include "exception.h" #include "folderfilesfilterwidget.h" +#include "importfolderutils.h" #include "notebookinfowidget.h" -#include "vnotex.h" #include "notebookmgr.h" -#include -#include -#include +#include "vnotex.h" #include #include -#include "exception.h" -#include "importfolderutils.h" +#include +#include +#include using namespace vnotex; NewNotebookFromFolderDialog::NewNotebookFromFolderDialog(QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(); + : ScrollDialog(p_parent) { + setupUI(); - m_filterWidget->getFolderPathEdit()->setFocus(); + m_filterWidget->getFolderPathEdit()->setFocus(); } -void NewNotebookFromFolderDialog::setupUI() -{ - auto widget = new QWidget(this); - auto mainLayout = new QVBoxLayout(widget); - setCentralWidget(widget); +void NewNotebookFromFolderDialog::setupUI() { + auto widget = new QWidget(this); + auto mainLayout = new QVBoxLayout(widget); + setCentralWidget(widget); - { - auto box = new QGroupBox(tr("Source Folder"), widget); - auto layout = new QVBoxLayout(box); - setupFolderFilesFilterWidget(widget); - layout->addWidget(m_filterWidget); + { + auto box = new QGroupBox(tr("Source Folder"), widget); + auto layout = new QVBoxLayout(box); + setupFolderFilesFilterWidget(widget); + layout->addWidget(m_filterWidget); - mainLayout->addWidget(box); - } + mainLayout->addWidget(box); + } - setupNotebookInfoWidget(widget); - mainLayout->addWidget(m_infoWidget); + setupNotebookInfoWidget(widget); + mainLayout->addWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setButtonEnabled(QDialogButtonBox::Ok, false); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setButtonEnabled(QDialogButtonBox::Ok, false); - setWindowTitle(tr("New Notebook From Folder")); + setWindowTitle(tr("New Notebook From Folder")); } -void NewNotebookFromFolderDialog::setupFolderFilesFilterWidget(QWidget *p_parent) -{ - m_filterWidget = new FolderFilesFilterWidget(p_parent); - connect(m_filterWidget, &FolderFilesFilterWidget::filesChanged, - this, [this]() { - m_infoWidget->setRootFolderPath(m_filterWidget->getFolderPath()); - validateInputs(); - }); +void NewNotebookFromFolderDialog::setupFolderFilesFilterWidget(QWidget *p_parent) { + m_filterWidget = new FolderFilesFilterWidget(p_parent); + connect(m_filterWidget, &FolderFilesFilterWidget::filesChanged, this, [this]() { + m_infoWidget->setRootFolderPath(m_filterWidget->getFolderPath()); + validateInputs(); + }); } -void NewNotebookFromFolderDialog::setupNotebookInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::CreateFromFolder, p_parent); - connect(m_infoWidget, &NotebookInfoWidget::basicInfoEdited, - this, &NewNotebookFromFolderDialog::validateInputs); +void NewNotebookFromFolderDialog::setupNotebookInfoWidget(QWidget *p_parent) { + m_infoWidget = new NotebookInfoWidget(NotebookInfoWidget::CreateFromFolder, p_parent); + connect(m_infoWidget, &NotebookInfoWidget::basicInfoEdited, this, + &NewNotebookFromFolderDialog::validateInputs); } -void NewNotebookFromFolderDialog::validateInputs() -{ - bool valid = true; - QString msg; +void NewNotebookFromFolderDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - valid = valid && validateRootFolderInput(msg); + valid = valid && validateNameInput(msg); + valid = valid && validateRootFolderInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - setButtonEnabled(QDialogButtonBox::Ok, valid); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + setButtonEnabled(QDialogButtonBox::Ok, valid); } -bool NewNotebookFromFolderDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool NewNotebookFromFolderDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - if (m_infoWidget->getName().isEmpty()) { - Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); - return false; - } + if (m_infoWidget->getName().isEmpty()) { + Utils::appendMsg(p_msg, tr("Please specify a name for the notebook.")); + return false; + } - return true; + return true; } -bool NewNotebookFromFolderDialog::validateRootFolderInput(QString &p_msg) -{ - auto rootFolderPath = m_infoWidget->getRootFolderPath(); - if (!QFileInfo::exists(rootFolderPath) || !PathUtils::isLegalPath(rootFolderPath)) { - Utils::appendMsg(p_msg, tr("Please specify a valid folder for the new notebook.")); - return false; +bool NewNotebookFromFolderDialog::validateRootFolderInput(QString &p_msg) { + auto rootFolderPath = m_infoWidget->getRootFolderPath(); + if (!QFileInfo::exists(rootFolderPath) || !PathUtils::isLegalPath(rootFolderPath)) { + Utils::appendMsg(p_msg, tr("Please specify a valid folder for the new notebook.")); + return false; + } + + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + + // Check if there already exists one notebook with the same root folder. + { + auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); + if (notebook) { + Utils::appendMsg(p_msg, tr("There already exists a notebook (%1) with the same root folder.") + .arg(notebook->getName())); + return false; } - - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - - // Check if there already exists one notebook with the same root folder. - { - auto notebook = notebookMgr.findNotebookByRootFolderPath(rootFolderPath); - if (notebook) { - Utils::appendMsg(p_msg, - tr("There already exists a notebook (%1) with the same root folder.").arg(notebook->getName())); - return false; - } + } + + // Warn if it is a valid bundle notebook root folder. + { + auto factory = notebookMgr.getBundleNotebookFactory(); + auto backend = + notebookMgr.createNotebookBackend(QStringLiteral("local.vnotex"), rootFolderPath); + if (factory->checkRootFolder(backend)) { + Utils::appendMsg(p_msg, + tr("The folder is likely to be the root folder of a valid bundle notebook. " + "You may want to use \"Open Other Notebooks\" to open it. " + "If continue, all existing information of the notebook may be lost.")); } + } - // Warn if it is a valid bundle notebook root folder. - { - auto factory = notebookMgr.getBundleNotebookFactory(); - auto backend = notebookMgr.createNotebookBackend(QStringLiteral("local.vnotex"), rootFolderPath); - if (factory->checkRootFolder(backend)) { - Utils::appendMsg(p_msg, - tr("The folder is likely to be the root folder of a valid bundle notebook. " - "You may want to use \"Open Other Notebooks\" to open it. " - "If continue, all existing information of the notebook may be lost.")); - } - } - - return true; + return true; } -void NewNotebookFromFolderDialog::acceptedButtonClicked() -{ - if (isCompleted() || newNotebookFromFolder()) { - accept(); - } +void NewNotebookFromFolderDialog::acceptedButtonClicked() { + if (isCompleted() || newNotebookFromFolder()) { + accept(); + } } -bool NewNotebookFromFolderDialog::newNotebookFromFolder() -{ - const auto rootFolderPath = m_infoWidget->getRootFolderPath(); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - auto paras = NotebookParameters::createNotebookParameters(notebookMgr, - m_infoWidget->getType(), - m_infoWidget->getName(), - m_infoWidget->getDescription(), - rootFolderPath, - m_infoWidget->getIcon(), - Notebook::c_defaultImageFolder, - Notebook::c_defaultAttachmentFolder, - QDateTime::currentDateTimeUtc(), - m_infoWidget->getBackend(), - m_infoWidget->getVersionController(), - m_infoWidget->getConfigMgr()); - paras->m_ensureEmptyRootFolder = false; - QSharedPointer nb; - try { - nb = notebookMgr.newNotebook(paras); - } catch (Exception &p_e) { - QString msg = tr("Failed to create notebook in %1 (%2).").arg(rootFolderPath, p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - QString errMsg; - auto rootNode = nb->getRootNode(); - ImportFolderUtils::importFolderContents(nb.data(), rootNode.data(), m_filterWidget->getSuffixes(), errMsg); - - emit nb->nodeUpdated(rootNode.data()); - - if (!errMsg.isEmpty()) { - qWarning() << errMsg; - setInformationText(errMsg, ScrollDialog::InformationLevel::Error); - completeButStay(); - return false; - } - - return true; +bool NewNotebookFromFolderDialog::newNotebookFromFolder() { + const auto rootFolderPath = m_infoWidget->getRootFolderPath(); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + auto paras = NotebookParameters::createNotebookParameters( + notebookMgr, m_infoWidget->getType(), m_infoWidget->getName(), m_infoWidget->getDescription(), + rootFolderPath, m_infoWidget->getIcon(), Notebook::c_defaultImageFolder, + Notebook::c_defaultAttachmentFolder, QDateTime::currentDateTimeUtc(), + m_infoWidget->getBackend(), m_infoWidget->getVersionController(), + m_infoWidget->getConfigMgr()); + paras->m_ensureEmptyRootFolder = false; + QSharedPointer nb; + try { + nb = notebookMgr.newNotebook(paras); + } catch (Exception &p_e) { + QString msg = tr("Failed to create notebook in %1 (%2).").arg(rootFolderPath, p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + QString errMsg; + auto rootNode = nb->getRootNode(); + ImportFolderUtils::importFolderContents(nb.data(), rootNode.data(), m_filterWidget->getSuffixes(), + errMsg); + + emit nb->nodeUpdated(rootNode.data()); + + if (!errMsg.isEmpty()) { + qWarning() << errMsg; + setInformationText(errMsg, ScrollDialog::InformationLevel::Error); + completeButStay(); + return false; + } + + return true; } diff --git a/src/widgets/dialogs/newnotebookfromfolderdialog.h b/src/widgets/dialogs/newnotebookfromfolderdialog.h index 8115380c90..d4797edac4 100644 --- a/src/widgets/dialogs/newnotebookfromfolderdialog.h +++ b/src/widgets/dialogs/newnotebookfromfolderdialog.h @@ -3,44 +3,42 @@ #include "scrolldialog.h" -namespace vnotex -{ - class NotebookInfoWidget; - class FolderFilesFilterWidget; - class Node; - class Notebook; +namespace vnotex { +class NotebookInfoWidget; +class FolderFilesFilterWidget; +class Node; +class Notebook; - class NewNotebookFromFolderDialog : public ScrollDialog - { - Q_OBJECT - public: - explicit NewNotebookFromFolderDialog(QWidget *p_parent = nullptr); +class NewNotebookFromFolderDialog : public ScrollDialog { + Q_OBJECT +public: + explicit NewNotebookFromFolderDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private slots: - void validateInputs(); +private slots: + void validateInputs(); - private: - void setupUI(); +private: + void setupUI(); - void setupFolderFilesFilterWidget(QWidget *p_parent = nullptr); + void setupFolderFilesFilterWidget(QWidget *p_parent = nullptr); - void setupNotebookInfoWidget(QWidget *p_parent = nullptr); + void setupNotebookInfoWidget(QWidget *p_parent = nullptr); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool validateRootFolderInput(QString &p_msg); + bool validateRootFolderInput(QString &p_msg); - // Create a new notebook. - // Return true if succeeded. - bool newNotebookFromFolder(); + // Create a new notebook. + // Return true if succeeded. + bool newNotebookFromFolder(); - NotebookInfoWidget *m_infoWidget = nullptr; + NotebookInfoWidget *m_infoWidget = nullptr; - FolderFilesFilterWidget *m_filterWidget = nullptr; - }; -} + FolderFilesFilterWidget *m_filterWidget = nullptr; +}; +} // namespace vnotex #endif // NEWNOTEBOOKFROMFOLDERDIALOG_H diff --git a/src/widgets/dialogs/newnotedialog.cpp b/src/widgets/dialogs/newnotedialog.cpp index 953463a998..6758b56a9b 100644 --- a/src/widgets/dialogs/newnotedialog.cpp +++ b/src/widgets/dialogs/newnotedialog.cpp @@ -1,179 +1,155 @@ #include "newnotedialog.h" -#include -#include #include #include -#include +#include +#include #include +#include -#include "notebook/notebook.h" -#include "notebook/node.h" #include "../widgetsfactory.h" -#include -#include #include "exception.h" #include "nodeinfowidget.h" +#include "notebook/node.h" +#include "notebook/notebook.h" #include "notetemplateselector.h" -#include -#include +#include #include +#include #include #include -#include +#include +#include +#include using namespace vnotex; QString NewNoteDialog::s_lastTemplate; -NewNoteDialog::NewNoteDialog(Node *p_node, QWidget *p_parent) - : ScrollDialog(p_parent) -{ - Q_ASSERT(p_node && p_node->isLoaded()); - setupUI(p_node); +NewNoteDialog::NewNoteDialog(Node *p_node, QWidget *p_parent) : ScrollDialog(p_parent) { + Q_ASSERT(p_node && p_node->isLoaded()); + setupUI(p_node); - initDefaultValues(p_node); + initDefaultValues(p_node); - m_infoWidget->getNameLineEdit()->setFocus(); + m_infoWidget->getNameLineEdit()->setFocus(); } -void NewNoteDialog::setupUI(const Node *p_node) -{ - setupNodeInfoWidget(p_node, this); - setCentralWidget(m_infoWidget); +void NewNoteDialog::setupUI(const Node *p_node) { + setupNodeInfoWidget(p_node, this); + setCentralWidget(m_infoWidget); - auto infoLayout = m_infoWidget->getMainLayout(); + auto infoLayout = m_infoWidget->getMainLayout(); - m_templateSelector = new NoteTemplateSelector(m_infoWidget); - infoLayout->addRow(tr("Template:"), m_templateSelector); + m_templateSelector = new NoteTemplateSelector(m_infoWidget); + infoLayout->addRow(tr("Template:"), m_templateSelector); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Note")); + setWindowTitle(tr("New Note")); } -void NewNoteDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) -{ - m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Content, p_parent); +void NewNoteDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) { + m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Content, p_parent); } -bool NewNoteDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool NewNoteDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool NewNoteDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool NewNoteDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - auto name = m_infoWidget->getName(); - if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { - p_msg = tr("Please specify a valid name for the note."); - return false; - } + auto name = m_infoWidget->getName(); + if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { + p_msg = tr("Please specify a valid name for the note."); + return false; + } - if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) { - p_msg = tr("Name conflicts with existing or built-in note."); - return false; - } + if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) { + p_msg = tr("Name conflicts with existing or built-in note."); + return false; + } - return true; + return true; } -void NewNoteDialog::acceptedButtonClicked() -{ - s_lastTemplate = m_templateSelector->getCurrentTemplate(); - - { - auto fileType = FileTypeHelper::getInst().getFileTypeByName(m_infoWidget->getFileType()).m_type; - ConfigMgr::getInst().getWidgetConfig().setNewNoteDefaultFileType(static_cast(fileType)); - } - - if (validateInputs()) { - Notebook *notebook = const_cast(m_infoWidget->getNotebook()); - Node *parentNode = const_cast(m_infoWidget->getParentNode()); - QString errMsg; - m_newNode = newNote(notebook, - parentNode, - m_infoWidget->getName(), - m_templateSelector->getTemplateContent(), - errMsg); - if (!m_newNode) { - setInformationText(errMsg, ScrollDialog::InformationLevel::Error); - return; - } - accept(); +void NewNoteDialog::acceptedButtonClicked() { + s_lastTemplate = m_templateSelector->getCurrentTemplate(); + + { + auto fileType = FileTypeHelper::getInst().getFileTypeByName(m_infoWidget->getFileType()).m_type; + ConfigMgr::getInst().getWidgetConfig().setNewNoteDefaultFileType(static_cast(fileType)); + } + + if (validateInputs()) { + Notebook *notebook = const_cast(m_infoWidget->getNotebook()); + Node *parentNode = const_cast(m_infoWidget->getParentNode()); + QString errMsg; + m_newNode = newNote(notebook, parentNode, m_infoWidget->getName(), + m_templateSelector->getTemplateContent(), errMsg); + if (!m_newNode) { + setInformationText(errMsg, ScrollDialog::InformationLevel::Error); + return; } + accept(); + } } -QSharedPointer NewNoteDialog::newNote(Notebook *p_notebook, - Node *p_parentNode, - const QString &p_name, - const QString &p_templateContent, - QString &p_errMsg) -{ - Q_ASSERT(p_notebook && p_parentNode); - - QSharedPointer newNode; - p_errMsg.clear(); - - try { - newNode = p_notebook->newNode(p_parentNode, - Node::Flag::Content, - p_name, - evaluateTemplateContent(p_templateContent, p_name)); - } catch (Exception &p_e) { - p_errMsg = tr("Failed to create note under (%1) in (%2) (%3).").arg(p_parentNode->getName(), - p_notebook->getName(), - p_e.what()); - qCritical() << p_errMsg; - return nullptr; - } - - emit p_notebook->nodeUpdated(newNode.data()); - return newNode; +QSharedPointer NewNoteDialog::newNote(Notebook *p_notebook, Node *p_parentNode, + const QString &p_name, const QString &p_templateContent, + QString &p_errMsg) { + Q_ASSERT(p_notebook && p_parentNode); + + QSharedPointer newNode; + p_errMsg.clear(); + + try { + newNode = p_notebook->newNode(p_parentNode, Node::Flag::Content, p_name, + evaluateTemplateContent(p_templateContent, p_name)); + } catch (Exception &p_e) { + p_errMsg = tr("Failed to create note under (%1) in (%2) (%3).") + .arg(p_parentNode->getName(), p_notebook->getName(), p_e.what()); + qCritical() << p_errMsg; + return nullptr; + } + + emit p_notebook->nodeUpdated(newNode.data()); + return newNode; } -const QSharedPointer &NewNoteDialog::getNewNode() const -{ - return m_newNode; -} +const QSharedPointer &NewNoteDialog::getNewNode() const { return m_newNode; } -void NewNoteDialog::initDefaultValues(const Node *p_node) -{ - { - int defaultType = ConfigMgr::getInst().getWidgetConfig().getNewNoteDefaultFileType(); - const auto &fileType = FileTypeHelper::getInst().getFileType(defaultType); +void NewNoteDialog::initDefaultValues(const Node *p_node) { + { + int defaultType = ConfigMgr::getInst().getWidgetConfig().getNewNoteDefaultFileType(); + const auto &fileType = FileTypeHelper::getInst().getFileType(defaultType); - m_infoWidget->setFileType(fileType.m_typeName); + m_infoWidget->setFileType(fileType.m_typeName); - auto lineEdit = m_infoWidget->getNameLineEdit(); - auto defaultName = FileUtils::generateFileNameWithSequence(p_node->fetchAbsolutePath(), - tr("note"), - fileType.preferredSuffix()); - lineEdit->setText(defaultName); - WidgetUtils::selectBaseName(lineEdit); - } + auto lineEdit = m_infoWidget->getNameLineEdit(); + auto defaultName = FileUtils::generateFileNameWithSequence( + p_node->fetchAbsolutePath(), tr("note"), fileType.preferredSuffix()); + lineEdit->setText(defaultName); + WidgetUtils::selectBaseName(lineEdit); + } - if (!s_lastTemplate.isEmpty()) { - // Restore. - if (!m_templateSelector->setCurrentTemplate(s_lastTemplate)) { - s_lastTemplate.clear(); - } + if (!s_lastTemplate.isEmpty()) { + // Restore. + if (!m_templateSelector->setCurrentTemplate(s_lastTemplate)) { + s_lastTemplate.clear(); } + } } -QString NewNoteDialog::evaluateTemplateContent(const QString &p_content, const QString &p_name) -{ - int cursorOffset = 0; - return SnippetMgr::getInst().applySnippetBySymbol(p_content, - QString(), - cursorOffset, - SnippetMgr::generateOverrides(p_name)); +QString NewNoteDialog::evaluateTemplateContent(const QString &p_content, const QString &p_name) { + int cursorOffset = 0; + return SnippetMgr::getInst().applySnippetBySymbol(p_content, QString(), cursorOffset, + SnippetMgr::generateOverrides(p_name)); } diff --git a/src/widgets/dialogs/newnotedialog.h b/src/widgets/dialogs/newnotedialog.h index fae6e4b151..9585aea38b 100644 --- a/src/widgets/dialogs/newnotedialog.h +++ b/src/widgets/dialogs/newnotedialog.h @@ -3,52 +3,48 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Notebook; - class Node; - class NodeInfoWidget; - class NoteTemplateSelector; +namespace vnotex { +class Notebook; +class Node; +class NodeInfoWidget; +class NoteTemplateSelector; - class NewNoteDialog : public ScrollDialog - { - Q_OBJECT - public: - // New a note under @p_node. - NewNoteDialog(Node *p_node, QWidget *p_parent = nullptr); +class NewNoteDialog : public ScrollDialog { + Q_OBJECT +public: + // New a note under @p_node. + NewNoteDialog(Node *p_node, QWidget *p_parent = nullptr); - const QSharedPointer &getNewNode() const; + const QSharedPointer &getNewNode() const; - static QSharedPointer newNote(Notebook *p_notebook, - Node *p_parentNode, - const QString &p_name, - const QString &p_templateContent, - QString &p_errMsg); + static QSharedPointer newNote(Notebook *p_notebook, Node *p_parentNode, + const QString &p_name, const QString &p_templateContent, + QString &p_errMsg); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(const Node *p_node); +private: + void setupUI(const Node *p_node); - void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent); + void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent); - bool validateInputs(); + bool validateInputs(); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - void initDefaultValues(const Node *p_node); + void initDefaultValues(const Node *p_node); - static QString evaluateTemplateContent(const QString &p_content, const QString &p_name); + static QString evaluateTemplateContent(const QString &p_content, const QString &p_name); - NodeInfoWidget *m_infoWidget = nullptr; + NodeInfoWidget *m_infoWidget = nullptr; - NoteTemplateSelector *m_templateSelector = nullptr; + NoteTemplateSelector *m_templateSelector = nullptr; - QSharedPointer m_newNode; + QSharedPointer m_newNode; - static QString s_lastTemplate; - }; -} // ns vnotex + static QString s_lastTemplate; +}; +} // namespace vnotex #endif // NEWNOTEDIALOG_H diff --git a/src/widgets/dialogs/newsnippetdialog.cpp b/src/widgets/dialogs/newsnippetdialog.cpp index e95f85b5e6..a69a295b39 100644 --- a/src/widgets/dialogs/newsnippetdialog.cpp +++ b/src/widgets/dialogs/newsnippetdialog.cpp @@ -2,88 +2,76 @@ #include "snippetinfowidget.h" -#include #include +#include using namespace vnotex; -NewSnippetDialog::NewSnippetDialog(QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(); +NewSnippetDialog::NewSnippetDialog(QWidget *p_parent) : ScrollDialog(p_parent) { + setupUI(); - m_infoWidget->setFocus(); + m_infoWidget->setFocus(); } -void NewSnippetDialog::setupUI() -{ - setupSnippetInfoWidget(this); - setCentralWidget(m_infoWidget); +void NewSnippetDialog::setupUI() { + setupSnippetInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Snippet")); + setWindowTitle(tr("New Snippet")); } -void NewSnippetDialog::setupSnippetInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new SnippetInfoWidget(p_parent); +void NewSnippetDialog::setupSnippetInfoWidget(QWidget *p_parent) { + m_infoWidget = new SnippetInfoWidget(p_parent); } -bool NewSnippetDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool NewSnippetDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -void NewSnippetDialog::acceptedButtonClicked() -{ - if (validateInputs() && newSnippet()) { - accept(); - } +void NewSnippetDialog::acceptedButtonClicked() { + if (validateInputs() && newSnippet()) { + accept(); + } } -bool NewSnippetDialog::newSnippet() -{ - auto snip = QSharedPointer::create(m_infoWidget->getName(), - m_infoWidget->getDescription(), - m_infoWidget->getContent(), - m_infoWidget->getShortcut(), - m_infoWidget->shouldIndentAsFirstLine(), - m_infoWidget->getCursorMark(), - m_infoWidget->getSelectionMark()); - Q_ASSERT(snip->isValid()); - try { - SnippetMgr::getInst().addSnippet(snip); - } catch (Exception &p_e) { - QString msg = tr("Failed to add snippet (%1) (%2).") - .arg(snip->getName(), p_e.what()); - qWarning() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - return true; +bool NewSnippetDialog::newSnippet() { + auto snip = QSharedPointer::create( + m_infoWidget->getName(), m_infoWidget->getDescription(), m_infoWidget->getContent(), + m_infoWidget->getShortcut(), m_infoWidget->shouldIndentAsFirstLine(), + m_infoWidget->getCursorMark(), m_infoWidget->getSelectionMark()); + Q_ASSERT(snip->isValid()); + try { + SnippetMgr::getInst().addSnippet(snip); + } catch (Exception &p_e) { + QString msg = tr("Failed to add snippet (%1) (%2).").arg(snip->getName(), p_e.what()); + qWarning() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + return true; } -bool NewSnippetDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool NewSnippetDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - const auto name = m_infoWidget->getName(); - if (name.isEmpty()) { - p_msg = tr("Please specify a name for the snippet."); - return false; - } + const auto name = m_infoWidget->getName(); + if (name.isEmpty()) { + p_msg = tr("Please specify a name for the snippet."); + return false; + } - if (SnippetMgr::getInst().find(name, Qt::CaseInsensitive)) { - p_msg = tr("Name conflicts with existing snippet."); - return false; - } + if (SnippetMgr::getInst().find(name, Qt::CaseInsensitive)) { + p_msg = tr("Name conflicts with existing snippet."); + return false; + } - return true; + return true; } diff --git a/src/widgets/dialogs/newsnippetdialog.h b/src/widgets/dialogs/newsnippetdialog.h index 5a7fc75757..4843b2846a 100644 --- a/src/widgets/dialogs/newsnippetdialog.h +++ b/src/widgets/dialogs/newsnippetdialog.h @@ -3,32 +3,30 @@ #include "scrolldialog.h" -namespace vnotex -{ - class SnippetInfoWidget; +namespace vnotex { +class SnippetInfoWidget; - class NewSnippetDialog : public ScrollDialog - { - Q_OBJECT - public: - explicit NewSnippetDialog(QWidget *p_parent = nullptr); +class NewSnippetDialog : public ScrollDialog { + Q_OBJECT +public: + explicit NewSnippetDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupSnippetInfoWidget(QWidget *p_parent); + void setupSnippetInfoWidget(QWidget *p_parent); - bool newSnippet(); + bool newSnippet(); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool validateInputs(); + bool validateInputs(); - SnippetInfoWidget *m_infoWidget = nullptr; - }; -} + SnippetInfoWidget *m_infoWidget = nullptr; +}; +} // namespace vnotex #endif // NEWSNIPPETDIALOG_H diff --git a/src/widgets/dialogs/newtagdialog.cpp b/src/widgets/dialogs/newtagdialog.cpp index 2cfff0a5ae..30099561a7 100644 --- a/src/widgets/dialogs/newtagdialog.cpp +++ b/src/widgets/dialogs/newtagdialog.cpp @@ -4,101 +4,91 @@ #include +#include "../lineeditwithsnippet.h" #include "../widgetsfactory.h" #include "levellabelwithupbutton.h" -#include "../lineeditwithsnippet.h" using namespace vnotex; NewTagDialog::NewTagDialog(TagI *p_tagI, Tag *p_tag, QWidget *p_parent) - : ScrollDialog(p_parent), - m_tagI(p_tagI), - m_parentTag(p_tag) -{ - setupUI(); + : ScrollDialog(p_parent), m_tagI(p_tagI), m_parentTag(p_tag) { + setupUI(); - m_nameLineEdit->setFocus(); + m_nameLineEdit->setFocus(); } -static QVector tagToLevels(const Tag *p_tag) -{ - QVector levels; - while (p_tag) { - LevelLabelWithUpButton::Level level; - level.m_name = p_tag->fetchPath(); - level.m_data = static_cast(p_tag); - levels.push_back(level); - p_tag = p_tag->getParent(); - } - - // Append an empty level. - levels.push_back(LevelLabelWithUpButton::Level()); - - return levels; +static QVector tagToLevels(const Tag *p_tag) { + QVector levels; + while (p_tag) { + LevelLabelWithUpButton::Level level; + level.m_name = p_tag->fetchPath(); + level.m_data = static_cast(p_tag); + levels.push_back(level); + p_tag = p_tag->getParent(); + } + + // Append an empty level. + levels.push_back(LevelLabelWithUpButton::Level()); + + return levels; } -void NewTagDialog::setupUI() -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); +void NewTagDialog::setupUI() { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); - auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); + auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); - { - m_parentTagLabel = new LevelLabelWithUpButton(this); - m_parentTagLabel->setLevels(tagToLevels(m_parentTag)); - mainLayout->addRow(tr("Location:"), m_parentTagLabel); - } + { + m_parentTagLabel = new LevelLabelWithUpButton(this); + m_parentTagLabel->setLevels(tagToLevels(m_parentTag)); + mainLayout->addRow(tr("Location:"), m_parentTagLabel); + } - m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(mainWidget); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); + m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(mainWidget); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Tag")); + setWindowTitle(tr("New Tag")); } -bool NewTagDialog::validateInputs() -{ - bool valid = true; - QString msg; - - auto name = getTagName(); - if (!Tag::isValidName(name)) { - valid = false; - msg = tr("Please specify a valid name for the tag."); - } else if (m_tagI->findTag(name)) { - valid = false; - msg = tr("Name conflicts with existing tag."); - } - - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; +bool NewTagDialog::validateInputs() { + bool valid = true; + QString msg; + + auto name = getTagName(); + if (!Tag::isValidName(name)) { + valid = false; + msg = tr("Please specify a valid name for the tag."); + } else if (m_tagI->findTag(name)) { + valid = false; + msg = tr("Name conflicts with existing tag."); + } + + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool NewTagDialog::newTag() -{ - const Tag *parentTag = static_cast(m_parentTagLabel->getLevel().m_data); - const auto parentName = parentTag ? parentTag->name() : QString(); - const auto name = getTagName(); - if (!m_tagI->newTag(name, parentName)) { - setInformationText(tr("Failed to create tag (%1).").arg(name), ScrollDialog::InformationLevel::Error); - // Tags maybe updated. Don't allow operation for now. - setButtonEnabled(QDialogButtonBox::Ok, false); - return false; - } - return true; +bool NewTagDialog::newTag() { + const Tag *parentTag = static_cast(m_parentTagLabel->getLevel().m_data); + const auto parentName = parentTag ? parentTag->name() : QString(); + const auto name = getTagName(); + if (!m_tagI->newTag(name, parentName)) { + setInformationText(tr("Failed to create tag (%1).").arg(name), + ScrollDialog::InformationLevel::Error); + // Tags maybe updated. Don't allow operation for now. + setButtonEnabled(QDialogButtonBox::Ok, false); + return false; + } + return true; } -void NewTagDialog::acceptedButtonClicked() -{ - if (validateInputs() && newTag()) { - accept(); - } +void NewTagDialog::acceptedButtonClicked() { + if (validateInputs() && newTag()) { + accept(); + } } -QString NewTagDialog::getTagName() const -{ - return m_nameLineEdit->evaluatedText(); -} +QString NewTagDialog::getTagName() const { return m_nameLineEdit->evaluatedText(); } diff --git a/src/widgets/dialogs/newtagdialog.h b/src/widgets/dialogs/newtagdialog.h index ff52ee4456..6b8781881d 100644 --- a/src/widgets/dialogs/newtagdialog.h +++ b/src/widgets/dialogs/newtagdialog.h @@ -3,40 +3,38 @@ #include "scrolldialog.h" -namespace vnotex -{ - class TagI; - class Tag; - class LevelLabelWithUpButton; - class LineEditWithSnippet; +namespace vnotex { +class TagI; +class Tag; +class LevelLabelWithUpButton; +class LineEditWithSnippet; - class NewTagDialog : public ScrollDialog - { - Q_OBJECT - public: - // New a tag under @p_tag. - NewTagDialog(TagI *p_tagI, Tag *p_tag, QWidget *p_parent = nullptr); +class NewTagDialog : public ScrollDialog { + Q_OBJECT +public: + // New a tag under @p_tag. + NewTagDialog(TagI *p_tagI, Tag *p_tag, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - bool validateInputs(); + bool validateInputs(); - bool newTag(); + bool newTag(); - QString getTagName() const; + QString getTagName() const; - TagI *m_tagI = nullptr; + TagI *m_tagI = nullptr; - Tag *m_parentTag = nullptr; + Tag *m_parentTag = nullptr; - LevelLabelWithUpButton *m_parentTagLabel = nullptr; + LevelLabelWithUpButton *m_parentTagLabel = nullptr; - LineEditWithSnippet *m_nameLineEdit = nullptr; - }; -} + LineEditWithSnippet *m_nameLineEdit = nullptr; +}; +} // namespace vnotex #endif // NEWTAGDIALOG_H diff --git a/src/widgets/dialogs/nodeinfowidget.cpp b/src/widgets/dialogs/nodeinfowidget.cpp index c6cdcd941f..70739a3503 100644 --- a/src/widgets/dialogs/nodeinfowidget.cpp +++ b/src/widgets/dialogs/nodeinfowidget.cpp @@ -1,215 +1,184 @@ #include "nodeinfowidget.h" #include +#include #include #include -#include -#include "notebook/notebook.h" +#include "../lineeditwithsnippet.h" #include "../widgetsfactory.h" -#include -#include #include "exception.h" #include "levellabelwithupbutton.h" -#include +#include "notebook/notebook.h" #include -#include "../lineeditwithsnippet.h" +#include +#include +#include using namespace vnotex; NodeInfoWidget::NodeInfoWidget(const Node *p_node, QWidget *p_parent) - : QWidget(p_parent), - m_mode(Mode::Edit) -{ - setupUI(p_node->getParent(), p_node->getFlags()); + : QWidget(p_parent), m_mode(Mode::Edit) { + setupUI(p_node->getParent(), p_node->getFlags()); - setNode(p_node); + setNode(p_node); } -NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode, - Node::Flags p_flags, - QWidget *p_parent) - : QWidget(p_parent), - m_mode(Mode::Create) -{ - setupUI(p_parentNode, p_flags); +NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode, Node::Flags p_flags, QWidget *p_parent) + : QWidget(p_parent), m_mode(Mode::Create) { + setupUI(p_parentNode, p_flags); } -static QVector nodeToLevels(const Node *p_node) -{ - QVector levels; - while (p_node) { - LevelLabelWithUpButton::Level level; - level.m_name = p_node->fetchPath(); - level.m_data = static_cast(p_node); - levels.push_back(level); - p_node = p_node->getParent(); - } - - return levels; +static QVector nodeToLevels(const Node *p_node) { + QVector levels; + while (p_node) { + LevelLabelWithUpButton::Level level; + level.m_name = p_node->fetchPath(); + level.m_data = static_cast(p_node); + levels.push_back(level); + p_node = p_node->getParent(); + } + + return levels; } -void NodeInfoWidget::setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags) -{ - const bool createMode = m_mode == Mode::Create; - const bool isNote = p_newNodeFlags & Node::Flag::Content; +void NodeInfoWidget::setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags) { + const bool createMode = m_mode == Mode::Create; + const bool isNote = p_newNodeFlags & Node::Flag::Content; - m_mainLayout = WidgetsFactory::createFormLayout(this); + m_mainLayout = WidgetsFactory::createFormLayout(this); - m_mainLayout->addRow(tr("Notebook:"), - new QLabel(p_parentNode->getNotebook()->getName(), this)); + m_mainLayout->addRow(tr("Notebook:"), new QLabel(p_parentNode->getNotebook()->getName(), this)); - { - m_parentNodeLabel = new LevelLabelWithUpButton(this); - m_parentNodeLabel->setReadOnly(!createMode); - m_parentNodeLabel->setLevels(nodeToLevels(p_parentNode)); - connect(m_parentNodeLabel, &LevelLabelWithUpButton::levelChanged, - this, &NodeInfoWidget::inputEdited); - m_mainLayout->addRow(tr("Location:"), m_parentNodeLabel); - } + { + m_parentNodeLabel = new LevelLabelWithUpButton(this); + m_parentNodeLabel->setReadOnly(!createMode); + m_parentNodeLabel->setLevels(nodeToLevels(p_parentNode)); + connect(m_parentNodeLabel, &LevelLabelWithUpButton::levelChanged, this, + &NodeInfoWidget::inputEdited); + m_mainLayout->addRow(tr("Location:"), m_parentNodeLabel); + } - if (createMode && isNote) { - setupFileTypeComboBox(this); - m_mainLayout->addRow(tr("File type:"), m_fileTypeComboBox); - } + if (createMode && isNote) { + setupFileTypeComboBox(this); + m_mainLayout->addRow(tr("File type:"), m_fileTypeComboBox); + } - setupNameLineEdit(this); - m_mainLayout->addRow(tr("Name:"), m_nameLineEdit); + setupNameLineEdit(this); + m_mainLayout->addRow(tr("Name:"), m_nameLineEdit); - if (!createMode) { - m_createdDateTimeLabel = new QLabel(this); - m_mainLayout->addRow(tr("Created time:"), m_createdDateTimeLabel); + if (!createMode) { + m_createdDateTimeLabel = new QLabel(this); + m_mainLayout->addRow(tr("Created time:"), m_createdDateTimeLabel); - m_modifiedDateTimeLabel = new QLabel(this); - m_mainLayout->addRow(tr("Modified time:"), m_modifiedDateTimeLabel); - } + m_modifiedDateTimeLabel = new QLabel(this); + m_mainLayout->addRow(tr("Modified time:"), m_modifiedDateTimeLabel); + } } -void NodeInfoWidget::setupNameLineEdit(QWidget *p_parent) -{ - m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(p_parent); - connect(m_nameLineEdit, &QLineEdit::textEdited, - this, [this]() { - // Choose the correct file type. - if (m_fileTypeComboBox) { - auto inputName = m_nameLineEdit->text(); - QString typeName; - int dotIdx = inputName.lastIndexOf(QLatin1Char('.')); - if (dotIdx != -1) { - auto suffix = inputName.mid(dotIdx + 1); - const auto &fileType = FileTypeHelper::getInst().getFileTypeBySuffix(suffix); - typeName = fileType.m_typeName; - } else { - typeName = FileTypeHelper::getInst().getFileType(FileType::Others).m_typeName; - } - - int idx = m_fileTypeComboBox->findData(typeName); - if (idx != -1) { - m_fileTypeComboBoxMuted = true; - m_fileTypeComboBox->setCurrentIndex(idx); - m_fileTypeComboBoxMuted = false; - } - } - - emit inputEdited(); - }); -} +void NodeInfoWidget::setupNameLineEdit(QWidget *p_parent) { + m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(p_parent); + connect(m_nameLineEdit, &QLineEdit::textEdited, this, [this]() { + // Choose the correct file type. + if (m_fileTypeComboBox) { + auto inputName = m_nameLineEdit->text(); + QString typeName; + int dotIdx = inputName.lastIndexOf(QLatin1Char('.')); + if (dotIdx != -1) { + auto suffix = inputName.mid(dotIdx + 1); + const auto &fileType = FileTypeHelper::getInst().getFileTypeBySuffix(suffix); + typeName = fileType.m_typeName; + } else { + typeName = FileTypeHelper::getInst().getFileType(FileType::Others).m_typeName; + } + + int idx = m_fileTypeComboBox->findData(typeName); + if (idx != -1) { + m_fileTypeComboBoxMuted = true; + m_fileTypeComboBox->setCurrentIndex(idx); + m_fileTypeComboBoxMuted = false; + } + } -QLineEdit *NodeInfoWidget::getNameLineEdit() const -{ - return m_nameLineEdit; + emit inputEdited(); + }); } -QString NodeInfoWidget::getName() const -{ - return m_nameLineEdit->evaluatedText().trimmed(); -} +QLineEdit *NodeInfoWidget::getNameLineEdit() const { return m_nameLineEdit; } -const Notebook *NodeInfoWidget::getNotebook() const -{ - return getParentNode()->getNotebook(); -} +QString NodeInfoWidget::getName() const { return m_nameLineEdit->evaluatedText().trimmed(); } -const Node *NodeInfoWidget::getParentNode() const -{ - return static_cast(m_parentNodeLabel->getLevel().m_data); +const Notebook *NodeInfoWidget::getNotebook() const { return getParentNode()->getNotebook(); } + +const Node *NodeInfoWidget::getParentNode() const { + return static_cast(m_parentNodeLabel->getLevel().m_data); } -void NodeInfoWidget::setNode(const Node *p_node) -{ - if (m_node == p_node) { - return; - } +void NodeInfoWidget::setNode(const Node *p_node) { + if (m_node == p_node) { + return; + } - Q_ASSERT(m_mode != Mode::Create); - m_node = p_node; - if (m_node) { - Q_ASSERT(getNotebook() == m_node->getNotebook()); - m_nameLineEdit->setText(m_node->getName()); - m_parentNodeLabel->setLevels(nodeToLevels(m_node->getParent())); + Q_ASSERT(m_mode != Mode::Create); + m_node = p_node; + if (m_node) { + Q_ASSERT(getNotebook() == m_node->getNotebook()); + m_nameLineEdit->setText(m_node->getName()); + m_parentNodeLabel->setLevels(nodeToLevels(m_node->getParent())); - auto createdTime = Utils::dateTimeString(m_node->getCreatedTimeUtc().toLocalTime()); - m_createdDateTimeLabel->setText(createdTime); + auto createdTime = Utils::dateTimeString(m_node->getCreatedTimeUtc().toLocalTime()); + m_createdDateTimeLabel->setText(createdTime); - auto modifiedTime = Utils::dateTimeString(m_node->getModifiedTimeUtc().toLocalTime()); - m_modifiedDateTimeLabel->setText(modifiedTime); - } + auto modifiedTime = Utils::dateTimeString(m_node->getModifiedTimeUtc().toLocalTime()); + m_modifiedDateTimeLabel->setText(modifiedTime); + } } -void NodeInfoWidget::setupFileTypeComboBox(QWidget *p_parent) -{ - m_fileTypeComboBox = WidgetsFactory::createComboBox(p_parent); - const auto &fileTypes = FileTypeHelper::getInst().getAllFileTypes(); - for (const auto &ft : fileTypes) { - if (m_mode == Mode::Create && !ft.m_isNewable) { - continue; - } - m_fileTypeComboBox->addItem(ft.m_displayName, ft.m_typeName); +void NodeInfoWidget::setupFileTypeComboBox(QWidget *p_parent) { + m_fileTypeComboBox = WidgetsFactory::createComboBox(p_parent); + const auto &fileTypes = FileTypeHelper::getInst().getAllFileTypes(); + for (const auto &ft : fileTypes) { + if (m_mode == Mode::Create && !ft.m_isNewable) { + continue; + } + m_fileTypeComboBox->addItem(ft.m_displayName, ft.m_typeName); + } + connect(m_fileTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { + if (m_fileTypeComboBoxMuted) { + return; + } + auto name = m_fileTypeComboBox->currentData().toString(); + const auto &fileType = FileTypeHelper::getInst().getFileTypeByName(name); + const auto suffix = fileType.preferredSuffix(); + if (!suffix.isEmpty()) { + // Change the suffix. + auto inputName = m_nameLineEdit->text(); + QString newName; + int dotIdx = inputName.lastIndexOf(QLatin1Char('.')); + if (dotIdx == -1) { + newName = inputName + QLatin1Char('.') + suffix; + } else if (inputName.mid(dotIdx + 1) != suffix) { + newName = inputName.left(dotIdx + 1) + suffix; + } + + if (!newName.isEmpty()) { + m_nameLineEdit->setText(newName); + emit inputEdited(); + } } - connect(m_fileTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this]() { - if (m_fileTypeComboBoxMuted) { - return; - } - auto name = m_fileTypeComboBox->currentData().toString(); - const auto &fileType = FileTypeHelper::getInst().getFileTypeByName(name); - const auto suffix = fileType.preferredSuffix(); - if (!suffix.isEmpty()) { - // Change the suffix. - auto inputName = m_nameLineEdit->text(); - QString newName; - int dotIdx = inputName.lastIndexOf(QLatin1Char('.')); - if (dotIdx == -1) { - newName = inputName + QLatin1Char('.') + suffix; - } else if (inputName.mid(dotIdx + 1) != suffix) { - newName = inputName.left(dotIdx + 1) + suffix; - } - - if (!newName.isEmpty()) { - m_nameLineEdit->setText(newName); - emit inputEdited(); - } - } - - WidgetUtils::selectBaseName(m_nameLineEdit); - m_nameLineEdit->setFocus(); - }); -} -QFormLayout *NodeInfoWidget::getMainLayout() const -{ - return m_mainLayout; + WidgetUtils::selectBaseName(m_nameLineEdit); + m_nameLineEdit->setFocus(); + }); } -QString NodeInfoWidget::getFileType() const -{ - return m_fileTypeComboBox->currentData().toString(); -} +QFormLayout *NodeInfoWidget::getMainLayout() const { return m_mainLayout; } -void NodeInfoWidget::setFileType(const QString &p_typeName) -{ - int idx = m_fileTypeComboBox->findData(p_typeName); - if (idx != -1) { - m_fileTypeComboBox->setCurrentIndex(idx); - } +QString NodeInfoWidget::getFileType() const { return m_fileTypeComboBox->currentData().toString(); } + +void NodeInfoWidget::setFileType(const QString &p_typeName) { + int idx = m_fileTypeComboBox->findData(p_typeName); + if (idx != -1) { + m_fileTypeComboBox->setCurrentIndex(idx); + } } diff --git a/src/widgets/dialogs/nodeinfowidget.h b/src/widgets/dialogs/nodeinfowidget.h index 35cd02dbc4..357bea5691 100644 --- a/src/widgets/dialogs/nodeinfowidget.h +++ b/src/widgets/dialogs/nodeinfowidget.h @@ -10,68 +10,64 @@ class QLabel; class QFormLayout; class QComboBox; -namespace vnotex -{ - class Notebook; - class LevelLabelWithUpButton; - class LineEditWithSnippet; +namespace vnotex { +class Notebook; +class LevelLabelWithUpButton; +class LineEditWithSnippet; - class NodeInfoWidget : public QWidget - { - Q_OBJECT - public: - enum Mode { Create, Edit }; +class NodeInfoWidget : public QWidget { + Q_OBJECT +public: + enum Mode { Create, Edit }; - NodeInfoWidget(const Node *p_node, QWidget *p_parent = nullptr); + NodeInfoWidget(const Node *p_node, QWidget *p_parent = nullptr); - NodeInfoWidget(const Node *p_parentNode, - Node::Flags p_flags, - QWidget *p_parent = nullptr); + NodeInfoWidget(const Node *p_parentNode, Node::Flags p_flags, QWidget *p_parent = nullptr); - QLineEdit *getNameLineEdit() const; + QLineEdit *getNameLineEdit() const; - QString getName() const; + QString getName() const; - const Notebook *getNotebook() const; + const Notebook *getNotebook() const; - const Node *getParentNode() const; + const Node *getParentNode() const; - // Allow upper level to add more widgets to the layout. - QFormLayout *getMainLayout() const; + // Allow upper level to add more widgets to the layout. + QFormLayout *getMainLayout() const; - QString getFileType() const; - void setFileType(const QString &p_typeName); + QString getFileType() const; + void setFileType(const QString &p_typeName); - signals: - void inputEdited(); +signals: + void inputEdited(); - private: - void setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags); +private: + void setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags); - void setupFileTypeComboBox(QWidget *p_parent); + void setupFileTypeComboBox(QWidget *p_parent); - void setupNameLineEdit(QWidget *p_parent); + void setupNameLineEdit(QWidget *p_parent); - void setNode(const Node *p_node); + void setNode(const Node *p_node); - Mode m_mode = Mode::Create; + Mode m_mode = Mode::Create; - QFormLayout *m_mainLayout = nullptr; + QFormLayout *m_mainLayout = nullptr; - QComboBox *m_fileTypeComboBox = nullptr; + QComboBox *m_fileTypeComboBox = nullptr; - LineEditWithSnippet *m_nameLineEdit = nullptr; + LineEditWithSnippet *m_nameLineEdit = nullptr; - LevelLabelWithUpButton *m_parentNodeLabel = nullptr; + LevelLabelWithUpButton *m_parentNodeLabel = nullptr; - QLabel *m_createdDateTimeLabel = nullptr; + QLabel *m_createdDateTimeLabel = nullptr; - QLabel *m_modifiedDateTimeLabel = nullptr; + QLabel *m_modifiedDateTimeLabel = nullptr; - const Node *m_node = nullptr; + const Node *m_node = nullptr; - bool m_fileTypeComboBoxMuted = false; - }; -} // ns vnotex + bool m_fileTypeComboBoxMuted = false; +}; +} // namespace vnotex #endif // NODEINFOWIDGET_H diff --git a/src/widgets/dialogs/notebookinfowidget.cpp b/src/widgets/dialogs/notebookinfowidget.cpp index e1ba05c8dd..293767068a 100644 --- a/src/widgets/dialogs/notebookinfowidget.cpp +++ b/src/widgets/dialogs/notebookinfowidget.cpp @@ -2,378 +2,323 @@ #include +#include "../lineeditwithsnippet.h" #include "../widgetsfactory.h" -#include "notebook/notebook.h" -#include "vnotex.h" +#include "configmgr.h" +#include "exception.h" #include "notebook/inotebookfactory.h" +#include "notebook/notebook.h" #include "notebook/notebookparameters.h" -#include "versioncontroller/iversioncontrollerfactory.h" -#include "versioncontroller/iversioncontroller.h" -#include "notebookconfigmgr/inotebookconfigmgrfactory.h" -#include "notebookconfigmgr/inotebookconfigmgr.h" -#include "notebookbackend/inotebookbackendfactory.h" #include "notebookbackend/inotebookbackend.h" +#include "notebookbackend/inotebookbackendfactory.h" +#include "notebookconfigmgr/inotebookconfigmgr.h" +#include "notebookconfigmgr/inotebookconfigmgrfactory.h" #include "notebookmgr.h" -#include "configmgr.h" +#include "versioncontroller/iversioncontroller.h" +#include "versioncontroller/iversioncontrollerfactory.h" +#include "vnotex.h" #include -#include "exception.h" #include -#include "../lineeditwithsnippet.h" using namespace vnotex; NotebookInfoWidget::NotebookInfoWidget(NotebookInfoWidget::Mode p_mode, QWidget *p_parent) - : QWidget(p_parent), - m_mode(p_mode) -{ - setupUI(); + : QWidget(p_parent), m_mode(p_mode) { + setupUI(); - setMode(p_mode); + setMode(p_mode); } -void NotebookInfoWidget::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); +void NotebookInfoWidget::setupUI() { + auto mainLayout = new QVBoxLayout(this); - auto basicInfoGroup = setupBasicInfoGroupBox(this); - mainLayout->addWidget(basicInfoGroup); + auto basicInfoGroup = setupBasicInfoGroupBox(this); + mainLayout->addWidget(basicInfoGroup); - auto advancedInfoGroup = setupAdvancedInfoGroupBox(this); - mainLayout->addWidget(advancedInfoGroup); + auto advancedInfoGroup = setupAdvancedInfoGroupBox(this); + mainLayout->addWidget(advancedInfoGroup); } -QGroupBox *NotebookInfoWidget::setupBasicInfoGroupBox(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("Basic Information"), p_parent); - auto mainLayout = WidgetsFactory::createFormLayout(box); - - { - setupNotebookTypeComboBox(box); - mainLayout->addRow(tr("Type:"), m_typeComboBox); - } - - { - m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(box); - m_nameLineEdit->setPlaceholderText(tr("Name of notebook")); - connect(m_nameLineEdit, &QLineEdit::textEdited, - this, &NotebookInfoWidget::basicInfoEdited); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); - } - - { - mainLayout->addRow(tr("Icon:"), new QLabel("default", box)); - } +QGroupBox *NotebookInfoWidget::setupBasicInfoGroupBox(QWidget *p_parent) { + auto box = new QGroupBox(tr("Basic Information"), p_parent); + auto mainLayout = WidgetsFactory::createFormLayout(box); + + { + setupNotebookTypeComboBox(box); + mainLayout->addRow(tr("Type:"), m_typeComboBox); + } + + { + m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(box); + m_nameLineEdit->setPlaceholderText(tr("Name of notebook")); + connect(m_nameLineEdit, &QLineEdit::textEdited, this, &NotebookInfoWidget::basicInfoEdited); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); + } + + { + mainLayout->addRow(tr("Icon:"), new QLabel("default", box)); + } + + { + m_descriptionLineEdit = WidgetsFactory::createLineEdit(box); + m_descriptionLineEdit->setPlaceholderText(tr("Description of notebook")); + connect(m_descriptionLineEdit, &QLineEdit::textEdited, this, + &NotebookInfoWidget::basicInfoEdited); + mainLayout->addRow(tr("Description:"), m_descriptionLineEdit); + } + + { + auto layout = setupNotebookRootFolderPath(box); + mainLayout->addRow(tr("Root folder:"), layout); + } + + return box; +} - { - m_descriptionLineEdit = WidgetsFactory::createLineEdit(box); - m_descriptionLineEdit->setPlaceholderText(tr("Description of notebook")); - connect(m_descriptionLineEdit, &QLineEdit::textEdited, - this, &NotebookInfoWidget::basicInfoEdited); - mainLayout->addRow(tr("Description:"), m_descriptionLineEdit); - } +void NotebookInfoWidget::setupNotebookTypeComboBox(QWidget *p_parent) { + m_typeComboBox = WidgetsFactory::createComboBox(p_parent); + m_typeComboBox->setToolTip(tr("Type of notebook")); - { - auto layout = setupNotebookRootFolderPath(box); - mainLayout->addRow(tr("Root folder:"), layout); - } + QString whatsThis = tr("Specify the type of notebook.
"); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + for (auto &factory : notebookMgr.getAllNotebookFactories()) { + m_typeComboBox->addItem(factory->getDisplayName(), factory->getName()); + whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), factory->getDescription()); + } - return box; + m_typeComboBox->setWhatsThis(whatsThis); } -void NotebookInfoWidget::setupNotebookTypeComboBox(QWidget *p_parent) -{ - m_typeComboBox = WidgetsFactory::createComboBox(p_parent); - m_typeComboBox->setToolTip(tr("Type of notebook")); - - QString whatsThis = tr("Specify the type of notebook.
"); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - for (auto &factory : notebookMgr.getAllNotebookFactories()) { - m_typeComboBox->addItem(factory->getDisplayName(), factory->getName()); - whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), - factory->getDescription()); +QLayout *NotebookInfoWidget::setupNotebookRootFolderPath(QWidget *p_parent) { + m_rootFolderPathLineEdit = WidgetsFactory::createLineEdit(p_parent); + m_rootFolderPathLineEdit->setPlaceholderText(tr("Path of notebook root folder")); + auto whatsThis = + tr("Notebook Root Folder is the folder containing all data of one notebook in %1.") + .arg(ConfigMgr::c_appName); + m_rootFolderPathLineEdit->setWhatsThis(whatsThis); + connect(m_rootFolderPathLineEdit, &QLineEdit::textChanged, this, [this]() { + emit rootFolderEdited(); + emit basicInfoEdited(); + }); + + m_rootFolderPathBrowseButton = new QPushButton(tr("Browse"), p_parent); + connect(m_rootFolderPathBrowseButton, &QPushButton::clicked, this, [this]() { + auto &config = ConfigMgr::getInst().getSessionConfig(); + auto browsePath = config.getNewNotebookDefaultRootFolderPath(); + auto rootFolderPath = QFileDialog::getExistingDirectory( + this, tr("Select Notebook Root Folder"), browsePath, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (!rootFolderPath.isEmpty()) { + config.setNewNotebookDefaultRootFolderPath(PathUtils::parentDirPath(rootFolderPath)); + m_rootFolderPathLineEdit->setText(rootFolderPath); } + }); - m_typeComboBox->setWhatsThis(whatsThis); + auto layout = new QHBoxLayout(); + layout->addWidget(m_rootFolderPathLineEdit); + layout->addWidget(m_rootFolderPathBrowseButton); + return layout; } -QLayout *NotebookInfoWidget::setupNotebookRootFolderPath(QWidget *p_parent) -{ - m_rootFolderPathLineEdit = WidgetsFactory::createLineEdit(p_parent); - m_rootFolderPathLineEdit->setPlaceholderText(tr("Path of notebook root folder")); - auto whatsThis = tr("Notebook Root Folder is the folder containing all data of one notebook in %1.").arg(ConfigMgr::c_appName); - m_rootFolderPathLineEdit->setWhatsThis(whatsThis); - connect(m_rootFolderPathLineEdit, &QLineEdit::textChanged, - this, [this]() { - emit rootFolderEdited(); - emit basicInfoEdited(); - }); - - m_rootFolderPathBrowseButton = new QPushButton(tr("Browse"), p_parent); - connect(m_rootFolderPathBrowseButton, &QPushButton::clicked, - this, [this]() { - auto &config = ConfigMgr::getInst().getSessionConfig(); - auto browsePath = config.getNewNotebookDefaultRootFolderPath(); - auto rootFolderPath = QFileDialog::getExistingDirectory(this, - tr("Select Notebook Root Folder"), - browsePath, - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - if (!rootFolderPath.isEmpty()) { - config.setNewNotebookDefaultRootFolderPath(PathUtils::parentDirPath(rootFolderPath)); - m_rootFolderPathLineEdit->setText(rootFolderPath); - } - }); - - auto layout = new QHBoxLayout(); - layout->addWidget(m_rootFolderPathLineEdit); - layout->addWidget(m_rootFolderPathBrowseButton); - return layout; -} +QGroupBox *NotebookInfoWidget::setupAdvancedInfoGroupBox(QWidget *p_parent) { + auto box = new QGroupBox(tr("Advanced Information"), p_parent); + auto mainLayout = WidgetsFactory::createFormLayout(box); -QGroupBox *NotebookInfoWidget::setupAdvancedInfoGroupBox(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("Advanced Information"), p_parent); - auto mainLayout = WidgetsFactory::createFormLayout(box); + { + setupConfigMgrComboBox(box); + mainLayout->addRow(tr("Configuration manager:"), m_configMgrComboBox); + } - { - setupConfigMgrComboBox(box); - mainLayout->addRow(tr("Configuration manager:"), m_configMgrComboBox); - } + { + setupVersionControllerComboBox(box); + mainLayout->addRow(tr("Version control:"), m_versionControllerComboBox); + } - { - setupVersionControllerComboBox(box); - mainLayout->addRow(tr("Version control:"), m_versionControllerComboBox); - } - - { - setupBackendComboBox(box); - mainLayout->addRow(tr("Backend:"), m_backendComboBox); - } + { + setupBackendComboBox(box); + mainLayout->addRow(tr("Backend:"), m_backendComboBox); + } - return box; + return box; } -void NotebookInfoWidget::setupConfigMgrComboBox(QWidget *p_parent) -{ - m_configMgrComboBox = WidgetsFactory::createComboBox(p_parent); - m_configMgrComboBox->setToolTip(tr("Configuration manager of notebook")); - - QString whatsThis = tr("Specify configruation manager of notebook.
"); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - for (auto &factory : notebookMgr.getAllNotebookConfigMgrFactories()) { - m_configMgrComboBox->addItem(factory->getDisplayName(), factory->getName()); - whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), - factory->getDescription()); - } - - m_configMgrComboBox->setWhatsThis(whatsThis); -} +void NotebookInfoWidget::setupConfigMgrComboBox(QWidget *p_parent) { + m_configMgrComboBox = WidgetsFactory::createComboBox(p_parent); + m_configMgrComboBox->setToolTip(tr("Configuration manager of notebook")); -void NotebookInfoWidget::setupVersionControllerComboBox(QWidget *p_parent) -{ - m_versionControllerComboBox = WidgetsFactory::createComboBox(p_parent); - m_versionControllerComboBox->setToolTip(tr("Version control of notebook")); - - QString whatsThis = tr("Specify version control of notebook.
"); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - for (auto &factory : notebookMgr.getAllVersionControllerFactories()) { - m_versionControllerComboBox->addItem(factory->getDisplayName(), factory->getName()); - whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), - factory->getDescription()); - } + QString whatsThis = tr("Specify configruation manager of notebook.
"); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + for (auto &factory : notebookMgr.getAllNotebookConfigMgrFactories()) { + m_configMgrComboBox->addItem(factory->getDisplayName(), factory->getName()); + whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), factory->getDescription()); + } - m_versionControllerComboBox->setWhatsThis(whatsThis); + m_configMgrComboBox->setWhatsThis(whatsThis); } -void NotebookInfoWidget::setupBackendComboBox(QWidget *p_parent) -{ - m_backendComboBox = WidgetsFactory::createComboBox(p_parent); - m_backendComboBox->setToolTip(tr("Backend of notebook")); - - QString whatsThis = tr("Specify backend of notebook.
"); - auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); - for (auto &factory : notebookMgr.getAllNotebookBackendFactories()) { - m_backendComboBox->addItem(factory->getDisplayName(), factory->getName()); - whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), - factory->getDescription()); - } +void NotebookInfoWidget::setupVersionControllerComboBox(QWidget *p_parent) { + m_versionControllerComboBox = WidgetsFactory::createComboBox(p_parent); + m_versionControllerComboBox->setToolTip(tr("Version control of notebook")); - m_backendComboBox->setWhatsThis(whatsThis); + QString whatsThis = tr("Specify version control of notebook.
"); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + for (auto &factory : notebookMgr.getAllVersionControllerFactories()) { + m_versionControllerComboBox->addItem(factory->getDisplayName(), factory->getName()); + whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), factory->getDescription()); + } - connect(m_backendComboBox, QOverload::of(&QComboBox::activated), - this, &NotebookInfoWidget::notebookBackendEdited); + m_versionControllerComboBox->setWhatsThis(whatsThis); } -static void setCurrentComboBoxByData(QComboBox *p_box, const QVariant &p_data) -{ - int idx = p_box->findData(p_data); - p_box->setCurrentIndex(idx); -} +void NotebookInfoWidget::setupBackendComboBox(QWidget *p_parent) { + m_backendComboBox = WidgetsFactory::createComboBox(p_parent); + m_backendComboBox->setToolTip(tr("Backend of notebook")); -void NotebookInfoWidget::setNotebook(const Notebook *p_notebook) -{ - Q_ASSERT(m_mode != Mode::Create - && m_mode != Mode::CreateFromFolder - && m_mode != Mode::CreateFromLegacy); - if (m_notebook == p_notebook) { - return; - } + QString whatsThis = tr("Specify backend of notebook.
"); + auto ¬ebookMgr = VNoteX::getInst().getNotebookMgr(); + for (auto &factory : notebookMgr.getAllNotebookBackendFactories()) { + m_backendComboBox->addItem(factory->getDisplayName(), factory->getName()); + whatsThis += tr("%1: %2
").arg(factory->getDisplayName(), factory->getDescription()); + } - bool isImport = m_mode == Mode::Import; - clear(isImport, isImport); - - m_notebook = p_notebook; - if (m_notebook) { - setCurrentComboBoxByData(m_typeComboBox, m_notebook->getType()); - m_nameLineEdit->setText(m_notebook->getName()); - m_descriptionLineEdit->setText(m_notebook->getDescription()); - m_rootFolderPathLineEdit->setText(m_notebook->getRootFolderPath()); - setCurrentComboBoxByData(m_configMgrComboBox, m_notebook->getConfigMgr()->getName()); - setCurrentComboBoxByData(m_versionControllerComboBox, m_notebook->getVersionController()->getName()); - setCurrentComboBoxByData(m_backendComboBox, m_notebook->getBackend()->getName()); - } -} + m_backendComboBox->setWhatsThis(whatsThis); -const Notebook *NotebookInfoWidget::getNotebook() const -{ - Q_ASSERT(m_mode != Mode::Create - && m_mode != Mode::CreateFromFolder - && m_mode != Mode::CreateFromLegacy); - return m_notebook; + connect(m_backendComboBox, QOverload::of(&QComboBox::activated), this, + &NotebookInfoWidget::notebookBackendEdited); } -QLineEdit *NotebookInfoWidget::getNameLineEdit() const -{ - return m_nameLineEdit; +static void setCurrentComboBoxByData(QComboBox *p_box, const QVariant &p_data) { + int idx = p_box->findData(p_data); + p_box->setCurrentIndex(idx); } -QLineEdit *NotebookInfoWidget::getRootFolderPathLineEdit() const -{ - return m_rootFolderPathLineEdit; +void NotebookInfoWidget::setNotebook(const Notebook *p_notebook) { + Q_ASSERT(m_mode != Mode::Create && m_mode != Mode::CreateFromFolder && + m_mode != Mode::CreateFromLegacy); + if (m_notebook == p_notebook) { + return; + } + + bool isImport = m_mode == Mode::Import; + clear(isImport, isImport); + + m_notebook = p_notebook; + if (m_notebook) { + setCurrentComboBoxByData(m_typeComboBox, m_notebook->getType()); + m_nameLineEdit->setText(m_notebook->getName()); + m_descriptionLineEdit->setText(m_notebook->getDescription()); + m_rootFolderPathLineEdit->setText(m_notebook->getRootFolderPath()); + setCurrentComboBoxByData(m_configMgrComboBox, m_notebook->getConfigMgr()->getName()); + setCurrentComboBoxByData(m_versionControllerComboBox, + m_notebook->getVersionController()->getName()); + setCurrentComboBoxByData(m_backendComboBox, m_notebook->getBackend()->getName()); + } } -QLineEdit *NotebookInfoWidget::getDescriptionLineEdit() const -{ - return m_descriptionLineEdit; +const Notebook *NotebookInfoWidget::getNotebook() const { + Q_ASSERT(m_mode != Mode::Create && m_mode != Mode::CreateFromFolder && + m_mode != Mode::CreateFromLegacy); + return m_notebook; } -QComboBox *NotebookInfoWidget::getTypeComboBox() const -{ - return m_typeComboBox; -} +QLineEdit *NotebookInfoWidget::getNameLineEdit() const { return m_nameLineEdit; } -QComboBox *NotebookInfoWidget::getConfigMgrComboBox() const -{ - return m_configMgrComboBox; +QLineEdit *NotebookInfoWidget::getRootFolderPathLineEdit() const { + return m_rootFolderPathLineEdit; } -QComboBox *NotebookInfoWidget::getVersionControllerComboBox() const -{ - return m_versionControllerComboBox; -} +QLineEdit *NotebookInfoWidget::getDescriptionLineEdit() const { return m_descriptionLineEdit; } -void NotebookInfoWidget::setStateAccordingToMode() -{ - switch (m_mode) { - case CreateFromFolder: - m_rootFolderPathLineEdit->setReadOnly(true); - m_rootFolderPathBrowseButton->setVisible(false); - break; - - case Edit: - m_typeComboBox->setEnabled(false); - m_rootFolderPathLineEdit->setReadOnly(true); - m_rootFolderPathBrowseButton->setVisible(false); - m_configMgrComboBox->setEnabled(false); - m_versionControllerComboBox->setEnabled(false); - m_backendComboBox->setEnabled(false); - break; - - case Import: - m_typeComboBox->setEnabled(false); - m_nameLineEdit->setEnabled(false); - m_descriptionLineEdit->setEnabled(false); - m_configMgrComboBox->setEnabled(false); - m_versionControllerComboBox->setEnabled(false); - break; - - case CreateFromLegacy: - // Support bundle notebook only. - m_typeComboBox->setEnabled(false); - break; - - default: - break; - } -} +QComboBox *NotebookInfoWidget::getTypeComboBox() const { return m_typeComboBox; } -QComboBox *NotebookInfoWidget::getBackendComboBox() const -{ - return m_backendComboBox; -} +QComboBox *NotebookInfoWidget::getConfigMgrComboBox() const { return m_configMgrComboBox; } -QString NotebookInfoWidget::getName() const -{ - return m_nameLineEdit->evaluatedText().trimmed(); +QComboBox *NotebookInfoWidget::getVersionControllerComboBox() const { + return m_versionControllerComboBox; } -QString NotebookInfoWidget::getDescription() const -{ - return getDescriptionLineEdit()->text().trimmed(); +void NotebookInfoWidget::setStateAccordingToMode() { + switch (m_mode) { + case CreateFromFolder: + m_rootFolderPathLineEdit->setReadOnly(true); + m_rootFolderPathBrowseButton->setVisible(false); + break; + + case Edit: + m_typeComboBox->setEnabled(false); + m_rootFolderPathLineEdit->setReadOnly(true); + m_rootFolderPathBrowseButton->setVisible(false); + m_configMgrComboBox->setEnabled(false); + m_versionControllerComboBox->setEnabled(false); + m_backendComboBox->setEnabled(false); + break; + + case Import: + m_typeComboBox->setEnabled(false); + m_nameLineEdit->setEnabled(false); + m_descriptionLineEdit->setEnabled(false); + m_configMgrComboBox->setEnabled(false); + m_versionControllerComboBox->setEnabled(false); + break; + + case CreateFromLegacy: + // Support bundle notebook only. + m_typeComboBox->setEnabled(false); + break; + + default: + break; + } } -QString NotebookInfoWidget::getRootFolderPath() const -{ - return getRootFolderPathLineEdit()->text().trimmed(); -} +QComboBox *NotebookInfoWidget::getBackendComboBox() const { return m_backendComboBox; } + +QString NotebookInfoWidget::getName() const { return m_nameLineEdit->evaluatedText().trimmed(); } -QIcon NotebookInfoWidget::getIcon() const -{ - return QIcon(); +QString NotebookInfoWidget::getDescription() const { + return getDescriptionLineEdit()->text().trimmed(); } -QString NotebookInfoWidget::getType() const -{ - return getTypeComboBox()->currentData().toString(); +QString NotebookInfoWidget::getRootFolderPath() const { + return getRootFolderPathLineEdit()->text().trimmed(); } -QString NotebookInfoWidget::getConfigMgr() const -{ - return getConfigMgrComboBox()->currentData().toString(); +QIcon NotebookInfoWidget::getIcon() const { return QIcon(); } + +QString NotebookInfoWidget::getType() const { return getTypeComboBox()->currentData().toString(); } + +QString NotebookInfoWidget::getConfigMgr() const { + return getConfigMgrComboBox()->currentData().toString(); } -QString NotebookInfoWidget::getVersionController() const -{ - return getVersionControllerComboBox()->currentData().toString(); +QString NotebookInfoWidget::getVersionController() const { + return getVersionControllerComboBox()->currentData().toString(); } -QString NotebookInfoWidget::getBackend() const -{ - return getBackendComboBox()->currentData().toString(); +QString NotebookInfoWidget::getBackend() const { + return getBackendComboBox()->currentData().toString(); } -void NotebookInfoWidget::clear(bool p_skipRootFolder, bool p_skipBackend) -{ - Q_UNUSED(p_skipBackend); +void NotebookInfoWidget::clear(bool p_skipRootFolder, bool p_skipBackend) { + Q_UNUSED(p_skipBackend); - m_notebook = nullptr; - m_nameLineEdit->clear(); - m_descriptionLineEdit->clear(); - if (!p_skipRootFolder) { - m_rootFolderPathLineEdit->clear(); - } + m_notebook = nullptr; + m_nameLineEdit->clear(); + m_descriptionLineEdit->clear(); + if (!p_skipRootFolder) { + m_rootFolderPathLineEdit->clear(); + } } -void NotebookInfoWidget::setRootFolderPath(const QString &p_path) -{ - Q_ASSERT(m_mode == Mode::CreateFromFolder); - m_rootFolderPathLineEdit->setText(p_path); - if (m_nameLineEdit->text().isEmpty()) { - m_nameLineEdit->setText(PathUtils::dirName(p_path)); - } +void NotebookInfoWidget::setRootFolderPath(const QString &p_path) { + Q_ASSERT(m_mode == Mode::CreateFromFolder); + m_rootFolderPathLineEdit->setText(p_path); + if (m_nameLineEdit->text().isEmpty()) { + m_nameLineEdit->setText(PathUtils::dirName(p_path)); + } } -void NotebookInfoWidget::setMode(Mode p_mode) -{ - m_mode = p_mode; - setStateAccordingToMode(); +void NotebookInfoWidget::setMode(Mode p_mode) { + m_mode = p_mode; + setStateAccordingToMode(); } diff --git a/src/widgets/dialogs/notebookinfowidget.h b/src/widgets/dialogs/notebookinfowidget.h index 124e3a18c9..e16f3470dd 100644 --- a/src/widgets/dialogs/notebookinfowidget.h +++ b/src/widgets/dialogs/notebookinfowidget.h @@ -8,106 +8,104 @@ class QPushButton; class QLineEdit; class QGroupBox; -namespace vnotex -{ - class Notebook; - class LineEditWithSnippet; +namespace vnotex { +class Notebook; +class LineEditWithSnippet; - class NotebookInfoWidget : public QWidget - { - Q_OBJECT - public: - enum Mode { Create, CreateFromFolder, Edit, Import, CreateFromLegacy }; +class NotebookInfoWidget : public QWidget { + Q_OBJECT +public: + enum Mode { Create, CreateFromFolder, Edit, Import, CreateFromLegacy }; - explicit NotebookInfoWidget(NotebookInfoWidget::Mode p_mode, QWidget *p_parent = nullptr); + explicit NotebookInfoWidget(NotebookInfoWidget::Mode p_mode, QWidget *p_parent = nullptr); - QLineEdit *getNameLineEdit() const; + QLineEdit *getNameLineEdit() const; - QLineEdit *getRootFolderPathLineEdit() const; - void setRootFolderPath(const QString &p_path); + QLineEdit *getRootFolderPathLineEdit() const; + void setRootFolderPath(const QString &p_path); - QString getName() const; + QString getName() const; - QString getDescription() const; + QString getDescription() const; - QString getRootFolderPath() const; + QString getRootFolderPath() const; - QIcon getIcon() const; + QIcon getIcon() const; - QString getType() const; + QString getType() const; - QString getConfigMgr() const; + QString getConfigMgr() const; - QString getVersionController() const; + QString getVersionController() const; - QString getBackend() const; + QString getBackend() const; - void clear(bool p_skipRootFolder = false, bool p_skipBackend = false); + void clear(bool p_skipRootFolder = false, bool p_skipBackend = false); - void setMode(Mode p_mode); + void setMode(Mode p_mode); - const Notebook *getNotebook() const; + const Notebook *getNotebook() const; - public slots: - void setNotebook(const Notebook *p_notebook); +public slots: + void setNotebook(const Notebook *p_notebook); - signals: - // Give caller a chance to change the name according to the root folder. - void rootFolderEdited(); +signals: + // Give caller a chance to change the name according to the root folder. + void rootFolderEdited(); - // Emit when name, description, or root folder path is edited. - void basicInfoEdited(); + // Emit when name, description, or root folder path is edited. + void basicInfoEdited(); - void notebookBackendEdited(); + void notebookBackendEdited(); - private: - void setupUI(); +private: + void setupUI(); - void setStateAccordingToMode(); + void setStateAccordingToMode(); - QGroupBox *setupBasicInfoGroupBox(QWidget *p_parent = nullptr); + QGroupBox *setupBasicInfoGroupBox(QWidget *p_parent = nullptr); - void setupNotebookTypeComboBox(QWidget *p_parent = nullptr); + void setupNotebookTypeComboBox(QWidget *p_parent = nullptr); - QLayout *setupNotebookRootFolderPath(QWidget *p_parent = nullptr); + QLayout *setupNotebookRootFolderPath(QWidget *p_parent = nullptr); - QGroupBox *setupAdvancedInfoGroupBox(QWidget *p_parent = nullptr); + QGroupBox *setupAdvancedInfoGroupBox(QWidget *p_parent = nullptr); - void setupConfigMgrComboBox(QWidget *p_parent = nullptr); + void setupConfigMgrComboBox(QWidget *p_parent = nullptr); - void setupVersionControllerComboBox(QWidget *p_parent = nullptr); + void setupVersionControllerComboBox(QWidget *p_parent = nullptr); - void setupBackendComboBox(QWidget *p_parent = nullptr); + void setupBackendComboBox(QWidget *p_parent = nullptr); - QLineEdit *getDescriptionLineEdit() const; + QLineEdit *getDescriptionLineEdit() const; - QComboBox *getTypeComboBox() const; + QComboBox *getTypeComboBox() const; - QComboBox *getConfigMgrComboBox() const; + QComboBox *getConfigMgrComboBox() const; - QComboBox *getVersionControllerComboBox() const; + QComboBox *getVersionControllerComboBox() const; - QComboBox *getBackendComboBox() const; + QComboBox *getBackendComboBox() const; - Mode m_mode = Mode::Create; + Mode m_mode = Mode::Create; - const Notebook *m_notebook = nullptr; + const Notebook *m_notebook = nullptr; - LineEditWithSnippet *m_nameLineEdit = nullptr; + LineEditWithSnippet *m_nameLineEdit = nullptr; - QLineEdit *m_descriptionLineEdit = nullptr; + QLineEdit *m_descriptionLineEdit = nullptr; - QComboBox *m_typeComboBox = nullptr; + QComboBox *m_typeComboBox = nullptr; - QComboBox *m_configMgrComboBox = nullptr; + QComboBox *m_configMgrComboBox = nullptr; - QComboBox *m_versionControllerComboBox = nullptr; + QComboBox *m_versionControllerComboBox = nullptr; - QComboBox *m_backendComboBox = nullptr; + QComboBox *m_backendComboBox = nullptr; - QLineEdit *m_rootFolderPathLineEdit = nullptr; - QPushButton *m_rootFolderPathBrowseButton = nullptr; - }; -} // ns vnotex + QLineEdit *m_rootFolderPathLineEdit = nullptr; + QPushButton *m_rootFolderPathBrowseButton = nullptr; +}; +} // namespace vnotex #endif // NOTEBOOKINFOWIDGET_H diff --git a/src/widgets/dialogs/notepropertiesdialog.cpp b/src/widgets/dialogs/notepropertiesdialog.cpp index 7c6262f8d3..d2bcfb802f 100644 --- a/src/widgets/dialogs/notepropertiesdialog.cpp +++ b/src/widgets/dialogs/notepropertiesdialog.cpp @@ -1,103 +1,94 @@ #include "notepropertiesdialog.h" -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include "../lineedit.h" #include "../widgetsfactory.h" #include "nodeinfowidget.h" -#include "../lineedit.h" using namespace vnotex; NotePropertiesDialog::NotePropertiesDialog(Node *p_node, QWidget *p_parent) - : ScrollDialog(p_parent), - m_node(p_node) -{ - Q_ASSERT(m_node); - setupUI(); + : ScrollDialog(p_parent), m_node(p_node) { + Q_ASSERT(m_node); + setupUI(); - LineEdit::selectBaseName(m_infoWidget->getNameLineEdit()); + LineEdit::selectBaseName(m_infoWidget->getNameLineEdit()); - m_infoWidget->getNameLineEdit()->setFocus(); + m_infoWidget->getNameLineEdit()->setFocus(); } -void NotePropertiesDialog::setupUI() -{ - setupNodeInfoWidget(this); - setCentralWidget(m_infoWidget); +void NotePropertiesDialog::setupUI() { + setupNodeInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("%1 Properties").arg(m_node->getName())); + setWindowTitle(tr("%1 Properties").arg(m_node->getName())); } -void NotePropertiesDialog::setupNodeInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new NodeInfoWidget(m_node, p_parent); +void NotePropertiesDialog::setupNodeInfoWidget(QWidget *p_parent) { + m_infoWidget = new NodeInfoWidget(m_node, p_parent); } -bool NotePropertiesDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool NotePropertiesDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool NotePropertiesDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool NotePropertiesDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - auto name = m_infoWidget->getName(); - if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { - p_msg = tr("Please specify a valid name for the note."); - return false; - } + auto name = m_infoWidget->getName(); + if (name.isEmpty() || !PathUtils::isLegalFileName(name)) { + p_msg = tr("Please specify a valid name for the note."); + return false; + } - Q_ASSERT(m_infoWidget->getParentNode() == m_node->getParent()); - if (!m_node->canRename(name)) { - p_msg = tr("Name conflicts with existing note."); - return false; - } + Q_ASSERT(m_infoWidget->getParentNode() == m_node->getParent()); + if (!m_node->canRename(name)) { + p_msg = tr("Name conflicts with existing note."); + return false; + } - return true; + return true; } -void NotePropertiesDialog::acceptedButtonClicked() -{ - if (validateInputs() && saveNoteProperties()) { - accept(); - } +void NotePropertiesDialog::acceptedButtonClicked() { + if (validateInputs() && saveNoteProperties()) { + accept(); + } } -bool NotePropertiesDialog::saveNoteProperties() -{ - try { - if (m_infoWidget->getName() != m_node->getName()) { - // Close the node first. - auto event = QSharedPointer::create(); - emit VNoteX::getInst().nodeAboutToRename(m_node, event); - if (!event->m_response.toBool()) { - return false; - } - - m_node->updateName(m_infoWidget->getName()); - } - } catch (Exception &p_e) { - QString msg = tr("Failed to save note (%1) in (%2) (%3).").arg(m_node->getName(), - m_node->getNotebook()->getName(), - p_e.what()); - qCritical() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); +bool NotePropertiesDialog::saveNoteProperties() { + try { + if (m_infoWidget->getName() != m_node->getName()) { + // Close the node first. + auto event = QSharedPointer::create(); + emit VNoteX::getInst().nodeAboutToRename(m_node, event); + if (!event->m_response.toBool()) { return false; - } + } - return true; + m_node->updateName(m_infoWidget->getName()); + } + } catch (Exception &p_e) { + QString msg = tr("Failed to save note (%1) in (%2) (%3).") + .arg(m_node->getName(), m_node->getNotebook()->getName(), p_e.what()); + qCritical() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } diff --git a/src/widgets/dialogs/notepropertiesdialog.h b/src/widgets/dialogs/notepropertiesdialog.h index d57400f815..a522f2f71c 100644 --- a/src/widgets/dialogs/notepropertiesdialog.h +++ b/src/widgets/dialogs/notepropertiesdialog.h @@ -3,35 +3,33 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Node; - class NodeInfoWidget; +namespace vnotex { +class Node; +class NodeInfoWidget; - class NotePropertiesDialog : public ScrollDialog - { - Q_OBJECT - public: - NotePropertiesDialog(Node *p_node, QWidget *p_parent = nullptr); +class NotePropertiesDialog : public ScrollDialog { + Q_OBJECT +public: + NotePropertiesDialog(Node *p_node, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupNodeInfoWidget(QWidget *p_parent); + void setupNodeInfoWidget(QWidget *p_parent); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool saveNoteProperties(); + bool saveNoteProperties(); - bool validateInputs(); + bool validateInputs(); - NodeInfoWidget *m_infoWidget = nullptr; + NodeInfoWidget *m_infoWidget = nullptr; - Node *m_node = nullptr; - }; -} // ns vnotex + Node *m_node = nullptr; +}; +} // namespace vnotex #endif // NOTEPROPERTIESDIALOG_H diff --git a/src/widgets/dialogs/notetemplateselector.cpp b/src/widgets/dialogs/notetemplateselector.cpp index 21e00b7a50..43c76c3ab3 100644 --- a/src/widgets/dialogs/notetemplateselector.cpp +++ b/src/widgets/dialogs/notetemplateselector.cpp @@ -1,13 +1,13 @@ #include "notetemplateselector.h" -#include -#include #include +#include #include #include +#include -#include #include +#include #include #include @@ -15,98 +15,84 @@ using namespace vnotex; -NoteTemplateSelector::NoteTemplateSelector(QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(); -} +NoteTemplateSelector::NoteTemplateSelector(QWidget *p_parent) : QWidget(p_parent) { setupUI(); } -void NoteTemplateSelector::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); +void NoteTemplateSelector::setupUI() { + auto mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); - auto selectorLayout = new QHBoxLayout(); - mainLayout->addLayout(selectorLayout); + auto selectorLayout = new QHBoxLayout(); + mainLayout->addLayout(selectorLayout); - setupTemplateComboBox(this); - selectorLayout->addWidget(m_templateComboBox, 1); + setupTemplateComboBox(this); + selectorLayout->addWidget(m_templateComboBox, 1); - auto manageBtn = new QPushButton(tr("Manage"), this); - selectorLayout->addWidget(manageBtn); - connect(manageBtn, &QPushButton::clicked, - this, []() { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(TemplateMgr::getInst().getTemplateFolder())); - }); + auto manageBtn = new QPushButton(tr("Manage"), this); + selectorLayout->addWidget(manageBtn); + connect(manageBtn, &QPushButton::clicked, this, []() { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(TemplateMgr::getInst().getTemplateFolder())); + }); - m_templateTextEdit = WidgetsFactory::createPlainTextConsole(this); - mainLayout->addWidget(m_templateTextEdit); - m_templateTextEdit->hide(); + m_templateTextEdit = WidgetsFactory::createPlainTextConsole(this); + mainLayout->addWidget(m_templateTextEdit); + m_templateTextEdit->hide(); } -void NoteTemplateSelector::setupTemplateComboBox(QWidget *p_parent) -{ - m_templateComboBox = WidgetsFactory::createComboBox(p_parent); +void NoteTemplateSelector::setupTemplateComboBox(QWidget *p_parent) { + m_templateComboBox = WidgetsFactory::createComboBox(p_parent); - // None. - m_templateComboBox->addItem(tr("None"), ""); + // None. + m_templateComboBox->addItem(tr("None"), ""); - int idx = 1; - auto templates = TemplateMgr::getInst().getTemplates(); - for (const auto &temp : templates) { - m_templateComboBox->addItem(temp, temp); - m_templateComboBox->setItemData(idx++, temp, Qt::ToolTipRole); - } + int idx = 1; + auto templates = TemplateMgr::getInst().getTemplates(); + for (const auto &temp : templates) { + m_templateComboBox->addItem(temp, temp); + m_templateComboBox->setItemData(idx++, temp, Qt::ToolTipRole); + } - m_templateComboBox->setCurrentIndex(0); + m_templateComboBox->setCurrentIndex(0); - connect(m_templateComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &NoteTemplateSelector::updateCurrentTemplate); + connect(m_templateComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &NoteTemplateSelector::updateCurrentTemplate); } -void NoteTemplateSelector::updateCurrentTemplate() -{ - m_templateContent.clear(); - m_templateTextEdit->clear(); - - auto templateName = m_templateComboBox->currentData().toString(); - if (templateName.isEmpty()) { - m_templateTextEdit->hide(); - emit templateChanged(); - return; - } - - const auto filePath = TemplateMgr::getInst().getTemplateFilePath(templateName); - try { - m_templateContent = FileUtils::readTextFile(filePath); - m_templateTextEdit->setPlainText(m_templateContent); - } catch (Exception &p_e) { - QString msg = tr("Failed to load template (%1) (%2).") - .arg(filePath, p_e.what()); - qCritical() << msg; - m_templateTextEdit->setPlainText(msg); - } - m_templateTextEdit->show(); +void NoteTemplateSelector::updateCurrentTemplate() { + m_templateContent.clear(); + m_templateTextEdit->clear(); + + auto templateName = m_templateComboBox->currentData().toString(); + if (templateName.isEmpty()) { + m_templateTextEdit->hide(); emit templateChanged(); + return; + } + + const auto filePath = TemplateMgr::getInst().getTemplateFilePath(templateName); + try { + m_templateContent = FileUtils::readTextFile(filePath); + m_templateTextEdit->setPlainText(m_templateContent); + } catch (Exception &p_e) { + QString msg = tr("Failed to load template (%1) (%2).").arg(filePath, p_e.what()); + qCritical() << msg; + m_templateTextEdit->setPlainText(msg); + } + m_templateTextEdit->show(); + emit templateChanged(); } -QString NoteTemplateSelector::getCurrentTemplate() const -{ - return m_templateComboBox->currentData().toString(); +QString NoteTemplateSelector::getCurrentTemplate() const { + return m_templateComboBox->currentData().toString(); } -bool NoteTemplateSelector::setCurrentTemplate(const QString &p_template) -{ - int idx = m_templateComboBox->findData(p_template); - if (idx != -1) { - m_templateComboBox->setCurrentIndex(idx); - return true; - } else { - return false; - } +bool NoteTemplateSelector::setCurrentTemplate(const QString &p_template) { + int idx = m_templateComboBox->findData(p_template); + if (idx != -1) { + m_templateComboBox->setCurrentIndex(idx); + return true; + } else { + return false; + } } -const QString& NoteTemplateSelector::getTemplateContent() const -{ - return m_templateContent; -} +const QString &NoteTemplateSelector::getTemplateContent() const { return m_templateContent; } diff --git a/src/widgets/dialogs/notetemplateselector.h b/src/widgets/dialogs/notetemplateselector.h index 9018001b84..8cd48daf16 100644 --- a/src/widgets/dialogs/notetemplateselector.h +++ b/src/widgets/dialogs/notetemplateselector.h @@ -6,35 +6,33 @@ class QComboBox; class QPlainTextEdit; -namespace vnotex -{ - class NoteTemplateSelector : public QWidget - { - Q_OBJECT - public: - explicit NoteTemplateSelector(QWidget *p_parent = nullptr); +namespace vnotex { +class NoteTemplateSelector : public QWidget { + Q_OBJECT +public: + explicit NoteTemplateSelector(QWidget *p_parent = nullptr); - QString getCurrentTemplate() const; - bool setCurrentTemplate(const QString &p_template); + QString getCurrentTemplate() const; + bool setCurrentTemplate(const QString &p_template); - const QString& getTemplateContent() const; + const QString &getTemplateContent() const; - signals: - void templateChanged(); +signals: + void templateChanged(); - private: - void setupUI(); +private: + void setupUI(); - void setupTemplateComboBox(QWidget *p_parent); + void setupTemplateComboBox(QWidget *p_parent); - void updateCurrentTemplate(); + void updateCurrentTemplate(); - QComboBox *m_templateComboBox = nullptr; + QComboBox *m_templateComboBox = nullptr; - QPlainTextEdit *m_templateTextEdit = nullptr; + QPlainTextEdit *m_templateTextEdit = nullptr; - QString m_templateContent; - }; -} + QString m_templateContent; +}; +} // namespace vnotex #endif // NOTETEMPLATESELECTOR_H diff --git a/src/widgets/dialogs/renametagdialog.cpp b/src/widgets/dialogs/renametagdialog.cpp index 5ec1318d06..1d6fc0a947 100644 --- a/src/widgets/dialogs/renametagdialog.cpp +++ b/src/widgets/dialogs/renametagdialog.cpp @@ -5,78 +5,69 @@ #include #include -#include "../widgetsfactory.h" #include "../lineeditwithsnippet.h" +#include "../widgetsfactory.h" using namespace vnotex; RenameTagDialog::RenameTagDialog(TagI *p_tagI, const QString &p_name, QWidget *p_parent) - : ScrollDialog(p_parent), - m_tagI(p_tagI), - m_tagName(p_name) -{ - setupUI(); - - m_nameLineEdit->setFocus(); - WidgetUtils::selectBaseName(m_nameLineEdit); + : ScrollDialog(p_parent), m_tagI(p_tagI), m_tagName(p_name) { + setupUI(); + + m_nameLineEdit->setFocus(); + WidgetUtils::selectBaseName(m_nameLineEdit); } -void RenameTagDialog::setupUI() -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); +void RenameTagDialog::setupUI() { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); - auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); + auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); - m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(m_tagName, mainWidget); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); + m_nameLineEdit = WidgetsFactory::createLineEditWithSnippet(m_tagName, mainWidget); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("Rename Tag")); + setWindowTitle(tr("Rename Tag")); } -bool RenameTagDialog::validateInputs() -{ - bool valid = true; - QString msg; - - auto name = getTagName(); - if (name == m_tagName) { - return true; - } - - if (!Tag::isValidName(name)) { - valid = false; - msg = tr("Please specify a valid name for the tag."); - } else if (m_tagI->findTag(name)) { - valid = false; - msg = tr("Name conflicts with existing tag."); - } - - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; -} - -bool RenameTagDialog::renameTag() -{ - if (!m_tagI->renameTag(m_tagName, getTagName())) { - setInformationText(tr("Failed to rename tag (%1) to (%2).").arg(m_tagName, getTagName()), ScrollDialog::InformationLevel::Error); - return false; - } +bool RenameTagDialog::validateInputs() { + bool valid = true; + QString msg; + auto name = getTagName(); + if (name == m_tagName) { return true; + } + + if (!Tag::isValidName(name)) { + valid = false; + msg = tr("Please specify a valid name for the tag."); + } else if (m_tagI->findTag(name)) { + valid = false; + msg = tr("Name conflicts with existing tag."); + } + + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -void RenameTagDialog::acceptedButtonClicked() -{ - if (validateInputs() && renameTag()) { - accept(); - } +bool RenameTagDialog::renameTag() { + if (!m_tagI->renameTag(m_tagName, getTagName())) { + setInformationText(tr("Failed to rename tag (%1) to (%2).").arg(m_tagName, getTagName()), + ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } -QString RenameTagDialog::getTagName() const -{ - return m_nameLineEdit->evaluatedText(); +void RenameTagDialog::acceptedButtonClicked() { + if (validateInputs() && renameTag()) { + accept(); + } } + +QString RenameTagDialog::getTagName() const { return m_nameLineEdit->evaluatedText(); } diff --git a/src/widgets/dialogs/renametagdialog.h b/src/widgets/dialogs/renametagdialog.h index 10b703e9a4..6877e5eb1b 100644 --- a/src/widgets/dialogs/renametagdialog.h +++ b/src/widgets/dialogs/renametagdialog.h @@ -3,35 +3,33 @@ #include "scrolldialog.h" -namespace vnotex -{ - class TagI; - class LineEditWithSnippet; +namespace vnotex { +class TagI; +class LineEditWithSnippet; - class RenameTagDialog : public ScrollDialog - { - Q_OBJECT - public: - RenameTagDialog(TagI *p_tagI, const QString &p_name, QWidget *p_parent = nullptr); +class RenameTagDialog : public ScrollDialog { + Q_OBJECT +public: + RenameTagDialog(TagI *p_tagI, const QString &p_name, QWidget *p_parent = nullptr); - QString getTagName() const; + QString getTagName() const; - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - bool validateInputs(); + bool validateInputs(); - bool renameTag(); + bool renameTag(); - TagI *m_tagI = nullptr; + TagI *m_tagI = nullptr; - const QString m_tagName; + const QString m_tagName; - LineEditWithSnippet *m_nameLineEdit = nullptr; - }; -} + LineEditWithSnippet *m_nameLineEdit = nullptr; +}; +} // namespace vnotex #endif // RENAMETAGDIALOG_H diff --git a/src/widgets/dialogs/scrolldialog.cpp b/src/widgets/dialogs/scrolldialog.cpp index d668871960..1b9bee1703 100644 --- a/src/widgets/dialogs/scrolldialog.cpp +++ b/src/widgets/dialogs/scrolldialog.cpp @@ -1,14 +1,14 @@ #include "scrolldialog.h" -#include -#include -#include #include -#include -#include +#include +#include #include #include -#include +#include +#include +#include +#include #include @@ -16,35 +16,29 @@ using namespace vnotex; -ScrollDialog::ScrollDialog(QWidget *p_parent, Qt::WindowFlags p_flags) - : Dialog(p_parent, p_flags) -{ - m_scrollArea = new QScrollArea(this); - m_scrollArea->setWidgetResizable(true); - m_layout->addWidget(m_scrollArea); +ScrollDialog::ScrollDialog(QWidget *p_parent, Qt::WindowFlags p_flags) : Dialog(p_parent, p_flags) { + m_scrollArea = new QScrollArea(this); + m_scrollArea->setWidgetResizable(true); + m_layout->addWidget(m_scrollArea); } -void ScrollDialog::setCentralWidget(QWidget *p_widget) -{ - Q_ASSERT(!m_centralWidget && p_widget); - m_centralWidget = p_widget; - m_centralWidget->setProperty(PropertyDefs::c_dialogCentralWidget, true); - m_scrollArea->setWidget(p_widget); +void ScrollDialog::setCentralWidget(QWidget *p_widget) { + Q_ASSERT(!m_centralWidget && p_widget); + m_centralWidget = p_widget; + m_centralWidget->setProperty(PropertyDefs::c_dialogCentralWidget, true); + m_scrollArea->setWidget(p_widget); } -void ScrollDialog::addBottomWidget(QWidget *p_widget) -{ - m_layout->insertWidget(m_layout->indexOf(m_scrollArea) + 1, p_widget); +void ScrollDialog::addBottomWidget(QWidget *p_widget) { + m_layout->insertWidget(m_layout->indexOf(m_scrollArea) + 1, p_widget); } -void ScrollDialog::showEvent(QShowEvent *p_event) -{ - Dialog::showEvent(p_event); +void ScrollDialog::showEvent(QShowEvent *p_event) { + Dialog::showEvent(p_event); - resizeToHideScrollBarLater(false, true); + resizeToHideScrollBarLater(false, true); } -void ScrollDialog::resizeToHideScrollBarLater(bool p_vertical, bool p_horizontal) -{ - WidgetUtils::resizeToHideScrollBarLater(m_scrollArea, p_vertical, p_horizontal); +void ScrollDialog::resizeToHideScrollBarLater(bool p_vertical, bool p_horizontal) { + WidgetUtils::resizeToHideScrollBarLater(m_scrollArea, p_vertical, p_horizontal); } diff --git a/src/widgets/dialogs/scrolldialog.h b/src/widgets/dialogs/scrolldialog.h index df6baf6264..955ab5fae2 100644 --- a/src/widgets/dialogs/scrolldialog.h +++ b/src/widgets/dialogs/scrolldialog.h @@ -5,26 +5,24 @@ class QScrollArea; -namespace vnotex -{ - class ScrollDialog : public Dialog - { - Q_OBJECT - public: - ScrollDialog(QWidget *p_parent = nullptr, Qt::WindowFlags p_flags = Qt::WindowFlags()); +namespace vnotex { +class ScrollDialog : public Dialog { + Q_OBJECT +public: + ScrollDialog(QWidget *p_parent = nullptr, Qt::WindowFlags p_flags = Qt::WindowFlags()); - void resizeToHideScrollBarLater(bool p_vertical, bool p_horizontal); + void resizeToHideScrollBarLater(bool p_vertical, bool p_horizontal); - protected: - void setCentralWidget(QWidget *p_widget) Q_DECL_OVERRIDE; +protected: + void setCentralWidget(QWidget *p_widget) Q_DECL_OVERRIDE; - void addBottomWidget(QWidget *p_widget) Q_DECL_OVERRIDE; + void addBottomWidget(QWidget *p_widget) Q_DECL_OVERRIDE; - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private: - QScrollArea *m_scrollArea = nullptr; - }; -} // ns vnotex +private: + QScrollArea *m_scrollArea = nullptr; +}; +} // namespace vnotex #endif // SCROLLDIALOG_H diff --git a/src/widgets/dialogs/selectdialog.cpp b/src/widgets/dialogs/selectdialog.cpp index 62d5f88c62..e94407dc37 100644 --- a/src/widgets/dialogs/selectdialog.cpp +++ b/src/widgets/dialogs/selectdialog.cpp @@ -2,155 +2,143 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include using namespace vnotex; const QChar SelectDialog::c_cancelShortcut = QLatin1Char('z'); SelectDialog::SelectDialog(const QString &p_title, QWidget *p_parent) - : SelectDialog(p_title, QString(), p_parent) -{ -} + : SelectDialog(p_title, QString(), p_parent) {} -SelectDialog::SelectDialog(const QString &p_title, - const QString &p_text, - QWidget *p_parent) - : QDialog(p_parent) -{ - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - m_shortcutIconForeground = themeMgr.paletteColor(QStringLiteral("widgets#quickselector#item_icon#fg")); - m_shortcutIconBorder = themeMgr.paletteColor(QStringLiteral("widgets#quickselector#item_icon#border")); +SelectDialog::SelectDialog(const QString &p_title, const QString &p_text, QWidget *p_parent) + : QDialog(p_parent) { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + m_shortcutIconForeground = + themeMgr.paletteColor(QStringLiteral("widgets#quickselector#item_icon#fg")); + m_shortcutIconBorder = + themeMgr.paletteColor(QStringLiteral("widgets#quickselector#item_icon#border")); - setupUI(p_title, p_text); + setupUI(p_title, p_text); } -void SelectDialog::setupUI(const QString &p_title, const QString &p_text) -{ - auto mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); +void SelectDialog::setupUI(const QString &p_title, const QString &p_text) { + auto mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); - if (!p_text.isNull()) { - m_label = new QLabel(p_text, this); - mainLayout->addWidget(m_label); - } + if (!p_text.isNull()) { + m_label = new QLabel(p_text, this); + mainLayout->addWidget(m_label); + } - m_list = new ListWidget(this); - m_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_list->setSelectionMode(QAbstractItemView::SingleSelection); - m_list->setAttribute(Qt::WA_MacShowFocusRect, false); - connect(m_list, &ListWidget::itemActivated, - this, &SelectDialog::selectionChosen); + m_list = new ListWidget(this); + m_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_list->setSelectionMode(QAbstractItemView::SingleSelection); + m_list->setAttribute(Qt::WA_MacShowFocusRect, false); + connect(m_list, &ListWidget::itemActivated, this, &SelectDialog::selectionChosen); - m_list->installEventFilter(this); + m_list->installEventFilter(this); - // Add cancel item. - { - const auto icon = IconUtils::drawTextIcon(c_cancelShortcut, m_shortcutIconForeground, m_shortcutIconBorder); - QListWidgetItem *cancelItem = new QListWidgetItem(icon, tr("Cancel")); - cancelItem->setData(Qt::UserRole, CANCEL_ID); + // Add cancel item. + { + const auto icon = + IconUtils::drawTextIcon(c_cancelShortcut, m_shortcutIconForeground, m_shortcutIconBorder); + QListWidgetItem *cancelItem = new QListWidgetItem(icon, tr("Cancel")); + cancelItem->setData(Qt::UserRole, CANCEL_ID); - m_shortcuts.insert(c_cancelShortcut, cancelItem); + m_shortcuts.insert(c_cancelShortcut, cancelItem); - m_list->addItem(cancelItem); - m_list->setCurrentRow(0); - } + m_list->addItem(cancelItem); + m_list->setCurrentRow(0); + } - mainLayout->addWidget(m_list); + mainLayout->addWidget(m_list); - setWindowTitle(p_title); + setWindowTitle(p_title); } -void SelectDialog::addSelection(const QString &p_selectStr, int p_selectID) -{ - Q_ASSERT(p_selectID >= 0); +void SelectDialog::addSelection(const QString &p_selectStr, int p_selectID) { + Q_ASSERT(p_selectID >= 0); - QChar shortcut; - if (m_nextShortcut < c_cancelShortcut) { - shortcut = m_nextShortcut; - m_nextShortcut = QChar(m_nextShortcut.toLatin1() + 1); - } - const auto icon = IconUtils::drawTextIcon(shortcut, m_shortcutIconForeground, m_shortcutIconBorder); - QListWidgetItem *item = new QListWidgetItem(icon, p_selectStr); - item->setData(Qt::UserRole, p_selectID); + QChar shortcut; + if (m_nextShortcut < c_cancelShortcut) { + shortcut = m_nextShortcut; + m_nextShortcut = QChar(m_nextShortcut.toLatin1() + 1); + } + const auto icon = + IconUtils::drawTextIcon(shortcut, m_shortcutIconForeground, m_shortcutIconBorder); + QListWidgetItem *item = new QListWidgetItem(icon, p_selectStr); + item->setData(Qt::UserRole, p_selectID); - if (!shortcut.isNull()) { - m_shortcuts.insert(shortcut, item); - } + if (!shortcut.isNull()) { + m_shortcuts.insert(shortcut, item); + } - m_list->insertItem(m_list->count() - 1, item); + m_list->insertItem(m_list->count() - 1, item); - m_list->setCurrentRow(0); + m_list->setCurrentRow(0); } -void SelectDialog::selectionChosen(QListWidgetItem *p_item) -{ - m_choice = p_item->data(Qt::UserRole).toInt(); - if (m_choice == CANCEL_ID) { - reject(); - } else { - accept(); - } +void SelectDialog::selectionChosen(QListWidgetItem *p_item) { + m_choice = p_item->data(Qt::UserRole).toInt(); + if (m_choice == CANCEL_ID) { + reject(); + } else { + accept(); + } } -int SelectDialog::getSelection() const -{ - return m_choice; -} +int SelectDialog::getSelection() const { return m_choice; } -void SelectDialog::updateSize() -{ - Q_ASSERT(m_list->count() > 0); +void SelectDialog::updateSize() { + Q_ASSERT(m_list->count() > 0); - int height = 0; - for (int i = 0; i < m_list->count(); ++i) { - height += m_list->sizeHintForRow(i); - } + int height = 0; + for (int i = 0; i < m_list->count(); ++i) { + height += m_list->sizeHintForRow(i); + } - height += 2 * m_list->count(); - int wid = width(); - m_list->resize(wid, height); - resize(wid, height); + height += 2 * m_list->count(); + int wid = width(); + m_list->resize(wid, height); + resize(wid, height); } -void SelectDialog::showEvent(QShowEvent *p_event) -{ - QDialog::showEvent(p_event); +void SelectDialog::showEvent(QShowEvent *p_event) { + QDialog::showEvent(p_event); - updateSize(); + updateSize(); } -void SelectDialog::keyPressEvent(QKeyEvent *p_event) -{ - if (WidgetUtils::processKeyEventLikeVi(m_list, p_event, this)) { - return; - } +void SelectDialog::keyPressEvent(QKeyEvent *p_event) { + if (WidgetUtils::processKeyEventLikeVi(m_list, p_event, this)) { + return; + } - QDialog::keyPressEvent(p_event); + QDialog::keyPressEvent(p_event); } -bool SelectDialog::eventFilter(QObject *p_watched, QEvent *p_event) -{ - if (p_watched == m_list && p_event->type() == QEvent::KeyPress) { - auto keyEve = static_cast(p_event); - // Handle shortcuts. - if (keyEve->modifiers() == Qt::NoModifier) { - auto keych = Utils::keyToChar(keyEve->key(), true); - if (keych.isLetter()) { - auto it = m_shortcuts.find(keych); - if (it != m_shortcuts.end()) { - selectionChosen(it.value()); - } - - return true; - } +bool SelectDialog::eventFilter(QObject *p_watched, QEvent *p_event) { + if (p_watched == m_list && p_event->type() == QEvent::KeyPress) { + auto keyEve = static_cast(p_event); + // Handle shortcuts. + if (keyEve->modifiers() == Qt::NoModifier) { + auto keych = Utils::keyToChar(keyEve->key(), true); + if (keych.isLetter()) { + auto it = m_shortcuts.find(keych); + if (it != m_shortcuts.end()) { + selectionChosen(it.value()); } + + return true; + } } + } - return QDialog::eventFilter(p_watched, p_event); + return QDialog::eventFilter(p_watched, p_event); } diff --git a/src/widgets/dialogs/selectdialog.h b/src/widgets/dialogs/selectdialog.h index 464c04c714..d5286dfa9b 100644 --- a/src/widgets/dialogs/selectdialog.h +++ b/src/widgets/dialogs/selectdialog.h @@ -12,56 +12,52 @@ class QShowEvent; class QKeyEvent; class QLabel; -namespace vnotex -{ - class SelectDialog : public QDialog - { - Q_OBJECT - public: - SelectDialog(const QString &p_title, QWidget *p_parent = nullptr); +namespace vnotex { +class SelectDialog : public QDialog { + Q_OBJECT +public: + SelectDialog(const QString &p_title, QWidget *p_parent = nullptr); - SelectDialog(const QString &p_title, - const QString &p_text, - QWidget *p_parent = nullptr); + SelectDialog(const QString &p_title, const QString &p_text, QWidget *p_parent = nullptr); - // @p_selectID should >= 0. - void addSelection(const QString &p_selectStr, int p_selectID); + // @p_selectID should >= 0. + void addSelection(const QString &p_selectStr, int p_selectID); - int getSelection() const; + int getSelection() const; - bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE; - protected: - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; +protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void selectionChosen(QListWidgetItem *p_item); +private slots: + void selectionChosen(QListWidgetItem *p_item); - private: - enum { CANCEL_ID = -1 }; +private: + enum { CANCEL_ID = -1 }; - void setupUI(const QString &p_title, const QString &p_text = QString()); + void setupUI(const QString &p_title, const QString &p_text = QString()); - void updateSize(); + void updateSize(); - int m_choice = CANCEL_ID; + int m_choice = CANCEL_ID; - QLabel *m_label = nullptr; + QLabel *m_label = nullptr; - QListWidget *m_list = nullptr; + QListWidget *m_list = nullptr; - QMap m_shortcuts; + QMap m_shortcuts; - QString m_shortcutIconForeground; + QString m_shortcutIconForeground; - QString m_shortcutIconBorder; + QString m_shortcutIconBorder; - QChar m_nextShortcut = QLatin1Char('a'); + QChar m_nextShortcut = QLatin1Char('a'); - static const QChar c_cancelShortcut; - }; -} // ns vnotex + static const QChar c_cancelShortcut; +}; +} // namespace vnotex #endif // SELECTDIALOG_H diff --git a/src/widgets/dialogs/selectionitemwidget.cpp b/src/widgets/dialogs/selectionitemwidget.cpp index f783dfc076..0706f45e28 100644 --- a/src/widgets/dialogs/selectionitemwidget.cpp +++ b/src/widgets/dialogs/selectionitemwidget.cpp @@ -1,89 +1,66 @@ #include "selectionitemwidget.h" #include -#include #include +#include #include #include "global.h" using namespace vnotex; -SelectionItemWidget::SelectionItemWidget(const QIcon &p_icon, - const QString &p_text, +SelectionItemWidget::SelectionItemWidget(const QIcon &p_icon, const QString &p_text, QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(p_text); + : QWidget(p_parent) { + setupUI(p_text); - setIcon(p_icon); + setIcon(p_icon); } -SelectionItemWidget::SelectionItemWidget(const QString &p_text, - QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(p_text); +SelectionItemWidget::SelectionItemWidget(const QString &p_text, QWidget *p_parent) + : QWidget(p_parent) { + setupUI(p_text); } -void SelectionItemWidget::setupUI(const QString &p_text) -{ - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->setContentsMargins(CONTENTS_MARGIN, 0, 0, 0); +void SelectionItemWidget::setupUI(const QString &p_text) { + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(CONTENTS_MARGIN, 0, 0, 0); - m_checkBox = new QCheckBox(this); - mainLayout->addWidget(m_checkBox); - connect(m_checkBox, &QCheckBox::stateChanged, - this, &SelectionItemWidget::checkStateChanged); + m_checkBox = new QCheckBox(this); + mainLayout->addWidget(m_checkBox); + connect(m_checkBox, &QCheckBox::stateChanged, this, &SelectionItemWidget::checkStateChanged); - m_iconLabel = new QLabel(this); - m_iconLabel->setVisible(false); - mainLayout->addWidget(m_iconLabel); + m_iconLabel = new QLabel(this); + m_iconLabel->setVisible(false); + mainLayout->addWidget(m_iconLabel); - m_textLabel = new QLabel(p_text, this); - mainLayout->addWidget(m_textLabel); + m_textLabel = new QLabel(p_text, this); + mainLayout->addWidget(m_textLabel); - mainLayout->addStretch(); + mainLayout->addStretch(); } -bool SelectionItemWidget::isChecked() const -{ - return m_checkBox->isChecked(); -} +bool SelectionItemWidget::isChecked() const { return m_checkBox->isChecked(); } -const QVariant &SelectionItemWidget::getData() const -{ - return m_data; -} +const QVariant &SelectionItemWidget::getData() const { return m_data; } -void SelectionItemWidget::setChecked(bool p_checked) -{ - m_checkBox->setChecked(p_checked); -} +void SelectionItemWidget::setChecked(bool p_checked) { m_checkBox->setChecked(p_checked); } -void SelectionItemWidget::setToolTip(const QString &p_tip) -{ - m_textLabel->setToolTip(p_tip); -} +void SelectionItemWidget::setToolTip(const QString &p_tip) { m_textLabel->setToolTip(p_tip); } -void SelectionItemWidget::setData(const QVariant &p_data) -{ - m_data = p_data; -} +void SelectionItemWidget::setData(const QVariant &p_data) { m_data = p_data; } -void SelectionItemWidget::setIcon(const QIcon &p_icon) -{ - if (!p_icon.isNull()) { - int iconHeight = qMax(m_textLabel->minimumSizeHint().height(), 16); - auto pixmap = p_icon.pixmap(QSize(iconHeight, iconHeight)); - m_iconLabel->setPixmap(pixmap); - } +void SelectionItemWidget::setIcon(const QIcon &p_icon) { + if (!p_icon.isNull()) { + int iconHeight = qMax(m_textLabel->minimumSizeHint().height(), 16); + auto pixmap = p_icon.pixmap(QSize(iconHeight, iconHeight)); + m_iconLabel->setPixmap(pixmap); + } - m_iconLabel->setVisible(!p_icon.isNull()); + m_iconLabel->setVisible(!p_icon.isNull()); } -void SelectionItemWidget::mouseDoubleClickEvent(QMouseEvent *p_event) -{ - p_event->accept(); - setChecked(!isChecked()); +void SelectionItemWidget::mouseDoubleClickEvent(QMouseEvent *p_event) { + p_event->accept(); + setChecked(!isChecked()); } diff --git a/src/widgets/dialogs/selectionitemwidget.h b/src/widgets/dialogs/selectionitemwidget.h index 09d3340f10..fc0649c5f6 100644 --- a/src/widgets/dialogs/selectionitemwidget.h +++ b/src/widgets/dialogs/selectionitemwidget.h @@ -1,54 +1,49 @@ #ifndef SELECTIONITEMWIDGET_H #define SELECTIONITEMWIDGET_H -#include #include +#include class QCheckBox; class QLabel; -namespace vnotex -{ - // Tree/List item widget with checkbox. - class SelectionItemWidget : public QWidget - { - Q_OBJECT - public: - SelectionItemWidget(const QIcon &p_icon, - const QString &p_text, - QWidget *p_parent = nullptr); +namespace vnotex { +// Tree/List item widget with checkbox. +class SelectionItemWidget : public QWidget { + Q_OBJECT +public: + SelectionItemWidget(const QIcon &p_icon, const QString &p_text, QWidget *p_parent = nullptr); - SelectionItemWidget(const QString &p_text, - QWidget *p_parent = nullptr); + SelectionItemWidget(const QString &p_text, QWidget *p_parent = nullptr); - bool isChecked() const; - void setChecked(bool p_checked); + bool isChecked() const; + void setChecked(bool p_checked); - const QVariant &getData() const; - void setData(const QVariant &p_data); + const QVariant &getData() const; + void setData(const QVariant &p_data); - void setToolTip(const QString &p_tip); + void setToolTip(const QString &p_tip); - void setIcon(const QIcon &p_icon); + void setIcon(const QIcon &p_icon); - signals: - // Emit when item's check state changed. - void checkStateChanged(int p_state); +signals: + // Emit when item's check state changed. + void checkStateChanged(int p_state); - protected: - void mouseDoubleClickEvent(QMouseEvent *p_event); +protected: + void mouseDoubleClickEvent(QMouseEvent *p_event); - private: - void setupUI(const QString &p_text); +private: + void setupUI(const QString &p_text); - QCheckBox *m_checkBox = nullptr; + QCheckBox *m_checkBox = nullptr; - QLabel *m_iconLabel = nullptr; + QLabel *m_iconLabel = nullptr; - QLabel *m_textLabel = nullptr; + QLabel *m_textLabel = nullptr; - QVariant m_data; - }; -} + QVariant m_data; +}; +} // namespace vnotex #endif // SELECTIONITEMWIDGET_H diff --git a/src/widgets/dialogs/settings/appearancepage.cpp b/src/widgets/dialogs/settings/appearancepage.cpp index 60f8219840..88d21a3c05 100644 --- a/src/widgets/dialogs/settings/appearancepage.cpp +++ b/src/widgets/dialogs/settings/appearancepage.cpp @@ -1,126 +1,117 @@ #include "appearancepage.h" #include +#include #include #include #include -#include -#include -#include -#include +#include #include +#include +#include #include -#include #include +#include #include -#include +#include using namespace vnotex; -AppearancePage::AppearancePage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} - -void AppearancePage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - { - const QString label(tr("System title bar")); - m_systemTitleBarCheckBox = WidgetsFactory::createCheckBox(label, this); - m_systemTitleBarCheckBox->setToolTip(tr("Use system title bar")); - mainLayout->addRow(m_systemTitleBarCheckBox); - addSearchItem(label, m_systemTitleBarCheckBox->toolTip(), m_systemTitleBarCheckBox); - connect(m_systemTitleBarCheckBox, &QCheckBox::stateChanged, - this, &AppearancePage::pageIsChangedWithRestartNeeded); - } - - { - m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this); - m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the main window tool bar")); - - m_toolBarIconSizeSpinBox->setRange(1, 48); - m_toolBarIconSizeSpinBox->setSingleStep(1); - - const QString label(tr("Main tool bar icon size:")); - mainLayout->addRow(label, m_toolBarIconSizeSpinBox); - addSearchItem(label, m_toolBarIconSizeSpinBox->toolTip(), m_toolBarIconSizeSpinBox); - connect(m_toolBarIconSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), - this, &AppearancePage::pageIsChangedWithRestartNeeded); +AppearancePage::AppearancePage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void AppearancePage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + { + const QString label(tr("System title bar")); + m_systemTitleBarCheckBox = WidgetsFactory::createCheckBox(label, this); + m_systemTitleBarCheckBox->setToolTip(tr("Use system title bar")); + mainLayout->addRow(m_systemTitleBarCheckBox); + addSearchItem(label, m_systemTitleBarCheckBox->toolTip(), m_systemTitleBarCheckBox); + connect(m_systemTitleBarCheckBox, &QCheckBox::stateChanged, this, + &AppearancePage::pageIsChangedWithRestartNeeded); + } + + { + m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this); + m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the main window tool bar")); + + m_toolBarIconSizeSpinBox->setRange(1, 48); + m_toolBarIconSizeSpinBox->setSingleStep(1); + + const QString label(tr("Main tool bar icon size:")); + mainLayout->addRow(label, m_toolBarIconSizeSpinBox); + addSearchItem(label, m_toolBarIconSizeSpinBox->toolTip(), m_toolBarIconSizeSpinBox); + connect(m_toolBarIconSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + &AppearancePage::pageIsChangedWithRestartNeeded); + } + + { + const auto &docks = VNoteX::getInst().getMainWindow()->getDocks(); + Q_ASSERT(!docks.isEmpty()); + m_keepDocksExpandingContentArea.resize(docks.size()); + + auto layout = new QVBoxLayout(); + + for (int i = 0; i < docks.size(); ++i) { + m_keepDocksExpandingContentArea[i].first = WidgetsFactory::createCheckBox( + docks[i]->property(PropertyDefs::c_dockWidgetTitle).toString(), this); + m_keepDocksExpandingContentArea[i].second = docks[i]->objectName(); + layout->addWidget(m_keepDocksExpandingContentArea[i].first); + connect(m_keepDocksExpandingContentArea[i].first, &QCheckBox::stateChanged, this, + &AppearancePage::pageIsChanged); } - { - const auto &docks = VNoteX::getInst().getMainWindow()->getDocks(); - Q_ASSERT(!docks.isEmpty()); - m_keepDocksExpandingContentArea.resize(docks.size()); - - auto layout = new QVBoxLayout(); - - for (int i = 0; i < docks.size(); ++i) { - m_keepDocksExpandingContentArea[i].first = WidgetsFactory::createCheckBox(docks[i]->property(PropertyDefs::c_dockWidgetTitle).toString(), this); - m_keepDocksExpandingContentArea[i].second = docks[i]->objectName(); - layout->addWidget(m_keepDocksExpandingContentArea[i].first); - connect(m_keepDocksExpandingContentArea[i].first, &QCheckBox::stateChanged, - this, &AppearancePage::pageIsChanged); - } - - const QString label(tr("Dock widgets kept when expanding content area:")); - mainLayout->addRow(label, layout); - addSearchItem(label, label, m_keepDocksExpandingContentArea.first().first); - } + const QString label(tr("Dock widgets kept when expanding content area:")); + mainLayout->addRow(label, layout); + addSearchItem(label, label, m_keepDocksExpandingContentArea.first().first); + } } -void AppearancePage::loadInternal() -{ - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - const auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig(); +void AppearancePage::loadInternal() { + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + const auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig(); - if (m_systemTitleBarCheckBox) { - m_systemTitleBarCheckBox->setChecked(sessionConfig.getSystemTitleBarEnabled()); - } + if (m_systemTitleBarCheckBox) { + m_systemTitleBarCheckBox->setChecked(sessionConfig.getSystemTitleBarEnabled()); + } - m_toolBarIconSizeSpinBox->setValue(coreConfig.getToolBarIconSize()); + m_toolBarIconSizeSpinBox->setValue(coreConfig.getToolBarIconSize()); - { - const auto &docks = widgetConfig.getMainWindowKeepDocksExpandingContentArea(); - for (const auto &cb : m_keepDocksExpandingContentArea) { - if (docks.contains(cb.second)) { - cb.first->setChecked(true); - } - } + { + const auto &docks = widgetConfig.getMainWindowKeepDocksExpandingContentArea(); + for (const auto &cb : m_keepDocksExpandingContentArea) { + if (docks.contains(cb.second)) { + cb.first->setChecked(true); + } } + } } -bool AppearancePage::saveInternal() -{ - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig(); +bool AppearancePage::saveInternal() { + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig(); - if (m_systemTitleBarCheckBox) { - sessionConfig.setSystemTitleBarEnabled(m_systemTitleBarCheckBox->isChecked()); - } + if (m_systemTitleBarCheckBox) { + sessionConfig.setSystemTitleBarEnabled(m_systemTitleBarCheckBox->isChecked()); + } - coreConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value()); + coreConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value()); - { - QStringList docks; - for (const auto &cb : m_keepDocksExpandingContentArea) { - if (cb.first->isChecked()) { - docks << cb.second; - } - } - widgetConfig.setMainWindowKeepDocksExpandingContentArea(docks); + { + QStringList docks; + for (const auto &cb : m_keepDocksExpandingContentArea) { + if (cb.first->isChecked()) { + docks << cb.second; + } } + widgetConfig.setMainWindowKeepDocksExpandingContentArea(docks); + } - return true; + return true; } -QString AppearancePage::title() const -{ - return tr("Appearance"); -} +QString AppearancePage::title() const { return tr("Appearance"); } diff --git a/src/widgets/dialogs/settings/appearancepage.h b/src/widgets/dialogs/settings/appearancepage.h index 2c04c9232d..740e5c6322 100644 --- a/src/widgets/dialogs/settings/appearancepage.h +++ b/src/widgets/dialogs/settings/appearancepage.h @@ -3,37 +3,35 @@ #include "settingspage.h" -#include #include +#include class QCheckBox; class QSpinBox; -namespace vnotex -{ - class AppearancePage : public SettingsPage - { - Q_OBJECT - public: - explicit AppearancePage(QWidget *p_parent = nullptr); +namespace vnotex { +class AppearancePage : public SettingsPage { + Q_OBJECT +public: + explicit AppearancePage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QCheckBox *m_systemTitleBarCheckBox = nullptr; + QCheckBox *m_systemTitleBarCheckBox = nullptr; - QSpinBox *m_toolBarIconSizeSpinBox = nullptr; + QSpinBox *m_toolBarIconSizeSpinBox = nullptr; - // . - QVector> m_keepDocksExpandingContentArea; - }; -} + // . + QVector> m_keepDocksExpandingContentArea; +}; +} // namespace vnotex #endif // APPEARANCEPAGE_H diff --git a/src/widgets/dialogs/settings/editorpage.cpp b/src/widgets/dialogs/settings/editorpage.cpp index 5404fcfa8d..1a51e43563 100644 --- a/src/widgets/dialogs/settings/editorpage.cpp +++ b/src/widgets/dialogs/settings/editorpage.cpp @@ -2,181 +2,169 @@ #include #include -#include -#include #include #include +#include +#include #include -#include -#include #include +#include #include #include #include +#include using namespace vnotex; -EditorPage::EditorPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} - -void EditorPage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); +EditorPage::EditorPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void EditorPage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + { + m_autoSavePolicyComboBox = WidgetsFactory::createComboBox(this); + m_autoSavePolicyComboBox->setToolTip(tr("Auto save policy")); + + m_autoSavePolicyComboBox->addItem(tr("None"), (int)EditorConfig::AutoSavePolicy::None); + m_autoSavePolicyComboBox->addItem(tr("Auto Save"), (int)EditorConfig::AutoSavePolicy::AutoSave); + m_autoSavePolicyComboBox->addItem(tr("Backup File"), + (int)EditorConfig::AutoSavePolicy::BackupFile); + + const QString label(tr("Auto save policy:")); + mainLayout->addRow(label, m_autoSavePolicyComboBox); + addSearchItem(label, m_autoSavePolicyComboBox->toolTip(), m_autoSavePolicyComboBox); + connect(m_autoSavePolicyComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &EditorPage::pageIsChanged); + } + + { + m_lineEndingComboBox = WidgetsFactory::createComboBox(this); + m_lineEndingComboBox->setToolTip(tr("Line ending")); + + m_lineEndingComboBox->addItem(tr("Follow Platform"), (int)LineEndingPolicy::Platform); + m_lineEndingComboBox->addItem(tr("Follow File"), (int)LineEndingPolicy::File); + m_lineEndingComboBox->addItem(tr("LF (Linux/macOS)"), (int)LineEndingPolicy::LF); + m_lineEndingComboBox->addItem(tr("CR LF (Windows)"), (int)LineEndingPolicy::CRLF); + m_lineEndingComboBox->addItem(tr("CR"), (int)LineEndingPolicy::CR); + + const QString label(tr("Line ending:")); + mainLayout->addRow(label, m_lineEndingComboBox); + addSearchItem(label, m_lineEndingComboBox->toolTip(), m_lineEndingComboBox); + connect(m_lineEndingComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &EditorPage::pageIsChanged); + } + + { + m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this); + m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the editor tool bar")); + + m_toolBarIconSizeSpinBox->setRange(1, 48); + m_toolBarIconSizeSpinBox->setSingleStep(1); + + const QString label(tr("Tool bar icon size:")); + mainLayout->addRow(label, m_toolBarIconSizeSpinBox); + addSearchItem(label, m_toolBarIconSizeSpinBox->toolTip(), m_toolBarIconSizeSpinBox); + connect(m_toolBarIconSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + &EditorPage::pageIsChanged); + } + + { + auto lineLayout = new QHBoxLayout(); + + m_spellCheckDictComboBox = WidgetsFactory::createComboBox(this); + m_spellCheckDictComboBox->setToolTip(tr("Default dictionary used for spell check")); + lineLayout->addWidget(m_spellCheckDictComboBox); { - m_autoSavePolicyComboBox = WidgetsFactory::createComboBox(this); - m_autoSavePolicyComboBox->setToolTip(tr("Auto save policy")); - - m_autoSavePolicyComboBox->addItem(tr("None"), (int)EditorConfig::AutoSavePolicy::None); - m_autoSavePolicyComboBox->addItem(tr("Auto Save"), (int)EditorConfig::AutoSavePolicy::AutoSave); - m_autoSavePolicyComboBox->addItem(tr("Backup File"), (int)EditorConfig::AutoSavePolicy::BackupFile); - - const QString label(tr("Auto save policy:")); - mainLayout->addRow(label, m_autoSavePolicyComboBox); - addSearchItem(label, m_autoSavePolicyComboBox->toolTip(), m_autoSavePolicyComboBox); - connect(m_autoSavePolicyComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &EditorPage::pageIsChanged); + auto dicts = vte::SpellChecker::getInst().availableDictionaries(); + for (auto it = dicts.constBegin(); it != dicts.constEnd(); ++it) { + m_spellCheckDictComboBox->addItem(it.key(), it.value()); + } } - { - m_lineEndingComboBox = WidgetsFactory::createComboBox(this); - m_lineEndingComboBox->setToolTip(tr("Line ending")); - - m_lineEndingComboBox->addItem(tr("Follow Platform"), (int)LineEndingPolicy::Platform); - m_lineEndingComboBox->addItem(tr("Follow File"), (int)LineEndingPolicy::File); - m_lineEndingComboBox->addItem(tr("LF (Linux/macOS)"), (int)LineEndingPolicy::LF); - m_lineEndingComboBox->addItem(tr("CR LF (Windows)"), (int)LineEndingPolicy::CRLF); - m_lineEndingComboBox->addItem(tr("CR"), (int)LineEndingPolicy::CR); - - const QString label(tr("Line ending:")); - mainLayout->addRow(label, m_lineEndingComboBox); - addSearchItem(label, m_lineEndingComboBox->toolTip(), m_lineEndingComboBox); - connect(m_lineEndingComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &EditorPage::pageIsChanged); - } - - { - m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this); - m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the editor tool bar")); - - m_toolBarIconSizeSpinBox->setRange(1, 48); - m_toolBarIconSizeSpinBox->setSingleStep(1); - - const QString label(tr("Tool bar icon size:")); - mainLayout->addRow(label, m_toolBarIconSizeSpinBox); - addSearchItem(label, m_toolBarIconSizeSpinBox->toolTip(), m_toolBarIconSizeSpinBox); - connect(m_toolBarIconSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), - this, &EditorPage::pageIsChanged); - - } - - { - auto lineLayout = new QHBoxLayout(); - - m_spellCheckDictComboBox = WidgetsFactory::createComboBox(this); - m_spellCheckDictComboBox->setToolTip(tr("Default dictionary used for spell check")); - lineLayout->addWidget(m_spellCheckDictComboBox); - - { - auto dicts = vte::SpellChecker::getInst().availableDictionaries(); - for (auto it = dicts.constBegin(); it != dicts.constEnd(); ++it) { - m_spellCheckDictComboBox->addItem(it.key(), it.value()); - } - } - - auto addBtn = new QPushButton(tr("Add Dictionary"), this); - connect(addBtn, &QPushButton::clicked, - this, [this]() { - const auto dictsFolder = ConfigMgr::getInst().getUserDictsFolder(); - MessageBoxHelper::notify( - MessageBoxHelper::Information, - tr("VNote uses [Hunspell](http://hunspell.github.io/) for spell check."), - tr("Please download Hunspell's dictionaries, put them under (%1) and restart VNote.").arg(dictsFolder), - QString(), - this); - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(dictsFolder)); - }); - lineLayout->addWidget(addBtn); - - lineLayout->addStretch(); - - const QString label(tr("Spell check dictionary:")); - mainLayout->addRow(label, lineLayout); - addSearchItem(label, m_spellCheckDictComboBox->toolTip(), m_spellCheckDictComboBox); - connect(m_spellCheckDictComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &EditorPage::pageIsChanged); - } + auto addBtn = new QPushButton(tr("Add Dictionary"), this); + connect(addBtn, &QPushButton::clicked, this, [this]() { + const auto dictsFolder = ConfigMgr::getInst().getUserDictsFolder(); + MessageBoxHelper::notify( + MessageBoxHelper::Information, + tr("VNote uses [Hunspell](http://hunspell.github.io/) for spell check."), + tr("Please download Hunspell's dictionaries, put them under (%1) and restart VNote.") + .arg(dictsFolder), + QString(), this); + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(dictsFolder)); + }); + lineLayout->addWidget(addBtn); + + lineLayout->addStretch(); + + const QString label(tr("Spell check dictionary:")); + mainLayout->addRow(label, lineLayout); + addSearchItem(label, m_spellCheckDictComboBox->toolTip(), m_spellCheckDictComboBox); + connect(m_spellCheckDictComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &EditorPage::pageIsChanged); + } } -void EditorPage::loadInternal() -{ - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); +void EditorPage::loadInternal() { + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - { - int idx = m_autoSavePolicyComboBox->findData(static_cast(editorConfig.getAutoSavePolicy())); - Q_ASSERT(idx != -1); - m_autoSavePolicyComboBox->setCurrentIndex(idx); - } + { + int idx = + m_autoSavePolicyComboBox->findData(static_cast(editorConfig.getAutoSavePolicy())); + Q_ASSERT(idx != -1); + m_autoSavePolicyComboBox->setCurrentIndex(idx); + } - { - int idx = m_lineEndingComboBox->findData(static_cast(editorConfig.getLineEndingPolicy())); - Q_ASSERT(idx != -1); - m_lineEndingComboBox->setCurrentIndex(idx); - } + { + int idx = m_lineEndingComboBox->findData(static_cast(editorConfig.getLineEndingPolicy())); + Q_ASSERT(idx != -1); + m_lineEndingComboBox->setCurrentIndex(idx); + } - m_toolBarIconSizeSpinBox->setValue(editorConfig.getToolBarIconSize()); + m_toolBarIconSizeSpinBox->setValue(editorConfig.getToolBarIconSize()); - { - int idx = m_spellCheckDictComboBox->findData(editorConfig.getSpellCheckDefaultDictionary()); - m_spellCheckDictComboBox->setCurrentIndex(idx == -1 ? 0 : idx); - } + { + int idx = m_spellCheckDictComboBox->findData(editorConfig.getSpellCheckDefaultDictionary()); + m_spellCheckDictComboBox->setCurrentIndex(idx == -1 ? 0 : idx); + } } -bool EditorPage::saveInternal() -{ - auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); +bool EditorPage::saveInternal() { + auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - { - auto policy = m_autoSavePolicyComboBox->currentData().toInt(); - editorConfig.setAutoSavePolicy(static_cast(policy)); - } + { + auto policy = m_autoSavePolicyComboBox->currentData().toInt(); + editorConfig.setAutoSavePolicy(static_cast(policy)); + } - { - auto ending = m_lineEndingComboBox->currentData().toInt(); - editorConfig.setLineEndingPolicy(static_cast(ending)); - } + { + auto ending = m_lineEndingComboBox->currentData().toInt(); + editorConfig.setLineEndingPolicy(static_cast(ending)); + } - editorConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value()); + editorConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value()); - { - editorConfig.setSpellCheckDefaultDictionary(m_spellCheckDictComboBox->currentData().toString()); - } + { + editorConfig.setSpellCheckDefaultDictionary(m_spellCheckDictComboBox->currentData().toString()); + } - notifyEditorConfigChange(); + notifyEditorConfigChange(); - return true; + return true; } -QString EditorPage::title() const -{ - return tr("Editor"); -} +QString EditorPage::title() const { return tr("Editor"); } -void EditorPage::notifyEditorConfigChange() -{ - static QTimer *timer = nullptr; - if (!timer) { - timer = new QTimer(); - timer->setSingleShot(true); - timer->setInterval(1000); - auto& configMgr = ConfigMgr::getInst(); - connect(timer, &QTimer::timeout, - &configMgr, &ConfigMgr::editorConfigChanged); - } +void EditorPage::notifyEditorConfigChange() { + static QTimer *timer = nullptr; + if (!timer) { + timer = new QTimer(); + timer->setSingleShot(true); + timer->setInterval(1000); + auto &configMgr = ConfigMgr::getInst(); + connect(timer, &QTimer::timeout, &configMgr, &ConfigMgr::editorConfigChanged); + } - timer->start(); + timer->start(); } diff --git a/src/widgets/dialogs/settings/editorpage.h b/src/widgets/dialogs/settings/editorpage.h index 4ff72cdc14..f49c917341 100644 --- a/src/widgets/dialogs/settings/editorpage.h +++ b/src/widgets/dialogs/settings/editorpage.h @@ -6,35 +6,33 @@ class QComboBox; class QSpinBox; -namespace vnotex -{ - class EditorPage : public SettingsPage - { - Q_OBJECT - public: - explicit EditorPage(QWidget *p_parent = nullptr); +namespace vnotex { +class EditorPage : public SettingsPage { + Q_OBJECT +public: + explicit EditorPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - // Should be called by all editors setting page when saved. - static void notifyEditorConfigChange(); + // Should be called by all editors setting page when saved. + static void notifyEditorConfigChange(); - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QComboBox *m_autoSavePolicyComboBox = nullptr; + QComboBox *m_autoSavePolicyComboBox = nullptr; - QSpinBox *m_toolBarIconSizeSpinBox = nullptr; + QSpinBox *m_toolBarIconSizeSpinBox = nullptr; - QComboBox *m_spellCheckDictComboBox = nullptr; + QComboBox *m_spellCheckDictComboBox = nullptr; - QComboBox *m_lineEndingComboBox = nullptr; - }; -} + QComboBox *m_lineEndingComboBox = nullptr; +}; +} // namespace vnotex #endif // EDITORPAGE_H diff --git a/src/widgets/dialogs/settings/fileassociationpage.cpp b/src/widgets/dialogs/settings/fileassociationpage.cpp index d59dbb481d..4e2bb01b4e 100644 --- a/src/widgets/dialogs/settings/fileassociationpage.cpp +++ b/src/widgets/dialogs/settings/fileassociationpage.cpp @@ -2,19 +2,19 @@ #include #include -#include #include +#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include using namespace vnotex; @@ -22,118 +22,105 @@ const char *FileAssociationPage::c_nameProperty = "name"; const QChar FileAssociationPage::c_suffixSeparator = QLatin1Char(';'); -FileAssociationPage::FileAssociationPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} +FileAssociationPage::FileAssociationPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } -void FileAssociationPage::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); +void FileAssociationPage::setupUI() { + auto mainLayout = new QVBoxLayout(this); - m_builtInFileTypesBox = new QGroupBox(tr("Built-In File Types"), this); - WidgetsFactory::createFormLayout(m_builtInFileTypesBox); - mainLayout->addWidget(m_builtInFileTypesBox); + m_builtInFileTypesBox = new QGroupBox(tr("Built-In File Types"), this); + WidgetsFactory::createFormLayout(m_builtInFileTypesBox); + mainLayout->addWidget(m_builtInFileTypesBox); - m_externalProgramsBox = new QGroupBox(tr("External Programs"), this); - WidgetsFactory::createFormLayout(m_externalProgramsBox); - mainLayout->addWidget(m_externalProgramsBox); + m_externalProgramsBox = new QGroupBox(tr("External Programs"), this); + WidgetsFactory::createFormLayout(m_externalProgramsBox); + mainLayout->addWidget(m_externalProgramsBox); - mainLayout->addStretch(); + mainLayout->addStretch(); } -void FileAssociationPage::loadInternal() -{ - loadBuiltInTypesGroup(m_builtInFileTypesBox); +void FileAssociationPage::loadInternal() { + loadBuiltInTypesGroup(m_builtInFileTypesBox); - loadExternalProgramsGroup(m_externalProgramsBox); + loadExternalProgramsGroup(m_externalProgramsBox); } -bool FileAssociationPage::saveInternal() -{ - auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - - QVector fileTypeSuffixes; - - auto lineEdits = m_builtInFileTypesBox->findChildren(QString()); - lineEdits << m_externalProgramsBox->findChildren(QString()); - fileTypeSuffixes.reserve(lineEdits.size()); - for (const auto lineEdit : lineEdits) { - auto name = lineEdit->property(c_nameProperty).toString(); - if (name.isEmpty()) { - continue; - } - auto suffixes = lineEdit->text().split(c_suffixSeparator, Qt::SkipEmptyParts); - fileTypeSuffixes.push_back(CoreConfig::FileTypeSuffix(name, Utils::toLower(suffixes))); +bool FileAssociationPage::saveInternal() { + auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + + QVector fileTypeSuffixes; + + auto lineEdits = m_builtInFileTypesBox->findChildren(QString()); + lineEdits << m_externalProgramsBox->findChildren(QString()); + fileTypeSuffixes.reserve(lineEdits.size()); + for (const auto lineEdit : lineEdits) { + auto name = lineEdit->property(c_nameProperty).toString(); + if (name.isEmpty()) { + continue; } + auto suffixes = lineEdit->text().split(c_suffixSeparator, Qt::SkipEmptyParts); + fileTypeSuffixes.push_back(CoreConfig::FileTypeSuffix(name, Utils::toLower(suffixes))); + } - coreConfig.setFileTypeSuffixes(fileTypeSuffixes); + coreConfig.setFileTypeSuffixes(fileTypeSuffixes); - FileTypeHelper::getInst().reload(); + FileTypeHelper::getInst().reload(); - BufferMgr::updateSuffixToFileType(coreConfig.getFileTypeSuffixes()); + BufferMgr::updateSuffixToFileType(coreConfig.getFileTypeSuffixes()); - return true; + return true; } -QString FileAssociationPage::title() const -{ - return tr("File Associations"); -} +QString FileAssociationPage::title() const { return tr("File Associations"); } -void FileAssociationPage::loadBuiltInTypesGroup(QGroupBox *p_box) -{ - auto layout = static_cast(p_box->layout()); - WidgetUtils::clearLayout(layout); +void FileAssociationPage::loadBuiltInTypesGroup(QGroupBox *p_box) { + auto layout = static_cast(p_box->layout()); + WidgetUtils::clearLayout(layout); - const auto &types = FileTypeHelper::getInst().getAllFileTypes(); + const auto &types = FileTypeHelper::getInst().getAllFileTypes(); - for (const auto &ft : types) { - if (ft.m_type == FileType::Others) { - continue; - } + for (const auto &ft : types) { + if (ft.m_type == FileType::Others) { + continue; + } - auto lineEdit = WidgetsFactory::createLineEdit(p_box); - layout->addRow(ft.m_displayName, lineEdit); - connect(lineEdit, &QLineEdit::textChanged, - this, &FileAssociationPage::pageIsChanged); + auto lineEdit = WidgetsFactory::createLineEdit(p_box); + layout->addRow(ft.m_displayName, lineEdit); + connect(lineEdit, &QLineEdit::textChanged, this, &FileAssociationPage::pageIsChanged); - lineEdit->setPlaceholderText(tr("Suffixes separated by ;")); - lineEdit->setToolTip(tr("List of suffixes for this file type")); - lineEdit->setProperty(c_nameProperty, ft.m_typeName); - lineEdit->setText(ft.m_suffixes.join(c_suffixSeparator)); - } + lineEdit->setPlaceholderText(tr("Suffixes separated by ;")); + lineEdit->setToolTip(tr("List of suffixes for this file type")); + lineEdit->setProperty(c_nameProperty, ft.m_typeName); + lineEdit->setText(ft.m_suffixes.join(c_suffixSeparator)); + } } -void FileAssociationPage::loadExternalProgramsGroup(QGroupBox *p_box) -{ - auto layout = static_cast(p_box->layout()); - WidgetUtils::clearLayout(layout); +void FileAssociationPage::loadExternalProgramsGroup(QGroupBox *p_box) { + auto layout = static_cast(p_box->layout()); + WidgetUtils::clearLayout(layout); - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - QStringList names; - for (const auto &pro : sessionConfig.getExternalPrograms()) { - names.push_back(pro.m_name); - } + QStringList names; + for (const auto &pro : sessionConfig.getExternalPrograms()) { + names.push_back(pro.m_name); + } - names << FileTypeHelper::s_systemDefaultProgram; + names << FileTypeHelper::s_systemDefaultProgram; - for (const auto &name : names) { - auto lineEdit = WidgetsFactory::createLineEdit(p_box); - layout->addRow(name, lineEdit); - connect(lineEdit, &QLineEdit::textChanged, - this, &FileAssociationPage::pageIsChanged); + for (const auto &name : names) { + auto lineEdit = WidgetsFactory::createLineEdit(p_box); + layout->addRow(name, lineEdit); + connect(lineEdit, &QLineEdit::textChanged, this, &FileAssociationPage::pageIsChanged); - lineEdit->setPlaceholderText(tr("Suffixes separated by ;")); - lineEdit->setToolTip(tr("List of suffixes to open with external program (or system default program)")); - lineEdit->setProperty(c_nameProperty, name); + lineEdit->setPlaceholderText(tr("Suffixes separated by ;")); + lineEdit->setToolTip( + tr("List of suffixes to open with external program (or system default program)")); + lineEdit->setProperty(c_nameProperty, name); - auto suffixes = coreConfig.findFileTypeSuffix(name); - if (suffixes) { - lineEdit->setText(suffixes->join(c_suffixSeparator)); - } + auto suffixes = coreConfig.findFileTypeSuffix(name); + if (suffixes) { + lineEdit->setText(suffixes->join(c_suffixSeparator)); } + } } diff --git a/src/widgets/dialogs/settings/fileassociationpage.h b/src/widgets/dialogs/settings/fileassociationpage.h index 87062f855a..85d46e6b5e 100644 --- a/src/widgets/dialogs/settings/fileassociationpage.h +++ b/src/widgets/dialogs/settings/fileassociationpage.h @@ -5,36 +5,34 @@ class QGroupBox; -namespace vnotex -{ - class FileAssociationPage : public SettingsPage - { - Q_OBJECT - public: - explicit FileAssociationPage(QWidget *p_parent = nullptr); +namespace vnotex { +class FileAssociationPage : public SettingsPage { + Q_OBJECT +public: + explicit FileAssociationPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void loadBuiltInTypesGroup(QGroupBox *p_box); + void loadBuiltInTypesGroup(QGroupBox *p_box); - void loadExternalProgramsGroup(QGroupBox *p_box); + void loadExternalProgramsGroup(QGroupBox *p_box); - QGroupBox *m_builtInFileTypesBox = nullptr; + QGroupBox *m_builtInFileTypesBox = nullptr; - QGroupBox *m_externalProgramsBox = nullptr; + QGroupBox *m_externalProgramsBox = nullptr; - static const char *c_nameProperty; + static const char *c_nameProperty; - static const QChar c_suffixSeparator; - }; -} + static const QChar c_suffixSeparator; +}; +} // namespace vnotex #endif // FILEASSOCIATIONPAGE_H diff --git a/src/widgets/dialogs/settings/generalpage.cpp b/src/widgets/dialogs/settings/generalpage.cpp index 5bef01be5c..d89fae06f3 100644 --- a/src/widgets/dialogs/settings/generalpage.cpp +++ b/src/widgets/dialogs/settings/generalpage.cpp @@ -1,151 +1,141 @@ #include "generalpage.h" +#include #include #include -#include -#include +#include #include #include -#include #include +#include using namespace vnotex; -GeneralPage::GeneralPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} +GeneralPage::GeneralPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void GeneralPage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + { + m_localeComboBox = WidgetsFactory::createComboBox(this); + m_localeComboBox->setToolTip(tr("Interface language")); -void GeneralPage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - { - m_localeComboBox = WidgetsFactory::createComboBox(this); - m_localeComboBox->setToolTip(tr("Interface language")); - - m_localeComboBox->addItem(tr("Default"), QString()); - for (const auto &loc : ConfigMgr::getInst().getCoreConfig().getAvailableLocales()) { - QLocale locale(loc); - m_localeComboBox->addItem(QStringLiteral("%1 (%2)").arg(locale.nativeLanguageName(), locale.nativeCountryName()), - loc); - } - - const QString label(tr("Language:")); - mainLayout->addRow(label, m_localeComboBox); - addSearchItem(label, m_localeComboBox->toolTip(), m_localeComboBox); - connect(m_localeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &GeneralPage::pageIsChangedWithRestartNeeded); + m_localeComboBox->addItem(tr("Default"), QString()); + for (const auto &loc : ConfigMgr::getInst().getCoreConfig().getAvailableLocales()) { + QLocale locale(loc); + m_localeComboBox->addItem( + QStringLiteral("%1 (%2)").arg(locale.nativeLanguageName(), locale.nativeCountryName()), + loc); } + const QString label(tr("Language:")); + mainLayout->addRow(label, m_localeComboBox); + addSearchItem(label, m_localeComboBox->toolTip(), m_localeComboBox); + connect(m_localeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &GeneralPage::pageIsChangedWithRestartNeeded); + } + #if defined(Q_OS_WIN) - { - m_openGLComboBox = WidgetsFactory::createComboBox(this); - m_openGLComboBox->setToolTip(tr("OpenGL implementation used to render application")); - - m_openGLComboBox->addItem(tr("None"), SessionConfig::OpenGL::None); - m_openGLComboBox->addItem(tr("Desktop"), SessionConfig::OpenGL::Desktop); - m_openGLComboBox->addItem(tr("OpenGL ES"), SessionConfig::OpenGL::Angle); - m_openGLComboBox->addItem(tr("Software"), SessionConfig::OpenGL::Software); - - const QString label(tr("OpenGL:")); - mainLayout->addRow(label, m_openGLComboBox); - addSearchItem(label, m_openGLComboBox->toolTip(), m_openGLComboBox); - connect(m_openGLComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &GeneralPage::pageIsChangedWithRestartNeeded); - } + { + m_openGLComboBox = WidgetsFactory::createComboBox(this); + m_openGLComboBox->setToolTip(tr("OpenGL implementation used to render application")); + + m_openGLComboBox->addItem(tr("None"), SessionConfig::OpenGL::None); + m_openGLComboBox->addItem(tr("Desktop"), SessionConfig::OpenGL::Desktop); + m_openGLComboBox->addItem(tr("OpenGL ES"), SessionConfig::OpenGL::Angle); + m_openGLComboBox->addItem(tr("Software"), SessionConfig::OpenGL::Software); + + const QString label(tr("OpenGL:")); + mainLayout->addRow(label, m_openGLComboBox); + addSearchItem(label, m_openGLComboBox->toolTip(), m_openGLComboBox); + connect(m_openGLComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &GeneralPage::pageIsChangedWithRestartNeeded); + } #endif #if !defined(Q_OS_MACOS) - { - const QString label(tr("Minimize to system tray")); - m_systemTrayCheckBox = WidgetsFactory::createCheckBox(label, this); - m_systemTrayCheckBox->setToolTip(tr("Minimize to system tray when closed")); - mainLayout->addRow(m_systemTrayCheckBox); - addSearchItem(label, m_systemTrayCheckBox->toolTip(), m_systemTrayCheckBox); - connect(m_systemTrayCheckBox, &QCheckBox::stateChanged, - this, &GeneralPage::pageIsChanged); - } + { + const QString label(tr("Minimize to system tray")); + m_systemTrayCheckBox = WidgetsFactory::createCheckBox(label, this); + m_systemTrayCheckBox->setToolTip(tr("Minimize to system tray when closed")); + mainLayout->addRow(m_systemTrayCheckBox); + addSearchItem(label, m_systemTrayCheckBox->toolTip(), m_systemTrayCheckBox); + connect(m_systemTrayCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::pageIsChanged); + } #endif - { - const QString label(tr("Recover last session on start")); - m_recoverLastSessionCheckBox = WidgetsFactory::createCheckBox(label, this); - m_recoverLastSessionCheckBox->setToolTip(tr("Recover last session (like buffers) on start of VNote")); - mainLayout->addRow(m_recoverLastSessionCheckBox); - addSearchItem(label, m_recoverLastSessionCheckBox->toolTip(), m_recoverLastSessionCheckBox); - connect(m_recoverLastSessionCheckBox, &QCheckBox::stateChanged, - this, &GeneralPage::pageIsChanged); - } - - { - const QString label(tr("Check for updates on start")); - m_checkForUpdatesCheckBox = WidgetsFactory::createCheckBox(label, this); - m_checkForUpdatesCheckBox->setToolTip(tr("Check for updates on start of VNote")); - mainLayout->addRow(m_checkForUpdatesCheckBox); - addSearchItem(label, m_checkForUpdatesCheckBox->toolTip(), m_checkForUpdatesCheckBox); - connect(m_checkForUpdatesCheckBox, &QCheckBox::stateChanged, - this, &GeneralPage::pageIsChanged); - } + { + const QString label(tr("Recover last session on start")); + m_recoverLastSessionCheckBox = WidgetsFactory::createCheckBox(label, this); + m_recoverLastSessionCheckBox->setToolTip( + tr("Recover last session (like buffers) on start of VNote")); + mainLayout->addRow(m_recoverLastSessionCheckBox); + addSearchItem(label, m_recoverLastSessionCheckBox->toolTip(), m_recoverLastSessionCheckBox); + connect(m_recoverLastSessionCheckBox, &QCheckBox::stateChanged, this, + &GeneralPage::pageIsChanged); + } + + { + const QString label(tr("Check for updates on start")); + m_checkForUpdatesCheckBox = WidgetsFactory::createCheckBox(label, this); + m_checkForUpdatesCheckBox->setToolTip(tr("Check for updates on start of VNote")); + mainLayout->addRow(m_checkForUpdatesCheckBox); + addSearchItem(label, m_checkForUpdatesCheckBox->toolTip(), m_checkForUpdatesCheckBox); + connect(m_checkForUpdatesCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::pageIsChanged); + } } -void GeneralPage::loadInternal() -{ - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); +void GeneralPage::loadInternal() { + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - { - int idx = m_localeComboBox->findData(coreConfig.getLocale()); - Q_ASSERT(idx != -1); - m_localeComboBox->setCurrentIndex(idx); - } + { + int idx = m_localeComboBox->findData(coreConfig.getLocale()); + Q_ASSERT(idx != -1); + m_localeComboBox->setCurrentIndex(idx); + } - if (m_openGLComboBox) { - int idx = m_openGLComboBox->findData(sessionConfig.getOpenGL()); - Q_ASSERT(idx != -1); - m_openGLComboBox->setCurrentIndex(idx); - } + if (m_openGLComboBox) { + int idx = m_openGLComboBox->findData(sessionConfig.getOpenGL()); + Q_ASSERT(idx != -1); + m_openGLComboBox->setCurrentIndex(idx); + } - if (m_systemTrayCheckBox) { - int toTray = sessionConfig.getMinimizeToSystemTray(); - m_systemTrayCheckBox->setChecked(toTray > 0); - } + if (m_systemTrayCheckBox) { + int toTray = sessionConfig.getMinimizeToSystemTray(); + m_systemTrayCheckBox->setChecked(toTray > 0); + } - m_recoverLastSessionCheckBox->setChecked(coreConfig.isRecoverLastSessionOnStartEnabled()); + m_recoverLastSessionCheckBox->setChecked(coreConfig.isRecoverLastSessionOnStartEnabled()); - m_checkForUpdatesCheckBox->setChecked(coreConfig.isCheckForUpdatesOnStartEnabled()); + m_checkForUpdatesCheckBox->setChecked(coreConfig.isCheckForUpdatesOnStartEnabled()); } -bool GeneralPage::saveInternal() -{ - auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); +bool GeneralPage::saveInternal() { + auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - { - auto locale = m_localeComboBox->currentData().toString(); - coreConfig.setLocale(locale); - } + { + auto locale = m_localeComboBox->currentData().toString(); + coreConfig.setLocale(locale); + } - if (m_openGLComboBox) { - int opt = m_openGLComboBox->currentData().toInt(); - sessionConfig.setOpenGL(static_cast(opt)); - } + if (m_openGLComboBox) { + int opt = m_openGLComboBox->currentData().toInt(); + sessionConfig.setOpenGL(static_cast(opt)); + } - if (m_systemTrayCheckBox) { - // This will override the -1 state. That is fine. - sessionConfig.setMinimizeToSystemTray(m_systemTrayCheckBox->isChecked()); - } + if (m_systemTrayCheckBox) { + // This will override the -1 state. That is fine. + sessionConfig.setMinimizeToSystemTray(m_systemTrayCheckBox->isChecked()); + } - coreConfig.setRecoverLastSessionOnStartEnabled(m_recoverLastSessionCheckBox->isChecked()); + coreConfig.setRecoverLastSessionOnStartEnabled(m_recoverLastSessionCheckBox->isChecked()); - coreConfig.setCheckForUpdatesOnStartEnabled(m_checkForUpdatesCheckBox->isChecked()); + coreConfig.setCheckForUpdatesOnStartEnabled(m_checkForUpdatesCheckBox->isChecked()); - return true; + return true; } -QString GeneralPage::title() const -{ - return tr("General"); -} +QString GeneralPage::title() const { return tr("General"); } diff --git a/src/widgets/dialogs/settings/generalpage.h b/src/widgets/dialogs/settings/generalpage.h index c48fc3cc8e..9411a752e8 100644 --- a/src/widgets/dialogs/settings/generalpage.h +++ b/src/widgets/dialogs/settings/generalpage.h @@ -6,34 +6,32 @@ class QComboBox; class QCheckBox; -namespace vnotex -{ - class GeneralPage : public SettingsPage - { - Q_OBJECT - public: - explicit GeneralPage(QWidget *p_parent = nullptr); +namespace vnotex { +class GeneralPage : public SettingsPage { + Q_OBJECT +public: + explicit GeneralPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QComboBox *m_localeComboBox = nullptr; + QComboBox *m_localeComboBox = nullptr; - QComboBox *m_openGLComboBox = nullptr; + QComboBox *m_openGLComboBox = nullptr; - QCheckBox *m_systemTrayCheckBox = nullptr; + QCheckBox *m_systemTrayCheckBox = nullptr; - QCheckBox *m_recoverLastSessionCheckBox = nullptr; + QCheckBox *m_recoverLastSessionCheckBox = nullptr; - QCheckBox *m_checkForUpdatesCheckBox = nullptr; - }; -} + QCheckBox *m_checkForUpdatesCheckBox = nullptr; +}; +} // namespace vnotex #endif // GENERALPAGE_H diff --git a/src/widgets/dialogs/settings/imagehostpage.cpp b/src/widgets/dialogs/settings/imagehostpage.cpp index 0844649f9e..000c546de4 100644 --- a/src/widgets/dialogs/settings/imagehostpage.cpp +++ b/src/widgets/dialogs/settings/imagehostpage.cpp @@ -1,313 +1,289 @@ #include "imagehostpage.h" +#include +#include #include -#include -#include #include +#include +#include #include #include -#include -#include -#include +#include -#include -#include #include -#include +#include #include +#include #include +#include #include "editorpage.h" #include "newimagehostdialog.h" using namespace vnotex; -ImageHostPage::ImageHostPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} - -void ImageHostPage::setupUI() -{ - m_mainLayout = new QVBoxLayout(this); +ImageHostPage::ImageHostPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } - // New Image Host. - { - auto layout = new QHBoxLayout(); - m_mainLayout->addLayout(layout); - - auto newBtn = new QPushButton(tr("New Image Host"), this); - connect(newBtn, &QPushButton::clicked, - this, &ImageHostPage::newImageHost); - layout->addWidget(newBtn); - layout->addStretch(); - } +void ImageHostPage::setupUI() { + m_mainLayout = new QVBoxLayout(this); - auto box = setupGeneralBox(this); - m_mainLayout->addWidget(box); + // New Image Host. + { + auto layout = new QHBoxLayout(); + m_mainLayout->addLayout(layout); - m_mainLayout->addStretch(); -} + auto newBtn = new QPushButton(tr("New Image Host"), this); + connect(newBtn, &QPushButton::clicked, this, &ImageHostPage::newImageHost); + layout->addWidget(newBtn); + layout->addStretch(); + } -QGroupBox *ImageHostPage::setupGeneralBox(QWidget *p_parent) -{ - auto box = new QGroupBox(tr("General"), p_parent); - auto layout = WidgetsFactory::createFormLayout(box); + auto box = setupGeneralBox(this); + m_mainLayout->addWidget(box); - { - // Add items in loadInternal(). - m_defaultImageHostComboBox = WidgetsFactory::createComboBox(box); - - const QString label(tr("Default image host:")); - layout->addRow(label, m_defaultImageHostComboBox); - addSearchItem(label, m_defaultImageHostComboBox); - connect(m_defaultImageHostComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &ImageHostPage::pageIsChanged); - } - - { - const QString label(tr("Clear obsolete images")); - m_clearObsoleteImageCheckBox = WidgetsFactory::createCheckBox(label, box); - m_clearObsoleteImageCheckBox->setToolTip(tr("Clear unused images at image host (based on current file only)")); - layout->addRow(m_clearObsoleteImageCheckBox); - addSearchItem(label, m_clearObsoleteImageCheckBox->toolTip(), m_clearObsoleteImageCheckBox); - connect(m_clearObsoleteImageCheckBox, &QCheckBox::stateChanged, - this, &ImageHostPage::pageIsChanged); - } - - return box; + m_mainLayout->addStretch(); } -void ImageHostPage::addWidgetToLayout(QWidget *p_widget) -{ - m_mainLayout->addWidget(p_widget); +QGroupBox *ImageHostPage::setupGeneralBox(QWidget *p_parent) { + auto box = new QGroupBox(tr("General"), p_parent); + auto layout = WidgetsFactory::createFormLayout(box); + + { + // Add items in loadInternal(). + m_defaultImageHostComboBox = WidgetsFactory::createComboBox(box); + + const QString label(tr("Default image host:")); + layout->addRow(label, m_defaultImageHostComboBox); + addSearchItem(label, m_defaultImageHostComboBox); + connect(m_defaultImageHostComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ImageHostPage::pageIsChanged); + } + + { + const QString label(tr("Clear obsolete images")); + m_clearObsoleteImageCheckBox = WidgetsFactory::createCheckBox(label, box); + m_clearObsoleteImageCheckBox->setToolTip( + tr("Clear unused images at image host (based on current file only)")); + layout->addRow(m_clearObsoleteImageCheckBox); + addSearchItem(label, m_clearObsoleteImageCheckBox->toolTip(), m_clearObsoleteImageCheckBox); + connect(m_clearObsoleteImageCheckBox, &QCheckBox::stateChanged, this, + &ImageHostPage::pageIsChanged); + } + + return box; } -void ImageHostPage::loadInternal() -{ - const auto &hosts = ImageHostMgr::getInst().getImageHosts(); - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); +void ImageHostPage::addWidgetToLayout(QWidget *p_widget) { m_mainLayout->addWidget(p_widget); } - { - m_defaultImageHostComboBox->clear(); +void ImageHostPage::loadInternal() { + const auto &hosts = ImageHostMgr::getInst().getImageHosts(); + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - m_defaultImageHostComboBox->addItem(tr("Local")); - for (const auto &host : hosts) { - m_defaultImageHostComboBox->addItem(host->getName(), host->getName()); - } + { + m_defaultImageHostComboBox->clear(); - auto defaultHost = ImageHostMgr::getInst().getDefaultImageHost(); - if (defaultHost) { - int idx = m_defaultImageHostComboBox->findData(defaultHost->getName()); - Q_ASSERT(idx > 0); - m_defaultImageHostComboBox->setCurrentIndex(idx); - } else { - m_defaultImageHostComboBox->setCurrentIndex(0); - } + m_defaultImageHostComboBox->addItem(tr("Local")); + for (const auto &host : hosts) { + m_defaultImageHostComboBox->addItem(host->getName(), host->getName()); } - m_clearObsoleteImageCheckBox->setChecked(editorConfig.isClearObsoleteImageAtImageHostEnabled()); - - // Clear all the boxes before. - { - auto boxes = findChildren(QString(), Qt::FindDirectChildrenOnly); - for (auto box : boxes) { - if (box->objectName().isEmpty()) { - continue; - } - - m_mainLayout->removeWidget(box); - box->deleteLater(); - } + auto defaultHost = ImageHostMgr::getInst().getDefaultImageHost(); + if (defaultHost) { + int idx = m_defaultImageHostComboBox->findData(defaultHost->getName()); + Q_ASSERT(idx > 0); + m_defaultImageHostComboBox->setCurrentIndex(idx); + } else { + m_defaultImageHostComboBox->setCurrentIndex(0); } + } - removeLastStretch(); + m_clearObsoleteImageCheckBox->setChecked(editorConfig.isClearObsoleteImageAtImageHostEnabled()); - // Setup boxes. - for (const auto &host : hosts) { - auto box = setupGroupBoxForImageHost(host, this); - addWidgetToLayout(box); + // Clear all the boxes before. + { + auto boxes = findChildren(QString(), Qt::FindDirectChildrenOnly); + for (auto box : boxes) { + if (box->objectName().isEmpty()) { + continue; + } + + m_mainLayout->removeWidget(box); + box->deleteLater(); } + } - m_mainLayout->addStretch(); -} + removeLastStretch(); -bool ImageHostPage::saveInternal() -{ - auto &hostMgr = ImageHostMgr::getInst(); - auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + // Setup boxes. + for (const auto &host : hosts) { + auto box = setupGroupBoxForImageHost(host, this); + addWidgetToLayout(box); + } + + m_mainLayout->addStretch(); +} - Q_ASSERT(m_hostToFields.size() == hostMgr.getImageHosts().size()); +bool ImageHostPage::saveInternal() { + auto &hostMgr = ImageHostMgr::getInst(); + auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - bool hasError = false; + Q_ASSERT(m_hostToFields.size() == hostMgr.getImageHosts().size()); - hostMgr.setDefaultImageHost(m_defaultImageHostComboBox->currentData().toString()); + bool hasError = false; - editorConfig.setClearObsoleteImageAtImageHostEnabled(m_clearObsoleteImageCheckBox->isChecked()); + hostMgr.setDefaultImageHost(m_defaultImageHostComboBox->currentData().toString()); - for (auto it = m_hostToFields.constBegin(); it != m_hostToFields.constEnd(); ++it) { - auto host = it.key(); - const auto &fields = it.value(); - Q_ASSERT(!fields.isEmpty()); + editorConfig.setClearObsoleteImageAtImageHostEnabled(m_clearObsoleteImageCheckBox->isChecked()); - // Name. - { - auto box = dynamic_cast(fields[0]->parent()); - Q_ASSERT(box); - auto nameLineEdit = box->findChild(QStringLiteral("_name"), Qt::FindDirectChildrenOnly); - Q_ASSERT(nameLineEdit); - const auto &newName = nameLineEdit->text(); - if (newName != host->getName()) { - if (!hostMgr.renameImageHost(host, newName)) { - setError(tr("Failed to rename image host (%1) to (%2).").arg(host->getName(), newName)); - hasError = true; - break; - } + for (auto it = m_hostToFields.constBegin(); it != m_hostToFields.constEnd(); ++it) { + auto host = it.key(); + const auto &fields = it.value(); + Q_ASSERT(!fields.isEmpty()); - box->setObjectName(newName); - } + // Name. + { + auto box = dynamic_cast(fields[0]->parent()); + Q_ASSERT(box); + auto nameLineEdit = + box->findChild(QStringLiteral("_name"), Qt::FindDirectChildrenOnly); + Q_ASSERT(nameLineEdit); + const auto &newName = nameLineEdit->text(); + if (newName != host->getName()) { + if (!hostMgr.renameImageHost(host, newName)) { + setError(tr("Failed to rename image host (%1) to (%2).").arg(host->getName(), newName)); + hasError = true; + break; } - // Configs. - const auto configObj = fieldsToConfig(fields); - host->setConfig(configObj); + box->setObjectName(newName); + } } - hostMgr.saveImageHosts(); - - // No need to notify editor since ImageHostMgr will signal out. - // EditorPage::notifyEditorConfigChange(); - return !hasError; -} - -QString ImageHostPage::title() const -{ - return tr("Image Host"); -} - -void ImageHostPage::newImageHost() -{ - NewImageHostDialog dialog(this); - if (dialog.exec()) { - removeLastStretch(); + // Configs. + const auto configObj = fieldsToConfig(fields); + host->setConfig(configObj); + } - auto box = setupGroupBoxForImageHost(dialog.getNewImageHost(), this); - addWidgetToLayout(box); + hostMgr.saveImageHosts(); - m_mainLayout->addStretch(); - } + // No need to notify editor since ImageHostMgr will signal out. + // EditorPage::notifyEditorConfigChange(); + return !hasError; } -QGroupBox *ImageHostPage::setupGroupBoxForImageHost(ImageHost *p_host, QWidget *p_parent) -{ - auto box = new QGroupBox(p_parent); - box->setObjectName(p_host->getName()); - auto layout = WidgetsFactory::createFormLayout(box); +QString ImageHostPage::title() const { return tr("Image Host"); } - // Add Test and Delete button. - { - auto btnLayout = new QHBoxLayout(); - btnLayout->addStretch(); - - layout->addRow(btnLayout); - - auto testBtn = new QPushButton(tr("Test"), box); - btnLayout->addWidget(testBtn); - connect(testBtn, &QPushButton::clicked, - this, [this, box]() { - const auto name = box->objectName(); - testImageHost(name); - }); - - auto deleteBtn = new QPushButton(tr("Delete"), box); - btnLayout->addWidget(deleteBtn); - connect(deleteBtn, &QPushButton::clicked, - this, [this, box]() { - const auto name = box->objectName(); - removeImageHost(name); - }); - } +void ImageHostPage::newImageHost() { + NewImageHostDialog dialog(this); + if (dialog.exec()) { + removeLastStretch(); - layout->addRow(tr("Type:"), new QLabel(ImageHost::typeString(p_host->getType()), box)); - - auto nameLineEdit = WidgetsFactory::createLineEdit(p_host->getName(), box); - nameLineEdit->setObjectName(QStringLiteral("_name")); - layout->addRow(tr("Name:"), nameLineEdit); - m_hostToFields[p_host].append(nameLineEdit); - connect(nameLineEdit, &QLineEdit::textChanged, - this, &ImageHostPage::pageIsChanged); - - const auto configObj = p_host->getConfig(); - const auto keys = configObj.keys(); - for (const auto &key : keys) { - Q_ASSERT(key != "_name"); - auto configLineEdit = WidgetsFactory::createLineEdit(configObj[key].toString(), box); - configLineEdit->setObjectName(key); - layout->addRow(tr("%1:").arg(key), configLineEdit); - m_hostToFields[p_host].append(configLineEdit); - connect(configLineEdit, &QLineEdit::textChanged, - this, &ImageHostPage::pageIsChanged); - } + auto box = setupGroupBoxForImageHost(dialog.getNewImageHost(), this); + addWidgetToLayout(box); - return box; + m_mainLayout->addStretch(); + } } -void ImageHostPage::removeImageHost(const QString &p_hostName) -{ - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Type::Question, - tr("Delete image host (%1)?").arg(p_hostName)); - if (ret != QMessageBox::Ok) { - return; - } +QGroupBox *ImageHostPage::setupGroupBoxForImageHost(ImageHost *p_host, QWidget *p_parent) { + auto box = new QGroupBox(p_parent); + box->setObjectName(p_host->getName()); + auto layout = WidgetsFactory::createFormLayout(box); + + // Add Test and Delete button. + { + auto btnLayout = new QHBoxLayout(); + btnLayout->addStretch(); + + layout->addRow(btnLayout); + + auto testBtn = new QPushButton(tr("Test"), box); + btnLayout->addWidget(testBtn); + connect(testBtn, &QPushButton::clicked, this, [this, box]() { + const auto name = box->objectName(); + testImageHost(name); + }); + + auto deleteBtn = new QPushButton(tr("Delete"), box); + btnLayout->addWidget(deleteBtn); + connect(deleteBtn, &QPushButton::clicked, this, [this, box]() { + const auto name = box->objectName(); + removeImageHost(name); + }); + } + + layout->addRow(tr("Type:"), new QLabel(ImageHost::typeString(p_host->getType()), box)); + + auto nameLineEdit = WidgetsFactory::createLineEdit(p_host->getName(), box); + nameLineEdit->setObjectName(QStringLiteral("_name")); + layout->addRow(tr("Name:"), nameLineEdit); + m_hostToFields[p_host].append(nameLineEdit); + connect(nameLineEdit, &QLineEdit::textChanged, this, &ImageHostPage::pageIsChanged); + + const auto configObj = p_host->getConfig(); + const auto keys = configObj.keys(); + for (const auto &key : keys) { + Q_ASSERT(key != "_name"); + auto configLineEdit = WidgetsFactory::createLineEdit(configObj[key].toString(), box); + configLineEdit->setObjectName(key); + layout->addRow(tr("%1:").arg(key), configLineEdit); + m_hostToFields[p_host].append(configLineEdit); + connect(configLineEdit, &QLineEdit::textChanged, this, &ImageHostPage::pageIsChanged); + } + + return box; +} - auto &hostMgr = ImageHostMgr::getInst(); - auto host = hostMgr.find(p_hostName); - Q_ASSERT(host); - hostMgr.removeImageHost(host); +void ImageHostPage::removeImageHost(const QString &p_hostName) { + int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Type::Question, + tr("Delete image host (%1)?").arg(p_hostName)); + if (ret != QMessageBox::Ok) { + return; + } + + auto &hostMgr = ImageHostMgr::getInst(); + auto host = hostMgr.find(p_hostName); + Q_ASSERT(host); + hostMgr.removeImageHost(host); + + // Remove the group box and related fields. + m_hostToFields.remove(host); + + auto box = findChild(p_hostName, Qt::FindDirectChildrenOnly); + Q_ASSERT(box); + m_mainLayout->removeWidget(box); + box->deleteLater(); +} - // Remove the group box and related fields. - m_hostToFields.remove(host); +QJsonObject ImageHostPage::fieldsToConfig(const QVector &p_fields) const { + QJsonObject configObj; + for (auto field : p_fields) { + configObj[field->objectName()] = field->text(); + } - auto box = findChild(p_hostName, Qt::FindDirectChildrenOnly); - Q_ASSERT(box); - m_mainLayout->removeWidget(box); - box->deleteLater(); + return configObj; } -QJsonObject ImageHostPage::fieldsToConfig(const QVector &p_fields) const -{ - QJsonObject configObj; - for (auto field : p_fields) { - configObj[field->objectName()] = field->text(); - } +void ImageHostPage::testImageHost(const QString &p_hostName) { + auto &hostMgr = ImageHostMgr::getInst(); + auto host = hostMgr.find(p_hostName); + Q_ASSERT(host); - return configObj; -} + auto it = m_hostToFields.find(host); + Q_ASSERT(it != m_hostToFields.end()); -void ImageHostPage::testImageHost(const QString &p_hostName) -{ - auto &hostMgr = ImageHostMgr::getInst(); - auto host = hostMgr.find(p_hostName); - Q_ASSERT(host); - - auto it = m_hostToFields.find(host); - Q_ASSERT(it != m_hostToFields.end()); - - const auto configObj = fieldsToConfig(it.value()); - QString msg; - bool ret = host->testConfig(configObj, msg); - MessageBoxHelper::notify(ret ? MessageBoxHelper::Information : MessageBoxHelper::Warning, - tr("Test %1.").arg(ret ? tr("succeeded") : tr("failed")), - QString(), - msg); + const auto configObj = fieldsToConfig(it.value()); + QString msg; + bool ret = host->testConfig(configObj, msg); + MessageBoxHelper::notify(ret ? MessageBoxHelper::Information : MessageBoxHelper::Warning, + tr("Test %1.").arg(ret ? tr("succeeded") : tr("failed")), QString(), + msg); } -void ImageHostPage::removeLastStretch() -{ - auto item = m_mainLayout->itemAt(m_mainLayout->count() - 1); - if (item) { - m_mainLayout->removeItem(item); - delete item; - } +void ImageHostPage::removeLastStretch() { + auto item = m_mainLayout->itemAt(m_mainLayout->count() - 1); + if (item) { + m_mainLayout->removeItem(item); + delete item; + } } diff --git a/src/widgets/dialogs/settings/imagehostpage.h b/src/widgets/dialogs/settings/imagehostpage.h index 9b23dc718b..4145a31a21 100644 --- a/src/widgets/dialogs/settings/imagehostpage.h +++ b/src/widgets/dialogs/settings/imagehostpage.h @@ -3,8 +3,8 @@ #include "settingspage.h" -#include #include +#include class QGroupBox; class QLineEdit; @@ -12,51 +12,49 @@ class QVBoxLayout; class QComboBox; class QCheckBox; -namespace vnotex -{ - class ImageHost; +namespace vnotex { +class ImageHost; - class ImageHostPage : public SettingsPage - { - Q_OBJECT - public: - explicit ImageHostPage(QWidget *p_parent = nullptr); +class ImageHostPage : public SettingsPage { + Q_OBJECT +public: + explicit ImageHostPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void newImageHost(); + void newImageHost(); - QGroupBox *setupGroupBoxForImageHost(ImageHost *p_host, QWidget *p_parent); + QGroupBox *setupGroupBoxForImageHost(ImageHost *p_host, QWidget *p_parent); - void removeImageHost(const QString &p_hostName); + void removeImageHost(const QString &p_hostName); - void addWidgetToLayout(QWidget *p_widget); + void addWidgetToLayout(QWidget *p_widget); - QJsonObject fieldsToConfig(const QVector &p_fields) const; + QJsonObject fieldsToConfig(const QVector &p_fields) const; - void testImageHost(const QString &p_hostName); + void testImageHost(const QString &p_hostName); - QGroupBox *setupGeneralBox(QWidget *p_parent); + QGroupBox *setupGeneralBox(QWidget *p_parent); - void removeLastStretch(); + void removeLastStretch(); - QVBoxLayout *m_mainLayout = nullptr; + QVBoxLayout *m_mainLayout = nullptr; - // [host] -> list of related fields. - QMap> m_hostToFields; + // [host] -> list of related fields. + QMap> m_hostToFields; - QComboBox *m_defaultImageHostComboBox = nullptr; + QComboBox *m_defaultImageHostComboBox = nullptr; - QCheckBox *m_clearObsoleteImageCheckBox = nullptr; - }; -} + QCheckBox *m_clearObsoleteImageCheckBox = nullptr; +}; +} // namespace vnotex #endif // IMAGEHOSTPAGE_H diff --git a/src/widgets/dialogs/settings/markdowneditorpage.cpp b/src/widgets/dialogs/settings/markdowneditorpage.cpp index 0c808b3f99..d886d4d47d 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.cpp +++ b/src/widgets/dialogs/settings/markdowneditorpage.cpp @@ -1,619 +1,620 @@ #include "markdowneditorpage.h" -#include -#include #include -#include -#include #include -#include -#include -#include +#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include -#include +#include #include #include -#include #include +#include #include "editorpage.h" -#include -#include -#include #include +#include #include +#include +#include using namespace vnotex; -MarkdownEditorPage::MarkdownEditorPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} +MarkdownEditorPage::MarkdownEditorPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } -void MarkdownEditorPage::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); +void MarkdownEditorPage::setupUI() { + auto mainLayout = new QVBoxLayout(this); - auto generalBox = setupGeneralGroup(); - mainLayout->addWidget(generalBox); + auto generalBox = setupGeneralGroup(); + mainLayout->addWidget(generalBox); - auto readBox = setupReadGroup(); - mainLayout->addWidget(readBox); + auto readBox = setupReadGroup(); + mainLayout->addWidget(readBox); - auto editBox = setupEditGroup(); - mainLayout->addWidget(editBox); + auto editBox = setupEditGroup(); + mainLayout->addWidget(editBox); - mainLayout->addStretch(); + mainLayout->addStretch(); } -void MarkdownEditorPage::loadInternal() -{ - const auto &markdownConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); +void MarkdownEditorPage::loadInternal() { + const auto &markdownConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - m_insertFileNameAsTitleCheckBox->setChecked(markdownConfig.getInsertFileNameAsTitle()); + m_insertFileNameAsTitleCheckBox->setChecked(markdownConfig.getInsertFileNameAsTitle()); - { - int idx = m_sectionNumberComboBox->findData(static_cast(markdownConfig.getSectionNumberMode())); - Q_ASSERT(idx != -1); - m_sectionNumberComboBox->setCurrentIndex(idx); + { + int idx = + m_sectionNumberComboBox->findData(static_cast(markdownConfig.getSectionNumberMode())); + Q_ASSERT(idx != -1); + m_sectionNumberComboBox->setCurrentIndex(idx); - m_sectionNumberBaseLevelSpinBox->setValue(markdownConfig.getSectionNumberBaseLevel()); + m_sectionNumberBaseLevelSpinBox->setValue(markdownConfig.getSectionNumberBaseLevel()); - idx = m_sectionNumberStyleComboBox->findData(static_cast(markdownConfig.getSectionNumberStyle())); - Q_ASSERT(idx != -1); - m_sectionNumberStyleComboBox->setCurrentIndex(idx); - } + idx = m_sectionNumberStyleComboBox->findData( + static_cast(markdownConfig.getSectionNumberStyle())); + Q_ASSERT(idx != -1); + m_sectionNumberStyleComboBox->setCurrentIndex(idx); + } - m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled()); + m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled()); - m_imageAlignCenterCheckBox->setChecked(markdownConfig.getImageAlignCenterEnabled()); + m_imageAlignCenterCheckBox->setChecked(markdownConfig.getImageAlignCenterEnabled()); - m_zoomFactorSpinBox->setValue(markdownConfig.getZoomFactorInReadMode()); + m_zoomFactorSpinBox->setValue(markdownConfig.getZoomFactorInReadMode()); - m_constrainInplacePreviewWidthCheckBox->setChecked(markdownConfig.getConstrainInplacePreviewWidthEnabled()); + m_constrainInplacePreviewWidthCheckBox->setChecked( + markdownConfig.getConstrainInplacePreviewWidthEnabled()); - { - auto srcs = markdownConfig.getInplacePreviewSources(); - m_inplacePreviewSourceImageLinkCheckBox->setChecked(srcs & MarkdownEditorConfig::InplacePreviewSource::ImageLink); - m_inplacePreviewSourceCodeBlockCheckBox->setChecked(srcs & MarkdownEditorConfig::InplacePreviewSource::CodeBlock); - m_inplacePreviewSourceMathCheckBox->setChecked(srcs & MarkdownEditorConfig::InplacePreviewSource::Math); - } + { + auto srcs = markdownConfig.getInplacePreviewSources(); + m_inplacePreviewSourceImageLinkCheckBox->setChecked( + srcs & MarkdownEditorConfig::InplacePreviewSource::ImageLink); + m_inplacePreviewSourceCodeBlockCheckBox->setChecked( + srcs & MarkdownEditorConfig::InplacePreviewSource::CodeBlock); + m_inplacePreviewSourceMathCheckBox->setChecked( + srcs & MarkdownEditorConfig::InplacePreviewSource::Math); + } - m_fetchImagesToLocalCheckBox->setChecked(markdownConfig.getFetchImagesInParseAndPaste()); + m_fetchImagesToLocalCheckBox->setChecked(markdownConfig.getFetchImagesInParseAndPaste()); - m_htmlTagCheckBox->setChecked(markdownConfig.getHtmlTagEnabled()); + m_htmlTagCheckBox->setChecked(markdownConfig.getHtmlTagEnabled()); - m_autoBreakCheckBox->setChecked(markdownConfig.getAutoBreakEnabled()); + m_autoBreakCheckBox->setChecked(markdownConfig.getAutoBreakEnabled()); - m_linkifyCheckBox->setChecked(markdownConfig.getLinkifyEnabled()); + m_linkifyCheckBox->setChecked(markdownConfig.getLinkifyEnabled()); - m_indentFirstLineCheckBox->setChecked(markdownConfig.getIndentFirstLineEnabled()); + m_indentFirstLineCheckBox->setChecked(markdownConfig.getIndentFirstLineEnabled()); - m_codeBlockLineNumberCheckBox->setChecked(markdownConfig.getCodeBlockLineNumberEnabled()); + m_codeBlockLineNumberCheckBox->setChecked(markdownConfig.getCodeBlockLineNumberEnabled()); - m_smartTableCheckBox->setChecked(markdownConfig.getSmartTableEnabled()); + m_smartTableCheckBox->setChecked(markdownConfig.getSmartTableEnabled()); - m_spellCheckCheckBox->setChecked(markdownConfig.isSpellCheckEnabled()); + m_spellCheckCheckBox->setChecked(markdownConfig.isSpellCheckEnabled()); - { - int idx = m_plantUmlModeComboBox->findData(markdownConfig.getWebPlantUml() ? 0 : 1); - m_plantUmlModeComboBox->setCurrentIndex(idx); - } + { + int idx = m_plantUmlModeComboBox->findData(markdownConfig.getWebPlantUml() ? 0 : 1); + m_plantUmlModeComboBox->setCurrentIndex(idx); + } - m_plantUmlJarFileInput->setText(markdownConfig.getPlantUmlJar()); + m_plantUmlJarFileInput->setText(markdownConfig.getPlantUmlJar()); - m_plantUmlWebServiceLineEdit->setText(markdownConfig.getPlantUmlWebService()); + m_plantUmlWebServiceLineEdit->setText(markdownConfig.getPlantUmlWebService()); - { - int idx = m_graphvizModeComboBox->findData(markdownConfig.getWebGraphviz() ? 0 : 1); - m_graphvizModeComboBox->setCurrentIndex(idx); - } + { + int idx = m_graphvizModeComboBox->findData(markdownConfig.getWebGraphviz() ? 0 : 1); + m_graphvizModeComboBox->setCurrentIndex(idx); + } - m_graphvizFileInput->setText(markdownConfig.getGraphvizExe()); + m_graphvizFileInput->setText(markdownConfig.getGraphvizExe()); - m_mathJaxScriptLineEdit->setText(markdownConfig.getMathJaxScript()); + m_mathJaxScriptLineEdit->setText(markdownConfig.getMathJaxScript()); - { - const auto &fontFamily = markdownConfig.getEditorOverriddenFontFamily(); - m_editorOverriddenFontFamilyCheckBox->setChecked(!fontFamily.isEmpty()); - if (!fontFamily.isEmpty()) { - QFont font; - font.setFamily(fontFamily); - m_editorOverriddenFontFamilyComboBox->setCurrentFont(font); - } + { + const auto &fontFamily = markdownConfig.getEditorOverriddenFontFamily(); + m_editorOverriddenFontFamilyCheckBox->setChecked(!fontFamily.isEmpty()); + if (!fontFamily.isEmpty()) { + QFont font; + font.setFamily(fontFamily); + m_editorOverriddenFontFamilyComboBox->setCurrentFont(font); } + } - m_richPasteByDefaultCheckBox->setChecked(markdownConfig.getRichPasteByDefaultEnabled()); + m_richPasteByDefaultCheckBox->setChecked(markdownConfig.getRichPasteByDefaultEnabled()); } -bool MarkdownEditorPage::saveInternal() -{ - auto &markdownConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); +bool MarkdownEditorPage::saveInternal() { + auto &markdownConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - markdownConfig.setInsertFileNameAsTitle(m_insertFileNameAsTitleCheckBox->isChecked()); + markdownConfig.setInsertFileNameAsTitle(m_insertFileNameAsTitleCheckBox->isChecked()); - { - auto mode = m_sectionNumberComboBox->currentData().toInt(); - markdownConfig.setSectionNumberMode(static_cast(mode)); + { + auto mode = m_sectionNumberComboBox->currentData().toInt(); + markdownConfig.setSectionNumberMode(static_cast(mode)); - if (m_sectionNumberBaseLevelSpinBox->isEnabled()) { - markdownConfig.setSectionNumberBaseLevel(m_sectionNumberBaseLevelSpinBox->value()); - } - - if (m_sectionNumberStyleComboBox->isEnabled()) { - auto style = m_sectionNumberStyleComboBox->currentData().toInt(); - markdownConfig.setSectionNumberStyle(static_cast(style)); - } + if (m_sectionNumberBaseLevelSpinBox->isEnabled()) { + markdownConfig.setSectionNumberBaseLevel(m_sectionNumberBaseLevelSpinBox->value()); } - markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked()); - - markdownConfig.setImageAlignCenterEnabled(m_imageAlignCenterCheckBox->isChecked()); - - markdownConfig.setZoomFactorInReadMode(m_zoomFactorSpinBox->value()); - - markdownConfig.setConstrainInplacePreviewWidthEnabled(m_constrainInplacePreviewWidthCheckBox->isChecked()); - - { - MarkdownEditorConfig::InplacePreviewSources srcs = MarkdownEditorConfig::InplacePreviewSource::NoInplacePreview; - if (m_inplacePreviewSourceImageLinkCheckBox->isChecked()) { - srcs |= MarkdownEditorConfig::InplacePreviewSource::ImageLink; - } - if (m_inplacePreviewSourceCodeBlockCheckBox->isChecked()) { - srcs |= MarkdownEditorConfig::InplacePreviewSource::CodeBlock; - } - if (m_inplacePreviewSourceMathCheckBox->isChecked()) { - srcs |= MarkdownEditorConfig::InplacePreviewSource::Math; - } - - markdownConfig.setInplacePreviewSources(srcs); + if (m_sectionNumberStyleComboBox->isEnabled()) { + auto style = m_sectionNumberStyleComboBox->currentData().toInt(); + markdownConfig.setSectionNumberStyle( + static_cast(style)); } + } - markdownConfig.setFetchImagesInParseAndPaste(m_fetchImagesToLocalCheckBox->isChecked()); + markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked()); - markdownConfig.setHtmlTagEnabled(m_htmlTagCheckBox->isChecked()); + markdownConfig.setImageAlignCenterEnabled(m_imageAlignCenterCheckBox->isChecked()); - markdownConfig.setAutoBreakEnabled(m_autoBreakCheckBox->isChecked()); + markdownConfig.setZoomFactorInReadMode(m_zoomFactorSpinBox->value()); - markdownConfig.setLinkifyEnabled(m_linkifyCheckBox->isChecked()); + markdownConfig.setConstrainInplacePreviewWidthEnabled( + m_constrainInplacePreviewWidthCheckBox->isChecked()); - markdownConfig.setIndentFirstLineEnabled(m_indentFirstLineCheckBox->isChecked()); - - markdownConfig.setCodeBlockLineNumberEnabled(m_codeBlockLineNumberCheckBox->isChecked()); - - markdownConfig.setSmartTableEnabled(m_smartTableCheckBox->isChecked()); - - markdownConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked()); - - markdownConfig.setWebPlantUml(m_plantUmlModeComboBox->currentData().toInt() == 0); - - markdownConfig.setPlantUmlJar(m_plantUmlJarFileInput->text()); - - markdownConfig.setPlantUmlWebService(m_plantUmlWebServiceLineEdit->text()); - - markdownConfig.setWebGraphviz(m_graphvizModeComboBox->currentData().toInt() == 0); - - markdownConfig.setGraphvizExe(m_graphvizFileInput->text()); - - markdownConfig.setMathJaxScript(m_mathJaxScriptLineEdit->text()); - - { - bool checked = m_editorOverriddenFontFamilyCheckBox->isChecked(); - markdownConfig.setEditorOverriddenFontFamily(checked ? m_editorOverriddenFontFamilyComboBox->currentFont().family() : QString()); + { + MarkdownEditorConfig::InplacePreviewSources srcs = + MarkdownEditorConfig::InplacePreviewSource::NoInplacePreview; + if (m_inplacePreviewSourceImageLinkCheckBox->isChecked()) { + srcs |= MarkdownEditorConfig::InplacePreviewSource::ImageLink; } - - markdownConfig.setRichPasteByDefaultEnabled(m_richPasteByDefaultCheckBox->isChecked()); - - EditorPage::notifyEditorConfigChange(); - - return true; -} - -QString MarkdownEditorPage::title() const -{ - return tr("Markdown Editor"); -} - -QGroupBox *MarkdownEditorPage::setupReadGroup() -{ - auto box = new QGroupBox(tr("Read"), this); - auto layout = WidgetsFactory::createFormLayout(box); - - { - const QString label(tr("Constrain image width")); - m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, box); - m_constrainImageWidthCheckBox->setToolTip(tr("Constrain image width to the window")); - layout->addRow(m_constrainImageWidthCheckBox); - addSearchItem(label, m_constrainImageWidthCheckBox->toolTip(), m_constrainImageWidthCheckBox); - connect(m_constrainImageWidthCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Center image")); - m_imageAlignCenterCheckBox = WidgetsFactory::createCheckBox(label, box); - m_imageAlignCenterCheckBox->setToolTip(tr("Center images")); - layout->addRow(m_imageAlignCenterCheckBox); - addSearchItem(label, m_imageAlignCenterCheckBox->toolTip(), m_imageAlignCenterCheckBox); - connect(m_imageAlignCenterCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - m_zoomFactorSpinBox = WidgetsFactory::createDoubleSpinBox(box); - m_zoomFactorSpinBox->setToolTip(tr("Zoom factor in read mode")); - - m_zoomFactorSpinBox->setRange(0.1, 10); - m_zoomFactorSpinBox->setSingleStep(0.1); - - const QString label(tr("Zoom factor:")); - layout->addRow(label, m_zoomFactorSpinBox); - addSearchItem(label, m_zoomFactorSpinBox->toolTip(), m_zoomFactorSpinBox); - connect(m_zoomFactorSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("HTML tag")); - m_htmlTagCheckBox = WidgetsFactory::createCheckBox(label, box); - m_htmlTagCheckBox->setToolTip(tr("Allow HTML tags in source")); - layout->addRow(m_htmlTagCheckBox); - addSearchItem(label, m_htmlTagCheckBox->toolTip(), m_htmlTagCheckBox); - connect(m_htmlTagCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Auto break")); - m_autoBreakCheckBox = WidgetsFactory::createCheckBox(label, box); - m_autoBreakCheckBox->setToolTip(tr("Automatically break a line with '\\n'")); - layout->addRow(m_autoBreakCheckBox); - addSearchItem(label, m_autoBreakCheckBox->toolTip(), m_autoBreakCheckBox); - connect(m_autoBreakCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); + if (m_inplacePreviewSourceCodeBlockCheckBox->isChecked()) { + srcs |= MarkdownEditorConfig::InplacePreviewSource::CodeBlock; } - - { - const QString label(tr("Linkify")); - m_linkifyCheckBox = WidgetsFactory::createCheckBox(label, box); - m_linkifyCheckBox->setToolTip(tr("Convert URL-like text to links")); - layout->addRow(m_linkifyCheckBox); - addSearchItem(label, m_linkifyCheckBox->toolTip(), m_linkifyCheckBox); - connect(m_linkifyCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Indent first line")); - m_indentFirstLineCheckBox = WidgetsFactory::createCheckBox(label, box); - m_indentFirstLineCheckBox->setToolTip(tr("Indent the first line of each paragraph")); - layout->addRow(m_indentFirstLineCheckBox); - addSearchItem(label, m_indentFirstLineCheckBox->toolTip(), m_indentFirstLineCheckBox); - connect(m_indentFirstLineCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); + if (m_inplacePreviewSourceMathCheckBox->isChecked()) { + srcs |= MarkdownEditorConfig::InplacePreviewSource::Math; } - { - const QString label(tr("Code block line number")); - m_codeBlockLineNumberCheckBox = WidgetsFactory::createCheckBox(label, box); - m_codeBlockLineNumberCheckBox->setToolTip(tr("Add line number to code block")); - layout->addRow(m_codeBlockLineNumberCheckBox); - addSearchItem(label, m_codeBlockLineNumberCheckBox->toolTip(), m_codeBlockLineNumberCheckBox); - connect(m_codeBlockLineNumberCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setInplacePreviewSources(srcs); + } - return box; -} + markdownConfig.setFetchImagesInParseAndPaste(m_fetchImagesToLocalCheckBox->isChecked()); -QGroupBox *MarkdownEditorPage::setupEditGroup() -{ - auto box = new QGroupBox(tr("Edit"), this); - auto layout = WidgetsFactory::createFormLayout(box); - - { - const QString label(tr("Insert file name as title")); - m_insertFileNameAsTitleCheckBox = WidgetsFactory::createCheckBox(label, box); - m_insertFileNameAsTitleCheckBox->setToolTip(tr("Insert file name as title when creating note")); - layout->addRow(m_insertFileNameAsTitleCheckBox); - addSearchItem(label, m_insertFileNameAsTitleCheckBox->toolTip(), m_insertFileNameAsTitleCheckBox); - connect(m_insertFileNameAsTitleCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setHtmlTagEnabled(m_htmlTagCheckBox->isChecked()); - { - const QString label(tr("Constrain in-place preview width")); - m_constrainInplacePreviewWidthCheckBox = WidgetsFactory::createCheckBox(label, box); - m_constrainInplacePreviewWidthCheckBox->setToolTip(tr("Constrain in-place preview width to the window")); - layout->addRow(m_constrainInplacePreviewWidthCheckBox); - addSearchItem(label, m_constrainInplacePreviewWidthCheckBox->toolTip(), m_constrainInplacePreviewWidthCheckBox); - connect(m_constrainInplacePreviewWidthCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setAutoBreakEnabled(m_autoBreakCheckBox->isChecked()); - { - auto srcLayout = new QVBoxLayout(); - layout->addRow(tr("In-place preview sources:"), srcLayout); + markdownConfig.setLinkifyEnabled(m_linkifyCheckBox->isChecked()); - m_inplacePreviewSourceImageLinkCheckBox = WidgetsFactory::createCheckBox(tr("Image link"), box); - srcLayout->addWidget(m_inplacePreviewSourceImageLinkCheckBox); - connect(m_inplacePreviewSourceImageLinkCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); + markdownConfig.setIndentFirstLineEnabled(m_indentFirstLineCheckBox->isChecked()); - m_inplacePreviewSourceCodeBlockCheckBox = WidgetsFactory::createCheckBox(tr("Code block"), box); - srcLayout->addWidget(m_inplacePreviewSourceCodeBlockCheckBox); - connect(m_inplacePreviewSourceCodeBlockCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); + markdownConfig.setCodeBlockLineNumberEnabled(m_codeBlockLineNumberCheckBox->isChecked()); - m_inplacePreviewSourceMathCheckBox = WidgetsFactory::createCheckBox(tr("Math"), box); - srcLayout->addWidget(m_inplacePreviewSourceMathCheckBox); - connect(m_inplacePreviewSourceMathCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setSmartTableEnabled(m_smartTableCheckBox->isChecked()); - { - const QString label(tr("Fetch images to local in Parse And Paste")); - m_fetchImagesToLocalCheckBox = WidgetsFactory::createCheckBox(label, box); - m_fetchImagesToLocalCheckBox->setToolTip(tr("Fetch images to local in Parse To Markdown And Paste")); - layout->addRow(m_fetchImagesToLocalCheckBox); - addSearchItem(label, m_fetchImagesToLocalCheckBox->toolTip(), m_fetchImagesToLocalCheckBox); - connect(m_fetchImagesToLocalCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked()); - { - const QString label(tr("Smart table")); - m_smartTableCheckBox = WidgetsFactory::createCheckBox(label, box); - m_smartTableCheckBox->setToolTip(tr("Smart table formation")); - layout->addRow(m_smartTableCheckBox); - addSearchItem(label, m_smartTableCheckBox->toolTip(), m_smartTableCheckBox); - connect(m_smartTableCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setWebPlantUml(m_plantUmlModeComboBox->currentData().toInt() == 0); - { - const QString label(tr("Spell check")); - m_spellCheckCheckBox = WidgetsFactory::createCheckBox(label, box); - m_spellCheckCheckBox->setToolTip(tr("Spell check")); - layout->addRow(m_spellCheckCheckBox); - addSearchItem(label, m_spellCheckCheckBox->toolTip(), m_spellCheckCheckBox); - connect(m_spellCheckCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + markdownConfig.setPlantUmlJar(m_plantUmlJarFileInput->text()); - { - auto fontLayout = new QHBoxLayout(); - fontLayout->setContentsMargins(0, 0, 0, 0); + markdownConfig.setPlantUmlWebService(m_plantUmlWebServiceLineEdit->text()); - const QString label(tr("Override font")); - m_editorOverriddenFontFamilyCheckBox = WidgetsFactory::createCheckBox(label, box); - m_editorOverriddenFontFamilyCheckBox->setToolTip(tr("Override editor font family of theme")); - fontLayout->addWidget(m_editorOverriddenFontFamilyCheckBox); - addSearchItem(label, m_editorOverriddenFontFamilyCheckBox->toolTip(), m_editorOverriddenFontFamilyCheckBox); + markdownConfig.setWebGraphviz(m_graphvizModeComboBox->currentData().toInt() == 0); - m_editorOverriddenFontFamilyComboBox = new QFontComboBox(box); - m_editorOverriddenFontFamilyComboBox->setEnabled(false); - fontLayout->addWidget(m_editorOverriddenFontFamilyComboBox); - connect(m_editorOverriddenFontFamilyComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &MarkdownEditorPage::pageIsChanged); + markdownConfig.setGraphvizExe(m_graphvizFileInput->text()); - fontLayout->addStretch(); + markdownConfig.setMathJaxScript(m_mathJaxScriptLineEdit->text()); - connect(m_editorOverriddenFontFamilyCheckBox, &QCheckBox::stateChanged, - this, [this](int state) { - m_editorOverriddenFontFamilyComboBox->setEnabled(state == Qt::Checked); - emit pageIsChanged(); - }); + { + bool checked = m_editorOverriddenFontFamilyCheckBox->isChecked(); + markdownConfig.setEditorOverriddenFontFamily( + checked ? m_editorOverriddenFontFamilyComboBox->currentFont().family() : QString()); + } - layout->addRow(fontLayout); - } + markdownConfig.setRichPasteByDefaultEnabled(m_richPasteByDefaultCheckBox->isChecked()); - { - const QString label(tr("Use Rich Paste by default")); - m_richPasteByDefaultCheckBox = WidgetsFactory::createCheckBox(label, box); - m_richPasteByDefaultCheckBox->setToolTip(tr("Use Rich Paste by default when pasting text")); - layout->addRow(m_richPasteByDefaultCheckBox); - addSearchItem(label, m_richPasteByDefaultCheckBox->toolTip(), m_richPasteByDefaultCheckBox); - connect(m_richPasteByDefaultCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + EditorPage::notifyEditorConfigChange(); - return box; + return true; } -QGroupBox *MarkdownEditorPage::setupGeneralGroup() -{ - auto box = new QGroupBox(tr("General"), this); - auto layout = WidgetsFactory::createFormLayout(box); - - { - auto sectionLayout = new QHBoxLayout(); - sectionLayout->setContentsMargins(0, 0, 0, 0); - - m_sectionNumberComboBox = WidgetsFactory::createComboBox(box); - m_sectionNumberComboBox->setToolTip(tr("Section number mode")); - m_sectionNumberComboBox->addItem(tr("None"), (int)MarkdownEditorConfig::SectionNumberMode::None); - m_sectionNumberComboBox->addItem(tr("Read"), (int)MarkdownEditorConfig::SectionNumberMode::Read); - m_sectionNumberComboBox->addItem(tr("Edit"), (int)MarkdownEditorConfig::SectionNumberMode::Edit); - sectionLayout->addWidget(m_sectionNumberComboBox); - connect(m_sectionNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &MarkdownEditorPage::pageIsChanged); - - m_sectionNumberBaseLevelSpinBox = WidgetsFactory::createSpinBox(box); - m_sectionNumberBaseLevelSpinBox->setToolTip(tr("Base level to start section numbering in edit mode")); - m_sectionNumberBaseLevelSpinBox->setRange(1, 6); - m_sectionNumberBaseLevelSpinBox->setSingleStep(1); - m_sectionNumberBaseLevelSpinBox->setEnabled(false); - sectionLayout->addWidget(m_sectionNumberBaseLevelSpinBox); - connect(m_sectionNumberBaseLevelSpinBox, QOverload::of(&QSpinBox::valueChanged), - this, &MarkdownEditorPage::pageIsChanged); - - m_sectionNumberStyleComboBox = WidgetsFactory::createComboBox(box); - m_sectionNumberStyleComboBox->setToolTip(tr("Section number style")); - m_sectionNumberStyleComboBox->addItem(tr("1.1."), (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot); - m_sectionNumberStyleComboBox->addItem(tr("1.1"), (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDig); - m_sectionNumberStyleComboBox->setEnabled(false); - sectionLayout->addWidget(m_sectionNumberStyleComboBox); - connect(m_sectionNumberStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &MarkdownEditorPage::pageIsChanged); - - connect(m_sectionNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this](int p_index) { - m_sectionNumberBaseLevelSpinBox->setEnabled(p_index != MarkdownEditorConfig::SectionNumberMode::None); - m_sectionNumberStyleComboBox->setEnabled(p_index == MarkdownEditorConfig::SectionNumberMode::Edit); - }); - - const QString label(tr("Section number:")); - layout->addRow(label, sectionLayout); - addSearchItem(label, m_sectionNumberComboBox->toolTip(), m_sectionNumberComboBox); - } - - { - m_plantUmlModeComboBox = WidgetsFactory::createComboBox(box); - m_plantUmlModeComboBox->setToolTip(tr("Use Web service or local JAR file to render PlantUml graphs")); - - m_plantUmlModeComboBox->addItem(tr("Web Service"), 0); - m_plantUmlModeComboBox->addItem(tr("Local JAR"), 1); - - const QString label(tr("PlantUml:")); - layout->addRow(label, m_plantUmlModeComboBox); - addSearchItem(label, m_plantUmlModeComboBox->toolTip(), m_plantUmlModeComboBox); - connect(m_plantUmlModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &MarkdownEditorPage::pageIsChanged); - } - - { - auto jarLayout = new QHBoxLayout(); - jarLayout->setContentsMargins(0, 0, 0, 0); - - m_plantUmlJarFileInput = new LocationInputWithBrowseButton(box); - m_plantUmlJarFileInput->setToolTip(tr("Local JAR file to render PlantUml graphs")); - connect(m_plantUmlJarFileInput, &LocationInputWithBrowseButton::clicked, - this, [this]() { - auto filePath = QFileDialog::getOpenFileName(this, - tr("Select PlantUml JAR File"), - QDir::homePath(), - "PlantUml JAR (*.jar)"); - if (!filePath.isEmpty()) { - m_plantUmlJarFileInput->setText(filePath); - } - }); - jarLayout->addWidget(m_plantUmlJarFileInput, 1); - - auto testBtn = new QPushButton(tr("Test"), box); - testBtn->setToolTip(tr("Test PlantUml JAR and Java Runtime Environment")); - connect(testBtn, &QPushButton::clicked, - this, [this]() { - const auto jar = m_plantUmlJarFileInput->text(); - if (jar.isEmpty() || !QFileInfo::exists(jar)) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("The JAR file (%1) specified does not exist.").arg(jar), - this); - return; - } - - auto testRet = PlantUmlHelper::testPlantUml(jar); - MessageBoxHelper::notify(MessageBoxHelper::Information, - tr("Test %1.").arg(testRet.first ? tr("succeeded") : tr("failed")), - QString(), - testRet.second, - this); - }); - jarLayout->addWidget(testBtn); - - const QString label(tr("PlantUml JAR file:")); - layout->addRow(label, jarLayout); - addSearchItem(label, m_plantUmlJarFileInput->toolTip(), m_plantUmlJarFileInput); - connect(m_plantUmlJarFileInput, &LocationInputWithBrowseButton::textChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - m_plantUmlWebServiceLineEdit = WidgetsFactory::createLineEdit(box); - m_plantUmlWebServiceLineEdit->setToolTip(tr("Override the Web service used to render PlantUml graphs")); - m_plantUmlWebServiceLineEdit->setPlaceholderText(tr("Empty to use default one")); - - const QString label(tr("Override PlantUml Web service:")); - layout->addRow(label, m_plantUmlWebServiceLineEdit); - addSearchItem(label, m_plantUmlWebServiceLineEdit->toolTip(), m_plantUmlWebServiceLineEdit); - connect(m_plantUmlWebServiceLineEdit, &QLineEdit::textChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - m_graphvizModeComboBox = WidgetsFactory::createComboBox(box); - m_graphvizModeComboBox->setToolTip(tr("Use Web service or local executable file to render Graphviz graphs")); - - m_graphvizModeComboBox->addItem(tr("Web Service"), 0); - m_graphvizModeComboBox->addItem(tr("Local Executable"), 1); - - const QString label(tr("Graphviz:")); - layout->addRow(label, m_graphvizModeComboBox); - addSearchItem(label, m_graphvizModeComboBox->toolTip(), m_graphvizModeComboBox); - connect(m_graphvizModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &MarkdownEditorPage::pageIsChanged); - } - - { - auto fileLayout = new QHBoxLayout(); - fileLayout->setContentsMargins(0, 0, 0, 0); - - m_graphvizFileInput = new LocationInputWithBrowseButton(box); - m_graphvizFileInput->setToolTip(tr("Local executable file to render Graphviz graphs")); - connect(m_graphvizFileInput, &LocationInputWithBrowseButton::clicked, - this, [this]() { - auto filePath = QFileDialog::getOpenFileName(this, - tr("Select Graphviz Executable File"), - QDir::homePath()); - if (!filePath.isEmpty()) { - m_graphvizFileInput->setText(filePath); - } - }); - fileLayout->addWidget(m_graphvizFileInput, 1); - - auto testBtn = new QPushButton(tr("Test"), box); - testBtn->setToolTip(tr("Test Graphviz executable file")); - connect(testBtn, &QPushButton::clicked, - this, [this]() { - const auto exe = m_graphvizFileInput->text(); - if (exe.isEmpty() || !QFileInfo::exists(exe)) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("The executable file (%1) specified does not exist.").arg(exe), - this); - return; - } - - auto testRet = GraphvizHelper::testGraphviz(exe); - MessageBoxHelper::notify(MessageBoxHelper::Information, - tr("Test %1.").arg(testRet.first ? tr("succeeded") : tr("failed")), - QString(), - testRet.second, - this); - }); - fileLayout->addWidget(testBtn); - - const QString label(tr("Graphviz executable file:")); - layout->addRow(label, fileLayout); - addSearchItem(label, m_graphvizFileInput->toolTip(), m_graphvizFileInput); - connect(m_graphvizFileInput, &LocationInputWithBrowseButton::textChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - m_mathJaxScriptLineEdit = WidgetsFactory::createLineEdit(box); - m_mathJaxScriptLineEdit->setToolTip(tr("Override the MathJax script used to render math formulas")); - m_mathJaxScriptLineEdit->setPlaceholderText(tr("Empty to use default one")); +QString MarkdownEditorPage::title() const { return tr("Markdown Editor"); } + +QGroupBox *MarkdownEditorPage::setupReadGroup() { + auto box = new QGroupBox(tr("Read"), this); + auto layout = WidgetsFactory::createFormLayout(box); + + { + const QString label(tr("Constrain image width")); + m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, box); + m_constrainImageWidthCheckBox->setToolTip(tr("Constrain image width to the window")); + layout->addRow(m_constrainImageWidthCheckBox); + addSearchItem(label, m_constrainImageWidthCheckBox->toolTip(), m_constrainImageWidthCheckBox); + connect(m_constrainImageWidthCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Center image")); + m_imageAlignCenterCheckBox = WidgetsFactory::createCheckBox(label, box); + m_imageAlignCenterCheckBox->setToolTip(tr("Center images")); + layout->addRow(m_imageAlignCenterCheckBox); + addSearchItem(label, m_imageAlignCenterCheckBox->toolTip(), m_imageAlignCenterCheckBox); + connect(m_imageAlignCenterCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + m_zoomFactorSpinBox = WidgetsFactory::createDoubleSpinBox(box); + m_zoomFactorSpinBox->setToolTip(tr("Zoom factor in read mode")); + + m_zoomFactorSpinBox->setRange(0.1, 10); + m_zoomFactorSpinBox->setSingleStep(0.1); + + const QString label(tr("Zoom factor:")); + layout->addRow(label, m_zoomFactorSpinBox); + addSearchItem(label, m_zoomFactorSpinBox->toolTip(), m_zoomFactorSpinBox); + connect(m_zoomFactorSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("HTML tag")); + m_htmlTagCheckBox = WidgetsFactory::createCheckBox(label, box); + m_htmlTagCheckBox->setToolTip(tr("Allow HTML tags in source")); + layout->addRow(m_htmlTagCheckBox); + addSearchItem(label, m_htmlTagCheckBox->toolTip(), m_htmlTagCheckBox); + connect(m_htmlTagCheckBox, &QCheckBox::stateChanged, this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Auto break")); + m_autoBreakCheckBox = WidgetsFactory::createCheckBox(label, box); + m_autoBreakCheckBox->setToolTip(tr("Automatically break a line with '\\n'")); + layout->addRow(m_autoBreakCheckBox); + addSearchItem(label, m_autoBreakCheckBox->toolTip(), m_autoBreakCheckBox); + connect(m_autoBreakCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Linkify")); + m_linkifyCheckBox = WidgetsFactory::createCheckBox(label, box); + m_linkifyCheckBox->setToolTip(tr("Convert URL-like text to links")); + layout->addRow(m_linkifyCheckBox); + addSearchItem(label, m_linkifyCheckBox->toolTip(), m_linkifyCheckBox); + connect(m_linkifyCheckBox, &QCheckBox::stateChanged, this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Indent first line")); + m_indentFirstLineCheckBox = WidgetsFactory::createCheckBox(label, box); + m_indentFirstLineCheckBox->setToolTip(tr("Indent the first line of each paragraph")); + layout->addRow(m_indentFirstLineCheckBox); + addSearchItem(label, m_indentFirstLineCheckBox->toolTip(), m_indentFirstLineCheckBox); + connect(m_indentFirstLineCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Code block line number")); + m_codeBlockLineNumberCheckBox = WidgetsFactory::createCheckBox(label, box); + m_codeBlockLineNumberCheckBox->setToolTip(tr("Add line number to code block")); + layout->addRow(m_codeBlockLineNumberCheckBox); + addSearchItem(label, m_codeBlockLineNumberCheckBox->toolTip(), m_codeBlockLineNumberCheckBox); + connect(m_codeBlockLineNumberCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + return box; +} - const QString label(tr("Override MathJax script:")); - layout->addRow(label, m_mathJaxScriptLineEdit); - addSearchItem(label, m_mathJaxScriptLineEdit->toolTip(), m_mathJaxScriptLineEdit); - connect(m_mathJaxScriptLineEdit, &QLineEdit::textChanged, - this, &MarkdownEditorPage::pageIsChanged); - } +QGroupBox *MarkdownEditorPage::setupEditGroup() { + auto box = new QGroupBox(tr("Edit"), this); + auto layout = WidgetsFactory::createFormLayout(box); + + { + const QString label(tr("Insert file name as title")); + m_insertFileNameAsTitleCheckBox = WidgetsFactory::createCheckBox(label, box); + m_insertFileNameAsTitleCheckBox->setToolTip(tr("Insert file name as title when creating note")); + layout->addRow(m_insertFileNameAsTitleCheckBox); + addSearchItem(label, m_insertFileNameAsTitleCheckBox->toolTip(), + m_insertFileNameAsTitleCheckBox); + connect(m_insertFileNameAsTitleCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Constrain in-place preview width")); + m_constrainInplacePreviewWidthCheckBox = WidgetsFactory::createCheckBox(label, box); + m_constrainInplacePreviewWidthCheckBox->setToolTip( + tr("Constrain in-place preview width to the window")); + layout->addRow(m_constrainInplacePreviewWidthCheckBox); + addSearchItem(label, m_constrainInplacePreviewWidthCheckBox->toolTip(), + m_constrainInplacePreviewWidthCheckBox); + connect(m_constrainInplacePreviewWidthCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + auto srcLayout = new QVBoxLayout(); + layout->addRow(tr("In-place preview sources:"), srcLayout); + + m_inplacePreviewSourceImageLinkCheckBox = WidgetsFactory::createCheckBox(tr("Image link"), box); + srcLayout->addWidget(m_inplacePreviewSourceImageLinkCheckBox); + connect(m_inplacePreviewSourceImageLinkCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + + m_inplacePreviewSourceCodeBlockCheckBox = WidgetsFactory::createCheckBox(tr("Code block"), box); + srcLayout->addWidget(m_inplacePreviewSourceCodeBlockCheckBox); + connect(m_inplacePreviewSourceCodeBlockCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + + m_inplacePreviewSourceMathCheckBox = WidgetsFactory::createCheckBox(tr("Math"), box); + srcLayout->addWidget(m_inplacePreviewSourceMathCheckBox); + connect(m_inplacePreviewSourceMathCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Fetch images to local in Parse And Paste")); + m_fetchImagesToLocalCheckBox = WidgetsFactory::createCheckBox(label, box); + m_fetchImagesToLocalCheckBox->setToolTip( + tr("Fetch images to local in Parse To Markdown And Paste")); + layout->addRow(m_fetchImagesToLocalCheckBox); + addSearchItem(label, m_fetchImagesToLocalCheckBox->toolTip(), m_fetchImagesToLocalCheckBox); + connect(m_fetchImagesToLocalCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Smart table")); + m_smartTableCheckBox = WidgetsFactory::createCheckBox(label, box); + m_smartTableCheckBox->setToolTip(tr("Smart table formation")); + layout->addRow(m_smartTableCheckBox); + addSearchItem(label, m_smartTableCheckBox->toolTip(), m_smartTableCheckBox); + connect(m_smartTableCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Spell check")); + m_spellCheckCheckBox = WidgetsFactory::createCheckBox(label, box); + m_spellCheckCheckBox->setToolTip(tr("Spell check")); + layout->addRow(m_spellCheckCheckBox); + addSearchItem(label, m_spellCheckCheckBox->toolTip(), m_spellCheckCheckBox); + connect(m_spellCheckCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + auto fontLayout = new QHBoxLayout(); + fontLayout->setContentsMargins(0, 0, 0, 0); + + const QString label(tr("Override font")); + m_editorOverriddenFontFamilyCheckBox = WidgetsFactory::createCheckBox(label, box); + m_editorOverriddenFontFamilyCheckBox->setToolTip(tr("Override editor font family of theme")); + fontLayout->addWidget(m_editorOverriddenFontFamilyCheckBox); + addSearchItem(label, m_editorOverriddenFontFamilyCheckBox->toolTip(), + m_editorOverriddenFontFamilyCheckBox); + + m_editorOverriddenFontFamilyComboBox = new QFontComboBox(box); + m_editorOverriddenFontFamilyComboBox->setEnabled(false); + fontLayout->addWidget(m_editorOverriddenFontFamilyComboBox); + connect(m_editorOverriddenFontFamilyComboBox, + QOverload::of(&QComboBox::currentIndexChanged), this, + &MarkdownEditorPage::pageIsChanged); + + fontLayout->addStretch(); + + connect(m_editorOverriddenFontFamilyCheckBox, &QCheckBox::stateChanged, this, + [this](int state) { + m_editorOverriddenFontFamilyComboBox->setEnabled(state == Qt::Checked); + emit pageIsChanged(); + }); + + layout->addRow(fontLayout); + } + + { + const QString label(tr("Use Rich Paste by default")); + m_richPasteByDefaultCheckBox = WidgetsFactory::createCheckBox(label, box); + m_richPasteByDefaultCheckBox->setToolTip(tr("Use Rich Paste by default when pasting text")); + layout->addRow(m_richPasteByDefaultCheckBox); + addSearchItem(label, m_richPasteByDefaultCheckBox->toolTip(), m_richPasteByDefaultCheckBox); + connect(m_richPasteByDefaultCheckBox, &QCheckBox::stateChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + return box; +} - return box; +QGroupBox *MarkdownEditorPage::setupGeneralGroup() { + auto box = new QGroupBox(tr("General"), this); + auto layout = WidgetsFactory::createFormLayout(box); + + { + auto sectionLayout = new QHBoxLayout(); + sectionLayout->setContentsMargins(0, 0, 0, 0); + + m_sectionNumberComboBox = WidgetsFactory::createComboBox(box); + m_sectionNumberComboBox->setToolTip(tr("Section number mode")); + m_sectionNumberComboBox->addItem(tr("None"), + (int)MarkdownEditorConfig::SectionNumberMode::None); + m_sectionNumberComboBox->addItem(tr("Read"), + (int)MarkdownEditorConfig::SectionNumberMode::Read); + m_sectionNumberComboBox->addItem(tr("Edit"), + (int)MarkdownEditorConfig::SectionNumberMode::Edit); + sectionLayout->addWidget(m_sectionNumberComboBox); + connect(m_sectionNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &MarkdownEditorPage::pageIsChanged); + + m_sectionNumberBaseLevelSpinBox = WidgetsFactory::createSpinBox(box); + m_sectionNumberBaseLevelSpinBox->setToolTip( + tr("Base level to start section numbering in edit mode")); + m_sectionNumberBaseLevelSpinBox->setRange(1, 6); + m_sectionNumberBaseLevelSpinBox->setSingleStep(1); + m_sectionNumberBaseLevelSpinBox->setEnabled(false); + sectionLayout->addWidget(m_sectionNumberBaseLevelSpinBox); + connect(m_sectionNumberBaseLevelSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + &MarkdownEditorPage::pageIsChanged); + + m_sectionNumberStyleComboBox = WidgetsFactory::createComboBox(box); + m_sectionNumberStyleComboBox->setToolTip(tr("Section number style")); + m_sectionNumberStyleComboBox->addItem( + tr("1.1."), (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot); + m_sectionNumberStyleComboBox->addItem(tr("1.1"), + (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDig); + m_sectionNumberStyleComboBox->setEnabled(false); + sectionLayout->addWidget(m_sectionNumberStyleComboBox); + connect(m_sectionNumberStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &MarkdownEditorPage::pageIsChanged); + + connect(m_sectionNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this](int p_index) { + m_sectionNumberBaseLevelSpinBox->setEnabled( + p_index != MarkdownEditorConfig::SectionNumberMode::None); + m_sectionNumberStyleComboBox->setEnabled( + p_index == MarkdownEditorConfig::SectionNumberMode::Edit); + }); + + const QString label(tr("Section number:")); + layout->addRow(label, sectionLayout); + addSearchItem(label, m_sectionNumberComboBox->toolTip(), m_sectionNumberComboBox); + } + + { + m_plantUmlModeComboBox = WidgetsFactory::createComboBox(box); + m_plantUmlModeComboBox->setToolTip( + tr("Use Web service or local JAR file to render PlantUml graphs")); + + m_plantUmlModeComboBox->addItem(tr("Web Service"), 0); + m_plantUmlModeComboBox->addItem(tr("Local JAR"), 1); + + const QString label(tr("PlantUml:")); + layout->addRow(label, m_plantUmlModeComboBox); + addSearchItem(label, m_plantUmlModeComboBox->toolTip(), m_plantUmlModeComboBox); + connect(m_plantUmlModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &MarkdownEditorPage::pageIsChanged); + } + + { + auto jarLayout = new QHBoxLayout(); + jarLayout->setContentsMargins(0, 0, 0, 0); + + m_plantUmlJarFileInput = new LocationInputWithBrowseButton(box); + m_plantUmlJarFileInput->setToolTip(tr("Local JAR file to render PlantUml graphs")); + connect(m_plantUmlJarFileInput, &LocationInputWithBrowseButton::clicked, this, [this]() { + auto filePath = QFileDialog::getOpenFileName(this, tr("Select PlantUml JAR File"), + QDir::homePath(), "PlantUml JAR (*.jar)"); + if (!filePath.isEmpty()) { + m_plantUmlJarFileInput->setText(filePath); + } + }); + jarLayout->addWidget(m_plantUmlJarFileInput, 1); + + auto testBtn = new QPushButton(tr("Test"), box); + testBtn->setToolTip(tr("Test PlantUml JAR and Java Runtime Environment")); + connect(testBtn, &QPushButton::clicked, this, [this]() { + const auto jar = m_plantUmlJarFileInput->text(); + if (jar.isEmpty() || !QFileInfo::exists(jar)) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("The JAR file (%1) specified does not exist.").arg(jar), this); + return; + } + + auto testRet = PlantUmlHelper::testPlantUml(jar); + MessageBoxHelper::notify(MessageBoxHelper::Information, + tr("Test %1.").arg(testRet.first ? tr("succeeded") : tr("failed")), + QString(), testRet.second, this); + }); + jarLayout->addWidget(testBtn); + + const QString label(tr("PlantUml JAR file:")); + layout->addRow(label, jarLayout); + addSearchItem(label, m_plantUmlJarFileInput->toolTip(), m_plantUmlJarFileInput); + connect(m_plantUmlJarFileInput, &LocationInputWithBrowseButton::textChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + m_plantUmlWebServiceLineEdit = WidgetsFactory::createLineEdit(box); + m_plantUmlWebServiceLineEdit->setToolTip( + tr("Override the Web service used to render PlantUml graphs")); + m_plantUmlWebServiceLineEdit->setPlaceholderText(tr("Empty to use default one")); + + const QString label(tr("Override PlantUml Web service:")); + layout->addRow(label, m_plantUmlWebServiceLineEdit); + addSearchItem(label, m_plantUmlWebServiceLineEdit->toolTip(), m_plantUmlWebServiceLineEdit); + connect(m_plantUmlWebServiceLineEdit, &QLineEdit::textChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + m_graphvizModeComboBox = WidgetsFactory::createComboBox(box); + m_graphvizModeComboBox->setToolTip( + tr("Use Web service or local executable file to render Graphviz graphs")); + + m_graphvizModeComboBox->addItem(tr("Web Service"), 0); + m_graphvizModeComboBox->addItem(tr("Local Executable"), 1); + + const QString label(tr("Graphviz:")); + layout->addRow(label, m_graphvizModeComboBox); + addSearchItem(label, m_graphvizModeComboBox->toolTip(), m_graphvizModeComboBox); + connect(m_graphvizModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &MarkdownEditorPage::pageIsChanged); + } + + { + auto fileLayout = new QHBoxLayout(); + fileLayout->setContentsMargins(0, 0, 0, 0); + + m_graphvizFileInput = new LocationInputWithBrowseButton(box); + m_graphvizFileInput->setToolTip(tr("Local executable file to render Graphviz graphs")); + connect(m_graphvizFileInput, &LocationInputWithBrowseButton::clicked, this, [this]() { + auto filePath = QFileDialog::getOpenFileName(this, tr("Select Graphviz Executable File"), + QDir::homePath()); + if (!filePath.isEmpty()) { + m_graphvizFileInput->setText(filePath); + } + }); + fileLayout->addWidget(m_graphvizFileInput, 1); + + auto testBtn = new QPushButton(tr("Test"), box); + testBtn->setToolTip(tr("Test Graphviz executable file")); + connect(testBtn, &QPushButton::clicked, this, [this]() { + const auto exe = m_graphvizFileInput->text(); + if (exe.isEmpty() || !QFileInfo::exists(exe)) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("The executable file (%1) specified does not exist.").arg(exe), + this); + return; + } + + auto testRet = GraphvizHelper::testGraphviz(exe); + MessageBoxHelper::notify(MessageBoxHelper::Information, + tr("Test %1.").arg(testRet.first ? tr("succeeded") : tr("failed")), + QString(), testRet.second, this); + }); + fileLayout->addWidget(testBtn); + + const QString label(tr("Graphviz executable file:")); + layout->addRow(label, fileLayout); + addSearchItem(label, m_graphvizFileInput->toolTip(), m_graphvizFileInput); + connect(m_graphvizFileInput, &LocationInputWithBrowseButton::textChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + { + m_mathJaxScriptLineEdit = WidgetsFactory::createLineEdit(box); + m_mathJaxScriptLineEdit->setToolTip( + tr("Override the MathJax script used to render math formulas")); + m_mathJaxScriptLineEdit->setPlaceholderText(tr("Empty to use default one")); + + const QString label(tr("Override MathJax script:")); + layout->addRow(label, m_mathJaxScriptLineEdit); + addSearchItem(label, m_mathJaxScriptLineEdit->toolTip(), m_mathJaxScriptLineEdit); + connect(m_mathJaxScriptLineEdit, &QLineEdit::textChanged, this, + &MarkdownEditorPage::pageIsChanged); + } + + return box; } diff --git a/src/widgets/dialogs/settings/markdowneditorpage.h b/src/widgets/dialogs/settings/markdowneditorpage.h index 8f65c95c26..6ededed6b6 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.h +++ b/src/widgets/dialogs/settings/markdowneditorpage.h @@ -11,88 +11,86 @@ class QComboBox; class QFontComboBox; class QLineEdit; -namespace vnotex -{ - class LocationInputWithBrowseButton; +namespace vnotex { +class LocationInputWithBrowseButton; - class MarkdownEditorPage : public SettingsPage - { - Q_OBJECT - public: - explicit MarkdownEditorPage(QWidget *p_parent = nullptr); +class MarkdownEditorPage : public SettingsPage { + Q_OBJECT +public: + explicit MarkdownEditorPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QGroupBox *setupGeneralGroup(); + QGroupBox *setupGeneralGroup(); - QGroupBox *setupReadGroup(); + QGroupBox *setupReadGroup(); - QGroupBox *setupEditGroup(); + QGroupBox *setupEditGroup(); - QCheckBox *m_insertFileNameAsTitleCheckBox = nullptr; + QCheckBox *m_insertFileNameAsTitleCheckBox = nullptr; - QCheckBox *m_constrainImageWidthCheckBox = nullptr; + QCheckBox *m_constrainImageWidthCheckBox = nullptr; - QCheckBox *m_imageAlignCenterCheckBox = nullptr; + QCheckBox *m_imageAlignCenterCheckBox = nullptr; - QCheckBox *m_constrainInplacePreviewWidthCheckBox = nullptr; + QCheckBox *m_constrainInplacePreviewWidthCheckBox = nullptr; - QCheckBox *m_inplacePreviewSourceImageLinkCheckBox = nullptr; + QCheckBox *m_inplacePreviewSourceImageLinkCheckBox = nullptr; - QCheckBox *m_inplacePreviewSourceCodeBlockCheckBox = nullptr; + QCheckBox *m_inplacePreviewSourceCodeBlockCheckBox = nullptr; - QCheckBox *m_inplacePreviewSourceMathCheckBox = nullptr; + QCheckBox *m_inplacePreviewSourceMathCheckBox = nullptr; - QCheckBox *m_fetchImagesToLocalCheckBox = nullptr; + QCheckBox *m_fetchImagesToLocalCheckBox = nullptr; - QCheckBox *m_htmlTagCheckBox = nullptr; + QCheckBox *m_htmlTagCheckBox = nullptr; - QCheckBox *m_autoBreakCheckBox = nullptr; + QCheckBox *m_autoBreakCheckBox = nullptr; - QCheckBox *m_linkifyCheckBox = nullptr; + QCheckBox *m_linkifyCheckBox = nullptr; - QCheckBox *m_indentFirstLineCheckBox = nullptr; + QCheckBox *m_indentFirstLineCheckBox = nullptr; - QCheckBox *m_codeBlockLineNumberCheckBox = nullptr; + QCheckBox *m_codeBlockLineNumberCheckBox = nullptr; - QDoubleSpinBox *m_zoomFactorSpinBox = nullptr; + QDoubleSpinBox *m_zoomFactorSpinBox = nullptr; - QComboBox *m_sectionNumberComboBox = nullptr; + QComboBox *m_sectionNumberComboBox = nullptr; - QSpinBox *m_sectionNumberBaseLevelSpinBox = nullptr; + QSpinBox *m_sectionNumberBaseLevelSpinBox = nullptr; - QComboBox *m_sectionNumberStyleComboBox = nullptr; + QComboBox *m_sectionNumberStyleComboBox = nullptr; - QCheckBox *m_smartTableCheckBox = nullptr; + QCheckBox *m_smartTableCheckBox = nullptr; - QCheckBox *m_spellCheckCheckBox = nullptr; + QCheckBox *m_spellCheckCheckBox = nullptr; - QComboBox *m_plantUmlModeComboBox = nullptr; + QComboBox *m_plantUmlModeComboBox = nullptr; - LocationInputWithBrowseButton *m_plantUmlJarFileInput = nullptr; + LocationInputWithBrowseButton *m_plantUmlJarFileInput = nullptr; - QLineEdit *m_plantUmlWebServiceLineEdit = nullptr; + QLineEdit *m_plantUmlWebServiceLineEdit = nullptr; - QComboBox *m_graphvizModeComboBox = nullptr; + QComboBox *m_graphvizModeComboBox = nullptr; - LocationInputWithBrowseButton *m_graphvizFileInput = nullptr; + LocationInputWithBrowseButton *m_graphvizFileInput = nullptr; - QLineEdit *m_mathJaxScriptLineEdit = nullptr; + QLineEdit *m_mathJaxScriptLineEdit = nullptr; - QCheckBox *m_editorOverriddenFontFamilyCheckBox = nullptr; + QCheckBox *m_editorOverriddenFontFamilyCheckBox = nullptr; - QFontComboBox *m_editorOverriddenFontFamilyComboBox = nullptr; + QFontComboBox *m_editorOverriddenFontFamilyComboBox = nullptr; - QCheckBox *m_richPasteByDefaultCheckBox = nullptr; - }; -} + QCheckBox *m_richPasteByDefaultCheckBox = nullptr; +}; +} // namespace vnotex #endif // MARKDOWNEDITORPAGE_H diff --git a/src/widgets/dialogs/settings/miscpage.cpp b/src/widgets/dialogs/settings/miscpage.cpp index e8d2127c9f..b400fb6e1a 100644 --- a/src/widgets/dialogs/settings/miscpage.cpp +++ b/src/widgets/dialogs/settings/miscpage.cpp @@ -2,35 +2,20 @@ #include -#include +#include #include #include -#include #include +#include using namespace vnotex; -MiscPage::MiscPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} - -void MiscPage::setupUI() -{ -} +MiscPage::MiscPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } -void MiscPage::loadInternal() -{ +void MiscPage::setupUI() {} -} +void MiscPage::loadInternal() {} -bool MiscPage::saveInternal() -{ - return true; -} +bool MiscPage::saveInternal() { return true; } -QString MiscPage::title() const -{ - return tr("Misc"); -} +QString MiscPage::title() const { return tr("Misc"); } diff --git a/src/widgets/dialogs/settings/miscpage.h b/src/widgets/dialogs/settings/miscpage.h index c1039443d0..43b4005f84 100644 --- a/src/widgets/dialogs/settings/miscpage.h +++ b/src/widgets/dialogs/settings/miscpage.h @@ -3,24 +3,22 @@ #include "settingspage.h" -namespace vnotex -{ - class MiscPage : public SettingsPage - { - Q_OBJECT - public: - explicit MiscPage(QWidget *p_parent = nullptr); +namespace vnotex { +class MiscPage : public SettingsPage { + Q_OBJECT +public: + explicit MiscPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); - }; -} +private: + void setupUI(); +}; +} // namespace vnotex #endif // MISCPAGE_H diff --git a/src/widgets/dialogs/settings/newimagehostdialog.cpp b/src/widgets/dialogs/settings/newimagehostdialog.cpp index a27c72474d..30ec3c4f13 100644 --- a/src/widgets/dialogs/settings/newimagehostdialog.cpp +++ b/src/widgets/dialogs/settings/newimagehostdialog.cpp @@ -1,88 +1,78 @@ #include "newimagehostdialog.h" -#include #include -#include +#include #include +#include -#include #include +#include using namespace vnotex; -NewImageHostDialog::NewImageHostDialog(QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(); -} +NewImageHostDialog::NewImageHostDialog(QWidget *p_parent) : ScrollDialog(p_parent) { setupUI(); } -void NewImageHostDialog::setupUI() -{ - auto widget = new QWidget(this); - setCentralWidget(widget); +void NewImageHostDialog::setupUI() { + auto widget = new QWidget(this); + setCentralWidget(widget); - auto mainLayout = WidgetsFactory::createFormLayout(widget); + auto mainLayout = WidgetsFactory::createFormLayout(widget); - { - m_typeComboBox = WidgetsFactory::createComboBox(widget); - mainLayout->addRow(tr("Type:"), m_typeComboBox); + { + m_typeComboBox = WidgetsFactory::createComboBox(widget); + mainLayout->addRow(tr("Type:"), m_typeComboBox); - for (int type = static_cast(ImageHost::GitHub); type < static_cast(ImageHost::MaxHost); ++type) { - m_typeComboBox->addItem(ImageHost::typeString(static_cast(type)), type); - } + for (int type = static_cast(ImageHost::GitHub); + type < static_cast(ImageHost::MaxHost); ++type) { + m_typeComboBox->addItem(ImageHost::typeString(static_cast(type)), type); } + } - m_nameLineEdit = WidgetsFactory::createLineEdit(widget); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); + m_nameLineEdit = WidgetsFactory::createLineEdit(widget); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("New Image Host")); + setWindowTitle(tr("New Image Host")); } -void NewImageHostDialog::acceptedButtonClicked() -{ - if (validateInputs() && newImageHost()) { - accept(); - } +void NewImageHostDialog::acceptedButtonClicked() { + if (validateInputs() && newImageHost()) { + accept(); + } } -bool NewImageHostDialog::validateInputs() -{ - bool valid = true; - QString msg; - - auto name = m_nameLineEdit->text(); - if (name.isEmpty()) { - msg = tr("Please specify a valid name for the image host."); - valid = false; - } else if (ImageHostMgr::getInst().find(name)) { - msg = tr("Name conflicts with existing image host."); - valid = false; - } - - if (!valid) { - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - - return true; +bool NewImageHostDialog::validateInputs() { + bool valid = true; + QString msg; + + auto name = m_nameLineEdit->text(); + if (name.isEmpty()) { + msg = tr("Please specify a valid name for the image host."); + valid = false; + } else if (ImageHostMgr::getInst().find(name)) { + msg = tr("Name conflicts with existing image host."); + valid = false; + } + + if (!valid) { + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + + return true; } -bool NewImageHostDialog::newImageHost() -{ - m_imageHost = ImageHostMgr::getInst().newImageHost(static_cast(m_typeComboBox->currentData().toInt()), - m_nameLineEdit->text()); - if (!m_imageHost) { - setInformationText(tr("Failed to create image host (%1).").arg(m_nameLineEdit->text()), - ScrollDialog::InformationLevel::Error); - return false; - } +bool NewImageHostDialog::newImageHost() { + m_imageHost = ImageHostMgr::getInst().newImageHost( + static_cast(m_typeComboBox->currentData().toInt()), m_nameLineEdit->text()); + if (!m_imageHost) { + setInformationText(tr("Failed to create image host (%1).").arg(m_nameLineEdit->text()), + ScrollDialog::InformationLevel::Error); + return false; + } - return true; + return true; } -ImageHost *NewImageHostDialog::getNewImageHost() const -{ - return m_imageHost; -} +ImageHost *NewImageHostDialog::getNewImageHost() const { return m_imageHost; } diff --git a/src/widgets/dialogs/settings/newimagehostdialog.h b/src/widgets/dialogs/settings/newimagehostdialog.h index b670703b93..5b06e74c37 100644 --- a/src/widgets/dialogs/settings/newimagehostdialog.h +++ b/src/widgets/dialogs/settings/newimagehostdialog.h @@ -6,34 +6,32 @@ class QComboBox; class QLineEdit; -namespace vnotex -{ - class ImageHost; +namespace vnotex { +class ImageHost; - class NewImageHostDialog : public ScrollDialog - { - Q_OBJECT - public: - explicit NewImageHostDialog(QWidget *p_parent = nullptr); +class NewImageHostDialog : public ScrollDialog { + Q_OBJECT +public: + explicit NewImageHostDialog(QWidget *p_parent = nullptr); - ImageHost *getNewImageHost() const; + ImageHost *getNewImageHost() const; - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - bool validateInputs(); + bool validateInputs(); - bool newImageHost(); + bool newImageHost(); - QComboBox *m_typeComboBox = nullptr; + QComboBox *m_typeComboBox = nullptr; - QLineEdit *m_nameLineEdit = nullptr; + QLineEdit *m_nameLineEdit = nullptr; - ImageHost *m_imageHost = nullptr; - }; -} + ImageHost *m_imageHost = nullptr; +}; +} // namespace vnotex #endif // NEWIMAGEHOSTDIALOG_H diff --git a/src/widgets/dialogs/settings/notemanagementpage.cpp b/src/widgets/dialogs/settings/notemanagementpage.cpp index 4104efb4e2..0a1dc0e101 100644 --- a/src/widgets/dialogs/settings/notemanagementpage.cpp +++ b/src/widgets/dialogs/settings/notemanagementpage.cpp @@ -1,111 +1,102 @@ #include "notemanagementpage.h" #include -#include #include +#include -#include -#include #include -#include +#include #include +#include +#include using namespace vnotex; -NoteManagementPage::NoteManagementPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); +NoteManagementPage::NoteManagementPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void NoteManagementPage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + { + const QString label(tr("Per-Notebook access history")); + m_perNotebookHistoryCheckBox = WidgetsFactory::createCheckBox(label, this); + m_perNotebookHistoryCheckBox->setToolTip(tr("Store note access history in its notebook")); + mainLayout->addRow(m_perNotebookHistoryCheckBox); + addSearchItem(label, m_perNotebookHistoryCheckBox->toolTip(), m_perNotebookHistoryCheckBox); + connect(m_perNotebookHistoryCheckBox, &QCheckBox::stateChanged, this, + &NoteManagementPage::pageIsChanged); + } + + { + m_lineEndingComboBox = WidgetsFactory::createComboBox(this); + m_lineEndingComboBox->setToolTip(tr("Line ending used to write configuration files")); + + m_lineEndingComboBox->addItem(tr("Follow Platform"), (int)LineEndingPolicy::Platform); + m_lineEndingComboBox->addItem(tr("LF (Linux/macOS)"), (int)LineEndingPolicy::LF); + m_lineEndingComboBox->addItem(tr("CR LF (Windows)"), (int)LineEndingPolicy::CRLF); + m_lineEndingComboBox->addItem(tr("CR"), (int)LineEndingPolicy::CR); + + const QString label(tr("Line ending:")); + mainLayout->addRow(label, m_lineEndingComboBox); + addSearchItem(label, m_lineEndingComboBox->toolTip(), m_lineEndingComboBox); + connect(m_lineEndingComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &NoteManagementPage::pageIsChanged); + } + + { + m_defaultOpenModeComboBox = WidgetsFactory::createComboBox(this); + m_defaultOpenModeComboBox->setToolTip(tr("Default mode when opening notes")); + + m_defaultOpenModeComboBox->addItem(tr("Read"), (int)ViewWindowMode::Read); + m_defaultOpenModeComboBox->addItem(tr("Edit"), (int)ViewWindowMode::Edit); + + const QString label(tr("Default open mode:")); + mainLayout->addRow(label, m_defaultOpenModeComboBox); + addSearchItem(label, m_defaultOpenModeComboBox->toolTip(), m_defaultOpenModeComboBox); + connect(m_defaultOpenModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &NoteManagementPage::pageIsChanged); + } } -void NoteManagementPage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - { - const QString label(tr("Per-Notebook access history")); - m_perNotebookHistoryCheckBox = WidgetsFactory::createCheckBox(label, this); - m_perNotebookHistoryCheckBox->setToolTip(tr("Store note access history in its notebook")); - mainLayout->addRow(m_perNotebookHistoryCheckBox); - addSearchItem(label, m_perNotebookHistoryCheckBox->toolTip(), m_perNotebookHistoryCheckBox); - connect(m_perNotebookHistoryCheckBox, &QCheckBox::stateChanged, - this, &NoteManagementPage::pageIsChanged); - } - - { - m_lineEndingComboBox = WidgetsFactory::createComboBox(this); - m_lineEndingComboBox->setToolTip(tr("Line ending used to write configuration files")); +void NoteManagementPage::loadInternal() { + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - m_lineEndingComboBox->addItem(tr("Follow Platform"), (int)LineEndingPolicy::Platform); - m_lineEndingComboBox->addItem(tr("LF (Linux/macOS)"), (int)LineEndingPolicy::LF); - m_lineEndingComboBox->addItem(tr("CR LF (Windows)"), (int)LineEndingPolicy::CRLF); - m_lineEndingComboBox->addItem(tr("CR"), (int)LineEndingPolicy::CR); + m_perNotebookHistoryCheckBox->setChecked(coreConfig.isPerNotebookHistoryEnabled()); - const QString label(tr("Line ending:")); - mainLayout->addRow(label, m_lineEndingComboBox); - addSearchItem(label, m_lineEndingComboBox->toolTip(), m_lineEndingComboBox); - connect(m_lineEndingComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &NoteManagementPage::pageIsChanged); + { + int idx = m_lineEndingComboBox->findData(static_cast(coreConfig.getLineEndingPolicy())); + if (idx == -1) { + idx = 0; } - - { - m_defaultOpenModeComboBox = WidgetsFactory::createComboBox(this); - m_defaultOpenModeComboBox->setToolTip(tr("Default mode when opening notes")); - - m_defaultOpenModeComboBox->addItem(tr("Read"), (int)ViewWindowMode::Read); - m_defaultOpenModeComboBox->addItem(tr("Edit"), (int)ViewWindowMode::Edit); - - const QString label(tr("Default open mode:")); - mainLayout->addRow(label, m_defaultOpenModeComboBox); - addSearchItem(label, m_defaultOpenModeComboBox->toolTip(), m_defaultOpenModeComboBox); - connect(m_defaultOpenModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &NoteManagementPage::pageIsChanged); + m_lineEndingComboBox->setCurrentIndex(idx); + } + + { + int idx = + m_defaultOpenModeComboBox->findData(static_cast(coreConfig.getDefaultOpenMode())); + if (idx == -1) { + idx = 0; } + m_defaultOpenModeComboBox->setCurrentIndex(idx); + } } -void NoteManagementPage::loadInternal() -{ - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - - m_perNotebookHistoryCheckBox->setChecked(coreConfig.isPerNotebookHistoryEnabled()); - - { - int idx = m_lineEndingComboBox->findData(static_cast(coreConfig.getLineEndingPolicy())); - if (idx == -1) { - idx = 0; - } - m_lineEndingComboBox->setCurrentIndex(idx); - } +bool NoteManagementPage::saveInternal() { + auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - { - int idx = m_defaultOpenModeComboBox->findData(static_cast(coreConfig.getDefaultOpenMode())); - if (idx == -1) { - idx = 0; - } - m_defaultOpenModeComboBox->setCurrentIndex(idx); - } -} + coreConfig.setPerNotebookHistoryEnabled(m_perNotebookHistoryCheckBox->isChecked()); -bool NoteManagementPage::saveInternal() -{ - auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + { + auto ending = m_lineEndingComboBox->currentData().toInt(); + coreConfig.setLineEndingPolicy(static_cast(ending)); + } - coreConfig.setPerNotebookHistoryEnabled(m_perNotebookHistoryCheckBox->isChecked()); + { + auto mode = m_defaultOpenModeComboBox->currentData().toInt(); + coreConfig.setDefaultOpenMode(static_cast(mode)); + } - { - auto ending = m_lineEndingComboBox->currentData().toInt(); - coreConfig.setLineEndingPolicy(static_cast(ending)); - } - - { - auto mode = m_defaultOpenModeComboBox->currentData().toInt(); - coreConfig.setDefaultOpenMode(static_cast(mode)); - } - - return true; + return true; } -QString NoteManagementPage::title() const -{ - return tr("Note Management"); -} +QString NoteManagementPage::title() const { return tr("Note Management"); } diff --git a/src/widgets/dialogs/settings/notemanagementpage.h b/src/widgets/dialogs/settings/notemanagementpage.h index 7cf33e15c7..3768efd453 100644 --- a/src/widgets/dialogs/settings/notemanagementpage.h +++ b/src/widgets/dialogs/settings/notemanagementpage.h @@ -6,30 +6,28 @@ class QCheckBox; class QComboBox; -namespace vnotex -{ - class NoteManagementPage : public SettingsPage - { - Q_OBJECT - public: - explicit NoteManagementPage(QWidget *p_parent = nullptr); +namespace vnotex { +class NoteManagementPage : public SettingsPage { + Q_OBJECT +public: + explicit NoteManagementPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QCheckBox *m_perNotebookHistoryCheckBox = nullptr; + QCheckBox *m_perNotebookHistoryCheckBox = nullptr; - QComboBox *m_lineEndingComboBox = nullptr; + QComboBox *m_lineEndingComboBox = nullptr; - QComboBox *m_defaultOpenModeComboBox = nullptr; - }; -} + QComboBox *m_defaultOpenModeComboBox = nullptr; +}; +} // namespace vnotex #endif // NOTEMANAGEMENTPAGE_H diff --git a/src/widgets/dialogs/settings/quickaccesspage.cpp b/src/widgets/dialogs/settings/quickaccesspage.cpp index d97cacbc22..fe63ed1f89 100644 --- a/src/widgets/dialogs/settings/quickaccesspage.cpp +++ b/src/widgets/dialogs/settings/quickaccesspage.cpp @@ -1,341 +1,317 @@ #include "quickaccesspage.h" -#include +#include +#include +#include +#include #include #include +#include +#include #include -#include -#include -#include #include -#include -#include -#include +#include -#include -#include #include +#include #include +#include #include #include -#include #include -#include +#include #include +#include #include "../notetemplateselector.h" using namespace vnotex; -QuickAccessPage::QuickAccessPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} +QuickAccessPage::QuickAccessPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } -void QuickAccessPage::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); +void QuickAccessPage::setupUI() { + auto mainLayout = new QVBoxLayout(this); - auto flashPageBox = setupFlashPageGroup(); - mainLayout->addWidget(flashPageBox); + auto flashPageBox = setupFlashPageGroup(); + mainLayout->addWidget(flashPageBox); - auto quickAccessBox = setupQuickAccessGroup(); - mainLayout->addWidget(quickAccessBox); + auto quickAccessBox = setupQuickAccessGroup(); + mainLayout->addWidget(quickAccessBox); - auto quickNoteBox = setupQuickNoteGroup(); - mainLayout->addWidget(quickNoteBox); + auto quickNoteBox = setupQuickNoteGroup(); + mainLayout->addWidget(quickNoteBox); - mainLayout->addStretch(); + mainLayout->addStretch(); } -void QuickAccessPage::loadInternal() -{ - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); +void QuickAccessPage::loadInternal() { + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - m_flashPageInput->setText(sessionConfig.getFlashPage()); + m_flashPageInput->setText(sessionConfig.getFlashPage()); - { - const auto &quickAccess = sessionConfig.getQuickAccessFiles(); - if (!quickAccess.isEmpty()) { - m_quickAccessTextEdit->setPlainText(quickAccess.join(QChar('\n'))); - } + { + const auto &quickAccess = sessionConfig.getQuickAccessFiles(); + if (!quickAccess.isEmpty()) { + m_quickAccessTextEdit->setPlainText(quickAccess.join(QChar('\n'))); } + } - loadQuickNoteSchemes(); + loadQuickNoteSchemes(); } -void QuickAccessPage::loadQuickNoteSchemes() -{ - const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - - m_quickNoteSchemes = sessionConfig.getQuickNoteSchemes(); - m_quickNoteCurrentIndex = -1; - - m_quickNoteSchemeComboBox->clear(); - for (const auto &scheme : m_quickNoteSchemes) { - m_quickNoteSchemeComboBox->addItem(scheme.m_name); - } - if (m_quickNoteSchemeComboBox->count() > 0) { - m_quickNoteSchemeComboBox->setCurrentIndex(0); - // Manually call the handler. - setCurrentQuickNote(0); - } +void QuickAccessPage::loadQuickNoteSchemes() { + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + + m_quickNoteSchemes = sessionConfig.getQuickNoteSchemes(); + m_quickNoteCurrentIndex = -1; + + m_quickNoteSchemeComboBox->clear(); + for (const auto &scheme : m_quickNoteSchemes) { + m_quickNoteSchemeComboBox->addItem(scheme.m_name); + } + if (m_quickNoteSchemeComboBox->count() > 0) { + m_quickNoteSchemeComboBox->setCurrentIndex(0); + // Manually call the handler. + setCurrentQuickNote(0); + } } -bool QuickAccessPage::saveInternal() -{ - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); +bool QuickAccessPage::saveInternal() { + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - sessionConfig.setFlashPage(m_flashPageInput->text()); + sessionConfig.setFlashPage(m_flashPageInput->text()); - { - auto text = m_quickAccessTextEdit->toPlainText(); - if (!text.isEmpty()) { - sessionConfig.setQuickAccessFiles(text.split(QChar('\n'))); - } + { + auto text = m_quickAccessTextEdit->toPlainText(); + if (!text.isEmpty()) { + sessionConfig.setQuickAccessFiles(text.split(QChar('\n'))); } + } - saveQuickNoteSchemes(); + saveQuickNoteSchemes(); - return true; + return true; } -void QuickAccessPage::saveQuickNoteSchemes() -{ - // Save current quick note scheme from inputs. - saveCurrentQuickNote(); +void QuickAccessPage::saveQuickNoteSchemes() { + // Save current quick note scheme from inputs. + saveCurrentQuickNote(); - auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); - sessionConfig.setQuickNoteSchemes(m_quickNoteSchemes); + auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + sessionConfig.setQuickNoteSchemes(m_quickNoteSchemes); } -QString QuickAccessPage::title() const -{ - return tr("Quick Access"); +QString QuickAccessPage::title() const { return tr("Quick Access"); } + +QGroupBox *QuickAccessPage::setupFlashPageGroup() { + auto box = new QGroupBox(tr("Flash Page"), this); + auto layout = WidgetsFactory::createFormLayout(box); + + { + m_flashPageInput = new LocationInputWithBrowseButton(box); + m_flashPageInput->setToolTip( + tr("Flash Page location (user could copy the path of one note and paste it here)")); + + const QString label(tr("Flash Page:")); + layout->addRow(label, m_flashPageInput); + addSearchItem(label, m_flashPageInput->toolTip(), m_flashPageInput); + connect(m_flashPageInput, &LocationInputWithBrowseButton::textChanged, this, + &QuickAccessPage::pageIsChanged); + connect(m_flashPageInput, &LocationInputWithBrowseButton::clicked, this, [this]() { + auto filePath = + QFileDialog::getOpenFileName(this, tr("Select Flash Page File"), QDir::homePath()); + if (!filePath.isEmpty()) { + m_flashPageInput->setText(filePath); + } + }); + } + + return box; } -QGroupBox *QuickAccessPage::setupFlashPageGroup() -{ - auto box = new QGroupBox(tr("Flash Page"), this); - auto layout = WidgetsFactory::createFormLayout(box); - - { - m_flashPageInput = new LocationInputWithBrowseButton(box); - m_flashPageInput->setToolTip(tr("Flash Page location (user could copy the path of one note and paste it here)")); - - const QString label(tr("Flash Page:")); - layout->addRow(label, m_flashPageInput); - addSearchItem(label, m_flashPageInput->toolTip(), m_flashPageInput); - connect(m_flashPageInput, &LocationInputWithBrowseButton::textChanged, - this, &QuickAccessPage::pageIsChanged); - connect(m_flashPageInput, &LocationInputWithBrowseButton::clicked, - this, [this]() { - auto filePath = QFileDialog::getOpenFileName(this, - tr("Select Flash Page File"), - QDir::homePath()); - if (!filePath.isEmpty()) { - m_flashPageInput->setText(filePath); - } - }); - } +QGroupBox *QuickAccessPage::setupQuickAccessGroup() { + auto box = new QGroupBox(tr("Quick Access"), this); + auto layout = WidgetsFactory::createFormLayout(box); - return box; -} + { + m_quickAccessTextEdit = WidgetsFactory::createPlainTextEdit(box); + m_quickAccessTextEdit->setToolTip( + tr("Edit the files pinned to Quick Access (one file per line)")); + m_quickAccessTextEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); -QGroupBox *QuickAccessPage::setupQuickAccessGroup() -{ - auto box = new QGroupBox(tr("Quick Access"), this); - auto layout = WidgetsFactory::createFormLayout(box); - - { - m_quickAccessTextEdit = WidgetsFactory::createPlainTextEdit(box); - m_quickAccessTextEdit->setToolTip(tr("Edit the files pinned to Quick Access (one file per line)")); - m_quickAccessTextEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - - const QString label(tr("Quick Access:")); - layout->addRow(label, m_quickAccessTextEdit); - addSearchItem(label, m_quickAccessTextEdit->toolTip(), m_quickAccessTextEdit); - connect(m_quickAccessTextEdit, &QPlainTextEdit::textChanged, - this, &QuickAccessPage::pageIsChanged); - } + const QString label(tr("Quick Access:")); + layout->addRow(label, m_quickAccessTextEdit); + addSearchItem(label, m_quickAccessTextEdit->toolTip(), m_quickAccessTextEdit); + connect(m_quickAccessTextEdit, &QPlainTextEdit::textChanged, this, + &QuickAccessPage::pageIsChanged); + } - return box; + return box; } -QString QuickAccessPage::getDefaultQuickNoteFolderPath() -{ - auto defaultPath = QDir::homePath(); - auto currentNotebook = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); - if (currentNotebook) { - defaultPath = currentNotebook->getRootFolderAbsolutePath(); - } - return defaultPath; +QString QuickAccessPage::getDefaultQuickNoteFolderPath() { + auto defaultPath = QDir::homePath(); + auto currentNotebook = VNoteX::getInst().getNotebookMgr().getCurrentNotebook(); + if (currentNotebook) { + defaultPath = currentNotebook->getRootFolderAbsolutePath(); + } + return defaultPath; } -QGroupBox *QuickAccessPage::setupQuickNoteGroup() -{ - auto box = new QGroupBox(tr("Quick Note"), this); - auto mainLayout = WidgetsFactory::createFormLayout(box); - - { - auto selectorLayout = new QHBoxLayout(); - - // Add items in loadInternal(). - m_quickNoteSchemeComboBox = WidgetsFactory::createComboBox(box); - selectorLayout->addWidget(m_quickNoteSchemeComboBox, 1); - m_quickNoteSchemeComboBox->setPlaceholderText(tr("No scheme to show")); - - auto newBtn = new QPushButton(tr("New"), box); - connect(newBtn, &QPushButton::clicked, - this, &QuickAccessPage::newQuickNoteScheme); - selectorLayout->addWidget(newBtn); - - auto deleteBtn = new QPushButton(tr("Delete"), box); - deleteBtn->setEnabled(false); - connect(deleteBtn, &QPushButton::clicked, - this, &QuickAccessPage::removeQuickNoteScheme); - selectorLayout->addWidget(deleteBtn); - - const QString label(tr("Scheme:")); - mainLayout->addRow(label, selectorLayout); - addSearchItem(label, m_quickNoteSchemeComboBox); - - connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &QuickAccessPage::pageIsChanged); - connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [deleteBtn](int idx) { - deleteBtn->setEnabled(idx > -1); - }); - } - - m_quickNoteInfoGroupBox = new QGroupBox(box); - mainLayout->addRow(m_quickNoteInfoGroupBox); - auto infoLayout = WidgetsFactory::createFormLayout(m_quickNoteInfoGroupBox); - - { - const QString label(tr("Folder:")); - m_quickNoteFolderPathInput = new LocationInputWithBrowseButton(m_quickNoteInfoGroupBox); - m_quickNoteFolderPathInput->setPlaceholderText(tr("Empty to use current explored folder dynamically")); - infoLayout->addRow(label, m_quickNoteFolderPathInput); - addSearchItem(label, m_quickNoteFolderPathInput); - connect(m_quickNoteFolderPathInput, &LocationInputWithBrowseButton::textChanged, - this, &QuickAccessPage::pageIsChanged); - connect(m_quickNoteFolderPathInput, &LocationInputWithBrowseButton::clicked, - this, [this]() { - auto folderPath = QFileDialog::getExistingDirectory(this, - tr("Select Quick Note Folder"), - getDefaultQuickNoteFolderPath()); - if (!folderPath.isEmpty()) { - m_quickNoteFolderPathInput->setText(folderPath); - } - }); - } +QGroupBox *QuickAccessPage::setupQuickNoteGroup() { + auto box = new QGroupBox(tr("Quick Note"), this); + auto mainLayout = WidgetsFactory::createFormLayout(box); + + { + auto selectorLayout = new QHBoxLayout(); + + // Add items in loadInternal(). + m_quickNoteSchemeComboBox = WidgetsFactory::createComboBox(box); + selectorLayout->addWidget(m_quickNoteSchemeComboBox, 1); + m_quickNoteSchemeComboBox->setPlaceholderText(tr("No scheme to show")); + + auto newBtn = new QPushButton(tr("New"), box); + connect(newBtn, &QPushButton::clicked, this, &QuickAccessPage::newQuickNoteScheme); + selectorLayout->addWidget(newBtn); + + auto deleteBtn = new QPushButton(tr("Delete"), box); + deleteBtn->setEnabled(false); + connect(deleteBtn, &QPushButton::clicked, this, &QuickAccessPage::removeQuickNoteScheme); + selectorLayout->addWidget(deleteBtn); + + const QString label(tr("Scheme:")); + mainLayout->addRow(label, selectorLayout); + addSearchItem(label, m_quickNoteSchemeComboBox); + + connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &QuickAccessPage::pageIsChanged); + connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [deleteBtn](int idx) { deleteBtn->setEnabled(idx > -1); }); + } + + m_quickNoteInfoGroupBox = new QGroupBox(box); + mainLayout->addRow(m_quickNoteInfoGroupBox); + auto infoLayout = WidgetsFactory::createFormLayout(m_quickNoteInfoGroupBox); + + { + const QString label(tr("Folder:")); + m_quickNoteFolderPathInput = new LocationInputWithBrowseButton(m_quickNoteInfoGroupBox); + m_quickNoteFolderPathInput->setPlaceholderText( + tr("Empty to use current explored folder dynamically")); + infoLayout->addRow(label, m_quickNoteFolderPathInput); + addSearchItem(label, m_quickNoteFolderPathInput); + connect(m_quickNoteFolderPathInput, &LocationInputWithBrowseButton::textChanged, this, + &QuickAccessPage::pageIsChanged); + connect(m_quickNoteFolderPathInput, &LocationInputWithBrowseButton::clicked, this, [this]() { + auto folderPath = QFileDialog::getExistingDirectory(this, tr("Select Quick Note Folder"), + getDefaultQuickNoteFolderPath()); + if (!folderPath.isEmpty()) { + m_quickNoteFolderPathInput->setText(folderPath); + } + }); + } + + { + const QString label(tr("Note name:")); + m_quickNoteNoteNameLineEdit = + WidgetsFactory::createLineEditWithSnippet(m_quickNoteInfoGroupBox); + infoLayout->addRow(label, m_quickNoteNoteNameLineEdit); + connect(m_quickNoteNoteNameLineEdit, &QLineEdit::textChanged, this, + &QuickAccessPage::pageIsChanged); + } + + { + const QString label(tr("Note template:")); + m_quickNoteTemplateSelector = new NoteTemplateSelector(m_quickNoteInfoGroupBox); + infoLayout->addRow(label, m_quickNoteTemplateSelector); + connect(m_quickNoteTemplateSelector, &NoteTemplateSelector::templateChanged, this, + &QuickAccessPage::pageIsChanged); + } + + m_quickNoteInfoGroupBox->setVisible(false); + connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this](int idx) { + if (isLoading()) { + return; + } + setCurrentQuickNote(idx); + }); + return box; +} - { - const QString label(tr("Note name:")); - m_quickNoteNoteNameLineEdit = WidgetsFactory::createLineEditWithSnippet(m_quickNoteInfoGroupBox); - infoLayout->addRow(label, m_quickNoteNoteNameLineEdit); - connect(m_quickNoteNoteNameLineEdit, &QLineEdit::textChanged, - this, &QuickAccessPage::pageIsChanged); +void QuickAccessPage::newQuickNoteScheme() { + bool isDuplicated = false; + QString schemeName; + do { + schemeName = QInputDialog::getText(this, tr("Quick Note Scheme"), + isDuplicated ? tr("Scheme name already exists! Try again:") + : tr("Scheme name:")); + if (schemeName.isEmpty()) { + return; } + isDuplicated = m_quickNoteSchemeComboBox->findText(schemeName) != -1; + } while (isDuplicated); - { - const QString label(tr("Note template:")); - m_quickNoteTemplateSelector = new NoteTemplateSelector(m_quickNoteInfoGroupBox); - infoLayout->addRow(label, m_quickNoteTemplateSelector); - connect(m_quickNoteTemplateSelector, &NoteTemplateSelector::templateChanged, - this, &QuickAccessPage::pageIsChanged); - } + SessionConfig::QuickNoteScheme scheme; + scheme.m_name = schemeName; + scheme.m_folderPath = getDefaultQuickNoteFolderPath(); + scheme.m_noteName = tr("quick_note_%da%.md"); + m_quickNoteSchemes.push_back(scheme); - m_quickNoteInfoGroupBox->setVisible(false); - connect(m_quickNoteSchemeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this](int idx) { - if (isLoading()) { - return; - } - setCurrentQuickNote(idx); - }); - return box; -} + m_quickNoteSchemeComboBox->addItem(schemeName); + m_quickNoteSchemeComboBox->setCurrentText(schemeName); -void QuickAccessPage::newQuickNoteScheme() -{ - bool isDuplicated = false; - QString schemeName; - do { - schemeName = QInputDialog::getText(this, tr("Quick Note Scheme"), - isDuplicated ? tr("Scheme name already exists! Try again:") : tr("Scheme name:")); - if (schemeName.isEmpty()) { - return; - } - isDuplicated = m_quickNoteSchemeComboBox->findText(schemeName) != -1; - } while (isDuplicated); - - SessionConfig::QuickNoteScheme scheme; - scheme.m_name = schemeName; - scheme.m_folderPath = getDefaultQuickNoteFolderPath(); - scheme.m_noteName = tr("quick_note_%da%.md"); - m_quickNoteSchemes.push_back(scheme); - - m_quickNoteSchemeComboBox->addItem(schemeName); - m_quickNoteSchemeComboBox->setCurrentText(schemeName); - - emit pageIsChanged(); + emit pageIsChanged(); } -void QuickAccessPage::removeQuickNoteScheme() -{ - int idx = m_quickNoteSchemeComboBox->currentIndex(); - Q_ASSERT(idx > -1); - - auto& scheme = m_quickNoteSchemes[idx]; - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Type::Question, - tr("Delete quick note scheme (%1)?").arg(scheme.m_name)); - if (ret != QMessageBox::Ok) { - return; - } - - m_quickNoteCurrentIndex = -1; - m_quickNoteSchemes.removeAt(idx); - m_quickNoteSchemeComboBox->removeItem(idx); - emit pageIsChanged(); +void QuickAccessPage::removeQuickNoteScheme() { + int idx = m_quickNoteSchemeComboBox->currentIndex(); + Q_ASSERT(idx > -1); + + auto &scheme = m_quickNoteSchemes[idx]; + int ret = MessageBoxHelper::questionOkCancel( + MessageBoxHelper::Type::Question, tr("Delete quick note scheme (%1)?").arg(scheme.m_name)); + if (ret != QMessageBox::Ok) { + return; + } + + m_quickNoteCurrentIndex = -1; + m_quickNoteSchemes.removeAt(idx); + m_quickNoteSchemeComboBox->removeItem(idx); + emit pageIsChanged(); } -void QuickAccessPage::saveCurrentQuickNote() -{ - if (m_quickNoteCurrentIndex < 0) { - return; - } - Q_ASSERT(m_quickNoteCurrentIndex < m_quickNoteSchemes.size()); - auto& scheme = m_quickNoteSchemes[m_quickNoteCurrentIndex]; - scheme.m_folderPath = m_quickNoteFolderPathInput->text(); - // No need to apply the snippet for now. - scheme.m_noteName = m_quickNoteNoteNameLineEdit->text(); - scheme.m_template = m_quickNoteTemplateSelector->getCurrentTemplate(); +void QuickAccessPage::saveCurrentQuickNote() { + if (m_quickNoteCurrentIndex < 0) { + return; + } + Q_ASSERT(m_quickNoteCurrentIndex < m_quickNoteSchemes.size()); + auto &scheme = m_quickNoteSchemes[m_quickNoteCurrentIndex]; + scheme.m_folderPath = m_quickNoteFolderPathInput->text(); + // No need to apply the snippet for now. + scheme.m_noteName = m_quickNoteNoteNameLineEdit->text(); + scheme.m_template = m_quickNoteTemplateSelector->getCurrentTemplate(); } -void QuickAccessPage::loadCurrentQuickNote() -{ - if (m_quickNoteCurrentIndex < 0) { - m_quickNoteFolderPathInput->setText(QString()); - m_quickNoteNoteNameLineEdit->setText(QString()); - m_quickNoteTemplateSelector->setCurrentTemplate(QString()); - return; - } - - Q_ASSERT(m_quickNoteCurrentIndex < m_quickNoteSchemes.size()); - const auto& scheme = m_quickNoteSchemes[m_quickNoteCurrentIndex]; - m_quickNoteFolderPathInput->setText(scheme.m_folderPath); - m_quickNoteNoteNameLineEdit->setText(scheme.m_noteName); - m_quickNoteTemplateSelector->setCurrentTemplate(scheme.m_template); +void QuickAccessPage::loadCurrentQuickNote() { + if (m_quickNoteCurrentIndex < 0) { + m_quickNoteFolderPathInput->setText(QString()); + m_quickNoteNoteNameLineEdit->setText(QString()); + m_quickNoteTemplateSelector->setCurrentTemplate(QString()); + return; + } + + Q_ASSERT(m_quickNoteCurrentIndex < m_quickNoteSchemes.size()); + const auto &scheme = m_quickNoteSchemes[m_quickNoteCurrentIndex]; + m_quickNoteFolderPathInput->setText(scheme.m_folderPath); + m_quickNoteNoteNameLineEdit->setText(scheme.m_noteName); + m_quickNoteTemplateSelector->setCurrentTemplate(scheme.m_template); } -void QuickAccessPage::setCurrentQuickNote(int idx) -{ - saveCurrentQuickNote(); - m_quickNoteCurrentIndex = idx; - loadCurrentQuickNote(); +void QuickAccessPage::setCurrentQuickNote(int idx) { + saveCurrentQuickNote(); + m_quickNoteCurrentIndex = idx; + loadCurrentQuickNote(); - m_quickNoteInfoGroupBox->setVisible(idx > -1); + m_quickNoteInfoGroupBox->setVisible(idx > -1); } diff --git a/src/widgets/dialogs/settings/quickaccesspage.h b/src/widgets/dialogs/settings/quickaccesspage.h index 7dee163806..0a83ab68ff 100644 --- a/src/widgets/dialogs/settings/quickaccesspage.h +++ b/src/widgets/dialogs/settings/quickaccesspage.h @@ -9,68 +9,66 @@ class QGroupBox; class QPlainTextEdit; class QComboBox; -namespace vnotex -{ - class LocationInputWithBrowseButton; - class LineEditWithSnippet; - class NoteTemplateSelector; +namespace vnotex { +class LocationInputWithBrowseButton; +class LineEditWithSnippet; +class NoteTemplateSelector; - class QuickAccessPage : public SettingsPage - { - Q_OBJECT - public: - explicit QuickAccessPage(QWidget *p_parent = nullptr); +class QuickAccessPage : public SettingsPage { + Q_OBJECT +public: + explicit QuickAccessPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QGroupBox *setupFlashPageGroup(); + QGroupBox *setupFlashPageGroup(); - QGroupBox *setupQuickAccessGroup(); + QGroupBox *setupQuickAccessGroup(); - QGroupBox *setupQuickNoteGroup(); + QGroupBox *setupQuickNoteGroup(); - void newQuickNoteScheme(); + void newQuickNoteScheme(); - void removeQuickNoteScheme(); + void removeQuickNoteScheme(); - void saveCurrentQuickNote(); + void saveCurrentQuickNote(); - void loadCurrentQuickNote(); + void loadCurrentQuickNote(); - void loadQuickNoteSchemes(); + void loadQuickNoteSchemes(); - void saveQuickNoteSchemes(); + void saveQuickNoteSchemes(); - void setCurrentQuickNote(int idx); + void setCurrentQuickNote(int idx); - static QString getDefaultQuickNoteFolderPath(); + static QString getDefaultQuickNoteFolderPath(); - LocationInputWithBrowseButton *m_flashPageInput = nullptr; + LocationInputWithBrowseButton *m_flashPageInput = nullptr; - QPlainTextEdit *m_quickAccessTextEdit = nullptr; + QPlainTextEdit *m_quickAccessTextEdit = nullptr; - QComboBox *m_quickNoteSchemeComboBox = nullptr; + QComboBox *m_quickNoteSchemeComboBox = nullptr; - LocationInputWithBrowseButton *m_quickNoteFolderPathInput = nullptr; + LocationInputWithBrowseButton *m_quickNoteFolderPathInput = nullptr; - LineEditWithSnippet *m_quickNoteNoteNameLineEdit = nullptr; + LineEditWithSnippet *m_quickNoteNoteNameLineEdit = nullptr; - NoteTemplateSelector *m_quickNoteTemplateSelector = nullptr; + NoteTemplateSelector *m_quickNoteTemplateSelector = nullptr; - QGroupBox *m_quickNoteInfoGroupBox = nullptr; + QGroupBox *m_quickNoteInfoGroupBox = nullptr; - QVector m_quickNoteSchemes; + QVector m_quickNoteSchemes; - int m_quickNoteCurrentIndex = -1; - }; -} + int m_quickNoteCurrentIndex = -1; +}; +} // namespace vnotex #endif // QUICKACCESSPAGE_H diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index 4aeff09ae9..11b2495bc5 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -1,344 +1,320 @@ #include "settingsdialog.h" +#include +#include #include -#include -#include #include #include -#include +#include #include -#include +#include -#include +#include +#include #include -#include -#include -#include #include -#include -#include +#include +#include +#include +#include -#include "generalpage.h" -#include "miscpage.h" +#include "appearancepage.h" #include "editorpage.h" -#include "texteditorpage.h" +#include "fileassociationpage.h" +#include "generalpage.h" +#include "imagehostpage.h" #include "markdowneditorpage.h" -#include "appearancepage.h" +#include "miscpage.h" +#include "notemanagementpage.h" #include "quickaccesspage.h" +#include "texteditorpage.h" #include "themepage.h" -#include "imagehostpage.h" #include "vipage.h" -#include "notemanagementpage.h" -#include "fileassociationpage.h" using namespace vnotex; -SettingsDialog::SettingsDialog(QWidget *p_parent) - : Dialog(p_parent) -{ - setupUI(); +SettingsDialog::SettingsDialog(QWidget *p_parent) : Dialog(p_parent) { + setupUI(); - setupPages(); + setupPages(); - connect(this, &QDialog::finished, - this, &SettingsDialog::checkOnFinish); + connect(this, &QDialog::finished, this, &SettingsDialog::checkOnFinish); } -void SettingsDialog::setupUI() -{ - auto *widget = new QWidget(this); - setCentralWidget(widget); +void SettingsDialog::setupUI() { + auto *widget = new QWidget(this); + setCentralWidget(widget); - auto mainLayout = new QHBoxLayout(widget); + auto mainLayout = new QHBoxLayout(widget); - setupPageExplorer(mainLayout, widget); + setupPageExplorer(mainLayout, widget); - { - m_scrollArea = new QScrollArea(widget); - m_scrollArea->setWidgetResizable(true); - mainLayout->addWidget(m_scrollArea, 6); + { + m_scrollArea = new QScrollArea(widget); + m_scrollArea->setWidgetResizable(true); + mainLayout->addWidget(m_scrollArea, 6); - auto scrollWidget = new QWidget(m_scrollArea); - m_scrollArea->setWidget(scrollWidget); + auto scrollWidget = new QWidget(m_scrollArea); + m_scrollArea->setWidget(scrollWidget); - m_pageLayout = new QStackedLayout(scrollWidget); - } + m_pageLayout = new QStackedLayout(scrollWidget); + } - setDialogButtonBox(QDialogButtonBox::Ok - | QDialogButtonBox::Apply - | QDialogButtonBox::Reset - | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Reset | + QDialogButtonBox::Cancel); - setWindowTitle(tr("Settings")); + setWindowTitle(tr("Settings")); } -void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent) -{ - auto layout = new QVBoxLayout(); - - m_searchTimer = new QTimer(this); - m_searchTimer->setSingleShot(true); - m_searchTimer->setInterval(500); - connect(m_searchTimer, &QTimer::timeout, - this, &SettingsDialog::search); - - m_searchEdit = WidgetsFactory::createLineEdit(p_parent); - m_searchEdit->setPlaceholderText(tr("Search")); - m_searchEdit->setClearButtonEnabled(true); - layout->addWidget(m_searchEdit); - connect(m_searchEdit, &QLineEdit::textChanged, - m_searchTimer, QOverload<>::of(&QTimer::start)); - - m_pageExplorer = new TreeWidget(TreeWidget::EnhancedStyle, p_parent); - TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false); - TreeWidget::showHorizontalScrollbar(m_pageExplorer); - m_pageExplorer->setMinimumWidth(128); - layout->addWidget(m_pageExplorer); - - connect(m_pageExplorer, &QTreeWidget::currentItemChanged, - this, [this](QTreeWidgetItem *p_item, QTreeWidgetItem *p_previous) { - Q_UNUSED(p_previous); - auto page = itemPage(p_item); - m_pageLayout->setCurrentWidget(page); - auto vsb = m_scrollArea->verticalScrollBar(); - if (vsb) { - vsb->setValue(0); - } - }); - - p_layout->addLayout(layout, 2); +void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent) { + auto layout = new QVBoxLayout(); + + m_searchTimer = new QTimer(this); + m_searchTimer->setSingleShot(true); + m_searchTimer->setInterval(500); + connect(m_searchTimer, &QTimer::timeout, this, &SettingsDialog::search); + + m_searchEdit = WidgetsFactory::createLineEdit(p_parent); + m_searchEdit->setPlaceholderText(tr("Search")); + m_searchEdit->setClearButtonEnabled(true); + layout->addWidget(m_searchEdit); + connect(m_searchEdit, &QLineEdit::textChanged, m_searchTimer, QOverload<>::of(&QTimer::start)); + + m_pageExplorer = new TreeWidget(TreeWidget::EnhancedStyle, p_parent); + TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false); + TreeWidget::showHorizontalScrollbar(m_pageExplorer); + m_pageExplorer->setMinimumWidth(128); + layout->addWidget(m_pageExplorer); + + connect(m_pageExplorer, &QTreeWidget::currentItemChanged, this, + [this](QTreeWidgetItem *p_item, QTreeWidgetItem *p_previous) { + Q_UNUSED(p_previous); + auto page = itemPage(p_item); + m_pageLayout->setCurrentWidget(page); + auto vsb = m_scrollArea->verticalScrollBar(); + if (vsb) { + vsb->setValue(0); + } + }); + + p_layout->addLayout(layout, 2); } -void SettingsDialog::setupPages() -{ - // General. +void SettingsDialog::setupPages() { + // General. + { + auto page = new GeneralPage(this); + addPage(page); + } + + // Note Management. + { + auto page = new NoteManagementPage(this); + addPage(page); + } + + // Appearance. + { + auto page = new AppearancePage(this); + auto item = addPage(page); + + // Theme. { - auto page = new GeneralPage(this); - addPage(page); + auto subPage = new ThemePage(this); + addSubPage(subPage, item); } + } - // Note Management. - { - auto page = new NoteManagementPage(this); - addPage(page); - } + // Quick Access. + { + auto page = new QuickAccessPage(this); + addPage(page); + } - // Appearance. - { - auto page = new AppearancePage(this); - auto item = addPage(page); - - // Theme. - { - auto subPage = new ThemePage(this); - addSubPage(subPage, item); - } - } + // Editor. + { + auto page = new EditorPage(this); + auto item = addPage(page); - // Quick Access. + // Image Host. { - auto page = new QuickAccessPage(this); - addPage(page); + auto subPage = new ImageHostPage(this); + addSubPage(subPage, item); } - // Editor. + // Vi. { - auto page = new EditorPage(this); - auto item = addPage(page); - - // Image Host. - { - auto subPage = new ImageHostPage(this); - addSubPage(subPage, item); - } - - // Vi. - { - auto subPage = new ViPage(this); - addSubPage(subPage, item); - } - - // Text Editor. - { - auto subPage = new TextEditorPage(this); - addSubPage(subPage, item); - } - - // Markdown Editor. - { - auto subPage = new MarkdownEditorPage(this); - addSubPage(subPage, item); - } + auto subPage = new ViPage(this); + addSubPage(subPage, item); } - // Misc. + // Text Editor. { - /* - auto page = new MiscPage(this); - addPage(page); - */ + auto subPage = new TextEditorPage(this); + addSubPage(subPage, item); } - // File Association. + // Markdown Editor. { - auto page = new FileAssociationPage(this); - addPage(page); + auto subPage = new MarkdownEditorPage(this); + addSubPage(subPage, item); } - - setChangesUnsaved(false); - m_pageExplorer->setCurrentItem(m_pageExplorer->topLevelItem(0), 0, QItemSelectionModel::ClearAndSelect); - m_pageExplorer->expandAll(); - m_pageLayout->setCurrentIndex(0); - - m_ready = true; + } + + // Misc. + { + /* + auto page = new MiscPage(this); + addPage(page); + */ + } + + // File Association. + { + auto page = new FileAssociationPage(this); + addPage(page); + } + + setChangesUnsaved(false); + m_pageExplorer->setCurrentItem(m_pageExplorer->topLevelItem(0), 0, + QItemSelectionModel::ClearAndSelect); + m_pageExplorer->expandAll(); + m_pageLayout->setCurrentIndex(0); + + m_ready = true; } -void SettingsDialog::setupPage(QTreeWidgetItem *p_item, SettingsPage *p_page) -{ - p_item->setText(0, p_page->title()); - p_item->setData(0, Qt::UserRole, QVariant::fromValue(p_page)); +void SettingsDialog::setupPage(QTreeWidgetItem *p_item, SettingsPage *p_page) { + p_item->setText(0, p_page->title()); + p_item->setData(0, Qt::UserRole, QVariant::fromValue(p_page)); - p_page->load(); + p_page->load(); - connect(p_page, &SettingsPage::changed, - this, [this]() { - if (m_ready) { - setChangesUnsaved(true); - } - }); + connect(p_page, &SettingsPage::changed, this, [this]() { + if (m_ready) { + setChangesUnsaved(true); + } + }); } -SettingsPage *SettingsDialog::itemPage(QTreeWidgetItem *p_item) const -{ - Q_ASSERT(p_item); - return p_item->data(0, Qt::UserRole).value(); +SettingsPage *SettingsDialog::itemPage(QTreeWidgetItem *p_item) const { + Q_ASSERT(p_item); + return p_item->data(0, Qt::UserRole).value(); } -void SettingsDialog::setChangesUnsaved(bool p_unsaved) -{ - m_changesUnsaved = p_unsaved; - setButtonEnabled(QDialogButtonBox::Apply, m_changesUnsaved); - setButtonEnabled(QDialogButtonBox::Reset, m_changesUnsaved); +void SettingsDialog::setChangesUnsaved(bool p_unsaved) { + m_changesUnsaved = p_unsaved; + setButtonEnabled(QDialogButtonBox::Apply, m_changesUnsaved); + setButtonEnabled(QDialogButtonBox::Reset, m_changesUnsaved); } -void SettingsDialog::acceptedButtonClicked() -{ - if (m_changesUnsaved) { - if (savePages()) { - accept(); - } - return; +void SettingsDialog::acceptedButtonClicked() { + if (m_changesUnsaved) { + if (savePages()) { + accept(); } + return; + } - accept(); + accept(); } -void SettingsDialog::resetButtonClicked() -{ - clearInformationText(); +void SettingsDialog::resetButtonClicked() { + clearInformationText(); - m_ready = false; - forEachPage([](SettingsPage *p_page) { - p_page->reset(); - return true; - }); - m_ready = true; + m_ready = false; + forEachPage([](SettingsPage *p_page) { + p_page->reset(); + return true; + }); + m_ready = true; - setChangesUnsaved(false); + setChangesUnsaved(false); } -void SettingsDialog::appliedButtonClicked() -{ - Q_ASSERT(m_changesUnsaved); - savePages(); +void SettingsDialog::appliedButtonClicked() { + Q_ASSERT(m_changesUnsaved); + savePages(); } -bool SettingsDialog::savePages() -{ - clearInformationText(); - - bool allSaved = true; - forEachPage([this, &allSaved](SettingsPage *p_page) { - if (!p_page->save()) { - allSaved = false; - m_pageLayout->setCurrentWidget(p_page); - if (!p_page->error().isEmpty()) { - setInformationText(p_page->error(), InformationLevel::Error); - } - return false; - } +bool SettingsDialog::savePages() { + clearInformationText(); + + bool allSaved = true; + forEachPage([this, &allSaved](SettingsPage *p_page) { + if (!p_page->save()) { + allSaved = false; + m_pageLayout->setCurrentWidget(p_page); + if (!p_page->error().isEmpty()) { + setInformationText(p_page->error(), InformationLevel::Error); + } + return false; + } - return true; - }); + return true; + }); - if (allSaved) { - setChangesUnsaved(false); - return true; - } + if (allSaved) { + setChangesUnsaved(false); + return true; + } - return false; + return false; } -void SettingsDialog::forEachPage(const std::function &p_func) -{ - for (int i = 0; i < m_pageLayout->count(); ++i) { - auto page = static_cast(m_pageLayout->widget(i)); - if (!p_func(page)) { - break; - } +void SettingsDialog::forEachPage(const std::function &p_func) { + for (int i = 0; i < m_pageLayout->count(); ++i) { + auto page = static_cast(m_pageLayout->widget(i)); + if (!p_func(page)) { + break; } + } } -QTreeWidgetItem *SettingsDialog::addPage(SettingsPage *p_page) -{ - m_pageLayout->addWidget(p_page); +QTreeWidgetItem *SettingsDialog::addPage(SettingsPage *p_page) { + m_pageLayout->addWidget(p_page); - auto item = new QTreeWidgetItem(m_pageExplorer); - setupPage(item, p_page); - return item; + auto item = new QTreeWidgetItem(m_pageExplorer); + setupPage(item, p_page); + return item; } -QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem) -{ - m_pageLayout->addWidget(p_page); +QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem) { + m_pageLayout->addWidget(p_page); - auto subItem = new QTreeWidgetItem(p_parentItem); - setupPage(subItem, p_page); - return subItem; + auto subItem = new QTreeWidgetItem(p_parentItem); + setupPage(subItem, p_page); + return subItem; } -void SettingsDialog::search() -{ - auto keywords = m_searchEdit->text().trimmed(); - TreeWidget::forEachItem(m_pageExplorer, [this, keywords](QTreeWidgetItem *item) { - auto page = itemPage(item); - if (page->search(keywords)) { - m_pageExplorer->mark(item, 0); - } else { - m_pageExplorer->unmark(item, 0); - } - return true; - }); +void SettingsDialog::search() { + auto keywords = m_searchEdit->text().trimmed(); + TreeWidget::forEachItem(m_pageExplorer, [this, keywords](QTreeWidgetItem *item) { + auto page = itemPage(item); + if (page->search(keywords)) { + m_pageExplorer->mark(item, 0); + } else { + m_pageExplorer->unmark(item, 0); + } + return true; + }); } -void SettingsDialog::checkOnFinish() -{ - // Check whether need to prompt for restart. - forEachPage([this](const SettingsPage *p_page) { - if (p_page->isRestartNeeded()) { - // Restart VNote. - int ret = MessageBoxHelper::questionYesNo(MessageBoxHelper::Type::Information, - tr("A restart of VNote may be needed to make changes take effect. Restart VNote now?"), - QString(), - QString(), - this); - if (ret == QMessageBox::Yes) { - QMetaObject::invokeMethod(VNoteX::getInst().getMainWindow(), - &MainWindow::restart, - Qt::QueuedConnection); - } - return false; - } - return true; - }); +void SettingsDialog::checkOnFinish() { + // Check whether need to prompt for restart. + forEachPage([this](const SettingsPage *p_page) { + if (p_page->isRestartNeeded()) { + // Restart VNote. + int ret = MessageBoxHelper::questionYesNo( + MessageBoxHelper::Type::Information, + tr("A restart of VNote may be needed to make changes take effect. Restart VNote now?"), + QString(), QString(), this); + if (ret == QMessageBox::Yes) { + QMetaObject::invokeMethod(VNoteX::getInst().getMainWindow(), &MainWindow::restart, + Qt::QueuedConnection); + } + return false; + } + return true; + }); } diff --git a/src/widgets/dialogs/settings/settingsdialog.h b/src/widgets/dialogs/settings/settingsdialog.h index fa567bfe82..0db949ce1d 100644 --- a/src/widgets/dialogs/settings/settingsdialog.h +++ b/src/widgets/dialogs/settings/settingsdialog.h @@ -11,64 +11,62 @@ class QTreeWidgetItem; class QScrollArea; class QTimer; -namespace vnotex -{ - class TreeWidget; - class SettingsPage; +namespace vnotex { +class TreeWidget; +class SettingsPage; - class SettingsDialog : public Dialog - { - Q_OBJECT - public: - explicit SettingsDialog(QWidget *p_parent = nullptr); +class SettingsDialog : public Dialog { + Q_OBJECT +public: + explicit SettingsDialog(QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - void resetButtonClicked() Q_DECL_OVERRIDE; + void resetButtonClicked() Q_DECL_OVERRIDE; - void appliedButtonClicked() Q_DECL_OVERRIDE; + void appliedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent); + void setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent); - void setupPages(); + void setupPages(); - void setupPage(QTreeWidgetItem *p_item, SettingsPage *p_page); + void setupPage(QTreeWidgetItem *p_item, SettingsPage *p_page); - SettingsPage *itemPage(QTreeWidgetItem *p_item) const; + SettingsPage *itemPage(QTreeWidgetItem *p_item) const; - void setChangesUnsaved(bool p_unsaved); + void setChangesUnsaved(bool p_unsaved); - bool savePages(); + bool savePages(); - // @p_func: return true to continue the iteration. - void forEachPage(const std::function &p_func); + // @p_func: return true to continue the iteration. + void forEachPage(const std::function &p_func); - QTreeWidgetItem *addPage(SettingsPage *p_page); + QTreeWidgetItem *addPage(SettingsPage *p_page); - QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem); + QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem); - void search(); + void search(); - void checkOnFinish(); + void checkOnFinish(); - QLineEdit *m_searchEdit = nullptr; + QLineEdit *m_searchEdit = nullptr; - TreeWidget *m_pageExplorer = nullptr; + TreeWidget *m_pageExplorer = nullptr; - QScrollArea *m_scrollArea = nullptr; + QScrollArea *m_scrollArea = nullptr; - QStackedLayout *m_pageLayout = nullptr; + QStackedLayout *m_pageLayout = nullptr; - bool m_changesUnsaved = false; + bool m_changesUnsaved = false; - bool m_ready = false; + bool m_ready = false; - QTimer *m_searchTimer = nullptr; - }; -} + QTimer *m_searchTimer = nullptr; +}; +} // namespace vnotex #endif // SETTINGSDIALOG_H diff --git a/src/widgets/dialogs/settings/settingspage.cpp b/src/widgets/dialogs/settings/settingspage.cpp index feccb03331..f5a2fa0456 100644 --- a/src/widgets/dialogs/settings/settingspage.cpp +++ b/src/widgets/dialogs/settings/settingspage.cpp @@ -5,120 +5,95 @@ using namespace vnotex; -SettingsPage::SettingsPage(QWidget *p_parent) - : QWidget(p_parent) -{ -} +SettingsPage::SettingsPage(QWidget *p_parent) : QWidget(p_parent) {} -SettingsPage::~SettingsPage() -{ -} +SettingsPage::~SettingsPage() {} -bool SettingsPage::search(const QString &p_key) -{ - bool hit = false; +bool SettingsPage::search(const QString &p_key) { + bool hit = false; - if (!p_key.isEmpty() && title().contains(p_key, Qt::CaseInsensitive)) { - hit = true; - } + if (!p_key.isEmpty() && title().contains(p_key, Qt::CaseInsensitive)) { + hit = true; + } - for (const auto& item : m_searchItems) { - if (!p_key.isEmpty() && item.m_words.contains(p_key, Qt::CaseInsensitive)) { - // Continue to search all the matched targets. - hit = true; - searchHit(item.m_target, true); - } else { - searchHit(item.m_target, false); - } + for (const auto &item : m_searchItems) { + if (!p_key.isEmpty() && item.m_words.contains(p_key, Qt::CaseInsensitive)) { + // Continue to search all the matched targets. + hit = true; + searchHit(item.m_target, true); + } else { + searchHit(item.m_target, false); } + } - return hit; + return hit; } -void SettingsPage::searchHit(QWidget *p_target, bool p_hit) -{ - if (!p_target) { - return; - } +void SettingsPage::searchHit(QWidget *p_target, bool p_hit) { + if (!p_target) { + return; + } - if (p_target->property(PropertyDefs::c_hitSettingWidget).toBool() == p_hit) { - return; - } + if (p_target->property(PropertyDefs::c_hitSettingWidget).toBool() == p_hit) { + return; + } - WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidget, p_hit); + WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidget, p_hit); } -void SettingsPage::addSearchItem(const QString &p_words, QWidget *p_target) -{ - m_searchItems.push_back(SearchItem(p_words, p_target)); +void SettingsPage::addSearchItem(const QString &p_words, QWidget *p_target) { + m_searchItems.push_back(SearchItem(p_words, p_target)); } -void SettingsPage::addSearchItem(const QString &p_name, const QString &p_tooltip, QWidget *p_target) -{ - addSearchItem(p_name + QStringLiteral(" ") + p_tooltip, p_target); +void SettingsPage::addSearchItem(const QString &p_name, const QString &p_tooltip, + QWidget *p_target) { + addSearchItem(p_name + QStringLiteral(" ") + p_tooltip, p_target); } -void SettingsPage::pageIsChanged() -{ - m_changed = true; - emit changed(); +void SettingsPage::pageIsChanged() { + m_changed = true; + emit changed(); } -void SettingsPage::pageIsChangedWithRestartNeeded() -{ - m_changed = true; - m_restartNeeded = true; - emit changed(); +void SettingsPage::pageIsChangedWithRestartNeeded() { + m_changed = true; + m_restartNeeded = true; + emit changed(); } -void SettingsPage::load() -{ - m_loading = true; - loadInternal(); - m_loading = false; - m_changed = false; - m_restartNeeded = false; +void SettingsPage::load() { + m_loading = true; + loadInternal(); + m_loading = false; + m_changed = false; + m_restartNeeded = false; } -bool SettingsPage::save() -{ - if (!m_changed) { - return true; - } +bool SettingsPage::save() { + if (!m_changed) { + return true; + } - if (saveInternal()) { - m_changed = false; - return true; - } + if (saveInternal()) { + m_changed = false; + return true; + } - return false; + return false; } -void SettingsPage::reset() -{ - if (!m_changed) { - return; - } +void SettingsPage::reset() { + if (!m_changed) { + return; + } - load(); + load(); } -const QString &SettingsPage::error() const -{ - return m_error; -} +const QString &SettingsPage::error() const { return m_error; } -void SettingsPage::setError(const QString &p_err) -{ - m_error = p_err; -} +void SettingsPage::setError(const QString &p_err) { m_error = p_err; } -bool SettingsPage::isRestartNeeded() const -{ - return m_restartNeeded; -} +bool SettingsPage::isRestartNeeded() const { return m_restartNeeded; } -bool SettingsPage::isLoading() const -{ - return m_loading; -} +bool SettingsPage::isLoading() const { return m_loading; } diff --git a/src/widgets/dialogs/settings/settingspage.h b/src/widgets/dialogs/settings/settingspage.h index f7fa57c870..92de70a31b 100644 --- a/src/widgets/dialogs/settings/settingspage.h +++ b/src/widgets/dialogs/settings/settingspage.h @@ -3,79 +3,72 @@ #include -namespace vnotex -{ - class SettingsPage : public QWidget - { - Q_OBJECT - public: - explicit SettingsPage(QWidget *p_parent = nullptr); +namespace vnotex { +class SettingsPage : public QWidget { + Q_OBJECT +public: + explicit SettingsPage(QWidget *p_parent = nullptr); - virtual ~SettingsPage(); + virtual ~SettingsPage(); - void load(); + void load(); - bool save(); + bool save(); - void reset(); + void reset(); - virtual QString title() const = 0; + virtual QString title() const = 0; - bool search(const QString &p_key); + bool search(const QString &p_key); - const QString &error() const; + const QString &error() const; - bool isRestartNeeded() const; + bool isRestartNeeded() const; - signals: - void changed(); +signals: + void changed(); - protected: - virtual void loadInternal() = 0; +protected: + virtual void loadInternal() = 0; - virtual bool saveInternal() = 0; + virtual bool saveInternal() = 0; - // Subclass could override this method to highlight matched target. - virtual void searchHit(QWidget *p_target, bool p_hit); + // Subclass could override this method to highlight matched target. + virtual void searchHit(QWidget *p_target, bool p_hit); - void addSearchItem(const QString &p_words, QWidget *p_target); + void addSearchItem(const QString &p_words, QWidget *p_target); - void addSearchItem(const QString &p_name, const QString &p_tooltip, QWidget *p_target); + void addSearchItem(const QString &p_name, const QString &p_tooltip, QWidget *p_target); - void setError(const QString &p_err); + void setError(const QString &p_err); - bool isLoading() const; + bool isLoading() const; - protected slots: - void pageIsChanged(); +protected slots: + void pageIsChanged(); - void pageIsChangedWithRestartNeeded(); + void pageIsChangedWithRestartNeeded(); - private: - struct SearchItem - { - SearchItem() = default; +private: + struct SearchItem { + SearchItem() = default; - SearchItem(const QString &p_words, QWidget *p_target) - : m_words(p_words), - m_target(p_target) - { - } + SearchItem(const QString &p_words, QWidget *p_target) : m_words(p_words), m_target(p_target) {} - QString m_words; - QWidget *m_target = nullptr; - }; + QString m_words; + QWidget *m_target = nullptr; + }; - QVector m_searchItems; + QVector m_searchItems; - bool m_changed = false; + bool m_changed = false; - bool m_restartNeeded = false; + bool m_restartNeeded = false; - bool m_loading = false; + bool m_loading = false; - QString m_error; - }; -} + QString m_error; +}; +} // namespace vnotex #endif // SETTINGSPAGE_H diff --git a/src/widgets/dialogs/settings/texteditorpage.cpp b/src/widgets/dialogs/settings/texteditorpage.cpp index 47d90ff5e9..b2038ba3db 100644 --- a/src/widgets/dialogs/settings/texteditorpage.cpp +++ b/src/widgets/dialogs/settings/texteditorpage.cpp @@ -1,243 +1,233 @@ #include "texteditorpage.h" +#include #include #include -#include #include -#include +#include #include #include -#include #include +#include #include "editorpage.h" using namespace vnotex; -TextEditorPage::TextEditorPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} - -void TextEditorPage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - { - m_lineNumberComboBox = WidgetsFactory::createComboBox(this); - m_lineNumberComboBox->setToolTip(tr("Line number type")); - - m_lineNumberComboBox->addItem(tr("None"), (int)TextEditorConfig::LineNumberType::None); - m_lineNumberComboBox->addItem(tr("Absolute"), (int)TextEditorConfig::LineNumberType::Absolute); - m_lineNumberComboBox->addItem(tr("Relative"), (int)TextEditorConfig::LineNumberType::Relative); - - const QString label(tr("Line number:")); - mainLayout->addRow(label, m_lineNumberComboBox); - addSearchItem(label, m_lineNumberComboBox->toolTip(), m_lineNumberComboBox); - connect(m_lineNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - const QString label(tr("Fold text")); - m_textFoldingCheckBox = WidgetsFactory::createCheckBox(label, this); - m_textFoldingCheckBox->setToolTip(tr("Text folding")); - mainLayout->addRow(m_textFoldingCheckBox); - addSearchItem(label, m_textFoldingCheckBox->toolTip(), m_textFoldingCheckBox); - connect(m_textFoldingCheckBox, &QCheckBox::stateChanged, - this, &TextEditorPage::pageIsChanged); - } - - { - m_inputModeComboBox = WidgetsFactory::createComboBox(this); - m_inputModeComboBox->setToolTip(tr("Input mode like Vi")); - - m_inputModeComboBox->addItem(tr("Normal"), (int)TextEditorConfig::InputMode::NormalMode); - m_inputModeComboBox->addItem(tr("Vi"), (int)TextEditorConfig::InputMode::ViMode); - m_inputModeComboBox->addItem(tr("VSCode"), (int)TextEditorConfig::InputMode::VscodeMode); - - const QString label(tr("Input mode:")); - mainLayout->addRow(label, m_inputModeComboBox); - addSearchItem(label, m_inputModeComboBox->toolTip(), m_inputModeComboBox); - connect(m_inputModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - m_centerCursorComboBox = WidgetsFactory::createComboBox(this); - m_centerCursorComboBox->setToolTip(tr("Force to center text cursor")); - - m_centerCursorComboBox->addItem(tr("Never"), (int)TextEditorConfig::CenterCursor::NeverCenter); - m_centerCursorComboBox->addItem(tr("Always Center"), (int)TextEditorConfig::CenterCursor::AlwaysCenter); - m_centerCursorComboBox->addItem(tr("Center On Bottom"), (int)TextEditorConfig::CenterCursor::CenterOnBottom); - - const QString label(tr("Center cursor:")); - mainLayout->addRow(label, m_centerCursorComboBox); - addSearchItem(label, m_centerCursorComboBox->toolTip(), m_centerCursorComboBox); - connect(m_centerCursorComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - m_wrapModeComboBox = WidgetsFactory::createComboBox(this); - m_wrapModeComboBox->setToolTip(tr("Word wrap mode of editor")); - - m_wrapModeComboBox->addItem(tr("No Wrap"), (int)TextEditorConfig::WrapMode::NoWrap); - m_wrapModeComboBox->addItem(tr("Word Wrap"), (int)TextEditorConfig::WrapMode::WordWrap); - m_wrapModeComboBox->addItem(tr("Wrap Anywhere"), (int)TextEditorConfig::WrapMode::WrapAnywhere); - m_wrapModeComboBox->addItem(tr("Word Wrap Or Wrap Anywhere"), (int)TextEditorConfig::WrapMode::WordWrapOrAnywhere); - - const QString label(tr("Wrap mode:")); - mainLayout->addRow(label, m_wrapModeComboBox); - addSearchItem(label, m_wrapModeComboBox->toolTip(), m_wrapModeComboBox); - connect(m_wrapModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - const QString label(tr("Expand Tab")); - m_expandTabCheckBox = WidgetsFactory::createCheckBox(label, this); - m_expandTabCheckBox->setToolTip(tr("Expand Tab into spaces")); - mainLayout->addRow(m_expandTabCheckBox); - addSearchItem(label, m_expandTabCheckBox->toolTip(), m_expandTabCheckBox); - connect(m_expandTabCheckBox, &QCheckBox::stateChanged, - this, &TextEditorPage::pageIsChanged); - } - - { - m_tabStopWidthSpinBox = WidgetsFactory::createSpinBox(this); - m_tabStopWidthSpinBox->setToolTip(tr("Number of spaces to use where Tab is needed")); - - m_tabStopWidthSpinBox->setRange(1, 32); - m_tabStopWidthSpinBox->setSingleStep(1); - - const QString label(tr("Tab stop width:")); - mainLayout->addRow(label, m_tabStopWidthSpinBox); - addSearchItem(label, m_tabStopWidthSpinBox->toolTip(), m_tabStopWidthSpinBox); - connect(m_tabStopWidthSpinBox, QOverload::of(&QSpinBox::valueChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - const QString label(tr("Highlight whitespace")); - m_highlightWhitespaceCheckBox = WidgetsFactory::createCheckBox(label, this); - m_highlightWhitespaceCheckBox->setToolTip(tr("Highlight Tab and trailing space")); - mainLayout->addRow(m_highlightWhitespaceCheckBox); - addSearchItem(label, m_highlightWhitespaceCheckBox->toolTip(), m_highlightWhitespaceCheckBox); - connect(m_highlightWhitespaceCheckBox, &QCheckBox::stateChanged, - this, &TextEditorPage::pageIsChanged); - } - - { - m_zoomDeltaSpinBox = WidgetsFactory::createSpinBox(this); - m_zoomDeltaSpinBox->setToolTip(tr("Zoom delta of the basic font size")); - - m_zoomDeltaSpinBox->setRange(-20, 20); - m_zoomDeltaSpinBox->setSingleStep(1); - - const QString label(tr("Zoom delta:")); - mainLayout->addRow(label, m_zoomDeltaSpinBox); - addSearchItem(label, m_zoomDeltaSpinBox->toolTip(), m_zoomDeltaSpinBox); - connect(m_zoomDeltaSpinBox, QOverload::of(&QSpinBox::valueChanged), - this, &TextEditorPage::pageIsChanged); - } - - { - const QString label(tr("Spell check")); - m_spellCheckCheckBox = WidgetsFactory::createCheckBox(label, this); - m_spellCheckCheckBox->setToolTip(tr("Spell check")); - mainLayout->addRow(m_spellCheckCheckBox); - addSearchItem(label, m_spellCheckCheckBox->toolTip(), m_spellCheckCheckBox); - connect(m_spellCheckCheckBox, &QCheckBox::stateChanged, - this, &TextEditorPage::pageIsChanged); - } +TextEditorPage::TextEditorPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void TextEditorPage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + { + m_lineNumberComboBox = WidgetsFactory::createComboBox(this); + m_lineNumberComboBox->setToolTip(tr("Line number type")); + + m_lineNumberComboBox->addItem(tr("None"), (int)TextEditorConfig::LineNumberType::None); + m_lineNumberComboBox->addItem(tr("Absolute"), (int)TextEditorConfig::LineNumberType::Absolute); + m_lineNumberComboBox->addItem(tr("Relative"), (int)TextEditorConfig::LineNumberType::Relative); + + const QString label(tr("Line number:")); + mainLayout->addRow(label, m_lineNumberComboBox); + addSearchItem(label, m_lineNumberComboBox->toolTip(), m_lineNumberComboBox); + connect(m_lineNumberComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + const QString label(tr("Fold text")); + m_textFoldingCheckBox = WidgetsFactory::createCheckBox(label, this); + m_textFoldingCheckBox->setToolTip(tr("Text folding")); + mainLayout->addRow(m_textFoldingCheckBox); + addSearchItem(label, m_textFoldingCheckBox->toolTip(), m_textFoldingCheckBox); + connect(m_textFoldingCheckBox, &QCheckBox::stateChanged, this, &TextEditorPage::pageIsChanged); + } + + { + m_inputModeComboBox = WidgetsFactory::createComboBox(this); + m_inputModeComboBox->setToolTip(tr("Input mode like Vi")); + + m_inputModeComboBox->addItem(tr("Normal"), (int)TextEditorConfig::InputMode::NormalMode); + m_inputModeComboBox->addItem(tr("Vi"), (int)TextEditorConfig::InputMode::ViMode); + m_inputModeComboBox->addItem(tr("VSCode"), (int)TextEditorConfig::InputMode::VscodeMode); + + const QString label(tr("Input mode:")); + mainLayout->addRow(label, m_inputModeComboBox); + addSearchItem(label, m_inputModeComboBox->toolTip(), m_inputModeComboBox); + connect(m_inputModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + m_centerCursorComboBox = WidgetsFactory::createComboBox(this); + m_centerCursorComboBox->setToolTip(tr("Force to center text cursor")); + + m_centerCursorComboBox->addItem(tr("Never"), (int)TextEditorConfig::CenterCursor::NeverCenter); + m_centerCursorComboBox->addItem(tr("Always Center"), + (int)TextEditorConfig::CenterCursor::AlwaysCenter); + m_centerCursorComboBox->addItem(tr("Center On Bottom"), + (int)TextEditorConfig::CenterCursor::CenterOnBottom); + + const QString label(tr("Center cursor:")); + mainLayout->addRow(label, m_centerCursorComboBox); + addSearchItem(label, m_centerCursorComboBox->toolTip(), m_centerCursorComboBox); + connect(m_centerCursorComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + m_wrapModeComboBox = WidgetsFactory::createComboBox(this); + m_wrapModeComboBox->setToolTip(tr("Word wrap mode of editor")); + + m_wrapModeComboBox->addItem(tr("No Wrap"), (int)TextEditorConfig::WrapMode::NoWrap); + m_wrapModeComboBox->addItem(tr("Word Wrap"), (int)TextEditorConfig::WrapMode::WordWrap); + m_wrapModeComboBox->addItem(tr("Wrap Anywhere"), (int)TextEditorConfig::WrapMode::WrapAnywhere); + m_wrapModeComboBox->addItem(tr("Word Wrap Or Wrap Anywhere"), + (int)TextEditorConfig::WrapMode::WordWrapOrAnywhere); + + const QString label(tr("Wrap mode:")); + mainLayout->addRow(label, m_wrapModeComboBox); + addSearchItem(label, m_wrapModeComboBox->toolTip(), m_wrapModeComboBox); + connect(m_wrapModeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + const QString label(tr("Expand Tab")); + m_expandTabCheckBox = WidgetsFactory::createCheckBox(label, this); + m_expandTabCheckBox->setToolTip(tr("Expand Tab into spaces")); + mainLayout->addRow(m_expandTabCheckBox); + addSearchItem(label, m_expandTabCheckBox->toolTip(), m_expandTabCheckBox); + connect(m_expandTabCheckBox, &QCheckBox::stateChanged, this, &TextEditorPage::pageIsChanged); + } + + { + m_tabStopWidthSpinBox = WidgetsFactory::createSpinBox(this); + m_tabStopWidthSpinBox->setToolTip(tr("Number of spaces to use where Tab is needed")); + + m_tabStopWidthSpinBox->setRange(1, 32); + m_tabStopWidthSpinBox->setSingleStep(1); + + const QString label(tr("Tab stop width:")); + mainLayout->addRow(label, m_tabStopWidthSpinBox); + addSearchItem(label, m_tabStopWidthSpinBox->toolTip(), m_tabStopWidthSpinBox); + connect(m_tabStopWidthSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + const QString label(tr("Highlight whitespace")); + m_highlightWhitespaceCheckBox = WidgetsFactory::createCheckBox(label, this); + m_highlightWhitespaceCheckBox->setToolTip(tr("Highlight Tab and trailing space")); + mainLayout->addRow(m_highlightWhitespaceCheckBox); + addSearchItem(label, m_highlightWhitespaceCheckBox->toolTip(), m_highlightWhitespaceCheckBox); + connect(m_highlightWhitespaceCheckBox, &QCheckBox::stateChanged, this, + &TextEditorPage::pageIsChanged); + } + + { + m_zoomDeltaSpinBox = WidgetsFactory::createSpinBox(this); + m_zoomDeltaSpinBox->setToolTip(tr("Zoom delta of the basic font size")); + + m_zoomDeltaSpinBox->setRange(-20, 20); + m_zoomDeltaSpinBox->setSingleStep(1); + + const QString label(tr("Zoom delta:")); + mainLayout->addRow(label, m_zoomDeltaSpinBox); + addSearchItem(label, m_zoomDeltaSpinBox->toolTip(), m_zoomDeltaSpinBox); + connect(m_zoomDeltaSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + &TextEditorPage::pageIsChanged); + } + + { + const QString label(tr("Spell check")); + m_spellCheckCheckBox = WidgetsFactory::createCheckBox(label, this); + m_spellCheckCheckBox->setToolTip(tr("Spell check")); + mainLayout->addRow(m_spellCheckCheckBox); + addSearchItem(label, m_spellCheckCheckBox->toolTip(), m_spellCheckCheckBox); + connect(m_spellCheckCheckBox, &QCheckBox::stateChanged, this, &TextEditorPage::pageIsChanged); + } } -void TextEditorPage::loadInternal() -{ - const auto &textConfig = ConfigMgr::getInst().getEditorConfig().getTextEditorConfig(); +void TextEditorPage::loadInternal() { + const auto &textConfig = ConfigMgr::getInst().getEditorConfig().getTextEditorConfig(); - { - int idx = m_lineNumberComboBox->findData(static_cast(textConfig.getLineNumberType())); - Q_ASSERT(idx != -1); - m_lineNumberComboBox->setCurrentIndex(idx); - } + { + int idx = m_lineNumberComboBox->findData(static_cast(textConfig.getLineNumberType())); + Q_ASSERT(idx != -1); + m_lineNumberComboBox->setCurrentIndex(idx); + } - m_textFoldingCheckBox->setChecked(textConfig.getTextFoldingEnabled()); + m_textFoldingCheckBox->setChecked(textConfig.getTextFoldingEnabled()); - { - int idx = m_inputModeComboBox->findData(static_cast(textConfig.getInputMode())); - Q_ASSERT(idx != -1); - m_inputModeComboBox->setCurrentIndex(idx); - } + { + int idx = m_inputModeComboBox->findData(static_cast(textConfig.getInputMode())); + Q_ASSERT(idx != -1); + m_inputModeComboBox->setCurrentIndex(idx); + } - { - int idx = m_centerCursorComboBox->findData(static_cast(textConfig.getCenterCursor())); - Q_ASSERT(idx != -1); - m_centerCursorComboBox->setCurrentIndex(idx); - } + { + int idx = m_centerCursorComboBox->findData(static_cast(textConfig.getCenterCursor())); + Q_ASSERT(idx != -1); + m_centerCursorComboBox->setCurrentIndex(idx); + } - { - int idx = m_wrapModeComboBox->findData(static_cast(textConfig.getWrapMode())); - Q_ASSERT(idx != -1); - m_wrapModeComboBox->setCurrentIndex(idx); - } + { + int idx = m_wrapModeComboBox->findData(static_cast(textConfig.getWrapMode())); + Q_ASSERT(idx != -1); + m_wrapModeComboBox->setCurrentIndex(idx); + } - m_expandTabCheckBox->setChecked(textConfig.getExpandTabEnabled()); + m_expandTabCheckBox->setChecked(textConfig.getExpandTabEnabled()); - m_tabStopWidthSpinBox->setValue(textConfig.getTabStopWidth()); + m_tabStopWidthSpinBox->setValue(textConfig.getTabStopWidth()); - m_highlightWhitespaceCheckBox->setChecked(textConfig.getHighlightWhitespaceEnabled()); + m_highlightWhitespaceCheckBox->setChecked(textConfig.getHighlightWhitespaceEnabled()); - m_zoomDeltaSpinBox->setValue(textConfig.getZoomDelta()); + m_zoomDeltaSpinBox->setValue(textConfig.getZoomDelta()); - m_spellCheckCheckBox->setChecked(textConfig.isSpellCheckEnabled()); + m_spellCheckCheckBox->setChecked(textConfig.isSpellCheckEnabled()); } -bool TextEditorPage::saveInternal() -{ - auto &textConfig = ConfigMgr::getInst().getEditorConfig().getTextEditorConfig(); +bool TextEditorPage::saveInternal() { + auto &textConfig = ConfigMgr::getInst().getEditorConfig().getTextEditorConfig(); - { - auto lineNumber = m_lineNumberComboBox->currentData().toInt(); - textConfig.setLineNumberType(static_cast(lineNumber)); - } + { + auto lineNumber = m_lineNumberComboBox->currentData().toInt(); + textConfig.setLineNumberType(static_cast(lineNumber)); + } - textConfig.setTextFoldingEnabled(m_textFoldingCheckBox->isChecked()); + textConfig.setTextFoldingEnabled(m_textFoldingCheckBox->isChecked()); - { - auto inputMode = m_inputModeComboBox->currentData().toInt(); - textConfig.setInputMode(static_cast(inputMode)); - } + { + auto inputMode = m_inputModeComboBox->currentData().toInt(); + textConfig.setInputMode(static_cast(inputMode)); + } - { - auto centerCursor = m_centerCursorComboBox->currentData().toInt(); - textConfig.setCenterCursor(static_cast(centerCursor)); - } + { + auto centerCursor = m_centerCursorComboBox->currentData().toInt(); + textConfig.setCenterCursor(static_cast(centerCursor)); + } - { - auto wrapMode = m_wrapModeComboBox->currentData().toInt(); - textConfig.setWrapMode(static_cast(wrapMode)); - } + { + auto wrapMode = m_wrapModeComboBox->currentData().toInt(); + textConfig.setWrapMode(static_cast(wrapMode)); + } - textConfig.setExpandTabEnabled(m_expandTabCheckBox->isChecked()); + textConfig.setExpandTabEnabled(m_expandTabCheckBox->isChecked()); - textConfig.setTabStopWidth(m_tabStopWidthSpinBox->value()); + textConfig.setTabStopWidth(m_tabStopWidthSpinBox->value()); - textConfig.setHighlightWhitespaceEnabled(m_highlightWhitespaceCheckBox->isChecked()); + textConfig.setHighlightWhitespaceEnabled(m_highlightWhitespaceCheckBox->isChecked()); - textConfig.setZoomDelta(m_zoomDeltaSpinBox->value()); + textConfig.setZoomDelta(m_zoomDeltaSpinBox->value()); - textConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked()); + textConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked()); - EditorPage::notifyEditorConfigChange(); + EditorPage::notifyEditorConfigChange(); - return true; + return true; } -QString TextEditorPage::title() const -{ - return tr("Text Editor"); -} +QString TextEditorPage::title() const { return tr("Text Editor"); } diff --git a/src/widgets/dialogs/settings/texteditorpage.h b/src/widgets/dialogs/settings/texteditorpage.h index 6b214b4c84..725799690d 100644 --- a/src/widgets/dialogs/settings/texteditorpage.h +++ b/src/widgets/dialogs/settings/texteditorpage.h @@ -7,44 +7,42 @@ class QComboBox; class QCheckBox; class QSpinBox; -namespace vnotex -{ - class TextEditorPage : public SettingsPage - { - Q_OBJECT - public: - explicit TextEditorPage(QWidget *p_parent = nullptr); +namespace vnotex { +class TextEditorPage : public SettingsPage { + Q_OBJECT +public: + explicit TextEditorPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QComboBox *m_lineNumberComboBox = nullptr; + QComboBox *m_lineNumberComboBox = nullptr; - QCheckBox *m_textFoldingCheckBox = nullptr; + QCheckBox *m_textFoldingCheckBox = nullptr; - QComboBox *m_inputModeComboBox = nullptr; + QComboBox *m_inputModeComboBox = nullptr; - QComboBox *m_centerCursorComboBox = nullptr; + QComboBox *m_centerCursorComboBox = nullptr; - QComboBox *m_wrapModeComboBox = nullptr; + QComboBox *m_wrapModeComboBox = nullptr; - QCheckBox *m_expandTabCheckBox = nullptr; + QCheckBox *m_expandTabCheckBox = nullptr; - QSpinBox *m_tabStopWidthSpinBox = nullptr; + QSpinBox *m_tabStopWidthSpinBox = nullptr; - QCheckBox *m_highlightWhitespaceCheckBox = nullptr; + QCheckBox *m_highlightWhitespaceCheckBox = nullptr; - QSpinBox *m_zoomDeltaSpinBox = nullptr; + QSpinBox *m_zoomDeltaSpinBox = nullptr; - QCheckBox *m_spellCheckCheckBox = nullptr; - }; -} + QCheckBox *m_spellCheckCheckBox = nullptr; +}; +} // namespace vnotex #endif // TEXTEDITORPAGE_H diff --git a/src/widgets/dialogs/settings/themepage.cpp b/src/widgets/dialogs/settings/themepage.cpp index 00110cb8ab..01531375e8 100644 --- a/src/widgets/dialogs/settings/themepage.cpp +++ b/src/widgets/dialogs/settings/themepage.cpp @@ -1,163 +1,145 @@ #include "themepage.h" #include -#include -#include +#include #include -#include #include -#include -#include +#include +#include #include +#include +#include -#include -#include #include -#include -#include -#include +#include #include #include +#include +#include #include +#include +#include using namespace vnotex; -ThemePage::ThemePage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); +ThemePage::ThemePage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void ThemePage::setupUI() { + auto mainLayout = new QVBoxLayout(this); + + // Theme. + { + auto layout = new QGridLayout(); + mainLayout->addLayout(layout); + + m_themeListWidget = new ListWidget(this); + layout->addWidget(m_themeListWidget, 0, 0, 3, 2); + connect(m_themeListWidget, &QListWidget::currentItemChanged, this, + [this](QListWidgetItem *p_current, QListWidgetItem *p_previous) { + Q_UNUSED(p_previous); + loadThemePreview(p_current ? p_current->data(Qt::UserRole).toString() : QString()); + pageIsChangedWithRestartNeeded(); + }); + + auto refreshBtn = new QPushButton(tr("Refresh"), this); + layout->addWidget(refreshBtn, 3, 0, 1, 1); + connect(refreshBtn, &QPushButton::clicked, this, [this]() { + VNoteX::getInst().getThemeMgr().refresh(); + loadThemes(); + }); + + auto addBtn = new QPushButton(tr("Add/Delete"), this); + layout->addWidget(addBtn, 3, 1, 1, 1); + // TODO: open an editor to edit the theme list. + connect(addBtn, &QPushButton::clicked, this, []() { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(ConfigMgr::getInst().getUserThemeFolder())); + }); + + auto updateBtn = new QPushButton(tr("Update"), this); + layout->addWidget(updateBtn, 4, 0, 1, 1); + + auto openLocationBtn = new QPushButton(tr("Open Location"), this); + layout->addWidget(openLocationBtn, 4, 1, 1, 1); + connect(openLocationBtn, &QPushButton::clicked, this, [this]() { + auto theme = VNoteX::getInst().getThemeMgr().findTheme(currentTheme()); + if (theme) { + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(theme->m_folderPath)); + } + }); + + m_noPreviewText = tr("No Preview Available"); + m_previewLabel = new QLabel(m_noPreviewText, this); + m_previewLabel->setScaledContents(true); + m_previewLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); + auto scrollArea = new QScrollArea(this); + scrollArea->setBackgroundRole(QPalette::Dark); + scrollArea->setWidget(m_previewLabel); + scrollArea->setMinimumSize(256, 256); + layout->addWidget(scrollArea, 0, 2, 5, 1); + } + + mainLayout->addStretch(); } -void ThemePage::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - - // Theme. - { - auto layout = new QGridLayout(); - mainLayout->addLayout(layout); - - m_themeListWidget = new ListWidget(this); - layout->addWidget(m_themeListWidget, 0, 0, 3, 2); - connect(m_themeListWidget, &QListWidget::currentItemChanged, - this, [this](QListWidgetItem *p_current, QListWidgetItem *p_previous) { - Q_UNUSED(p_previous); - loadThemePreview(p_current ? p_current->data(Qt::UserRole).toString() : QString()); - pageIsChangedWithRestartNeeded(); - }); - - auto refreshBtn = new QPushButton(tr("Refresh"), this); - layout->addWidget(refreshBtn, 3, 0, 1, 1); - connect(refreshBtn, &QPushButton::clicked, - this, [this]() { - VNoteX::getInst().getThemeMgr().refresh(); - loadThemes(); - }); - - auto addBtn = new QPushButton(tr("Add/Delete"), this); - layout->addWidget(addBtn, 3, 1, 1, 1); - // TODO: open an editor to edit the theme list. - connect(addBtn, &QPushButton::clicked, - this, []() { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(ConfigMgr::getInst().getUserThemeFolder())); - }); - - auto updateBtn = new QPushButton(tr("Update"), this); - layout->addWidget(updateBtn, 4, 0, 1, 1); - - auto openLocationBtn = new QPushButton(tr("Open Location"), this); - layout->addWidget(openLocationBtn, 4, 1, 1, 1); - connect(openLocationBtn, &QPushButton::clicked, - this, [this]() { - auto theme = VNoteX::getInst().getThemeMgr().findTheme(currentTheme()); - if (theme) { - WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(theme->m_folderPath)); - } - }); - - m_noPreviewText = tr("No Preview Available"); - m_previewLabel = new QLabel(m_noPreviewText, this); - m_previewLabel->setScaledContents(true); - m_previewLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); - auto scrollArea = new QScrollArea(this); - scrollArea->setBackgroundRole(QPalette::Dark); - scrollArea->setWidget(m_previewLabel); - scrollArea->setMinimumSize(256, 256); - layout->addWidget(scrollArea, 0, 2, 5, 1); - } - - mainLayout->addStretch(); -} - -void ThemePage::loadInternal() -{ - loadThemes(); -} - -bool ThemePage::saveInternal() -{ - auto theme = currentTheme(); - if (!theme.isEmpty()) { - ConfigMgr::getInst().getCoreConfig().setTheme(theme); - } +void ThemePage::loadInternal() { loadThemes(); } - return true; -} +bool ThemePage::saveInternal() { + auto theme = currentTheme(); + if (!theme.isEmpty()) { + ConfigMgr::getInst().getCoreConfig().setTheme(theme); + } -QString ThemePage::title() const -{ - return tr("Theme"); + return true; } -void ThemePage::loadThemes() -{ - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - const auto &themes = themeMgr.getAllThemes(); - - m_themeListWidget->clear(); - for (const auto &info : themes) { - auto item = new QListWidgetItem(info.m_displayName, m_themeListWidget); - item->setData(Qt::UserRole, info.m_name); - item->setToolTip(info.m_folderPath); +QString ThemePage::title() const { return tr("Theme"); } + +void ThemePage::loadThemes() { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + const auto &themes = themeMgr.getAllThemes(); + + m_themeListWidget->clear(); + for (const auto &info : themes) { + auto item = new QListWidgetItem(info.m_displayName, m_themeListWidget); + item->setData(Qt::UserRole, info.m_name); + item->setToolTip(info.m_folderPath); + } + + // Set current theme. + bool found = false; + const auto curThemeName = themeMgr.getCurrentTheme().name(); + for (int i = 0; i < m_themeListWidget->count(); ++i) { + if (m_themeListWidget->item(i)->data(Qt::UserRole).toString() == curThemeName) { + m_themeListWidget->setCurrentRow(i); + found = true; + break; } + } - // Set current theme. - bool found = false; - const auto curThemeName = themeMgr.getCurrentTheme().name(); - for (int i = 0; i < m_themeListWidget->count(); ++i) { - if (m_themeListWidget->item(i)->data(Qt::UserRole).toString() == curThemeName) { - m_themeListWidget->setCurrentRow(i); - found = true; - break; - } - } - - if (!found && m_themeListWidget->count() > 0) { - m_themeListWidget->setCurrentRow(0); - } + if (!found && m_themeListWidget->count() > 0) { + m_themeListWidget->setCurrentRow(0); + } } -void ThemePage::loadThemePreview(const QString &p_name) -{ - if (p_name.isEmpty()) { - m_previewLabel->setText(m_noPreviewText); - } - - auto pixmap = VNoteX::getInst().getThemeMgr().getThemePreview(p_name); - if (pixmap.isNull()) { - m_previewLabel->setText(m_noPreviewText); - } else { - const int pwidth = 512; - m_previewLabel->setPixmap(pixmap.scaledToWidth(pwidth, Qt::SmoothTransformation)); - } - m_previewLabel->adjustSize(); +void ThemePage::loadThemePreview(const QString &p_name) { + if (p_name.isEmpty()) { + m_previewLabel->setText(m_noPreviewText); + } + + auto pixmap = VNoteX::getInst().getThemeMgr().getThemePreview(p_name); + if (pixmap.isNull()) { + m_previewLabel->setText(m_noPreviewText); + } else { + const int pwidth = 512; + m_previewLabel->setPixmap(pixmap.scaledToWidth(pwidth, Qt::SmoothTransformation)); + } + m_previewLabel->adjustSize(); } -QString ThemePage::currentTheme() const -{ - auto item = m_themeListWidget->currentItem(); - if (item) { - return item->data(Qt::UserRole).toString(); - } - return QString(); +QString ThemePage::currentTheme() const { + auto item = m_themeListWidget->currentItem(); + if (item) { + return item->data(Qt::UserRole).toString(); + } + return QString(); } diff --git a/src/widgets/dialogs/settings/themepage.h b/src/widgets/dialogs/settings/themepage.h index e288a66f87..48a058070d 100644 --- a/src/widgets/dialogs/settings/themepage.h +++ b/src/widgets/dialogs/settings/themepage.h @@ -6,36 +6,34 @@ class QListWidget; class QLabel; -namespace vnotex -{ - class ThemePage : public SettingsPage - { - Q_OBJECT - public: - explicit ThemePage(QWidget *p_parent = nullptr); +namespace vnotex { +class ThemePage : public SettingsPage { + Q_OBJECT +public: + explicit ThemePage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void loadThemes(); + void loadThemes(); - void loadThemePreview(const QString &p_name); + void loadThemePreview(const QString &p_name); - QString currentTheme() const; + QString currentTheme() const; - QListWidget *m_themeListWidget = nullptr; + QListWidget *m_themeListWidget = nullptr; - QLabel *m_previewLabel = nullptr; + QLabel *m_previewLabel = nullptr; - QString m_noPreviewText; - }; -} + QString m_noPreviewText; +}; +} // namespace vnotex #endif // THEMEPAGE_H diff --git a/src/widgets/dialogs/settings/vipage.cpp b/src/widgets/dialogs/settings/vipage.cpp index 22c619b3d3..614f53dd63 100644 --- a/src/widgets/dialogs/settings/vipage.cpp +++ b/src/widgets/dialogs/settings/vipage.cpp @@ -5,58 +5,47 @@ #include -#include -#include #include +#include #include +#include #include "editorpage.h" using namespace vnotex; -ViPage::ViPage(QWidget *p_parent) - : SettingsPage(p_parent) -{ - setupUI(); -} +ViPage::ViPage(QWidget *p_parent) : SettingsPage(p_parent) { setupUI(); } + +void ViPage::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); -void ViPage::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - { - const QString label(tr("Ctrl+C/X to copy/cut")); - m_controlCToCopyCheckBox = WidgetsFactory::createCheckBox(label, this); - m_controlCToCopyCheckBox->setToolTip(tr("Use Ctrl+C/X to copy/cut text")); - mainLayout->addRow(m_controlCToCopyCheckBox); - addSearchItem(label, m_controlCToCopyCheckBox->toolTip(), m_controlCToCopyCheckBox); - connect(m_controlCToCopyCheckBox, &QCheckBox::stateChanged, - this, &ViPage::pageIsChanged); - } + { + const QString label(tr("Ctrl+C/X to copy/cut")); + m_controlCToCopyCheckBox = WidgetsFactory::createCheckBox(label, this); + m_controlCToCopyCheckBox->setToolTip(tr("Use Ctrl+C/X to copy/cut text")); + mainLayout->addRow(m_controlCToCopyCheckBox); + addSearchItem(label, m_controlCToCopyCheckBox->toolTip(), m_controlCToCopyCheckBox); + connect(m_controlCToCopyCheckBox, &QCheckBox::stateChanged, this, &ViPage::pageIsChanged); + } } -void ViPage::loadInternal() -{ - const auto &viConfig = ConfigMgr::getInst().getEditorConfig().getViConfig(); +void ViPage::loadInternal() { + const auto &viConfig = ConfigMgr::getInst().getEditorConfig().getViConfig(); - m_controlCToCopyCheckBox->setChecked(viConfig->m_controlCToCopy); + m_controlCToCopyCheckBox->setChecked(viConfig->m_controlCToCopy); } -bool ViPage::saveInternal() -{ - auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - auto &viConfig = editorConfig.getViConfig(); +bool ViPage::saveInternal() { + auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + auto &viConfig = editorConfig.getViConfig(); - viConfig->m_controlCToCopy = m_controlCToCopyCheckBox->isChecked(); + viConfig->m_controlCToCopy = m_controlCToCopyCheckBox->isChecked(); - editorConfig.update(); + editorConfig.update(); - EditorPage::notifyEditorConfigChange(); + EditorPage::notifyEditorConfigChange(); - return true; + return true; } -QString ViPage::title() const -{ - return tr("Vi Input Mode"); -} +QString ViPage::title() const { return tr("Vi Input Mode"); } diff --git a/src/widgets/dialogs/settings/vipage.h b/src/widgets/dialogs/settings/vipage.h index a753167627..6f0335902a 100644 --- a/src/widgets/dialogs/settings/vipage.h +++ b/src/widgets/dialogs/settings/vipage.h @@ -5,26 +5,24 @@ class QCheckBox; -namespace vnotex -{ - class ViPage : public SettingsPage - { - Q_OBJECT - public: - explicit ViPage(QWidget *p_parent = nullptr); +namespace vnotex { +class ViPage : public SettingsPage { + Q_OBJECT +public: + explicit ViPage(QWidget *p_parent = nullptr); - QString title() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; - protected: - void loadInternal() Q_DECL_OVERRIDE; +protected: + void loadInternal() Q_DECL_OVERRIDE; - bool saveInternal() Q_DECL_OVERRIDE; + bool saveInternal() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - QCheckBox *m_controlCToCopyCheckBox = nullptr; - }; -} + QCheckBox *m_controlCToCopyCheckBox = nullptr; +}; +} // namespace vnotex #endif // VIPAGE_H diff --git a/src/widgets/dialogs/snippetinfowidget.cpp b/src/widgets/dialogs/snippetinfowidget.cpp index 85cf6568cc..8dde741ade 100644 --- a/src/widgets/dialogs/snippetinfowidget.cpp +++ b/src/widgets/dialogs/snippetinfowidget.cpp @@ -1,195 +1,164 @@ #include "snippetinfowidget.h" -#include -#include +#include #include #include -#include +#include +#include -#include #include #include -#include #include +#include +#include using namespace vnotex; -SnippetInfoWidget::SnippetInfoWidget(QWidget *p_parent) - : QWidget(p_parent), - m_mode(Mode::Create) -{ - setupUI(); +SnippetInfoWidget::SnippetInfoWidget(QWidget *p_parent) : QWidget(p_parent), m_mode(Mode::Create) { + setupUI(); } SnippetInfoWidget::SnippetInfoWidget(const Snippet *p_snippet, QWidget *p_parent) - : QWidget(p_parent), - m_mode(Mode::Edit) -{ - setupUI(); + : QWidget(p_parent), m_mode(Mode::Edit) { + setupUI(); - setSnippet(p_snippet); + setSnippet(p_snippet); } -void SnippetInfoWidget::setupUI() -{ - auto mainLayout = WidgetsFactory::createFormLayout(this); - - m_nameLineEdit = WidgetsFactory::createLineEdit(this); - auto validator = new QRegularExpressionValidator(QRegularExpression(PathUtils::c_fileNameRegularExpression), - m_nameLineEdit); - m_nameLineEdit->setValidator(validator); - connect(m_nameLineEdit, &QLineEdit::textEdited, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(tr("Name:"), m_nameLineEdit); - - setFocusProxy(m_nameLineEdit); - - m_descriptionLineEdit = WidgetsFactory::createLineEdit(this); - connect(m_descriptionLineEdit, &QLineEdit::textEdited, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(tr("Description:"), m_descriptionLineEdit); - - setupTypeComboBox(this); - mainLayout->addRow(tr("Type:"), m_typeComboBox); - - setupShortcutComboBox(this); - mainLayout->addRow(tr("Shortcut:"), m_shortcutComboBox); - - m_cursorMarkLineEdit = WidgetsFactory::createLineEdit(this); - m_cursorMarkLineEdit->setText(Snippet::c_defaultCursorMark); - m_cursorMarkLineEdit->setToolTip(tr("A mark in the snippet content indicating the cursor position after the application")); - connect(m_cursorMarkLineEdit, &QLineEdit::textEdited, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(tr("Cursor mark:"), m_cursorMarkLineEdit); - - m_selectionMarkLineEdit = WidgetsFactory::createLineEdit(this); - m_selectionMarkLineEdit->setText(Snippet::c_defaultSelectionMark); - m_selectionMarkLineEdit->setToolTip(tr("A mark in the snippet content that will be replaced with the selected text before the application")); - connect(m_selectionMarkLineEdit, &QLineEdit::textEdited, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(tr("Selection mark:"), m_selectionMarkLineEdit); - - m_indentAsFirstLineCheckBox = WidgetsFactory::createCheckBox(tr("Indent as first line"), this); - m_indentAsFirstLineCheckBox->setChecked(true); - connect(m_indentAsFirstLineCheckBox, &QCheckBox::stateChanged, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(m_indentAsFirstLineCheckBox); - - m_contentTextEdit = WidgetsFactory::createPlainTextEdit(this); - m_contentTextEdit->setPlaceholderText(tr("Nested snippet is supported, like `%time%` to embed the snippet `time`")); - connect(m_contentTextEdit, &QPlainTextEdit::textChanged, - this, &SnippetInfoWidget::inputEdited); - mainLayout->addRow(tr("Content:"), m_contentTextEdit); +void SnippetInfoWidget::setupUI() { + auto mainLayout = WidgetsFactory::createFormLayout(this); + + m_nameLineEdit = WidgetsFactory::createLineEdit(this); + auto validator = new QRegularExpressionValidator( + QRegularExpression(PathUtils::c_fileNameRegularExpression), m_nameLineEdit); + m_nameLineEdit->setValidator(validator); + connect(m_nameLineEdit, &QLineEdit::textEdited, this, &SnippetInfoWidget::inputEdited); + mainLayout->addRow(tr("Name:"), m_nameLineEdit); + + setFocusProxy(m_nameLineEdit); + + m_descriptionLineEdit = WidgetsFactory::createLineEdit(this); + connect(m_descriptionLineEdit, &QLineEdit::textEdited, this, &SnippetInfoWidget::inputEdited); + mainLayout->addRow(tr("Description:"), m_descriptionLineEdit); + + setupTypeComboBox(this); + mainLayout->addRow(tr("Type:"), m_typeComboBox); + + setupShortcutComboBox(this); + mainLayout->addRow(tr("Shortcut:"), m_shortcutComboBox); + + m_cursorMarkLineEdit = WidgetsFactory::createLineEdit(this); + m_cursorMarkLineEdit->setText(Snippet::c_defaultCursorMark); + m_cursorMarkLineEdit->setToolTip( + tr("A mark in the snippet content indicating the cursor position after the application")); + connect(m_cursorMarkLineEdit, &QLineEdit::textEdited, this, &SnippetInfoWidget::inputEdited); + mainLayout->addRow(tr("Cursor mark:"), m_cursorMarkLineEdit); + + m_selectionMarkLineEdit = WidgetsFactory::createLineEdit(this); + m_selectionMarkLineEdit->setText(Snippet::c_defaultSelectionMark); + m_selectionMarkLineEdit->setToolTip(tr("A mark in the snippet content that will be replaced with " + "the selected text before the application")); + connect(m_selectionMarkLineEdit, &QLineEdit::textEdited, this, &SnippetInfoWidget::inputEdited); + mainLayout->addRow(tr("Selection mark:"), m_selectionMarkLineEdit); + + m_indentAsFirstLineCheckBox = WidgetsFactory::createCheckBox(tr("Indent as first line"), this); + m_indentAsFirstLineCheckBox->setChecked(true); + connect(m_indentAsFirstLineCheckBox, &QCheckBox::stateChanged, this, + &SnippetInfoWidget::inputEdited); + mainLayout->addRow(m_indentAsFirstLineCheckBox); + + m_contentTextEdit = WidgetsFactory::createPlainTextEdit(this); + m_contentTextEdit->setPlaceholderText( + tr("Nested snippet is supported, like `%time%` to embed the snippet `time`")); + connect(m_contentTextEdit, &QPlainTextEdit::textChanged, this, &SnippetInfoWidget::inputEdited); + mainLayout->addRow(tr("Content:"), m_contentTextEdit); } -void SnippetInfoWidget::setupTypeComboBox(QWidget *p_parent) -{ - m_typeComboBox = WidgetsFactory::createComboBox(p_parent); - m_typeComboBox->addItem(tr("Text"), static_cast(Snippet::Type::Text)); - if (m_mode == Mode::Edit) { - m_typeComboBox->addItem(tr("Dynamic"), static_cast(Snippet::Type::Dynamic)); - } - connect(m_typeComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, [this]() { - emit inputEdited(); - }); +void SnippetInfoWidget::setupTypeComboBox(QWidget *p_parent) { + m_typeComboBox = WidgetsFactory::createComboBox(p_parent); + m_typeComboBox->addItem(tr("Text"), static_cast(Snippet::Type::Text)); + if (m_mode == Mode::Edit) { + m_typeComboBox->addItem(tr("Dynamic"), static_cast(Snippet::Type::Dynamic)); + } + connect(m_typeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this]() { emit inputEdited(); }); } -void SnippetInfoWidget::setupShortcutComboBox(QWidget *p_parent) -{ - m_shortcutComboBox = WidgetsFactory::createComboBox(p_parent); - if (m_mode == Mode::Create) { - initShortcutComboBox(); - } - connect(m_shortcutComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &SnippetInfoWidget::inputEdited); +void SnippetInfoWidget::setupShortcutComboBox(QWidget *p_parent) { + m_shortcutComboBox = WidgetsFactory::createComboBox(p_parent); + if (m_mode == Mode::Create) { + initShortcutComboBox(); + } + connect(m_shortcutComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &SnippetInfoWidget::inputEdited); } -QString SnippetInfoWidget::getName() const -{ - return m_nameLineEdit->text(); -} +QString SnippetInfoWidget::getName() const { return m_nameLineEdit->text(); } -Snippet::Type SnippetInfoWidget::getType() const -{ - return static_cast(m_typeComboBox->currentData().toInt()); +Snippet::Type SnippetInfoWidget::getType() const { + return static_cast(m_typeComboBox->currentData().toInt()); } -int SnippetInfoWidget::getShortcut() const -{ - return m_shortcutComboBox->currentData().toInt(); -} +int SnippetInfoWidget::getShortcut() const { return m_shortcutComboBox->currentData().toInt(); } -QString SnippetInfoWidget::getCursorMark() const -{ - return m_cursorMarkLineEdit->text(); -} +QString SnippetInfoWidget::getCursorMark() const { return m_cursorMarkLineEdit->text(); } -QString SnippetInfoWidget::getSelectionMark() const -{ - return m_selectionMarkLineEdit->text(); -} +QString SnippetInfoWidget::getSelectionMark() const { return m_selectionMarkLineEdit->text(); } -bool SnippetInfoWidget::shouldIndentAsFirstLine() const -{ - return m_indentAsFirstLineCheckBox->isChecked(); +bool SnippetInfoWidget::shouldIndentAsFirstLine() const { + return m_indentAsFirstLineCheckBox->isChecked(); } -QString SnippetInfoWidget::getContent() const -{ - return m_contentTextEdit->toPlainText(); -} - -QString SnippetInfoWidget::getDescription() const -{ - return m_descriptionLineEdit->text(); -} - -void SnippetInfoWidget::setSnippet(const Snippet *p_snippet) -{ - if (m_snippet == p_snippet) { - return; - } - - Q_ASSERT(m_mode == Mode::Edit); - m_snippet = p_snippet; - initShortcutComboBox(); - if (m_snippet) { - const bool readOnly = m_snippet->isReadOnly(); - m_nameLineEdit->setText(m_snippet->getName()); - m_nameLineEdit->setEnabled(!readOnly); - m_descriptionLineEdit->setText(m_snippet->getDescription()); - m_descriptionLineEdit->setEnabled(!readOnly); - m_typeComboBox->setCurrentIndex(m_typeComboBox->findData(static_cast(m_snippet->getType()))); - m_typeComboBox->setEnabled(!readOnly); - m_shortcutComboBox->setCurrentIndex(m_shortcutComboBox->findData(m_snippet->getShortcut())); - m_shortcutComboBox->setEnabled(!readOnly); - m_cursorMarkLineEdit->setText(m_snippet->getCursorMark()); - m_cursorMarkLineEdit->setEnabled(!readOnly); - m_selectionMarkLineEdit->setText(m_snippet->getSelectionMark()); - m_selectionMarkLineEdit->setEnabled(!readOnly); - m_indentAsFirstLineCheckBox->setChecked(m_snippet->isIndentAsFirstLineEnabled()); - m_indentAsFirstLineCheckBox->setEnabled(!readOnly); - m_contentTextEdit->setPlainText(m_snippet->getContent()); - m_contentTextEdit->setEnabled(!readOnly); - } else { - m_nameLineEdit->clear(); - m_descriptionLineEdit->clear(); - m_typeComboBox->setCurrentIndex(m_typeComboBox->findData(static_cast(Snippet::Type::Text))); - m_shortcutComboBox->setCurrentIndex(m_shortcutComboBox->findData(Snippet::InvalidShortcut)); - m_cursorMarkLineEdit->setText(Snippet::c_defaultCursorMark); - m_selectionMarkLineEdit->setText(Snippet::c_defaultSelectionMark); - m_indentAsFirstLineCheckBox->setChecked(true); - m_contentTextEdit->clear(); - } +QString SnippetInfoWidget::getContent() const { return m_contentTextEdit->toPlainText(); } + +QString SnippetInfoWidget::getDescription() const { return m_descriptionLineEdit->text(); } + +void SnippetInfoWidget::setSnippet(const Snippet *p_snippet) { + if (m_snippet == p_snippet) { + return; + } + + Q_ASSERT(m_mode == Mode::Edit); + m_snippet = p_snippet; + initShortcutComboBox(); + if (m_snippet) { + const bool readOnly = m_snippet->isReadOnly(); + m_nameLineEdit->setText(m_snippet->getName()); + m_nameLineEdit->setEnabled(!readOnly); + m_descriptionLineEdit->setText(m_snippet->getDescription()); + m_descriptionLineEdit->setEnabled(!readOnly); + m_typeComboBox->setCurrentIndex( + m_typeComboBox->findData(static_cast(m_snippet->getType()))); + m_typeComboBox->setEnabled(!readOnly); + m_shortcutComboBox->setCurrentIndex(m_shortcutComboBox->findData(m_snippet->getShortcut())); + m_shortcutComboBox->setEnabled(!readOnly); + m_cursorMarkLineEdit->setText(m_snippet->getCursorMark()); + m_cursorMarkLineEdit->setEnabled(!readOnly); + m_selectionMarkLineEdit->setText(m_snippet->getSelectionMark()); + m_selectionMarkLineEdit->setEnabled(!readOnly); + m_indentAsFirstLineCheckBox->setChecked(m_snippet->isIndentAsFirstLineEnabled()); + m_indentAsFirstLineCheckBox->setEnabled(!readOnly); + m_contentTextEdit->setPlainText(m_snippet->getContent()); + m_contentTextEdit->setEnabled(!readOnly); + } else { + m_nameLineEdit->clear(); + m_descriptionLineEdit->clear(); + m_typeComboBox->setCurrentIndex( + m_typeComboBox->findData(static_cast(Snippet::Type::Text))); + m_shortcutComboBox->setCurrentIndex(m_shortcutComboBox->findData(Snippet::InvalidShortcut)); + m_cursorMarkLineEdit->setText(Snippet::c_defaultCursorMark); + m_selectionMarkLineEdit->setText(Snippet::c_defaultSelectionMark); + m_indentAsFirstLineCheckBox->setChecked(true); + m_contentTextEdit->clear(); + } } -void SnippetInfoWidget::initShortcutComboBox() -{ - m_shortcutComboBox->clear(); - m_shortcutComboBox->addItem(tr("None"), Snippet::InvalidShortcut); - const auto shortcuts = SnippetMgr::getInst().getAvailableShortcuts(m_snippet ? m_snippet->getShortcut() : Snippet::InvalidShortcut); - for (auto sh : shortcuts) { - m_shortcutComboBox->addItem(Utils::intToString(sh, 2), sh); - } +void SnippetInfoWidget::initShortcutComboBox() { + m_shortcutComboBox->clear(); + m_shortcutComboBox->addItem(tr("None"), Snippet::InvalidShortcut); + const auto shortcuts = SnippetMgr::getInst().getAvailableShortcuts( + m_snippet ? m_snippet->getShortcut() : Snippet::InvalidShortcut); + for (auto sh : shortcuts) { + m_shortcutComboBox->addItem(Utils::intToString(sh, 2), sh); + } } diff --git a/src/widgets/dialogs/snippetinfowidget.h b/src/widgets/dialogs/snippetinfowidget.h index 9a6408ee30..2126c01dac 100644 --- a/src/widgets/dialogs/snippetinfowidget.h +++ b/src/widgets/dialogs/snippetinfowidget.h @@ -10,68 +10,66 @@ class QComboBox; class QCheckBox; class QPlainTextEdit; -namespace vnotex -{ - class SnippetInfoWidget : public QWidget - { - Q_OBJECT - public: - enum Mode { Create, Edit }; +namespace vnotex { +class SnippetInfoWidget : public QWidget { + Q_OBJECT +public: + enum Mode { Create, Edit }; - explicit SnippetInfoWidget(QWidget *p_parent = nullptr); + explicit SnippetInfoWidget(QWidget *p_parent = nullptr); - SnippetInfoWidget(const Snippet *p_snippet, QWidget *p_parent = nullptr); + SnippetInfoWidget(const Snippet *p_snippet, QWidget *p_parent = nullptr); - QString getName() const; + QString getName() const; - Snippet::Type getType() const; + Snippet::Type getType() const; - int getShortcut() const; + int getShortcut() const; - QString getCursorMark() const; + QString getCursorMark() const; - QString getSelectionMark() const; + QString getSelectionMark() const; - bool shouldIndentAsFirstLine() const; + bool shouldIndentAsFirstLine() const; - QString getContent() const; + QString getContent() const; - QString getDescription() const; + QString getDescription() const; - signals: - void inputEdited(); +signals: + void inputEdited(); - private: - void setupUI(); +private: + void setupUI(); - void setupTypeComboBox(QWidget *p_parent); + void setupTypeComboBox(QWidget *p_parent); - void setupShortcutComboBox(QWidget *p_parent); + void setupShortcutComboBox(QWidget *p_parent); - void setSnippet(const Snippet *p_snippet); + void setSnippet(const Snippet *p_snippet); - void initShortcutComboBox(); + void initShortcutComboBox(); - Mode m_mode = Mode::Create; + Mode m_mode = Mode::Create; - const Snippet *m_snippet = nullptr; + const Snippet *m_snippet = nullptr; - QLineEdit *m_nameLineEdit = nullptr; + QLineEdit *m_nameLineEdit = nullptr; - QLineEdit *m_descriptionLineEdit = nullptr; + QLineEdit *m_descriptionLineEdit = nullptr; - QComboBox *m_typeComboBox = nullptr; + QComboBox *m_typeComboBox = nullptr; - QComboBox *m_shortcutComboBox = nullptr; + QComboBox *m_shortcutComboBox = nullptr; - QLineEdit *m_cursorMarkLineEdit = nullptr; + QLineEdit *m_cursorMarkLineEdit = nullptr; - QLineEdit *m_selectionMarkLineEdit = nullptr; + QLineEdit *m_selectionMarkLineEdit = nullptr; - QCheckBox *m_indentAsFirstLineCheckBox = nullptr; + QCheckBox *m_indentAsFirstLineCheckBox = nullptr; - QPlainTextEdit *m_contentTextEdit = nullptr; - }; -} + QPlainTextEdit *m_contentTextEdit = nullptr; +}; +} // namespace vnotex #endif // SNIPPETINFOWIDGET_H diff --git a/src/widgets/dialogs/snippetpropertiesdialog.cpp b/src/widgets/dialogs/snippetpropertiesdialog.cpp index 3fc37899c6..2ad83f590d 100644 --- a/src/widgets/dialogs/snippetpropertiesdialog.cpp +++ b/src/widgets/dialogs/snippetpropertiesdialog.cpp @@ -1,99 +1,87 @@ #include "snippetpropertiesdialog.h" +#include #include #include -#include #include "snippetinfowidget.h" using namespace vnotex; SnippetPropertiesDialog::SnippetPropertiesDialog(Snippet *p_snippet, QWidget *p_parent) - : ScrollDialog(p_parent), - m_snippet(p_snippet) -{ - Q_ASSERT(m_snippet); - setupUI(); + : ScrollDialog(p_parent), m_snippet(p_snippet) { + Q_ASSERT(m_snippet); + setupUI(); - m_infoWidget->setFocus(); + m_infoWidget->setFocus(); } -void SnippetPropertiesDialog::setupUI() -{ - setupSnippetInfoWidget(this); - setCentralWidget(m_infoWidget); +void SnippetPropertiesDialog::setupUI() { + setupSnippetInfoWidget(this); + setCentralWidget(m_infoWidget); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - if (m_snippet->isReadOnly()) { - setButtonEnabled(QDialogButtonBox::Ok, false); - } + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + if (m_snippet->isReadOnly()) { + setButtonEnabled(QDialogButtonBox::Ok, false); + } - setWindowTitle(tr("%1 Properties").arg(m_snippet->getName())); + setWindowTitle(tr("%1 Properties").arg(m_snippet->getName())); } -void SnippetPropertiesDialog::setupSnippetInfoWidget(QWidget *p_parent) -{ - m_infoWidget = new SnippetInfoWidget(m_snippet, p_parent); +void SnippetPropertiesDialog::setupSnippetInfoWidget(QWidget *p_parent) { + m_infoWidget = new SnippetInfoWidget(m_snippet, p_parent); } -bool SnippetPropertiesDialog::validateInputs() -{ - bool valid = true; - QString msg; +bool SnippetPropertiesDialog::validateInputs() { + bool valid = true; + QString msg; - valid = valid && validateNameInput(msg); - setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info - : ScrollDialog::InformationLevel::Error); - return valid; + valid = valid && validateNameInput(msg); + setInformationText(msg, valid ? ScrollDialog::InformationLevel::Info + : ScrollDialog::InformationLevel::Error); + return valid; } -bool SnippetPropertiesDialog::validateNameInput(QString &p_msg) -{ - p_msg.clear(); +bool SnippetPropertiesDialog::validateNameInput(QString &p_msg) { + p_msg.clear(); - auto name = m_infoWidget->getName(); - if (name.isEmpty()) { - p_msg = tr("Please specify a name for the snippet."); - return false; - } + auto name = m_infoWidget->getName(); + if (name.isEmpty()) { + p_msg = tr("Please specify a name for the snippet."); + return false; + } - if (name.toLower() == m_snippet->getName().toLower()) { - return true; - } + if (name.toLower() == m_snippet->getName().toLower()) { + return true; + } - if (SnippetMgr::getInst().find(name)) { - p_msg = tr("Name conflicts with existing snippet."); - return false; - } + if (SnippetMgr::getInst().find(name)) { + p_msg = tr("Name conflicts with existing snippet."); + return false; + } - return true; + return true; } -void SnippetPropertiesDialog::acceptedButtonClicked() -{ - if (validateInputs() && saveSnippetProperties()) { - accept(); - } +void SnippetPropertiesDialog::acceptedButtonClicked() { + if (validateInputs() && saveSnippetProperties()) { + accept(); + } } -bool SnippetPropertiesDialog::saveSnippetProperties() -{ - auto snip = QSharedPointer::create(m_infoWidget->getName(), - m_infoWidget->getDescription(), - m_infoWidget->getContent(), - m_infoWidget->getShortcut(), - m_infoWidget->shouldIndentAsFirstLine(), - m_infoWidget->getCursorMark(), - m_infoWidget->getSelectionMark()); - Q_ASSERT(snip->isValid()); - try { - SnippetMgr::getInst().updateSnippet(m_snippet->getName(), snip); - } catch (Exception &p_e) { - QString msg = tr("Failed to update snippet (%1) (%2).") - .arg(snip->getName(), p_e.what()); - qWarning() << msg; - setInformationText(msg, ScrollDialog::InformationLevel::Error); - return false; - } - return true; +bool SnippetPropertiesDialog::saveSnippetProperties() { + auto snip = QSharedPointer::create( + m_infoWidget->getName(), m_infoWidget->getDescription(), m_infoWidget->getContent(), + m_infoWidget->getShortcut(), m_infoWidget->shouldIndentAsFirstLine(), + m_infoWidget->getCursorMark(), m_infoWidget->getSelectionMark()); + Q_ASSERT(snip->isValid()); + try { + SnippetMgr::getInst().updateSnippet(m_snippet->getName(), snip); + } catch (Exception &p_e) { + QString msg = tr("Failed to update snippet (%1) (%2).").arg(snip->getName(), p_e.what()); + qWarning() << msg; + setInformationText(msg, ScrollDialog::InformationLevel::Error); + return false; + } + return true; } diff --git a/src/widgets/dialogs/snippetpropertiesdialog.h b/src/widgets/dialogs/snippetpropertiesdialog.h index 7719c4ca0a..8180920020 100644 --- a/src/widgets/dialogs/snippetpropertiesdialog.h +++ b/src/widgets/dialogs/snippetpropertiesdialog.h @@ -3,35 +3,33 @@ #include "scrolldialog.h" -namespace vnotex -{ - class Snippet; - class SnippetInfoWidget; +namespace vnotex { +class Snippet; +class SnippetInfoWidget; - class SnippetPropertiesDialog : public ScrollDialog - { - Q_OBJECT - public: - SnippetPropertiesDialog(Snippet *p_snippet, QWidget *p_parent = nullptr); +class SnippetPropertiesDialog : public ScrollDialog { + Q_OBJECT +public: + SnippetPropertiesDialog(Snippet *p_snippet, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setupSnippetInfoWidget(QWidget *p_parent); + void setupSnippetInfoWidget(QWidget *p_parent); - bool validateNameInput(QString &p_msg); + bool validateNameInput(QString &p_msg); - bool saveSnippetProperties(); + bool saveSnippetProperties(); - bool validateInputs(); + bool validateInputs(); - SnippetInfoWidget *m_infoWidget = nullptr; + SnippetInfoWidget *m_infoWidget = nullptr; - Snippet *m_snippet = nullptr; - }; -} + Snippet *m_snippet = nullptr; +}; +} // namespace vnotex #endif // SNIPPETPROPERTIESDIALOG_H diff --git a/src/widgets/dialogs/sortdialog.cpp b/src/widgets/dialogs/sortdialog.cpp index 2836021841..b708816ebc 100644 --- a/src/widgets/dialogs/sortdialog.cpp +++ b/src/widgets/dialogs/sortdialog.cpp @@ -1,263 +1,244 @@ #include "sortdialog.h" +#include +#include #include #include #include -#include -#include +#include #include -#include #include -#include +#include using namespace vnotex; -SortDialog::SortDialog(const QString &p_title, - const QString &p_info, - QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(p_title, p_info); +SortDialog::SortDialog(const QString &p_title, const QString &p_info, QWidget *p_parent) + : ScrollDialog(p_parent) { + setupUI(p_title, p_info); } -void SortDialog::setupUI(const QString &p_title, const QString &p_info) -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); - - auto mainLayout = new QVBoxLayout(mainWidget); - - if (!p_info.isEmpty()) { - auto infoLabel = new QLabel(p_info, mainWidget); - infoLabel->setWordWrap(true); - mainLayout->addWidget(infoLabel); - } - - { - auto bodyLayout = new QHBoxLayout(); - mainLayout->addLayout(bodyLayout); - - // Tree widget. - // We want to sort it case-insensitive. QTreeView and QSortFilterProxyModel should be the choice. - // For simplicity, we subclass QTreeWidgetItem here. - m_treeWidget = new TreeWidget(mainWidget); - m_treeWidget->setRootIsDecorated(false); - m_treeWidget->setSelectionMode(QAbstractItemView::ContiguousSelection); - m_treeWidget->setDragDropMode(QAbstractItemView::InternalMove); - bodyLayout->addWidget(m_treeWidget); - - // Buttons for top/up/down/bottom. - auto btnLayout = new QVBoxLayout(); - bodyLayout->addLayout(btnLayout); - - auto topBtn = new QPushButton(tr("&Top"), mainWidget); - connect(topBtn, &QPushButton::clicked, - this, [this]() { - handleMoveOperation(MoveOperation::Top); - }); - btnLayout->addWidget(topBtn); - - auto upBtn = new QPushButton(tr("&Up"), mainWidget); - connect(upBtn, &QPushButton::clicked, - this, [this]() { - handleMoveOperation(MoveOperation::Up); - }); - btnLayout->addWidget(upBtn); - - auto downBtn = new QPushButton(tr("&Down"), mainWidget); - connect(downBtn, &QPushButton::clicked, - this, [this]() { - handleMoveOperation(MoveOperation::Down); - }); - btnLayout->addWidget(downBtn); - - auto bottomBtn = new QPushButton(tr("&Bottom"), mainWidget); - connect(bottomBtn, &QPushButton::clicked, - this, [this]() { - handleMoveOperation(MoveOperation::Bottom); - }); - btnLayout->addWidget(bottomBtn); - - btnLayout->addStretch(); - } - - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(p_title); +void SortDialog::setupUI(const QString &p_title, const QString &p_info) { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); + + auto mainLayout = new QVBoxLayout(mainWidget); + + if (!p_info.isEmpty()) { + auto infoLabel = new QLabel(p_info, mainWidget); + infoLabel->setWordWrap(true); + mainLayout->addWidget(infoLabel); + } + + { + auto bodyLayout = new QHBoxLayout(); + mainLayout->addLayout(bodyLayout); + + // Tree widget. + // We want to sort it case-insensitive. QTreeView and QSortFilterProxyModel should be the + // choice. For simplicity, we subclass QTreeWidgetItem here. + m_treeWidget = new TreeWidget(mainWidget); + m_treeWidget->setRootIsDecorated(false); + m_treeWidget->setSelectionMode(QAbstractItemView::ContiguousSelection); + m_treeWidget->setDragDropMode(QAbstractItemView::InternalMove); + bodyLayout->addWidget(m_treeWidget); + + // Buttons for top/up/down/bottom. + auto btnLayout = new QVBoxLayout(); + bodyLayout->addLayout(btnLayout); + + auto topBtn = new QPushButton(tr("&Top"), mainWidget); + connect(topBtn, &QPushButton::clicked, this, + [this]() { handleMoveOperation(MoveOperation::Top); }); + btnLayout->addWidget(topBtn); + + auto upBtn = new QPushButton(tr("&Up"), mainWidget); + connect(upBtn, &QPushButton::clicked, this, + [this]() { handleMoveOperation(MoveOperation::Up); }); + btnLayout->addWidget(upBtn); + + auto downBtn = new QPushButton(tr("&Down"), mainWidget); + connect(downBtn, &QPushButton::clicked, this, + [this]() { handleMoveOperation(MoveOperation::Down); }); + btnLayout->addWidget(downBtn); + + auto bottomBtn = new QPushButton(tr("&Bottom"), mainWidget); + connect(bottomBtn, &QPushButton::clicked, this, + [this]() { handleMoveOperation(MoveOperation::Bottom); }); + btnLayout->addWidget(bottomBtn); + + btnLayout->addStretch(); + } + + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setWindowTitle(p_title); } -QTreeWidget *SortDialog::getTreeWidget() const -{ - return m_treeWidget; -} +QTreeWidget *SortDialog::getTreeWidget() const { return m_treeWidget; } -void SortDialog::updateTreeWidget() -{ - int cols = m_treeWidget->columnCount(); - for (int i = 0; i < cols; ++i) { - m_treeWidget->resizeColumnToContents(i); - } +void SortDialog::updateTreeWidget() { + int cols = m_treeWidget->columnCount(); + for (int i = 0; i < cols; ++i) { + m_treeWidget->resizeColumnToContents(i); + } - QHeaderView *header = m_treeWidget->header(); - if (header) { - header->setStretchLastSection(true); - } + QHeaderView *header = m_treeWidget->header(); + if (header) { + header->setStretchLastSection(true); + } - // We just need single level. - int cnt = m_treeWidget->topLevelItemCount(); - for (int i = 0; i < cnt; ++i) { - QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); - item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled); - } + // We just need single level. + int cnt = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < cnt; ++i) { + QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); + item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled); + } - m_treeWidget->sortByColumn(-1, Qt::AscendingOrder); - m_treeWidget->setSortingEnabled(true); + m_treeWidget->sortByColumn(-1, Qt::AscendingOrder); + m_treeWidget->setSortingEnabled(true); } -QVector SortDialog::getSortedData() const -{ - const int cnt = m_treeWidget->topLevelItemCount(); - QVector data(cnt); - for (int i = 0; i < cnt; ++i) { - QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); - Q_ASSERT(item); - data[i] = item->data(0, Qt::UserRole); - } +QVector SortDialog::getSortedData() const { + const int cnt = m_treeWidget->topLevelItemCount(); + QVector data(cnt); + for (int i = 0; i < cnt; ++i) { + QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); + Q_ASSERT(item); + data[i] = item->data(0, Qt::UserRole); + } - return data; + return data; } -void SortDialog::handleMoveOperation(MoveOperation p_op) -{ - const QList selectedItems = m_treeWidget->selectedItems(); - if (selectedItems.isEmpty()) { - return; +void SortDialog::handleMoveOperation(MoveOperation p_op) { + const QList selectedItems = m_treeWidget->selectedItems(); + if (selectedItems.isEmpty()) { + return; + } + + int first = m_treeWidget->topLevelItemCount(); + int last = -1; + for (const auto &it : selectedItems) { + int idx = m_treeWidget->indexOfTopLevelItem(it); + Q_ASSERT(idx > -1); + if (idx < first) { + first = idx; } - int first = m_treeWidget->topLevelItemCount(); - int last = -1; - for (const auto &it : selectedItems) { - int idx = m_treeWidget->indexOfTopLevelItem(it); - Q_ASSERT(idx > -1); - if (idx < first) { - first = idx; - } - - if (idx > last) { - last = idx; - } + if (idx > last) { + last = idx; } + } - Q_ASSERT(first <= last && (last - first + 1) == selectedItems.size()); - QTreeWidgetItem *firstItem = nullptr; + Q_ASSERT(first <= last && (last - first + 1) == selectedItems.size()); + QTreeWidgetItem *firstItem = nullptr; - m_treeWidget->sortByColumn(-1, Qt::AscendingOrder); + m_treeWidget->sortByColumn(-1, Qt::AscendingOrder); - switch (p_op) { - case MoveOperation::Top: - if (first == 0) { - break; - } + switch (p_op) { + case MoveOperation::Top: + if (first == 0) { + break; + } - m_treeWidget->clearSelection(); + m_treeWidget->clearSelection(); - // Insert item[last] to index 0 repeatedly. - for (int i = last - first; i >= 0; --i) { - QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last); - Q_ASSERT(item); - m_treeWidget->insertTopLevelItem(0, item); - item->setSelected(true); - } + // Insert item[last] to index 0 repeatedly. + for (int i = last - first; i >= 0; --i) { + QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last); + Q_ASSERT(item); + m_treeWidget->insertTopLevelItem(0, item); + item->setSelected(true); + } - firstItem = m_treeWidget->topLevelItem(0); + firstItem = m_treeWidget->topLevelItem(0); - break; + break; - case MoveOperation::Up: - if (first == 0) { - break; - } + case MoveOperation::Up: + if (first == 0) { + break; + } - m_treeWidget->clearSelection(); + m_treeWidget->clearSelection(); - // Insert item[last] to index (first -1) repeatedly. - for (int i = last - first; i >= 0; --i) { - QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last); - Q_ASSERT(item); - m_treeWidget->insertTopLevelItem(first - 1, item); - item->setSelected(true); - } + // Insert item[last] to index (first -1) repeatedly. + for (int i = last - first; i >= 0; --i) { + QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(last); + Q_ASSERT(item); + m_treeWidget->insertTopLevelItem(first - 1, item); + item->setSelected(true); + } - firstItem = m_treeWidget->topLevelItem(first - 1); + firstItem = m_treeWidget->topLevelItem(first - 1); - break; + break; - case MoveOperation::Down: - if (last == m_treeWidget->topLevelItemCount() - 1) { - break; - } + case MoveOperation::Down: + if (last == m_treeWidget->topLevelItemCount() - 1) { + break; + } - m_treeWidget->clearSelection(); + m_treeWidget->clearSelection(); - // Insert item[first] to index (last) repeatedly. - for (int i = last - first; i >= 0; --i) { - QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first); - Q_ASSERT(item); - m_treeWidget->insertTopLevelItem(last + 1, item); - item->setSelected(true); + // Insert item[first] to index (last) repeatedly. + for (int i = last - first; i >= 0; --i) { + QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first); + Q_ASSERT(item); + m_treeWidget->insertTopLevelItem(last + 1, item); + item->setSelected(true); - if (!firstItem) { - firstItem = item; - } - } + if (!firstItem) { + firstItem = item; + } + } - break; + break; - case MoveOperation::Bottom: - if (last == m_treeWidget->topLevelItemCount() - 1) { - break; - } + case MoveOperation::Bottom: + if (last == m_treeWidget->topLevelItemCount() - 1) { + break; + } - m_treeWidget->clearSelection(); + m_treeWidget->clearSelection(); - // Insert item[first] to the last of the tree repeatedly. - for (int i = last - first; i >= 0; --i) { - QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first); - Q_ASSERT(item); - m_treeWidget->addTopLevelItem(item); - item->setSelected(true); + // Insert item[first] to the last of the tree repeatedly. + for (int i = last - first; i >= 0; --i) { + QTreeWidgetItem *item = m_treeWidget->takeTopLevelItem(first); + Q_ASSERT(item); + m_treeWidget->addTopLevelItem(item); + item->setSelected(true); - if (!firstItem) { - firstItem = item; - } - } + if (!firstItem) { + firstItem = item; + } + } - break; + break; - default: - return; - } + default: + return; + } - if (firstItem) { - m_treeWidget->setCurrentItem(firstItem); - m_treeWidget->scrollToItem(firstItem); - } + if (firstItem) { + m_treeWidget->setCurrentItem(firstItem); + m_treeWidget->scrollToItem(firstItem); + } } -QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols) -{ - auto item = new TreeWidgetItem(m_treeWidget, p_cols); - return item; +QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols) { + auto item = new TreeWidgetItem(m_treeWidget, p_cols); + return item; } -QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols, const QStringList &p_comparisonCols) -{ - Q_ASSERT(p_cols.size() == p_comparisonCols.size()); - auto item = new TreeWidgetItem(m_treeWidget, p_cols); - for (int i = 0; i < p_cols.size(); ++i) { - if (!p_comparisonCols[i].isNull()) { - item->setData(i, Role::ComparisonRole, p_comparisonCols[i]); - } +QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols, + const QStringList &p_comparisonCols) { + Q_ASSERT(p_cols.size() == p_comparisonCols.size()); + auto item = new TreeWidgetItem(m_treeWidget, p_cols); + for (int i = 0; i < p_cols.size(); ++i) { + if (!p_comparisonCols[i].isNull()) { + item->setData(i, Role::ComparisonRole, p_comparisonCols[i]); } - return item; + } + return item; } diff --git a/src/widgets/dialogs/sortdialog.h b/src/widgets/dialogs/sortdialog.h index aa10216281..7f092837f8 100644 --- a/src/widgets/dialogs/sortdialog.h +++ b/src/widgets/dialogs/sortdialog.h @@ -7,46 +7,38 @@ class QTreeWidget; class QTreeWidgetItem; class QPushButton; -namespace vnotex -{ - class SortDialog : public ScrollDialog - { - Q_OBJECT - public: - SortDialog(const QString &p_title, const QString &p_info, QWidget *p_parent = nullptr); - - QTreeWidget *getTreeWidget() const; - - // Called after updating the QTreeWidget from getTreeWidget(). - void updateTreeWidget(); - - // Get user data of column 0 from sorted items. - QVector getSortedData() const; - - // Add one item to the tree. - QTreeWidgetItem *addItem(const QStringList &p_cols); - - // Add one item to the tree. - // @p_comparisonCols: for column i, if it is not null, use it for comparison. - QTreeWidgetItem *addItem(const QStringList &p_cols, const QStringList &p_comparisonCols); - - private: - enum MoveOperation - { - Top, - Up, - Down, - Bottom - }; - - private slots: - void handleMoveOperation(MoveOperation p_op); - - private: - void setupUI(const QString &p_title, const QString &p_info); - - QTreeWidget *m_treeWidget = nullptr; - }; -} +namespace vnotex { +class SortDialog : public ScrollDialog { + Q_OBJECT +public: + SortDialog(const QString &p_title, const QString &p_info, QWidget *p_parent = nullptr); + + QTreeWidget *getTreeWidget() const; + + // Called after updating the QTreeWidget from getTreeWidget(). + void updateTreeWidget(); + + // Get user data of column 0 from sorted items. + QVector getSortedData() const; + + // Add one item to the tree. + QTreeWidgetItem *addItem(const QStringList &p_cols); + + // Add one item to the tree. + // @p_comparisonCols: for column i, if it is not null, use it for comparison. + QTreeWidgetItem *addItem(const QStringList &p_cols, const QStringList &p_comparisonCols); + +private: + enum MoveOperation { Top, Up, Down, Bottom }; + +private slots: + void handleMoveOperation(MoveOperation p_op); + +private: + void setupUI(const QString &p_title, const QString &p_info); + + QTreeWidget *m_treeWidget = nullptr; +}; +} // namespace vnotex #endif // SORTDIALOG_H diff --git a/src/widgets/dialogs/tableinsertdialog.cpp b/src/widgets/dialogs/tableinsertdialog.cpp index fc653fd9db..777ff614fc 100644 --- a/src/widgets/dialogs/tableinsertdialog.cpp +++ b/src/widgets/dialogs/tableinsertdialog.cpp @@ -1,93 +1,81 @@ #include "tableinsertdialog.h" -#include -#include +#include #include #include #include -#include +#include +#include #include using namespace vnotex; TableInsertDialog::TableInsertDialog(const QString &p_title, QWidget *p_parent) - : ScrollDialog(p_parent) -{ - setupUI(p_title); + : ScrollDialog(p_parent) { + setupUI(p_title); } -void TableInsertDialog::setupUI(const QString &p_title) -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); - - auto mainLayout = new QGridLayout(mainWidget); - - m_rowCountSpinBox = WidgetsFactory::createSpinBox(mainWidget); - m_rowCountSpinBox->setToolTip(tr("Row count of the table body")); - m_rowCountSpinBox->setMaximum(1000); - m_rowCountSpinBox->setMinimum(0); - - mainLayout->addWidget(new QLabel(tr("Row:")), 0, 0, 1, 1); - mainLayout->addWidget(m_rowCountSpinBox, 0, 1, 1, 1); - - m_colCountSpinBox = WidgetsFactory::createSpinBox(mainWidget); - m_colCountSpinBox->setToolTip(tr("Column count of the table")); - m_colCountSpinBox->setMaximum(1000); - m_colCountSpinBox->setMinimum(1); - - mainLayout->addWidget(new QLabel(tr("Column:")), 0, 2, 1, 1); - mainLayout->addWidget(m_colCountSpinBox, 0, 3, 1, 1); - - { - auto noneBtn = new QRadioButton(tr("None"), mainWidget); - auto leftBtn = new QRadioButton(tr("Left"), mainWidget); - auto centerBtn = new QRadioButton(tr("Center"), mainWidget); - auto rightBtn = new QRadioButton(tr("Right"), mainWidget); - - auto alignLayout = new QHBoxLayout(); - alignLayout->addWidget(noneBtn); - alignLayout->addWidget(leftBtn); - alignLayout->addWidget(centerBtn); - alignLayout->addWidget(rightBtn); - alignLayout->addStretch(); - - mainLayout->addWidget(new QLabel(tr("Alignment:")), 1, 0, 1, 1); - mainLayout->addLayout(alignLayout, 1, 1, 1, 3); - - auto buttonGroup = new QButtonGroup(mainWidget); - buttonGroup->addButton(noneBtn, static_cast(Alignment::None)); - buttonGroup->addButton(leftBtn, static_cast(Alignment::Left)); - buttonGroup->addButton(centerBtn, static_cast(Alignment::Center)); - buttonGroup->addButton(rightBtn, static_cast(Alignment::Right)); - - noneBtn->setChecked(true); - connect(buttonGroup, (void(QButtonGroup::*)(int, bool))(&QButtonGroup::buttonToggled), - - - this, [this](int p_id, bool p_checked){ - if (p_checked) { - m_alignment = static_cast(p_id); - } - }); - } - - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(p_title); +void TableInsertDialog::setupUI(const QString &p_title) { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); + + auto mainLayout = new QGridLayout(mainWidget); + + m_rowCountSpinBox = WidgetsFactory::createSpinBox(mainWidget); + m_rowCountSpinBox->setToolTip(tr("Row count of the table body")); + m_rowCountSpinBox->setMaximum(1000); + m_rowCountSpinBox->setMinimum(0); + + mainLayout->addWidget(new QLabel(tr("Row:")), 0, 0, 1, 1); + mainLayout->addWidget(m_rowCountSpinBox, 0, 1, 1, 1); + + m_colCountSpinBox = WidgetsFactory::createSpinBox(mainWidget); + m_colCountSpinBox->setToolTip(tr("Column count of the table")); + m_colCountSpinBox->setMaximum(1000); + m_colCountSpinBox->setMinimum(1); + + mainLayout->addWidget(new QLabel(tr("Column:")), 0, 2, 1, 1); + mainLayout->addWidget(m_colCountSpinBox, 0, 3, 1, 1); + + { + auto noneBtn = new QRadioButton(tr("None"), mainWidget); + auto leftBtn = new QRadioButton(tr("Left"), mainWidget); + auto centerBtn = new QRadioButton(tr("Center"), mainWidget); + auto rightBtn = new QRadioButton(tr("Right"), mainWidget); + + auto alignLayout = new QHBoxLayout(); + alignLayout->addWidget(noneBtn); + alignLayout->addWidget(leftBtn); + alignLayout->addWidget(centerBtn); + alignLayout->addWidget(rightBtn); + alignLayout->addStretch(); + + mainLayout->addWidget(new QLabel(tr("Alignment:")), 1, 0, 1, 1); + mainLayout->addLayout(alignLayout, 1, 1, 1, 3); + + auto buttonGroup = new QButtonGroup(mainWidget); + buttonGroup->addButton(noneBtn, static_cast(Alignment::None)); + buttonGroup->addButton(leftBtn, static_cast(Alignment::Left)); + buttonGroup->addButton(centerBtn, static_cast(Alignment::Center)); + buttonGroup->addButton(rightBtn, static_cast(Alignment::Right)); + + noneBtn->setChecked(true); + connect(buttonGroup, (void (QButtonGroup::*)(int, bool))(&QButtonGroup::buttonToggled), + + this, [this](int p_id, bool p_checked) { + if (p_checked) { + m_alignment = static_cast(p_id); + } + }); + } + + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setWindowTitle(p_title); } -int TableInsertDialog::getRowCount() const -{ - return m_rowCountSpinBox->value(); -} +int TableInsertDialog::getRowCount() const { return m_rowCountSpinBox->value(); } -int TableInsertDialog::getColumnCount() const -{ - return m_colCountSpinBox->value(); -} +int TableInsertDialog::getColumnCount() const { return m_colCountSpinBox->value(); } -Alignment TableInsertDialog::getAlignment() const -{ - return m_alignment; -} +Alignment TableInsertDialog::getAlignment() const { return m_alignment; } diff --git a/src/widgets/dialogs/tableinsertdialog.h b/src/widgets/dialogs/tableinsertdialog.h index 7d43472719..00e17040f6 100644 --- a/src/widgets/dialogs/tableinsertdialog.h +++ b/src/widgets/dialogs/tableinsertdialog.h @@ -7,29 +7,27 @@ class QSpinBox; -namespace vnotex -{ - class TableInsertDialog : public ScrollDialog - { - Q_OBJECT - public: - TableInsertDialog(const QString &p_title, QWidget *p_parent = nullptr); +namespace vnotex { +class TableInsertDialog : public ScrollDialog { + Q_OBJECT +public: + TableInsertDialog(const QString &p_title, QWidget *p_parent = nullptr); - int getRowCount() const; + int getRowCount() const; - int getColumnCount() const; + int getColumnCount() const; - Alignment getAlignment() const; + Alignment getAlignment() const; - private: - void setupUI(const QString &p_title); +private: + void setupUI(const QString &p_title); - QSpinBox *m_rowCountSpinBox = nullptr; + QSpinBox *m_rowCountSpinBox = nullptr; - QSpinBox *m_colCountSpinBox = nullptr; + QSpinBox *m_colCountSpinBox = nullptr; - Alignment m_alignment = Alignment::None; - }; -} + Alignment m_alignment = Alignment::None; +}; +} // namespace vnotex #endif // TABLEINSERTDIALOG_H diff --git a/src/widgets/dialogs/updater.cpp b/src/widgets/dialogs/updater.cpp index c3cb428f50..c569263775 100644 --- a/src/widgets/dialogs/updater.cpp +++ b/src/widgets/dialogs/updater.cpp @@ -1,104 +1,100 @@ #include "updater.h" -#include +#include #include -#include +#include +#include #include -#include -#include #include #include -#include #include +#include +#include -#include -#include #include +#include #include +#include using namespace vnotex; -Updater::Updater(QWidget *p_parent) - : Dialog(p_parent) -{ - setupUI(); -} +Updater::Updater(QWidget *p_parent) : Dialog(p_parent) { setupUI(); } -void Updater::setupUI() -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); +void Updater::setupUI() { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); - auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); + auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); - mainLayout->addRow(tr("Version:"), new QLabel(qApp->applicationVersion(), mainWidget)); + mainLayout->addRow(tr("Version:"), new QLabel(qApp->applicationVersion(), mainWidget)); - m_latestVersionLabel = new QLabel(tr("Fetching information..."), mainWidget); - mainLayout->addRow(tr("Latest version:"), m_latestVersionLabel); + m_latestVersionLabel = new QLabel(tr("Fetching information..."), mainWidget); + mainLayout->addRow(tr("Latest version:"), m_latestVersionLabel); - setDialogButtonBox(QDialogButtonBox::Ok); + setDialogButtonBox(QDialogButtonBox::Ok); - { - auto btnBox = getDialogButtonBox(); - auto viewBtn = btnBox->addButton(tr("View Releases"), QDialogButtonBox::AcceptRole); - connect(viewBtn, &QPushButton::clicked, - this, []() { - WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/releases")); - }); - } + { + auto btnBox = getDialogButtonBox(); + auto viewBtn = btnBox->addButton(tr("View Releases"), QDialogButtonBox::AcceptRole); + connect(viewBtn, &QPushButton::clicked, this, []() { + WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/releases")); + }); + } - setWindowTitle(tr("Check for Updates")); + setWindowTitle(tr("Check for Updates")); } -void Updater::showEvent(QShowEvent *p_event) -{ - Dialog::showEvent(p_event); +void Updater::showEvent(QShowEvent *p_event) { + Dialog::showEvent(p_event); - QTimer::singleShot(1000, this, &Updater::start); + QTimer::singleShot(1000, this, &Updater::start); } -void Updater::start() -{ - checkForUpdates(this, [this](bool p_hasUpdate, const QString &p_version, const QString &p_errMsg) { - Q_UNUSED(p_hasUpdate); - if (p_version.isEmpty()) { - setInformationText(tr("Failed to fetch information (%1).").arg(p_errMsg), InformationLevel::Warning); - m_latestVersionLabel->setText(""); - } else { - clearInformationText(); - m_latestVersionLabel->setText(p_version); - } - }); -} - -void Updater::checkForUpdates(QObject *p_receiver, const std::function &p_callback) -{ - QPointer receiver(p_receiver); - - // Will delete it in the callback. - auto mgr = new QNetworkAccessManager(); - connect(mgr, &QNetworkAccessManager::finished, - mgr, [mgr, receiver, p_callback](QNetworkReply *p_reply) { - bool hasUpdate = false; - QString version; - QString errMsg; - if (p_reply->error() != QNetworkReply::NoError) { - errMsg = vte::NetworkUtils::networkErrorStr(p_reply->error()); - } else { - auto obj = Utils::fromJsonString(p_reply->readAll()); - version = obj["tag_name"].toString(); - if (version.startsWith('v')) { - version = version.mid(1); +void Updater::start() { + checkForUpdates(this, + [this](bool p_hasUpdate, const QString &p_version, const QString &p_errMsg) { + Q_UNUSED(p_hasUpdate); + if (p_version.isEmpty()) { + setInformationText(tr("Failed to fetch information (%1).").arg(p_errMsg), + InformationLevel::Warning); + m_latestVersionLabel->setText(""); + } else { + clearInformationText(); + m_latestVersionLabel->setText(p_version); } - hasUpdate = version != qApp->applicationVersion(); - } - - if (receiver) { - p_callback(hasUpdate, version, errMsg); - } - p_reply->deleteLater(); - mgr->deleteLater(); - }); + }); +} - mgr->get(vte::NetworkUtils::networkRequest(QUrl("https://api.github.com/repos/vnotex/vnote/releases/latest"))); +void Updater::checkForUpdates( + QObject *p_receiver, + const std::function &p_callback) { + QPointer receiver(p_receiver); + + // Will delete it in the callback. + auto mgr = new QNetworkAccessManager(); + connect(mgr, &QNetworkAccessManager::finished, mgr, + [mgr, receiver, p_callback](QNetworkReply *p_reply) { + bool hasUpdate = false; + QString version; + QString errMsg; + if (p_reply->error() != QNetworkReply::NoError) { + errMsg = vte::NetworkUtils::networkErrorStr(p_reply->error()); + } else { + auto obj = Utils::fromJsonString(p_reply->readAll()); + version = obj["tag_name"].toString(); + if (version.startsWith('v')) { + version = version.mid(1); + } + hasUpdate = version != qApp->applicationVersion(); + } + + if (receiver) { + p_callback(hasUpdate, version, errMsg); + } + p_reply->deleteLater(); + mgr->deleteLater(); + }); + + mgr->get(vte::NetworkUtils::networkRequest( + QUrl("https://api.github.com/repos/vnotex/vnote/releases/latest"))); } diff --git a/src/widgets/dialogs/updater.h b/src/widgets/dialogs/updater.h index 8b14d35a01..015a475351 100644 --- a/src/widgets/dialogs/updater.h +++ b/src/widgets/dialogs/updater.h @@ -7,28 +7,28 @@ class QLabel; -namespace vnotex -{ - class Updater : public Dialog - { - Q_OBJECT - public: - explicit Updater(QWidget *p_parent = nullptr); +namespace vnotex { +class Updater : public Dialog { + Q_OBJECT +public: + explicit Updater(QWidget *p_parent = nullptr); - // Callback(hasUpdate, VersionOnSuccess, errMsg). - static void checkForUpdates(QObject *p_receiver, const std::function &p_callback); + // Callback(hasUpdate, VersionOnSuccess, errMsg). + static void + checkForUpdates(QObject *p_receiver, + const std::function &p_callback); - protected: - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; +protected: + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void start(); +private slots: + void start(); - private: - void setupUI(); +private: + void setupUI(); - QLabel *m_latestVersionLabel = nullptr; - }; -} + QLabel *m_latestVersionLabel = nullptr; +}; +} // namespace vnotex #endif // UPDATER_H diff --git a/src/widgets/dialogs/viewtagsdialog.cpp b/src/widgets/dialogs/viewtagsdialog.cpp index c088685978..730ae8856a 100644 --- a/src/widgets/dialogs/viewtagsdialog.cpp +++ b/src/widgets/dialogs/viewtagsdialog.cpp @@ -1,69 +1,63 @@ #include "viewtagsdialog.h" #include -#include #include +#include #include -#include "../widgetsfactory.h" #include "../tagviewer.h" +#include "../widgetsfactory.h" using namespace vnotex; -ViewTagsDialog::ViewTagsDialog(Node *p_node, QWidget *p_parent) - : Dialog(p_parent) -{ - setupUI(); +ViewTagsDialog::ViewTagsDialog(Node *p_node, QWidget *p_parent) : Dialog(p_parent) { + setupUI(); - setNode(p_node); + setNode(p_node); - m_tagViewer->setFocus(); + m_tagViewer->setFocus(); } -void ViewTagsDialog::setupUI() -{ - auto mainWidget = new QWidget(this); - setCentralWidget(mainWidget); +void ViewTagsDialog::setupUI() { + auto mainWidget = new QWidget(this); + setCentralWidget(mainWidget); - auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); + auto mainLayout = WidgetsFactory::createFormLayout(mainWidget); - m_nodeNameLabel = new QLabel(mainWidget); - mainLayout->addRow(tr("Name:"), m_nodeNameLabel); + m_nodeNameLabel = new QLabel(mainWidget); + mainLayout->addRow(tr("Name:"), m_nodeNameLabel); - m_tagViewer = new TagViewer(false, mainWidget); - mainLayout->addRow(tr("Tags:"), m_tagViewer); + m_tagViewer = new TagViewer(false, mainWidget); + mainLayout->addRow(tr("Tags:"), m_tagViewer); - setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - setWindowTitle(tr("Tags")); + setWindowTitle(tr("Tags")); } -void ViewTagsDialog::acceptedButtonClicked() -{ - m_tagViewer->save(); - accept(); +void ViewTagsDialog::acceptedButtonClicked() { + m_tagViewer->save(); + accept(); } -void ViewTagsDialog::setNode(Node *p_node) -{ - if (m_node == p_node) { - return; - } +void ViewTagsDialog::setNode(Node *p_node) { + if (m_node == p_node) { + return; + } - m_node = p_node; - Q_ASSERT(m_node); + m_node = p_node; + Q_ASSERT(m_node); - m_nodeNameLabel->setText(m_node->getName()); - m_tagViewer->setNode(m_node); + m_nodeNameLabel->setText(m_node->getName()); + m_tagViewer->setNode(m_node); } -void ViewTagsDialog::keyPressEvent(QKeyEvent *p_event) -{ - if (p_event->key() == Qt::Key_Enter || p_event->key() == Qt::Key_Return) { - // Prevent it from closing the dialog. - return; - } +void ViewTagsDialog::keyPressEvent(QKeyEvent *p_event) { + if (p_event->key() == Qt::Key_Enter || p_event->key() == Qt::Key_Return) { + // Prevent it from closing the dialog. + return; + } - Dialog::keyPressEvent(p_event); + Dialog::keyPressEvent(p_event); } diff --git a/src/widgets/dialogs/viewtagsdialog.h b/src/widgets/dialogs/viewtagsdialog.h index 97eb9ce1f4..46cd593f47 100644 --- a/src/widgets/dialogs/viewtagsdialog.h +++ b/src/widgets/dialogs/viewtagsdialog.h @@ -5,33 +5,31 @@ class QLabel; -namespace vnotex -{ - class Node; - class TagViewer; +namespace vnotex { +class Node; +class TagViewer; - class ViewTagsDialog : public Dialog - { - Q_OBJECT - public: - ViewTagsDialog(Node *p_node, QWidget *p_parent = nullptr); +class ViewTagsDialog : public Dialog { + Q_OBJECT +public: + ViewTagsDialog(Node *p_node, QWidget *p_parent = nullptr); - protected: - void acceptedButtonClicked() Q_DECL_OVERRIDE; +protected: + void acceptedButtonClicked() Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; - private: - void setupUI(); +private: + void setupUI(); - void setNode(Node *p_node); + void setNode(Node *p_node); - Node *m_node = nullptr; + Node *m_node = nullptr; - QLabel *m_nodeNameLabel = nullptr; + QLabel *m_nodeNameLabel = nullptr; - TagViewer *m_tagViewer = nullptr; - }; -} + TagViewer *m_tagViewer = nullptr; +}; +} // namespace vnotex #endif // VIEWTAGSDIALOG_H diff --git a/src/widgets/dockwidgethelper.cpp b/src/widgets/dockwidgethelper.cpp index 2c50d3b8a9..3ea2f6a2a4 100644 --- a/src/widgets/dockwidgethelper.cpp +++ b/src/widgets/dockwidgethelper.cpp @@ -1,589 +1,557 @@ #include "dockwidgethelper.h" -#include -#include #include +#include #include -#include #include +#include #include +#include -#include -#include #include #include +#include +#include #include #include #include +#include "consoleviewer.h" +#include "historypanel.h" +#include "locationlist.h" #include "mainwindow.h" -#include "propertydefs.h" #include "notebookexplorer.h" #include "outlineviewer.h" -#include "locationlist.h" +#include "propertydefs.h" #include "searchpanel.h" #include "snippetpanel.h" -#include "historypanel.h" -#include "windowspanel.h" #include "tagexplorer.h" -#include "consoleviewer.h" +#include "windowspanel.h" using namespace vnotex; -DockWidgetHelper::NavigationItemInfo::NavigationItemInfo(QTabBar *p_tabBar, int p_tabIndex, int p_dockIndex) - : m_tabBar(p_tabBar), - m_tabIndex(p_tabIndex), - m_dockIndex(p_dockIndex) -{ -} +DockWidgetHelper::NavigationItemInfo::NavigationItemInfo(QTabBar *p_tabBar, int p_tabIndex, + int p_dockIndex) + : m_tabBar(p_tabBar), m_tabIndex(p_tabIndex), m_dockIndex(p_dockIndex) {} DockWidgetHelper::NavigationItemInfo::NavigationItemInfo(int p_dockIndex) - : m_dockIndex(p_dockIndex) -{ -} + : m_dockIndex(p_dockIndex) {} DockWidgetHelper::DockWidgetHelper(MainWindow *p_mainWindow) - : QObject(p_mainWindow), - NavigationMode(NavigationMode::Type::DoubleKeys, p_mainWindow), - m_mainWindow(p_mainWindow) -{ -} + : QObject(p_mainWindow), NavigationMode(NavigationMode::Type::DoubleKeys, p_mainWindow), + m_mainWindow(p_mainWindow) {} -static int rotationAngle(Qt::DockWidgetArea p_area) -{ - switch (p_area) { - case Qt::LeftDockWidgetArea: - return 90; +static int rotationAngle(Qt::DockWidgetArea p_area) { + switch (p_area) { + case Qt::LeftDockWidgetArea: + return 90; - case Qt::RightDockWidgetArea: - return 270; + case Qt::RightDockWidgetArea: + return 270; - default: - return -1; - } + default: + return -1; + } } -QString DockWidgetHelper::iconFileName(DockIndex p_dockIndex) -{ - switch (p_dockIndex) { - case DockIndex::NavigationDock: - return "navigation_dock.svg"; - case DockIndex::OutlineDock: - return "outline_dock.svg"; - case DockIndex::HistoryDock: - return "history_dock.svg"; - case DockIndex::WindowsDock: - return "windows_dock.svg"; - case DockIndex::TagDock: - return "tag_dock.svg"; - case DockIndex::SearchDock: - return "search_dock.svg"; - case DockIndex::SnippetDock: - return "snippet_dock.svg"; - case DockIndex::LocationListDock: - return "location_list_dock.svg"; - case DockIndex::ConsoleDock: - return "console_dock.svg"; - default: - return QString(); - } +QString DockWidgetHelper::iconFileName(DockIndex p_dockIndex) { + switch (p_dockIndex) { + case DockIndex::NavigationDock: + return "navigation_dock.svg"; + case DockIndex::OutlineDock: + return "outline_dock.svg"; + case DockIndex::HistoryDock: + return "history_dock.svg"; + case DockIndex::WindowsDock: + return "windows_dock.svg"; + case DockIndex::TagDock: + return "tag_dock.svg"; + case DockIndex::SearchDock: + return "search_dock.svg"; + case DockIndex::SnippetDock: + return "snippet_dock.svg"; + case DockIndex::LocationListDock: + return "location_list_dock.svg"; + case DockIndex::ConsoleDock: + return "console_dock.svg"; + default: + return QString(); + } } -void DockWidgetHelper::setupDocks() -{ - m_mainWindow->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West); - m_mainWindow->setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East); - m_mainWindow->setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North); - m_mainWindow->setTabPosition(Qt::BottomDockWidgetArea, QTabWidget::North); - m_mainWindow->setDockNestingEnabled(true); +void DockWidgetHelper::setupDocks() { + m_mainWindow->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West); + m_mainWindow->setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East); + m_mainWindow->setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North); + m_mainWindow->setTabPosition(Qt::BottomDockWidgetArea, QTabWidget::North); + m_mainWindow->setDockNestingEnabled(true); - m_dockIcons.resize(DockIndex::MaxDock); + m_dockIcons.resize(DockIndex::MaxDock); - // The order of m_docks should be identical with enum DockIndex. - QVector tabifiedDockIndex; + // The order of m_docks should be identical with enum DockIndex. + QVector tabifiedDockIndex; - tabifiedDockIndex.append(m_docks.size()); - setupNavigationDock(); + tabifiedDockIndex.append(m_docks.size()); + setupNavigationDock(); - tabifiedDockIndex.append(m_docks.size()); - setupHistoryDock(); + tabifiedDockIndex.append(m_docks.size()); + setupHistoryDock(); - tabifiedDockIndex.append(m_docks.size()); - setupTagDock(); + tabifiedDockIndex.append(m_docks.size()); + setupTagDock(); - tabifiedDockIndex.append(m_docks.size()); - setupSearchDock(); + tabifiedDockIndex.append(m_docks.size()); + setupSearchDock(); - tabifiedDockIndex.append(m_docks.size()); - setupSnippetDock(); + tabifiedDockIndex.append(m_docks.size()); + setupSnippetDock(); - setupOutlineDock(); + setupOutlineDock(); - setupWindowsDock(); + setupWindowsDock(); - setupConsoleDock(); + setupConsoleDock(); - setupLocationListDock(); + setupLocationListDock(); - setupShortcuts(); + setupShortcuts(); - for (int i = 1; i < tabifiedDockIndex.size(); ++i) { - m_mainWindow->tabifyDockWidget(m_docks[tabifiedDockIndex[i - 1]], m_docks[tabifiedDockIndex[i]]); - } + for (int i = 1; i < tabifiedDockIndex.size(); ++i) { + m_mainWindow->tabifyDockWidget(m_docks[tabifiedDockIndex[i - 1]], + m_docks[tabifiedDockIndex[i]]); + } } -static void addWidgetToDock(QDockWidget *p_dock, QWidget *p_widget) -{ - p_dock->setWidget(p_widget); - p_dock->setFocusProxy(p_widget); +static void addWidgetToDock(QDockWidget *p_dock, QWidget *p_widget) { + p_dock->setWidget(p_widget); + p_dock->setFocusProxy(p_widget); } -void DockWidgetHelper::setupNavigationDock() -{ - auto dock = createDockWidget(DockIndex::NavigationDock, tr("Navigation"), m_mainWindow); +void DockWidgetHelper::setupNavigationDock() { + auto dock = createDockWidget(DockIndex::NavigationDock, tr("Navigation"), m_mainWindow); - dock->setObjectName(QStringLiteral("NavigationDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("NavigationDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_notebookExplorer); - m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_notebookExplorer); + m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); } -void DockWidgetHelper::setupOutlineDock() -{ - auto dock = createDockWidget(DockIndex::OutlineDock, tr("Outline"), m_mainWindow); +void DockWidgetHelper::setupOutlineDock() { + auto dock = createDockWidget(DockIndex::OutlineDock, tr("Outline"), m_mainWindow); - dock->setObjectName(QStringLiteral("OutlineDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("OutlineDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_outlineViewer); - m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_outlineViewer); + m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); } -void DockWidgetHelper::setupWindowsDock() -{ - auto dock = createDockWidget(DockIndex::WindowsDock, tr("Open Windows"), m_mainWindow); +void DockWidgetHelper::setupWindowsDock() { + auto dock = createDockWidget(DockIndex::WindowsDock, tr("Open Windows"), m_mainWindow); - dock->setObjectName(QStringLiteral("WindowsDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("WindowsDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_windowsPanel); - m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_windowsPanel); + m_mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock); } -void DockWidgetHelper::setupConsoleDock() -{ - auto dock = createDockWidget(DockIndex::ConsoleDock, tr("Console"), m_mainWindow); +void DockWidgetHelper::setupConsoleDock() { + auto dock = createDockWidget(DockIndex::ConsoleDock, tr("Console"), m_mainWindow); - dock->setObjectName(QStringLiteral("ConsoleDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("ConsoleDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_consoleViewer); - m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); - dock->hide(); + addWidgetToDock(dock, m_mainWindow->m_consoleViewer); + m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); + dock->hide(); } -void DockWidgetHelper::setupSearchDock() -{ - auto dock = createDockWidget(DockIndex::SearchDock, tr("Search"), m_mainWindow); +void DockWidgetHelper::setupSearchDock() { + auto dock = createDockWidget(DockIndex::SearchDock, tr("Search"), m_mainWindow); - dock->setObjectName(QStringLiteral("SearchDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("SearchDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_searchPanel); - m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_searchPanel); + m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); } -void DockWidgetHelper::setupSnippetDock() -{ - auto dock = createDockWidget(DockIndex::SnippetDock, tr("Snippets"), m_mainWindow); +void DockWidgetHelper::setupSnippetDock() { + auto dock = createDockWidget(DockIndex::SnippetDock, tr("Snippets"), m_mainWindow); - dock->setObjectName(QStringLiteral("SnippetDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("SnippetDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_snippetPanel); - m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_snippetPanel); + m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); } -void DockWidgetHelper::setupHistoryDock() -{ - auto dock = createDockWidget(DockIndex::HistoryDock, tr("History"), m_mainWindow); +void DockWidgetHelper::setupHistoryDock() { + auto dock = createDockWidget(DockIndex::HistoryDock, tr("History"), m_mainWindow); - dock->setObjectName(QStringLiteral("HistoryDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("HistoryDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_historyPanel); - m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_historyPanel); + m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); } -void DockWidgetHelper::setupTagDock() -{ - auto dock = createDockWidget(DockIndex::TagDock, tr("Tags"), m_mainWindow); +void DockWidgetHelper::setupTagDock() { + auto dock = createDockWidget(DockIndex::TagDock, tr("Tags"), m_mainWindow); - dock->setObjectName(QStringLiteral("TagDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("TagDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_tagExplorer); - m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); + addWidgetToDock(dock, m_mainWindow->m_tagExplorer); + m_mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); } -void DockWidgetHelper::setupLocationListDock() -{ - auto dock = createDockWidget(DockIndex::LocationListDock, tr("Location List"), m_mainWindow); +void DockWidgetHelper::setupLocationListDock() { + auto dock = createDockWidget(DockIndex::LocationListDock, tr("Location List"), m_mainWindow); - dock->setObjectName(QStringLiteral("LocationListDock.vnotex")); - dock->setAllowedAreas(Qt::AllDockWidgetAreas); + dock->setObjectName(QStringLiteral("LocationListDock.vnotex")); + dock->setAllowedAreas(Qt::AllDockWidgetAreas); - addWidgetToDock(dock, m_mainWindow->m_locationList); - m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); - dock->hide(); + addWidgetToDock(dock, m_mainWindow->m_locationList); + m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); + dock->hide(); } -QDockWidget *DockWidgetHelper::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(PropertyDefs::c_dockWidgetIndex, p_dockIndex); - dock->setProperty(PropertyDefs::c_dockWidgetTitle, p_title); - m_docks.push_back(dock); - return dock; +QDockWidget *DockWidgetHelper::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(PropertyDefs::c_dockWidgetIndex, p_dockIndex); + dock->setProperty(PropertyDefs::c_dockWidgetTitle, p_title); + m_docks.push_back(dock); + return dock; } -void DockWidgetHelper::activateDock(DockIndex p_dockIndex) -{ - Q_ASSERT(p_dockIndex < DockIndex::MaxDock); - activateDock(getDock(p_dockIndex)); +void DockWidgetHelper::activateDock(DockIndex p_dockIndex) { + Q_ASSERT(p_dockIndex < DockIndex::MaxDock); + activateDock(getDock(p_dockIndex)); } -void DockWidgetHelper::activateDock(QDockWidget *p_dock) -{ - bool needUpdateTabBar = !p_dock->isVisible(); - - p_dock->show(); - Q_FOREACH(QTabBar* tabBar, m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { - bool found = false; - for (int i = 0; i < tabBar->count(); ++i) { - if (p_dock == reinterpret_cast(tabBar->tabData(i).toULongLong())) { - tabBar->setCurrentIndex(i); - found = true; - break; - } - } - - if (found) { - break; - } - } +void DockWidgetHelper::activateDock(QDockWidget *p_dock) { + bool needUpdateTabBar = !p_dock->isVisible(); - p_dock->setFocus(); + p_dock->show(); + Q_FOREACH (QTabBar *tabBar, + m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + bool found = false; + for (int i = 0; i < tabBar->count(); ++i) { + if (p_dock == reinterpret_cast(tabBar->tabData(i).toULongLong())) { + tabBar->setCurrentIndex(i); + found = true; + break; + } + } - if (needUpdateTabBar) { - updateDockWidgetTabBar(); + if (found) { + break; } -} + } -const QVector &DockWidgetHelper::getDocks() const -{ - return m_docks; -} + p_dock->setFocus(); -QDockWidget *DockWidgetHelper::getDock(DockIndex p_dockIndex) const -{ - Q_ASSERT(p_dockIndex < DockIndex::MaxDock); - return m_docks[p_dockIndex]; + if (needUpdateTabBar) { + updateDockWidgetTabBar(); + } } -void DockWidgetHelper::setupShortcuts() -{ - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); +const QVector &DockWidgetHelper::getDocks() const { return m_docks; } - setupDockActivateShortcut(m_docks[DockIndex::NavigationDock], - coreConfig.getShortcut(CoreConfig::Shortcut::NavigationDock)); +QDockWidget *DockWidgetHelper::getDock(DockIndex p_dockIndex) const { + Q_ASSERT(p_dockIndex < DockIndex::MaxDock); + return m_docks[p_dockIndex]; +} + +void DockWidgetHelper::setupShortcuts() { + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - setupDockActivateShortcut(m_docks[DockIndex::OutlineDock], - coreConfig.getShortcut(CoreConfig::Shortcut::OutlineDock)); + setupDockActivateShortcut(m_docks[DockIndex::NavigationDock], + coreConfig.getShortcut(CoreConfig::Shortcut::NavigationDock)); - setupDockActivateShortcut(m_docks[DockIndex::HistoryDock], - coreConfig.getShortcut(CoreConfig::Shortcut::HistoryDock)); + setupDockActivateShortcut(m_docks[DockIndex::OutlineDock], + coreConfig.getShortcut(CoreConfig::Shortcut::OutlineDock)); - setupDockActivateShortcut(m_docks[DockIndex::TagDock], - coreConfig.getShortcut(CoreConfig::Shortcut::TagDock)); + setupDockActivateShortcut(m_docks[DockIndex::HistoryDock], + coreConfig.getShortcut(CoreConfig::Shortcut::HistoryDock)); - setupDockActivateShortcut(m_docks[DockIndex::SearchDock], - coreConfig.getShortcut(CoreConfig::Shortcut::SearchDock)); - // Extra shortcut for SearchDock. - setupDockActivateShortcut(m_docks[DockIndex::SearchDock], - coreConfig.getShortcut(CoreConfig::Shortcut::Search)); + setupDockActivateShortcut(m_docks[DockIndex::TagDock], + coreConfig.getShortcut(CoreConfig::Shortcut::TagDock)); - setupDockActivateShortcut(m_docks[DockIndex::LocationListDock], - coreConfig.getShortcut(CoreConfig::Shortcut::LocationListDock)); + setupDockActivateShortcut(m_docks[DockIndex::SearchDock], + coreConfig.getShortcut(CoreConfig::Shortcut::SearchDock)); + // Extra shortcut for SearchDock. + setupDockActivateShortcut(m_docks[DockIndex::SearchDock], + coreConfig.getShortcut(CoreConfig::Shortcut::Search)); - setupDockActivateShortcut(m_docks[DockIndex::SnippetDock], - coreConfig.getShortcut(CoreConfig::Shortcut::SnippetDock)); + setupDockActivateShortcut(m_docks[DockIndex::LocationListDock], + coreConfig.getShortcut(CoreConfig::Shortcut::LocationListDock)); - setupDockActivateShortcut(m_docks[DockIndex::WindowsDock], - coreConfig.getShortcut(CoreConfig::Shortcut::WindowsDock)); + setupDockActivateShortcut(m_docks[DockIndex::SnippetDock], + coreConfig.getShortcut(CoreConfig::Shortcut::SnippetDock)); + setupDockActivateShortcut(m_docks[DockIndex::WindowsDock], + coreConfig.getShortcut(CoreConfig::Shortcut::WindowsDock)); } -void DockWidgetHelper::setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys) -{ - auto shortcut = WidgetUtils::createShortcut(p_keys, m_mainWindow); - if (shortcut) { - p_dock->setToolTip(QStringLiteral("%1\t%2").arg(p_dock->windowTitle(), - QKeySequence(p_keys).toString(QKeySequence::NativeText))); - connect(shortcut, &QShortcut::activated, - this, [this, p_dock]() { - activateDock(p_dock); - }); - } +void DockWidgetHelper::setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys) { + auto shortcut = WidgetUtils::createShortcut(p_keys, m_mainWindow); + if (shortcut) { + p_dock->setToolTip(QStringLiteral("%1\t%2").arg( + p_dock->windowTitle(), QKeySequence(p_keys).toString(QKeySequence::NativeText))); + connect(shortcut, &QShortcut::activated, this, [this, p_dock]() { activateDock(p_dock); }); + } } -void DockWidgetHelper::postSetup() -{ - updateDockWidgetTabBar(); +void DockWidgetHelper::postSetup() { + updateDockWidgetTabBar(); - for (const auto dock : m_docks) { - connect(dock, &QDockWidget::dockLocationChanged, - this, &DockWidgetHelper::updateDockWidgetTabBar); - connect(dock, &QDockWidget::topLevelChanged, - this, &DockWidgetHelper::updateDockWidgetTabBar); - } + for (const auto dock : m_docks) { + connect(dock, &QDockWidget::dockLocationChanged, this, + &DockWidgetHelper::updateDockWidgetTabBar); + connect(dock, &QDockWidget::topLevelChanged, this, &DockWidgetHelper::updateDockWidgetTabBar); + } } -void DockWidgetHelper::updateDockWidgetTabBar() -{ - QBitArray tabifiedDocks(m_docks.size(), false); - Q_FOREACH(QTabBar* tabBar, m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { - if (!m_tabBarsMonitored.contains(tabBar)) { - m_tabBarsMonitored.insert(tabBar); - tabBar->installEventFilter(this); - } - - 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; - } - - bool isSideBar = iconOnly && (tabShape == QTabBar::RoundedWest || tabShape == QTabBar::TriangularWest); - if (tabBar->property(PropertyDefs::c_mainWindowSideBar).toBool() != isSideBar) { - WidgetUtils::setPropertyDynamically(tabBar, PropertyDefs::c_mainWindowSideBar, isSideBar); - } - - for (int i = 0; i < cnt; ++i) { - auto dock = reinterpret_cast(tabBar->tabData(i).toULongLong()); - if (!dock) { - continue; - } - int dockIdx = dock->property(PropertyDefs::c_dockWidgetIndex).toInt(); - tabifiedDocks.setBit(dockIdx); - if (iconOnly) { - dock->setWindowTitle(QString()); - } else if (dock->windowTitle().isEmpty()) { - dock->setWindowTitle(dock->property(PropertyDefs::c_dockWidgetTitle).toString()); - } - tabBar->setTabIcon(i, getDockIcon(static_cast(dockIdx), isSideBar)); - - if (dock->property(PropertyDefs::c_mainWindowSideBar).toBool() != isSideBar) { - WidgetUtils::setPropertyDynamically(dock, PropertyDefs::c_mainWindowSideBar, isSideBar); - } - } +void DockWidgetHelper::updateDockWidgetTabBar() { + QBitArray tabifiedDocks(m_docks.size(), false); + Q_FOREACH (QTabBar *tabBar, + m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + if (!m_tabBarsMonitored.contains(tabBar)) { + m_tabBarsMonitored.insert(tabBar); + tabBar->installEventFilter(this); } - // 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(PropertyDefs::c_dockWidgetTitle).toString()); - } - } + tabBar->setDrawBase(false); - emit m_mainWindow->layoutChanged(); -} + const int sz = ConfigMgr::getInst().getCoreConfig().getDocksTabBarIconSize(); + tabBar->setIconSize(QSize(sz, sz)); -bool DockWidgetHelper::eventFilter(QObject *p_obj, QEvent *p_event) -{ - if (p_event->type() == QEvent::ToolTip) { - // The QTabBar of the tabified dock widgets does not show tooltip due to Qt's internal implementation. - auto helpEve = static_cast(p_event); - auto tabBar = static_cast(p_obj); - int idx = tabBar->tabAt(helpEve->pos()); - bool done = false; - if (idx > -1) { - auto dock = reinterpret_cast(tabBar->tabData(idx).toULongLong()); - if (dock) { - done = true; - QToolTip::showText(helpEve->globalPos(), dock->property(PropertyDefs::c_dockWidgetTitle).toString()); - } - } - - if (!done) { - QToolTip::hideText(); - p_event->ignore(); - } - - return true; + 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; } - return QObject::eventFilter(p_obj, p_event); -} - -QStringList DockWidgetHelper::getVisibleDocks() const -{ - QStringList visibleDocks; - for (const auto dock : m_docks) { - if (dock->isVisible()) { - visibleDocks.push_back(dock->objectName()); - } + bool isSideBar = + iconOnly && (tabShape == QTabBar::RoundedWest || tabShape == QTabBar::TriangularWest); + if (tabBar->property(PropertyDefs::c_mainWindowSideBar).toBool() != isSideBar) { + WidgetUtils::setPropertyDynamically(tabBar, PropertyDefs::c_mainWindowSideBar, isSideBar); } - return visibleDocks; -} -QStringList DockWidgetHelper::hideDocks() -{ - const auto &keepDocks = ConfigMgr::getInst().getWidgetConfig().getMainWindowKeepDocksExpandingContentArea(); - QStringList visibleDocks; - for (const auto dock : m_docks) { - const auto objName = dock->objectName(); - if (dock->isVisible()) { - visibleDocks.push_back(objName); - } - - if (dock->isFloating() || keepDocks.contains(objName)) { - continue; - } - - dock->setVisible(false); + for (int i = 0; i < cnt; ++i) { + auto dock = reinterpret_cast(tabBar->tabData(i).toULongLong()); + if (!dock) { + continue; + } + int dockIdx = dock->property(PropertyDefs::c_dockWidgetIndex).toInt(); + tabifiedDocks.setBit(dockIdx); + if (iconOnly) { + dock->setWindowTitle(QString()); + } else if (dock->windowTitle().isEmpty()) { + dock->setWindowTitle(dock->property(PropertyDefs::c_dockWidgetTitle).toString()); + } + tabBar->setTabIcon(i, getDockIcon(static_cast(dockIdx), isSideBar)); + + if (dock->property(PropertyDefs::c_mainWindowSideBar).toBool() != isSideBar) { + WidgetUtils::setPropertyDynamically(dock, PropertyDefs::c_mainWindowSideBar, isSideBar); + } } + } - return visibleDocks; -} - -void DockWidgetHelper::restoreDocks(const QStringList &p_visibleDocks) -{ - const auto &keepDocks = ConfigMgr::getInst().getWidgetConfig().getMainWindowKeepDocksExpandingContentArea(); - bool hasVisible = false; - for (const auto dock : m_docks) { - const auto objName = dock->objectName(); - if (dock->isFloating() || keepDocks.contains(objName)) { - continue; - } - - const bool visible = p_visibleDocks.contains(objName); - hasVisible = hasVisible || visible; - - dock->setVisible(visible); + // 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(PropertyDefs::c_dockWidgetTitle).toString()); + } + } + + emit m_mainWindow->layoutChanged(); +} + +bool DockWidgetHelper::eventFilter(QObject *p_obj, QEvent *p_event) { + if (p_event->type() == QEvent::ToolTip) { + // The QTabBar of the tabified dock widgets does not show tooltip due to Qt's internal + // implementation. + auto helpEve = static_cast(p_event); + auto tabBar = static_cast(p_obj); + int idx = tabBar->tabAt(helpEve->pos()); + bool done = false; + if (idx > -1) { + auto dock = reinterpret_cast(tabBar->tabData(idx).toULongLong()); + if (dock) { + done = true; + QToolTip::showText(helpEve->globalPos(), + dock->property(PropertyDefs::c_dockWidgetTitle).toString()); + } } - if (!hasVisible) { - // At least make one visible. - getDock(DockIndex::NavigationDock)->setVisible(true); + if (!done) { + QToolTip::hideText(); + p_event->ignore(); } - updateDockWidgetTabBar(); + return true; + } + + return QObject::eventFilter(p_obj, p_event); } -QVector DockWidgetHelper::getVisibleNavigationItems() -{ - m_navigationItems.clear(); - - QBitArray tabifiedDocks(m_docks.size(), false); - Q_FOREACH(QTabBar* tabBar, m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { - if (!tabBar->isVisible()) { - continue; - } - - const int cnt = tabBar->count(); - for (int i = 0; i < cnt; ++i) { - auto dock = reinterpret_cast(tabBar->tabData(i).toULongLong()); - if (!dock) { - continue; - } - int dockIdx = dock->property(PropertyDefs::c_dockWidgetIndex).toInt(); - tabifiedDocks.setBit(dockIdx); - - m_navigationItems.push_back(NavigationItemInfo(tabBar, i, dockIdx)); - } +QStringList DockWidgetHelper::getVisibleDocks() const { + QStringList visibleDocks; + for (const auto dock : m_docks) { + if (dock->isVisible()) { + visibleDocks.push_back(dock->objectName()); } - - // Non-tabified docks. - for (int i = 0; i < m_docks.size(); ++i) { - if (!tabifiedDocks[i] && m_docks[i]->isVisible()) { - m_navigationItems.push_back(NavigationItemInfo(i)); - } + } + return visibleDocks; +} + +QStringList DockWidgetHelper::hideDocks() { + const auto &keepDocks = + ConfigMgr::getInst().getWidgetConfig().getMainWindowKeepDocksExpandingContentArea(); + QStringList visibleDocks; + for (const auto dock : m_docks) { + const auto objName = dock->objectName(); + if (dock->isVisible()) { + visibleDocks.push_back(objName); } - QVector items; - for (auto &item : m_navigationItems) { - items.push_back(&item); + if (dock->isFloating() || keepDocks.contains(objName)) { + continue; } - return items; -} -const QIcon &DockWidgetHelper::getDockIcon(DockIndex p_dockIndex, bool p_isSideBar) -{ - static const auto fg = VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#dockwidget_tabbar#icon#fg"); - static const auto selectedFg = VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#dockwidget_tabbar#icon#selected#fg"); - static auto sideBarFg = VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#side_bar#icon#fg"); - static auto sideBarSelectedFg = VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#side_bar#icon#selected#fg"); + dock->setVisible(false); + } - if (sideBarFg.isEmpty()) { - sideBarFg = fg; - } - if (sideBarSelectedFg.isEmpty()) { - sideBarSelectedFg = selectedFg; - } + return visibleDocks; +} - const auto area = m_mainWindow->dockWidgetArea(m_docks[p_dockIndex]); - const int newAngle = rotationAngle(area); - if ((m_dockIcons[p_dockIndex].m_rotationAngle != newAngle - || m_dockIcons[p_dockIndex].m_isSideBar != p_isSideBar) - && area != Qt::NoDockWidgetArea) { - QVector colors; - colors.push_back(IconUtils::OverriddenColor(p_isSideBar ? sideBarFg : fg, QIcon::Normal)); - // FIXME: the Selected Mode is not used by the selected tab of a QTabBar. - colors.push_back(IconUtils::OverriddenColor(p_isSideBar ? sideBarSelectedFg : selectedFg, - QIcon::Selected)); - - auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile(iconFileName(p_dockIndex)); - m_dockIcons[p_dockIndex].m_icon = IconUtils::fetchIcon(iconFile, colors, newAngle); - m_dockIcons[p_dockIndex].m_rotationAngle = newAngle; - m_dockIcons[p_dockIndex].m_isSideBar = p_isSideBar; +void DockWidgetHelper::restoreDocks(const QStringList &p_visibleDocks) { + const auto &keepDocks = + ConfigMgr::getInst().getWidgetConfig().getMainWindowKeepDocksExpandingContentArea(); + bool hasVisible = false; + for (const auto dock : m_docks) { + const auto objName = dock->objectName(); + if (dock->isFloating() || keepDocks.contains(objName)) { + continue; } - return m_dockIcons[p_dockIndex].m_icon; + const bool visible = p_visibleDocks.contains(objName); + hasVisible = hasVisible || visible; + + dock->setVisible(visible); + } + + if (!hasVisible) { + // At least make one visible. + getDock(DockIndex::NavigationDock)->setVisible(true); + } + + updateDockWidgetTabBar(); } -void DockWidgetHelper::placeNavigationLabel(int p_idx, void *p_item, QLabel *p_label) -{ - Q_UNUSED(p_idx); - auto info = static_cast(p_item); - if (info->m_tabBar) { - auto pos = info->m_tabBar->tabRect(info->m_tabIndex).topLeft(); - pos = info->m_tabBar->mapToGlobal(pos); - p_label->move(m_mainWindow->mapFromGlobal(pos)); - } else { - p_label->setParent(m_docks[info->m_dockIndex]); - p_label->move(0, 0); +QVector DockWidgetHelper::getVisibleNavigationItems() { + m_navigationItems.clear(); + + QBitArray tabifiedDocks(m_docks.size(), false); + Q_FOREACH (QTabBar *tabBar, + m_mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + if (!tabBar->isVisible()) { + continue; } -} -void DockWidgetHelper::handleTargetHit(void *p_item) -{ - auto info = static_cast(p_item); - activateDock(static_cast(info->m_dockIndex)); -} + const int cnt = tabBar->count(); + for (int i = 0; i < cnt; ++i) { + auto dock = reinterpret_cast(tabBar->tabData(i).toULongLong()); + if (!dock) { + continue; + } + int dockIdx = dock->property(PropertyDefs::c_dockWidgetIndex).toInt(); + tabifiedDocks.setBit(dockIdx); -void DockWidgetHelper::clearNavigation() -{ - NavigationMode::clearNavigation(); + m_navigationItems.push_back(NavigationItemInfo(tabBar, i, dockIdx)); + } + } - m_navigationItems.clear(); + // Non-tabified docks. + for (int i = 0; i < m_docks.size(); ++i) { + if (!tabifiedDocks[i] && m_docks[i]->isVisible()) { + m_navigationItems.push_back(NavigationItemInfo(i)); + } + } + + QVector items; + for (auto &item : m_navigationItems) { + items.push_back(&item); + } + return items; +} + +const QIcon &DockWidgetHelper::getDockIcon(DockIndex p_dockIndex, bool p_isSideBar) { + static const auto fg = + VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#dockwidget_tabbar#icon#fg"); + static const auto selectedFg = VNoteX::getInst().getThemeMgr().paletteColor( + "widgets#mainwindow#dockwidget_tabbar#icon#selected#fg"); + static auto sideBarFg = + VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#side_bar#icon#fg"); + static auto sideBarSelectedFg = + VNoteX::getInst().getThemeMgr().paletteColor("widgets#mainwindow#side_bar#icon#selected#fg"); + + if (sideBarFg.isEmpty()) { + sideBarFg = fg; + } + if (sideBarSelectedFg.isEmpty()) { + sideBarSelectedFg = selectedFg; + } + + const auto area = m_mainWindow->dockWidgetArea(m_docks[p_dockIndex]); + const int newAngle = rotationAngle(area); + if ((m_dockIcons[p_dockIndex].m_rotationAngle != newAngle || + m_dockIcons[p_dockIndex].m_isSideBar != p_isSideBar) && + area != Qt::NoDockWidgetArea) { + QVector colors; + colors.push_back(IconUtils::OverriddenColor(p_isSideBar ? sideBarFg : fg, QIcon::Normal)); + // FIXME: the Selected Mode is not used by the selected tab of a QTabBar. + colors.push_back( + IconUtils::OverriddenColor(p_isSideBar ? sideBarSelectedFg : selectedFg, QIcon::Selected)); + + auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile(iconFileName(p_dockIndex)); + m_dockIcons[p_dockIndex].m_icon = IconUtils::fetchIcon(iconFile, colors, newAngle); + m_dockIcons[p_dockIndex].m_rotationAngle = newAngle; + m_dockIcons[p_dockIndex].m_isSideBar = p_isSideBar; + } + + return m_dockIcons[p_dockIndex].m_icon; +} + +void DockWidgetHelper::placeNavigationLabel(int p_idx, void *p_item, QLabel *p_label) { + Q_UNUSED(p_idx); + auto info = static_cast(p_item); + if (info->m_tabBar) { + auto pos = info->m_tabBar->tabRect(info->m_tabIndex).topLeft(); + pos = info->m_tabBar->mapToGlobal(pos); + p_label->move(m_mainWindow->mapFromGlobal(pos)); + } else { + p_label->setParent(m_docks[info->m_dockIndex]); + p_label->move(0, 0); + } +} + +void DockWidgetHelper::handleTargetHit(void *p_item) { + auto info = static_cast(p_item); + activateDock(static_cast(info->m_dockIndex)); +} + +void DockWidgetHelper::clearNavigation() { + NavigationMode::clearNavigation(); + + m_navigationItems.clear(); } diff --git a/src/widgets/dockwidgethelper.h b/src/widgets/dockwidgethelper.h index 387cbce85f..035fac4278 100644 --- a/src/widgets/dockwidgethelper.h +++ b/src/widgets/dockwidgethelper.h @@ -1,140 +1,135 @@ #ifndef DOCKWIDGETHELPER_H #define DOCKWIDGETHELPER_H -#include #include -#include #include +#include +#include #include "navigationmode.h" class QDockWidget; class QTabBar; -namespace vnotex -{ - class MainWindow; +namespace vnotex { +class MainWindow; - // Dock widget helper for MainWindow. - class DockWidgetHelper : public QObject, public NavigationMode - { - Q_OBJECT - public: - // Index in m_docks. - enum DockIndex - { - NavigationDock = 0, - HistoryDock, - TagDock, - SearchDock, - SnippetDock, - OutlineDock, - WindowsDock, - ConsoleDock, - LocationListDock, - MaxDock - }; - Q_ENUM(DockIndex) +// Dock widget helper for MainWindow. +class DockWidgetHelper : public QObject, public NavigationMode { + Q_OBJECT +public: + // Index in m_docks. + enum DockIndex { + NavigationDock = 0, + HistoryDock, + TagDock, + SearchDock, + SnippetDock, + OutlineDock, + WindowsDock, + ConsoleDock, + LocationListDock, + MaxDock + }; + Q_ENUM(DockIndex) - explicit DockWidgetHelper(MainWindow *p_mainWindow); + explicit DockWidgetHelper(MainWindow *p_mainWindow); - void setupDocks(); + void setupDocks(); - void postSetup(); + void postSetup(); - void activateDock(DockIndex p_dockIndex); + void activateDock(DockIndex p_dockIndex); - QDockWidget *getDock(DockIndex p_dockIndex) const; + QDockWidget *getDock(DockIndex p_dockIndex) const; - const QVector &getDocks() const; + const QVector &getDocks() const; - void updateDockWidgetTabBar(); + void updateDockWidgetTabBar(); - QStringList getVisibleDocks() const; + QStringList getVisibleDocks() const; - QStringList hideDocks(); + QStringList hideDocks(); - void restoreDocks(const QStringList &p_visibleDocks); + void restoreDocks(const QStringList &p_visibleDocks); - // NavigationMode. - protected: - QVector getVisibleNavigationItems() Q_DECL_OVERRIDE; + // NavigationMode. +protected: + QVector getVisibleNavigationItems() Q_DECL_OVERRIDE; - void placeNavigationLabel(int p_idx, void *p_item, QLabel *p_label) Q_DECL_OVERRIDE; + void placeNavigationLabel(int p_idx, void *p_item, QLabel *p_label) Q_DECL_OVERRIDE; - void handleTargetHit(void *p_item) Q_DECL_OVERRIDE; + void handleTargetHit(void *p_item) Q_DECL_OVERRIDE; - void clearNavigation() Q_DECL_OVERRIDE; + void clearNavigation() Q_DECL_OVERRIDE; - protected: - bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE; +protected: + bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE; - private: - struct NavigationItemInfo - { - NavigationItemInfo() = default; +private: + struct NavigationItemInfo { + NavigationItemInfo() = default; - NavigationItemInfo(QTabBar *p_tabBar, int p_tabIndex, int p_dockIndex); + NavigationItemInfo(QTabBar *p_tabBar, int p_tabIndex, int p_dockIndex); - NavigationItemInfo(int p_dockIndex); + NavigationItemInfo(int p_dockIndex); - QTabBar *m_tabBar = nullptr; + QTabBar *m_tabBar = nullptr; - int m_tabIndex = -1; + int m_tabIndex = -1; - int m_dockIndex = -1; - }; + int m_dockIndex = -1; + }; - struct IconInfo - { - QIcon m_icon; + struct IconInfo { + QIcon m_icon; - int m_rotationAngle = INT_MIN; + int m_rotationAngle = INT_MIN; - bool m_isSideBar = false; - }; + bool m_isSideBar = false; + }; - void setupNavigationDock(); + void setupNavigationDock(); - void setupOutlineDock(); + void setupOutlineDock(); - void setupWindowsDock(); + void setupWindowsDock(); - void setupConsoleDock(); + void setupConsoleDock(); - void setupSearchDock(); + void setupSearchDock(); - void setupSnippetDock(); + void setupSnippetDock(); - void setupHistoryDock(); + void setupHistoryDock(); - void setupTagDock(); + void setupTagDock(); - void setupLocationListDock(); + void setupLocationListDock(); - QDockWidget *createDockWidget(DockIndex p_dockIndex, const QString &p_title, QWidget *p_parent); + QDockWidget *createDockWidget(DockIndex p_dockIndex, const QString &p_title, QWidget *p_parent); - void setupShortcuts(); + void setupShortcuts(); - void activateDock(QDockWidget *p_dock); + void activateDock(QDockWidget *p_dock); - void setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys); + void setupDockActivateShortcut(QDockWidget *p_dock, const QString &p_keys); - const QIcon &getDockIcon(DockIndex p_dockIndex, bool p_isSideBar); + const QIcon &getDockIcon(DockIndex p_dockIndex, bool p_isSideBar); - static QString iconFileName(DockIndex p_dockIndex); + static QString iconFileName(DockIndex p_dockIndex); - MainWindow *m_mainWindow = nullptr; + MainWindow *m_mainWindow = nullptr; - QVector m_dockIcons; + QVector m_dockIcons; - QVector m_docks; + QVector m_docks; - // We need to install event filter to the tabbar of tabified dock widgets. - QSet m_tabBarsMonitored; + // We need to install event filter to the tabbar of tabified dock widgets. + QSet m_tabBarsMonitored; - QVector m_navigationItems; - }; -} + QVector m_navigationItems; +}; +} // namespace vnotex #endif // DOCKWIDGETHELPER_H diff --git a/src/widgets/dragdropareaindicator.cpp b/src/widgets/dragdropareaindicator.cpp index 4ef3ae5dc4..4df26635a1 100644 --- a/src/widgets/dragdropareaindicator.cpp +++ b/src/widgets/dragdropareaindicator.cpp @@ -1,51 +1,44 @@ #include "dragdropareaindicator.h" -#include -#include #include #include +#include +#include using namespace vnotex; DragDropAreaIndicator::DragDropAreaIndicator(DragDropAreaIndicatorInterface *p_interface, - const QString &p_text, - QWidget *p_parent) - : QFrame(p_parent), - m_interface(p_interface) -{ - setupUI(p_text); - - setAcceptDrops(true); + const QString &p_text, QWidget *p_parent) + : QFrame(p_parent), m_interface(p_interface) { + setupUI(p_text); + + setAcceptDrops(true); } -void DragDropAreaIndicator::setupUI(const QString &p_text) -{ - auto mainLayout = new QHBoxLayout(this); +void DragDropAreaIndicator::setupUI(const QString &p_text) { + auto mainLayout = new QHBoxLayout(this); - auto label = new QLabel(p_text, this); - label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - mainLayout->addWidget(label); + auto label = new QLabel(p_text, this); + label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + mainLayout->addWidget(label); } -void DragDropAreaIndicator::dragEnterEvent(QDragEnterEvent *p_event) -{ - if (m_interface->handleDragEnterEvent(p_event)) { - return; - } - QFrame::dragEnterEvent(p_event); +void DragDropAreaIndicator::dragEnterEvent(QDragEnterEvent *p_event) { + if (m_interface->handleDragEnterEvent(p_event)) { + return; + } + QFrame::dragEnterEvent(p_event); } -void DragDropAreaIndicator::dropEvent(QDropEvent *p_event) -{ - if (m_interface->handleDropEvent(p_event)) { - hide(); - return; - } - QFrame::dropEvent(p_event); +void DragDropAreaIndicator::dropEvent(QDropEvent *p_event) { + if (m_interface->handleDropEvent(p_event)) { + hide(); + return; + } + QFrame::dropEvent(p_event); } -void DragDropAreaIndicator::mouseReleaseEvent(QMouseEvent *p_event) -{ - QFrame::mouseReleaseEvent(p_event); - hide(); +void DragDropAreaIndicator::mouseReleaseEvent(QMouseEvent *p_event) { + QFrame::mouseReleaseEvent(p_event); + hide(); } diff --git a/src/widgets/dragdropareaindicator.h b/src/widgets/dragdropareaindicator.h index 32418366c7..02cb389298 100644 --- a/src/widgets/dragdropareaindicator.h +++ b/src/widgets/dragdropareaindicator.h @@ -3,40 +3,36 @@ #include -namespace vnotex -{ - class DragDropAreaIndicatorInterface - { - public: - virtual ~DragDropAreaIndicatorInterface() {} +namespace vnotex { +class DragDropAreaIndicatorInterface { +public: + virtual ~DragDropAreaIndicatorInterface() {} - virtual bool handleDragEnterEvent(QDragEnterEvent *p_event) = 0; + virtual bool handleDragEnterEvent(QDragEnterEvent *p_event) = 0; - virtual bool handleDropEvent(QDropEvent *p_event) = 0; - }; + virtual bool handleDropEvent(QDropEvent *p_event) = 0; +}; - class DragDropAreaIndicator : public QFrame - { - Q_OBJECT - public: - DragDropAreaIndicator(DragDropAreaIndicatorInterface *p_interface, - const QString &p_text, - QWidget *p_parent = nullptr); +class DragDropAreaIndicator : public QFrame { + Q_OBJECT +public: + DragDropAreaIndicator(DragDropAreaIndicatorInterface *p_interface, const QString &p_text, + QWidget *p_parent = nullptr); - protected: - // To accept specific drop. - void dragEnterEvent(QDragEnterEvent *p_event) Q_DECL_OVERRIDE; +protected: + // To accept specific drop. + void dragEnterEvent(QDragEnterEvent *p_event) Q_DECL_OVERRIDE; - // Drop the data. - void dropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE; + // Drop the data. + void dropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; - private: - void setupUI(const QString &p_text); +private: + void setupUI(const QString &p_text); - DragDropAreaIndicatorInterface *m_interface = nullptr; - }; -} + DragDropAreaIndicatorInterface *m_interface = nullptr; +}; +} // namespace vnotex #endif // DRAGDROPAREAINDICATOR_H diff --git a/src/widgets/editors/graphhelper.cpp b/src/widgets/editors/graphhelper.cpp index a817ff0deb..44f9c312cd 100644 --- a/src/widgets/editors/graphhelper.cpp +++ b/src/widgets/editors/graphhelper.cpp @@ -10,201 +10,187 @@ using namespace vnotex; #define TaskIdProperty "GraphTaskId" #define TaskTimeStampProperty "GraphTaskTimeStamp" -GraphHelper::GraphHelper() - : m_cache(100, CacheItem()) -{ -} - -QStringList GraphHelper::getArgsToUse(const QStringList &p_args) -{ - if (p_args.isEmpty()) { - return QStringList(); - } +GraphHelper::GraphHelper() : m_cache(100, CacheItem()) {} - if (p_args[0] == "-c") { - // Combine all the arguments except the first one. - QStringList args; - args << p_args[0]; +QStringList GraphHelper::getArgsToUse(const QStringList &p_args) { + if (p_args.isEmpty()) { + return QStringList(); + } - QString subCmd; - for (int i = 1; i < p_args.size(); ++i) { - subCmd += " " + p_args[i]; - } - args << subCmd; + if (p_args[0] == "-c") { + // Combine all the arguments except the first one. + QStringList args; + args << p_args[0]; - return args; - } else { - return p_args; + QString subCmd; + for (int i = 1; i < p_args.size(); ++i) { + subCmd += " " + p_args[i]; } -} + args << subCmd; -void GraphHelper::process(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QString &p_text, - QObject *p_owner, - const ResultCallback &p_callback) -{ - Task task; - task.m_id = p_id; - task.m_timeStamp = p_timeStamp; - task.m_format = p_format; - task.m_text = p_text; - task.m_owner = p_owner; - task.m_callback = p_callback; - - m_tasks.enqueue(task); - - processOneTask(); + return args; + } else { + return p_args; + } } -void GraphHelper::processOneTask() -{ - if (m_taskOngoing || m_tasks.isEmpty()) { - return; - } +void GraphHelper::process(quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, + const QString &p_text, QObject *p_owner, + const ResultCallback &p_callback) { + Task task; + task.m_id = p_id; + task.m_timeStamp = p_timeStamp; + task.m_format = p_format; + task.m_text = p_text; + task.m_owner = p_owner; + task.m_callback = p_callback; - m_taskOngoing = true; + m_tasks.enqueue(task); - const auto &task = m_tasks.head(); + processOneTask(); +} - const auto &cachedData = m_cache.get(task.m_text); - if (!cachedData.isNull() && cachedData.m_format == task.m_format) { - finishOneTask(cachedData.m_data); - return; - } +void GraphHelper::processOneTask() { + if (m_taskOngoing || m_tasks.isEmpty()) { + return; + } + + m_taskOngoing = true; + + const auto &task = m_tasks.head(); + + const auto &cachedData = m_cache.get(task.m_text); + if (!cachedData.isNull() && cachedData.m_format == task.m_format) { + finishOneTask(cachedData.m_data); + return; + } + + if (!m_programValid) { + qWarning() << "program to execute for rendering is not valid" << m_program; + finishOneTask(QString()); + return; + } + + // Will be released in finishOneTask. + QProcess *process = new QProcess(); + process->setProperty(TaskIdProperty, task.m_id); + process->setProperty(TaskTimeStampProperty, task.m_timeStamp); + QObject::connect(process, QOverload::of(&QProcess::finished), + [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + finishOneTask(process, exitCode, exitStatus); + }); + + if (m_overriddenCommand.isEmpty()) { + Q_ASSERT(!m_program.isEmpty()); + QStringList args(m_args); + args << getFormatArgs(task.m_format); + process->start(m_program, getArgsToUse(args)); + } else { + auto cmd = getCommandToUse(m_overriddenCommand, task.m_format); + process->start(cmd); + } + + if (process->write(task.m_text.toUtf8()) == -1) { + qWarning() << "Graph task" << task.m_id + << "failed to write to process stdin:" << process->errorString(); + } + + process->closeWriteChannel(); +} - if (!m_programValid) { - qWarning() << "program to execute for rendering is not valid" << m_program; - finishOneTask(QString()); - return; - } +void GraphHelper::finishOneTask(QProcess *p_process, int p_exitCode, + QProcess::ExitStatus p_exitStatus) { + Q_ASSERT(m_taskOngoing && !m_tasks.isEmpty()); - // Will be released in finishOneTask. - QProcess *process = new QProcess(); - process->setProperty(TaskIdProperty, task.m_id); - process->setProperty(TaskTimeStampProperty, task.m_timeStamp); - QObject::connect(process, QOverload::of(&QProcess::finished), - [this, process](int exitCode, QProcess::ExitStatus exitStatus) { - finishOneTask(process, exitCode, exitStatus); - }); - - if (m_overriddenCommand.isEmpty()) { - Q_ASSERT(!m_program.isEmpty()); - QStringList args(m_args); - args << getFormatArgs(task.m_format); - process->start(m_program, getArgsToUse(args)); - } else { - auto cmd = getCommandToUse(m_overriddenCommand, task.m_format); - process->start(cmd); - } + const auto task = m_tasks.dequeue(); - if (process->write(task.m_text.toUtf8()) == -1) { - qWarning() << "Graph task" << task.m_id << "failed to write to process stdin:" << process->errorString(); - } + const quint64 id = p_process->property(TaskIdProperty).toULongLong(); + const quint64 timeStamp = p_process->property(TaskTimeStampProperty).toULongLong(); + Q_ASSERT(task.m_id == id && task.m_timeStamp == timeStamp); - process->closeWriteChannel(); -} + qDebug() << "Graph task" << id << timeStamp << "finished"; -void GraphHelper::finishOneTask(QProcess *p_process, int p_exitCode, QProcess::ExitStatus p_exitStatus) -{ - Q_ASSERT(m_taskOngoing && !m_tasks.isEmpty()); - - const auto task = m_tasks.dequeue(); - - const quint64 id = p_process->property(TaskIdProperty).toULongLong(); - const quint64 timeStamp = p_process->property(TaskTimeStampProperty).toULongLong(); - Q_ASSERT(task.m_id == id && task.m_timeStamp == timeStamp); - - qDebug() << "Graph task" << id << timeStamp << "finished"; - - bool failed = true; - if (p_exitStatus == QProcess::NormalExit) { - if (p_exitCode < 0) { - qWarning() << "Graph task" << id << "failed:" << p_exitCode; - } else { - failed = false; - const auto outBa = p_process->readAllStandardOutput(); - QString data; - if (task.m_format == QStringLiteral("svg")) { - data = QString::fromLocal8Bit(outBa); - callbackOneTask(task, id, timeStamp, task.m_format, data); - } else { - data = QString::fromLocal8Bit(outBa.toBase64()); - callbackOneTask(task, id, timeStamp, task.m_format, data); - } - - CacheItem item; - item.m_format = task.m_format; - item.m_data = data; - m_cache.set(task.m_text, item); - } + bool failed = true; + if (p_exitStatus == QProcess::NormalExit) { + if (p_exitCode < 0) { + qWarning() << "Graph task" << id << "failed:" << p_exitCode; } else { - qWarning() << "Graph task" << id << "failed to start" << p_exitCode << p_exitStatus; - } - - const QByteArray errBa = p_process->readAllStandardError(); - if (!errBa.isEmpty()) { - QString errStr(QString::fromLocal8Bit(errBa)); - if (failed) { - qWarning() << "Graph task" << id << "stderr:" << errStr; - } else { - qDebug() << "Graph task" << id << "stderr:" << errStr; - } + failed = false; + const auto outBa = p_process->readAllStandardOutput(); + QString data; + if (task.m_format == QStringLiteral("svg")) { + data = QString::fromLocal8Bit(outBa); + callbackOneTask(task, id, timeStamp, task.m_format, data); + } else { + data = QString::fromLocal8Bit(outBa.toBase64()); + callbackOneTask(task, id, timeStamp, task.m_format, data); + } + + CacheItem item; + item.m_format = task.m_format; + item.m_data = data; + m_cache.set(task.m_text, item); } + } else { + qWarning() << "Graph task" << id << "failed to start" << p_exitCode << p_exitStatus; + } + const QByteArray errBa = p_process->readAllStandardError(); + if (!errBa.isEmpty()) { + QString errStr(QString::fromLocal8Bit(errBa)); if (failed) { - callbackOneTask(task, id, task.m_timeStamp, task.m_format, QString()); + qWarning() << "Graph task" << id << "stderr:" << errStr; + } else { + qDebug() << "Graph task" << id << "stderr:" << errStr; } + } + + if (failed) { + callbackOneTask(task, id, task.m_timeStamp, task.m_format, QString()); + } - p_process->deleteLater(); + p_process->deleteLater(); - m_taskOngoing = false; - processOneTask(); + m_taskOngoing = false; + processOneTask(); } -void GraphHelper::finishOneTask(const QString &p_data) -{ - Q_ASSERT(m_taskOngoing && !m_tasks.isEmpty()); +void GraphHelper::finishOneTask(const QString &p_data) { + Q_ASSERT(m_taskOngoing && !m_tasks.isEmpty()); - const auto task = m_tasks.dequeue(); + const auto task = m_tasks.dequeue(); - qDebug() << "Graph task" << task.m_id << task.m_timeStamp << "finished by cache" << p_data.size(); + qDebug() << "Graph task" << task.m_id << task.m_timeStamp << "finished by cache" << p_data.size(); - callbackOneTask(task, task.m_id, task.m_timeStamp, task.m_format, p_data); + callbackOneTask(task, task.m_id, task.m_timeStamp, task.m_format, p_data); - m_taskOngoing = false; - processOneTask(); + m_taskOngoing = false; + processOneTask(); } -QString GraphHelper::getCommandToUse(const QString &p_command, const QString &p_format) -{ - auto cmd(p_command); - cmd.replace("%1", p_format); - return cmd; +QString GraphHelper::getCommandToUse(const QString &p_command, const QString &p_format) { + auto cmd(p_command); + cmd.replace("%1", p_format); + return cmd; } -void GraphHelper::clearCache() -{ - m_cache.clear(); -} +void GraphHelper::clearCache() { m_cache.clear(); } -void GraphHelper::checkValidProgram() -{ - m_programValid = true; - if (m_overriddenCommand.isEmpty()) { - if (m_program.isEmpty()) { - m_programValid = false; - } else { - QFileInfo finfo(m_program); - m_programValid = !finfo.isAbsolute() || finfo.isExecutable(); - } +void GraphHelper::checkValidProgram() { + m_programValid = true; + if (m_overriddenCommand.isEmpty()) { + if (m_program.isEmpty()) { + m_programValid = false; + } else { + QFileInfo finfo(m_program); + m_programValid = !finfo.isAbsolute() || finfo.isExecutable(); } + } } -void GraphHelper::callbackOneTask(const Task &p_task, quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_data) const -{ - if (p_task.m_owner) { - p_task.m_callback(p_id, p_timeStamp, p_format, p_data); - } +void GraphHelper::callbackOneTask(const Task &p_task, quint64 p_id, TimeStamp p_timeStamp, + const QString &p_format, const QString &p_data) const { + if (p_task.m_owner) { + p_task.m_callback(p_id, p_timeStamp, p_format, p_data); + } } diff --git a/src/widgets/editors/graphhelper.h b/src/widgets/editors/graphhelper.h index 2a244ae659..30d17e4c19 100644 --- a/src/widgets/editors/graphhelper.h +++ b/src/widgets/editors/graphhelper.h @@ -1,97 +1,86 @@ #ifndef GRAPHHELPER_H #define GRAPHHELPER_H -#include -#include #include -#include #include +#include +#include +#include -#include #include +#include #include -namespace vnotex -{ - class GraphHelper : private Noncopyable - { - public: - typedef std::function ResultCallback; +namespace vnotex { +class GraphHelper : private Noncopyable { +public: + typedef std::function ResultCallback; - GraphHelper(); + GraphHelper(); - void process(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QString &p_text, - QObject *p_owner, - const ResultCallback &p_callback); + void process(quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_text, + QObject *p_owner, const ResultCallback &p_callback); - protected: - virtual QStringList getFormatArgs(const QString &p_format) = 0; +protected: + virtual QStringList getFormatArgs(const QString &p_format) = 0; - void clearCache(); + void clearCache(); - void checkValidProgram(); + void checkValidProgram(); - static QStringList getArgsToUse(const QStringList &p_args); + static QStringList getArgsToUse(const QStringList &p_args); - static QString getCommandToUse(const QString &p_command, - const QString &p_format); + static QString getCommandToUse(const QString &p_command, const QString &p_format); - QString m_program; + QString m_program; - QStringList m_args; + QStringList m_args; - // If this is not empty, @m_program and @m_args will be ignored. - QString m_overriddenCommand; + // If this is not empty, @m_program and @m_args will be ignored. + QString m_overriddenCommand; - private: - struct Task - { - quint64 m_id = 0; +private: + struct Task { + quint64 m_id = 0; - TimeStamp m_timeStamp = 0; + TimeStamp m_timeStamp = 0; - QString m_format; + QString m_format; - QString m_text; + QString m_text; - QPointer m_owner; + QPointer m_owner; - ResultCallback m_callback; - }; + ResultCallback m_callback; + }; - struct CacheItem - { - bool isNull() const - { - return m_data.isNull(); - } + struct CacheItem { + bool isNull() const { return m_data.isNull(); } - QString m_format; + QString m_format; - QString m_data; - }; + QString m_data; + }; - void processOneTask(); + void processOneTask(); - void finishOneTask(QProcess *p_process, int p_exitCode, QProcess::ExitStatus p_exitStatus); + void finishOneTask(QProcess *p_process, int p_exitCode, QProcess::ExitStatus p_exitStatus); - void finishOneTask(const QString &p_data); + void finishOneTask(const QString &p_data); - void callbackOneTask(const Task &p_task, quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_data) const; + void callbackOneTask(const Task &p_task, quint64 p_id, TimeStamp p_timeStamp, + const QString &p_format, const QString &p_data) const; - QQueue m_tasks; + QQueue m_tasks; - bool m_taskOngoing = false; + bool m_taskOngoing = false; - // {text} -> CacheItem. - vte::LruCache m_cache; + // {text} -> CacheItem. + vte::LruCache m_cache; - // Whether @m_program is valid. - bool m_programValid = false; - }; -} + // Whether @m_program is valid. + bool m_programValid = false; +}; +} // namespace vnotex #endif // GRAPHHELPER_H diff --git a/src/widgets/editors/graphvizhelper.cpp b/src/widgets/editors/graphvizhelper.cpp index f3b5edd9c8..121ae5cfba 100644 --- a/src/widgets/editors/graphvizhelper.cpp +++ b/src/widgets/editors/graphvizhelper.cpp @@ -3,76 +3,69 @@ #include #include -#include -#include #include #include #include +#include +#include using namespace vnotex; -GraphvizHelper &GraphvizHelper::getInst() -{ - static bool initialized = false; - static GraphvizHelper inst; - if (!initialized) { - initialized = true; - const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - inst.update(markdownEditorConfig.getGraphvizExe()); - } - return inst; +GraphvizHelper &GraphvizHelper::getInst() { + static bool initialized = false; + static GraphvizHelper inst; + if (!initialized) { + initialized = true; + const auto &markdownEditorConfig = + ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); + inst.update(markdownEditorConfig.getGraphvizExe()); + } + return inst; } -void GraphvizHelper::update(const QString &p_graphvizFile) -{ - prepareProgramAndArgs(p_graphvizFile, m_program, m_args); +void GraphvizHelper::update(const QString &p_graphvizFile) { + prepareProgramAndArgs(p_graphvizFile, m_program, m_args); - checkValidProgram(); + checkValidProgram(); - clearCache(); + clearCache(); } -void GraphvizHelper::prepareProgramAndArgs(const QString &p_graphvizFile, - QString &p_program, - QStringList &p_args) -{ - p_program.clear(); - p_args.clear(); +void GraphvizHelper::prepareProgramAndArgs(const QString &p_graphvizFile, QString &p_program, + QStringList &p_args) { + p_program.clear(); + p_args.clear(); - p_program = p_graphvizFile.isEmpty() ? QStringLiteral("dot") : QDir::toNativeSeparators(PathUtils::absolutePath(p_graphvizFile)); + p_program = p_graphvizFile.isEmpty() + ? QStringLiteral("dot") + : QDir::toNativeSeparators(PathUtils::absolutePath(p_graphvizFile)); } -QPair GraphvizHelper::testGraphviz(const QString &p_graphvizFile) -{ - auto ret = qMakePair(false, QString()); +QPair GraphvizHelper::testGraphviz(const QString &p_graphvizFile) { + auto ret = qMakePair(false, QString()); - QString program; - QStringList args; - prepareProgramAndArgs(p_graphvizFile, program, args); - args << "-Tsvg"; + QString program; + QStringList args; + prepareProgramAndArgs(p_graphvizFile, program, args); + args << "-Tsvg"; - const QString testGraph("digraph G {VNote->Markdown}"); + const QString testGraph("digraph G {VNote->Markdown}"); - int exitCode = -1; - QByteArray outData; - QByteArray errData; - auto state = ProcessUtils::start(program, - args, - testGraph.toUtf8(), - exitCode, - outData, - errData); - ret.first = (state == ProcessUtils::Succeeded) && (exitCode == 0); + int exitCode = -1; + QByteArray outData; + QByteArray errData; + auto state = ProcessUtils::start(program, args, testGraph.toUtf8(), exitCode, outData, errData); + ret.first = (state == ProcessUtils::Succeeded) && (exitCode == 0); - ret.second = QStringLiteral("%1 %2\n\nExitcode: %3\n\nOutput: %4\n\nError: %5") - .arg(program, args.join(' '), QString::number(exitCode), QString::fromLocal8Bit(outData), QString::fromLocal8Bit(errData)); + ret.second = QStringLiteral("%1 %2\n\nExitcode: %3\n\nOutput: %4\n\nError: %5") + .arg(program, args.join(' '), QString::number(exitCode), + QString::fromLocal8Bit(outData), QString::fromLocal8Bit(errData)); - return ret; + return ret; } -QStringList GraphvizHelper::getFormatArgs(const QString &p_format) -{ - QStringList args; - args << ("-T" + p_format); - return args; +QStringList GraphvizHelper::getFormatArgs(const QString &p_format) { + QStringList args; + args << ("-T" + p_format); + return args; } diff --git a/src/widgets/editors/graphvizhelper.h b/src/widgets/editors/graphvizhelper.h index 025f942d5f..36e7c56530 100644 --- a/src/widgets/editors/graphvizhelper.h +++ b/src/widgets/editors/graphvizhelper.h @@ -3,26 +3,23 @@ #include "graphhelper.h" -namespace vnotex -{ - class GraphvizHelper : public GraphHelper - { - public: - void update(const QString &p_graphvizFile); +namespace vnotex { +class GraphvizHelper : public GraphHelper { +public: + void update(const QString &p_graphvizFile); - static GraphvizHelper &getInst(); + static GraphvizHelper &getInst(); - static QPair testGraphviz(const QString &p_graphvizFile); + static QPair testGraphviz(const QString &p_graphvizFile); - private: - GraphvizHelper() = default; +private: + GraphvizHelper() = default; - QStringList getFormatArgs(const QString &p_format) Q_DECL_OVERRIDE; + QStringList getFormatArgs(const QString &p_format) Q_DECL_OVERRIDE; - static void prepareProgramAndArgs(const QString &p_graphvizFile, - QString &p_program, - QStringList &p_args); - }; -} + static void prepareProgramAndArgs(const QString &p_graphvizFile, QString &p_program, + QStringList &p_args); +}; +} // namespace vnotex #endif // GRAPHVIZHELPER_H diff --git a/src/widgets/editors/markdowneditor.cpp b/src/widgets/editors/markdowneditor.cpp index f1659024f4..e531265f30 100644 --- a/src/widgets/editors/markdowneditor.cpp +++ b/src/widgets/editors/markdowneditor.cpp @@ -1,36 +1,34 @@ #include "markdowneditor.h" -#include +#include #include +#include #include -#include -#include #include -#include -#include +#include +#include #include -#include -#include +#include +#include +#include #include +#include +#include #include #include -#include -#include -#include #include -#include -#include -#include -#include #include #include -#include #include +#include #include +#include +#include +#include -#include #include +#include #include #include @@ -38,1765 +36,1649 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include +#include #include #include -#include -#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include -#include "previewhelper.h" #include "../outlineprovider.h" #include "markdowntablehelper.h" +#include "previewhelper.h" using namespace vnotex; -MarkdownEditor::Heading::Heading(const QString &p_name, - int p_level, - const QString &p_sectionNumber, +MarkdownEditor::Heading::Heading(const QString &p_name, int p_level, const QString &p_sectionNumber, int p_blockNumber) - : m_name(p_name), - m_level(p_level), - m_sectionNumber(p_sectionNumber), - m_blockNumber(p_blockNumber) -{ -} + : m_name(p_name), m_level(p_level), m_sectionNumber(p_sectionNumber), + m_blockNumber(p_blockNumber) {} MarkdownEditor::MarkdownEditor(const MarkdownEditorConfig &p_config, const QSharedPointer &p_editorConfig, const QSharedPointer &p_editorParas, QWidget *p_parent) - : vte::VMarkdownEditor(p_editorConfig, p_editorParas, p_parent), - m_config(p_config) -{ - setupShortcuts(); - - connect(m_textEdit, &vte::VTextEdit::canInsertFromMimeDataRequested, - this, &MarkdownEditor::handleCanInsertFromMimeData); - connect(m_textEdit, &vte::VTextEdit::insertFromMimeDataRequested, - this, &MarkdownEditor::handleInsertFromMimeData); - connect(m_textEdit, &vte::VTextEdit::contextMenuEventRequested, - this, &MarkdownEditor::handleContextMenuEvent); - - connect(getHighlighter(), &vte::PegMarkdownHighlighter::headersUpdated, - this, &MarkdownEditor::updateHeadings); - - setupTableHelper(); - - m_headingTimer = new QTimer(this); - m_headingTimer->setInterval(500); - m_headingTimer->setSingleShot(true); - connect(m_headingTimer, &QTimer::timeout, - this, &MarkdownEditor::currentHeadingChanged); - connect(m_textEdit, &vte::VTextEdit::cursorLineChanged, - m_headingTimer, QOverload<>::of(&QTimer::start)); - - m_sectionNumberTimer = new QTimer(this); - m_sectionNumberTimer->setInterval(1000); - m_sectionNumberTimer->setSingleShot(true); - connect(m_sectionNumberTimer, &QTimer::timeout, - this, [this]() { - updateSectionNumber(m_headings); - }); - - updateFromConfig(false); + : vte::VMarkdownEditor(p_editorConfig, p_editorParas, p_parent), m_config(p_config) { + setupShortcuts(); + + connect(m_textEdit, &vte::VTextEdit::canInsertFromMimeDataRequested, this, + &MarkdownEditor::handleCanInsertFromMimeData); + connect(m_textEdit, &vte::VTextEdit::insertFromMimeDataRequested, this, + &MarkdownEditor::handleInsertFromMimeData); + connect(m_textEdit, &vte::VTextEdit::contextMenuEventRequested, this, + &MarkdownEditor::handleContextMenuEvent); + + connect(getHighlighter(), &vte::PegMarkdownHighlighter::headersUpdated, this, + &MarkdownEditor::updateHeadings); + + setupTableHelper(); + + m_headingTimer = new QTimer(this); + m_headingTimer->setInterval(500); + m_headingTimer->setSingleShot(true); + connect(m_headingTimer, &QTimer::timeout, this, &MarkdownEditor::currentHeadingChanged); + connect(m_textEdit, &vte::VTextEdit::cursorLineChanged, m_headingTimer, + QOverload<>::of(&QTimer::start)); + + m_sectionNumberTimer = new QTimer(this); + m_sectionNumberTimer->setInterval(1000); + m_sectionNumberTimer->setSingleShot(true); + connect(m_sectionNumberTimer, &QTimer::timeout, this, + [this]() { updateSectionNumber(m_headings); }); + + updateFromConfig(false); } -MarkdownEditor::~MarkdownEditor() -{ - +MarkdownEditor::~MarkdownEditor() {} + +void MarkdownEditor::setPreviewHelper(PreviewHelper *p_helper) { + auto highlighter = getHighlighter(); + connect(highlighter, &vte::PegMarkdownHighlighter::codeBlocksUpdated, p_helper, + &PreviewHelper::codeBlocksUpdated); + connect(highlighter, &vte::PegMarkdownHighlighter::mathBlocksUpdated, p_helper, + &PreviewHelper::mathBlocksUpdated); + + auto previewMgr = getPreviewMgr(); + connect(p_helper, &PreviewHelper::inplacePreviewCodeBlockUpdated, previewMgr, + &vte::PreviewMgr::updateCodeBlocks); + connect(p_helper, &PreviewHelper::inplacePreviewMathBlockUpdated, previewMgr, + &vte::PreviewMgr::updateMathBlocks); + connect(p_helper, &PreviewHelper::potentialObsoletePreviewBlocksUpdated, previewMgr, + &vte::PreviewMgr::checkBlocksForObsoletePreview); } -void MarkdownEditor::setPreviewHelper(PreviewHelper *p_helper) -{ - auto highlighter = getHighlighter(); - connect(highlighter, &vte::PegMarkdownHighlighter::codeBlocksUpdated, - p_helper, &PreviewHelper::codeBlocksUpdated); - connect(highlighter, &vte::PegMarkdownHighlighter::mathBlocksUpdated, - p_helper, &PreviewHelper::mathBlocksUpdated); - - auto previewMgr = getPreviewMgr(); - connect(p_helper, &PreviewHelper::inplacePreviewCodeBlockUpdated, - previewMgr, &vte::PreviewMgr::updateCodeBlocks); - connect(p_helper, &PreviewHelper::inplacePreviewMathBlockUpdated, - previewMgr, &vte::PreviewMgr::updateMathBlocks); - connect(p_helper, &PreviewHelper::potentialObsoletePreviewBlocksUpdated, - previewMgr, &vte::PreviewMgr::checkBlocksForObsoletePreview); +void MarkdownEditor::typeHeading(int p_level) { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeHeading(m_textEdit, p_level); } -void MarkdownEditor::typeHeading(int p_level) -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeHeading(m_textEdit, p_level); +void MarkdownEditor::typeBold() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeBold(m_textEdit); } -void MarkdownEditor::typeBold() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeBold(m_textEdit); +void MarkdownEditor::typeItalic() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeItalic(m_textEdit); } -void MarkdownEditor::typeItalic() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeItalic(m_textEdit); +void MarkdownEditor::typeStrikethrough() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeStrikethrough(m_textEdit); } -void MarkdownEditor::typeStrikethrough() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeStrikethrough(m_textEdit); -} - -void MarkdownEditor::typeMark() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeMark(m_textEdit); +void MarkdownEditor::typeMark() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeMark(m_textEdit); } -void MarkdownEditor::typeUnorderedList() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeUnorderedList(m_textEdit); +void MarkdownEditor::typeUnorderedList() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeUnorderedList(m_textEdit); } -void MarkdownEditor::typeOrderedList() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeOrderedList(m_textEdit); +void MarkdownEditor::typeOrderedList() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeOrderedList(m_textEdit); } -void MarkdownEditor::typeTodoList(bool p_checked) -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeTodoList(m_textEdit, p_checked); +void MarkdownEditor::typeTodoList(bool p_checked) { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeTodoList(m_textEdit, p_checked); } -void MarkdownEditor::typeCode() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeCode(m_textEdit); +void MarkdownEditor::typeCode() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeCode(m_textEdit); } -void MarkdownEditor::typeCodeBlock() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeCodeBlock(m_textEdit); +void MarkdownEditor::typeCodeBlock() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeCodeBlock(m_textEdit); } -void MarkdownEditor::typeMath() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeMath(m_textEdit); +void MarkdownEditor::typeMath() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeMath(m_textEdit); } -void MarkdownEditor::typeMathBlock() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeMathBlock(m_textEdit); +void MarkdownEditor::typeMathBlock() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeMathBlock(m_textEdit); } -void MarkdownEditor::typeQuote() -{ - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeQuote(m_textEdit); +void MarkdownEditor::typeQuote() { + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeQuote(m_textEdit); } -void MarkdownEditor::typeLink() -{ - QString linkText; - QString linkUrl; - - // Try get Url or text from selection. - auto cursor = m_textEdit->textCursor(); - QRegularExpression urlReg("[\\.\\\\/]"); - if (cursor.hasSelection()) { - auto text = vte::TextEditUtils::getSelectedText(cursor).trimmed(); - if (!text.isEmpty() && !text.contains(QLatin1Char('\n'))) { - if (text.contains(urlReg) && QUrl::fromUserInput(text).isValid()) { - linkUrl = text; - } else { - linkText = text; - } - } - } - - // Fetch link from clipboard. - if (linkUrl.isEmpty() && linkText.isEmpty()) { - const auto clipboard = QApplication::clipboard(); - const auto mimeData = clipboard->mimeData(); - const QString text = mimeData->text().trimmed(); - // No multi-line. - if (!text.isEmpty() && !text.contains(QLatin1Char('\n'))) { - if (text.contains(urlReg) && QUrl::fromUserInput(text).isValid()) { - linkUrl = text; - } else { - linkText = text; - } - } - } - - LinkInsertDialog dialog(tr("Insert Link"), linkText, linkUrl, false, this); - if (dialog.exec() == QDialog::Accepted) { - linkText = dialog.getLinkText(); - linkUrl = dialog.getLinkUrl(); +void MarkdownEditor::typeLink() { + QString linkText; + QString linkUrl; + + // Try get Url or text from selection. + auto cursor = m_textEdit->textCursor(); + QRegularExpression urlReg("[\\.\\\\/]"); + if (cursor.hasSelection()) { + auto text = vte::TextEditUtils::getSelectedText(cursor).trimmed(); + if (!text.isEmpty() && !text.contains(QLatin1Char('\n'))) { + if (text.contains(urlReg) && QUrl::fromUserInput(text).isValid()) { + linkUrl = text; + } else { + linkText = text; + } + } + } + + // Fetch link from clipboard. + if (linkUrl.isEmpty() && linkText.isEmpty()) { + const auto clipboard = QApplication::clipboard(); + const auto mimeData = clipboard->mimeData(); + const QString text = mimeData->text().trimmed(); + // No multi-line. + if (!text.isEmpty() && !text.contains(QLatin1Char('\n'))) { + if (text.contains(urlReg) && QUrl::fromUserInput(text).isValid()) { + linkUrl = text; + } else { + linkText = text; + } + } + } + + LinkInsertDialog dialog(tr("Insert Link"), linkText, linkUrl, false, this); + if (dialog.exec() == QDialog::Accepted) { + linkText = dialog.getLinkText(); + linkUrl = dialog.getLinkUrl(); - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeLink(m_textEdit, linkText, linkUrl); - } + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeLink(m_textEdit, linkText, linkUrl); + } } -void MarkdownEditor::typeImage() -{ - Q_ASSERT(m_buffer); - ImageInsertDialog dialog(tr("Insert Image"), "", "", "", true, this); - - // Try fetch image from clipboard. - { - QClipboard *clipboard = QApplication::clipboard(); - const QMimeData *mimeData = clipboard->mimeData(); - - QUrl url; - if (mimeData->hasImage()) { - QImage im = qvariant_cast(mimeData->imageData()); - if (im.isNull()) { - return; - } - - dialog.setImage(im); - dialog.setImageSource(ImageInsertDialog::Source::ImageData); - } else if (mimeData->hasUrls()) { - QList urls = mimeData->urls(); - if (urls.size() == 1) { - url = urls[0]; - } - } else if (mimeData->hasText()) { - url = QUrl::fromUserInput(mimeData->text()); - } +void MarkdownEditor::typeImage() { + Q_ASSERT(m_buffer); + ImageInsertDialog dialog(tr("Insert Image"), "", "", "", true, this); - if (url.isValid()) { - if (url.isLocalFile()) { - dialog.setImagePath(url.toLocalFile()); - } else { - dialog.setImagePath(url.toString()); - } - } - } + // Try fetch image from clipboard. + { + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); - if (dialog.exec() != QDialog::Accepted) { + QUrl url; + if (mimeData->hasImage()) { + QImage im = qvariant_cast(mimeData->imageData()); + if (im.isNull()) { return; - } - - enterInsertModeIfApplicable(); - if (dialog.getImageSource() == ImageInsertDialog::Source::LocalFile) { - insertImageToBufferFromLocalFile(dialog.getImageTitle(), - dialog.getImageAltText(), - dialog.getImagePath(), - dialog.getScaledWidth()); - } else { - auto image = dialog.getImage(); - if (!image.isNull()) { - insertImageToBufferFromData(dialog.getImageTitle(), - dialog.getImageAltText(), - image, - dialog.getScaledWidth()); - } - } + } + + dialog.setImage(im); + dialog.setImageSource(ImageInsertDialog::Source::ImageData); + } else if (mimeData->hasUrls()) { + QList urls = mimeData->urls(); + if (urls.size() == 1) { + url = urls[0]; + } + } else if (mimeData->hasText()) { + url = QUrl::fromUserInput(mimeData->text()); + } + + if (url.isValid()) { + if (url.isLocalFile()) { + dialog.setImagePath(url.toLocalFile()); + } else { + dialog.setImagePath(url.toString()); + } + } + } + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + enterInsertModeIfApplicable(); + if (dialog.getImageSource() == ImageInsertDialog::Source::LocalFile) { + insertImageToBufferFromLocalFile(dialog.getImageTitle(), dialog.getImageAltText(), + dialog.getImagePath(), dialog.getScaledWidth()); + } else { + auto image = dialog.getImage(); + if (!image.isNull()) { + insertImageToBufferFromData(dialog.getImageTitle(), dialog.getImageAltText(), image, + dialog.getScaledWidth()); + } + } } -void MarkdownEditor::typeTable() -{ - TableInsertDialog dialog(tr("Insert Table"), this); - if (dialog.exec() != QDialog::Accepted) { - return; - } - - auto cursor = m_textEdit->textCursor(); - cursor.beginEditBlock(); - if (cursor.hasSelection()) { - cursor.setPosition(qMax(cursor.selectionStart(), cursor.selectionEnd())); - } - - bool newBlock = !cursor.atBlockEnd(); - if (!newBlock && !cursor.atBlockStart()) { - QString text = cursor.block().text().trimmed(); - if (!text.isEmpty() && text != QStringLiteral(">")) { - // Insert a new block before inserting table. - newBlock = true; - } - } - - if (newBlock) { - auto indentationStr = vte::TextEditUtils::fetchIndentationSpaces(cursor.block()); - vte::TextEditUtils::insertBlock(cursor, false); - cursor.insertText(indentationStr); - } - - cursor.endEditBlock(); - m_textEdit->setTextCursor(cursor); - - // Insert table. - m_tableHelper->insertTable(dialog.getRowCount(), dialog.getColumnCount(), dialog.getAlignment()); +void MarkdownEditor::typeTable() { + TableInsertDialog dialog(tr("Insert Table"), this); + if (dialog.exec() != QDialog::Accepted) { + return; + } + + auto cursor = m_textEdit->textCursor(); + cursor.beginEditBlock(); + if (cursor.hasSelection()) { + cursor.setPosition(qMax(cursor.selectionStart(), cursor.selectionEnd())); + } + + bool newBlock = !cursor.atBlockEnd(); + if (!newBlock && !cursor.atBlockStart()) { + QString text = cursor.block().text().trimmed(); + if (!text.isEmpty() && text != QStringLiteral(">")) { + // Insert a new block before inserting table. + newBlock = true; + } + } + + if (newBlock) { + auto indentationStr = vte::TextEditUtils::fetchIndentationSpaces(cursor.block()); + vte::TextEditUtils::insertBlock(cursor, false); + cursor.insertText(indentationStr); + } + + cursor.endEditBlock(); + m_textEdit->setTextCursor(cursor); + + // Insert table. + m_tableHelper->insertTable(dialog.getRowCount(), dialog.getColumnCount(), dialog.getAlignment()); } -void MarkdownEditor::setBuffer(Buffer *p_buffer) -{ - m_buffer = p_buffer; -} +void MarkdownEditor::setBuffer(Buffer *p_buffer) { m_buffer = p_buffer; } bool MarkdownEditor::insertImageToBufferFromLocalFile(const QString &p_title, const QString &p_altText, const QString &p_srcImagePath, - int p_scaledWidth, - int p_scaledHeight, - bool p_insertText, - QString *p_urlInLink) -{ - auto destFileName = generateImageFileNameToInsertAs(p_title, QFileInfo(p_srcImagePath).suffix()); - - QString destFilePath; - - if (m_imageHost) { - // Save to image host. - QByteArray ba; - try { - ba = FileUtils::readFile(p_srcImagePath); - } catch (Exception &e) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to read local image file (%1) (%2).").arg(p_srcImagePath, e.what()), - this); - return false; - } - destFilePath = saveToImageHost(ba, destFileName); - if (destFilePath.isEmpty()) { - return false; - } - } else { - try { - destFilePath = m_buffer->insertImage(p_srcImagePath, destFileName); - } catch (Exception &e) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to insert image from local file (%1) (%2).").arg(p_srcImagePath, e.what()), - this); - return false; - } - } - - insertImageLink(p_title, p_altText, destFilePath, p_scaledWidth, p_scaledHeight, p_insertText, p_urlInLink); - return true; + int p_scaledWidth, int p_scaledHeight, + bool p_insertText, QString *p_urlInLink) { + auto destFileName = generateImageFileNameToInsertAs(p_title, QFileInfo(p_srcImagePath).suffix()); + + QString destFilePath; + + if (m_imageHost) { + // Save to image host. + QByteArray ba; + try { + ba = FileUtils::readFile(p_srcImagePath); + } catch (Exception &e) { + MessageBoxHelper::notify( + MessageBoxHelper::Warning, + tr("Failed to read local image file (%1) (%2).").arg(p_srcImagePath, e.what()), this); + return false; + } + destFilePath = saveToImageHost(ba, destFileName); + if (destFilePath.isEmpty()) { + return false; + } + } else { + try { + destFilePath = m_buffer->insertImage(p_srcImagePath, destFileName); + } catch (Exception &e) { + MessageBoxHelper::notify( + MessageBoxHelper::Warning, + tr("Failed to insert image from local file (%1) (%2).").arg(p_srcImagePath, e.what()), + this); + return false; + } + } + + insertImageLink(p_title, p_altText, destFilePath, p_scaledWidth, p_scaledHeight, p_insertText, + p_urlInLink); + return true; } -QString MarkdownEditor::generateImageFileNameToInsertAs(const QString &p_title, const QString &p_suffix) -{ - return FileUtils::generateRandomFileName(p_title, p_suffix); +QString MarkdownEditor::generateImageFileNameToInsertAs(const QString &p_title, + const QString &p_suffix) { + return FileUtils::generateRandomFileName(p_title, p_suffix); } -bool MarkdownEditor::insertImageToBufferFromData(const QString &p_title, - const QString &p_altText, - const QImage &p_image, - int p_scaledWidth, - int p_scaledHeight) -{ - // Save as PNG by default. - const QString format("png"); - const auto destFileName = generateImageFileNameToInsertAs(p_title, format); - - QString destFilePath; - - if (m_imageHost) { - // Save to image host. - QByteArray ba; - QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - p_image.save(&buffer, format.toStdString().c_str()); - - destFilePath = saveToImageHost(ba, destFileName); - if (destFilePath.isEmpty()) { - return false; - } - } else { - try { - destFilePath = m_buffer->insertImage(p_image, destFileName); - } catch (Exception &e) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to insert image from data (%1).").arg(e.what()), - this); - return false; - } - } - - insertImageLink(p_title, p_altText, destFilePath, p_scaledWidth, p_scaledHeight); - return true; +bool MarkdownEditor::insertImageToBufferFromData(const QString &p_title, const QString &p_altText, + const QImage &p_image, int p_scaledWidth, + int p_scaledHeight) { + // Save as PNG by default. + const QString format("png"); + const auto destFileName = generateImageFileNameToInsertAs(p_title, format); + + QString destFilePath; + + if (m_imageHost) { + // Save to image host. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + p_image.save(&buffer, format.toStdString().c_str()); + + destFilePath = saveToImageHost(ba, destFileName); + if (destFilePath.isEmpty()) { + return false; + } + } else { + try { + destFilePath = m_buffer->insertImage(p_image, destFileName); + } catch (Exception &e) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("Failed to insert image from data (%1).").arg(e.what()), this); + return false; + } + } + + insertImageLink(p_title, p_altText, destFilePath, p_scaledWidth, p_scaledHeight); + return true; } -void MarkdownEditor::insertImageLink(const QString &p_title, - const QString &p_altText, - const QString &p_destImagePath, - int p_scaledWidth, - int p_scaledHeight, - bool p_insertText, - QString *p_urlInLink) -{ - const auto urlInLink = getRelativeLink(p_destImagePath); - if (p_urlInLink) { - *p_urlInLink = urlInLink; - } - static_cast(m_buffer)->addInsertedImage(p_destImagePath, urlInLink); - if (p_insertText) { - const auto imageLink = vte::MarkdownUtils::generateImageLink(p_title, - urlInLink, - p_altText, - p_scaledWidth, - p_scaledHeight); - m_textEdit->insertPlainText(imageLink); - } +void MarkdownEditor::insertImageLink(const QString &p_title, const QString &p_altText, + const QString &p_destImagePath, int p_scaledWidth, + int p_scaledHeight, bool p_insertText, QString *p_urlInLink) { + const auto urlInLink = getRelativeLink(p_destImagePath); + if (p_urlInLink) { + *p_urlInLink = urlInLink; + } + static_cast(m_buffer)->addInsertedImage(p_destImagePath, urlInLink); + if (p_insertText) { + const auto imageLink = vte::MarkdownUtils::generateImageLink(p_title, urlInLink, p_altText, + p_scaledWidth, p_scaledHeight); + m_textEdit->insertPlainText(imageLink); + } } -void MarkdownEditor::handleCanInsertFromMimeData(const QMimeData *p_source, bool *p_handled, bool *p_allowed) -{ - m_shouldTriggerRichPaste = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getRichPasteByDefaultEnabled(); +void MarkdownEditor::handleCanInsertFromMimeData(const QMimeData *p_source, bool *p_handled, + bool *p_allowed) { + m_shouldTriggerRichPaste = ConfigMgr::getInst() + .getEditorConfig() + .getMarkdownEditorConfig() + .getRichPasteByDefaultEnabled(); - if (m_plainTextPasteAsked) { - m_shouldTriggerRichPaste = false; - return; - } + if (m_plainTextPasteAsked) { + m_shouldTriggerRichPaste = false; + return; + } - if (m_richPasteAsked) { - m_shouldTriggerRichPaste = true; - *p_handled = true; - *p_allowed = true; - return; - } + if (m_richPasteAsked) { + m_shouldTriggerRichPaste = true; + *p_handled = true; + *p_allowed = true; + return; + } - if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) { - m_shouldTriggerRichPaste = !m_shouldTriggerRichPaste; - } + if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) { + m_shouldTriggerRichPaste = !m_shouldTriggerRichPaste; + } - if (m_shouldTriggerRichPaste) { - *p_handled = true; - *p_allowed = true; - return; - } + if (m_shouldTriggerRichPaste) { + *p_handled = true; + *p_allowed = true; + return; + } - if (p_source->hasImage()) { - m_shouldTriggerRichPaste = true; - *p_handled = true; - *p_allowed = true; - return; - } + if (p_source->hasImage()) { + m_shouldTriggerRichPaste = true; + *p_handled = true; + *p_allowed = true; + return; + } - if (p_source->hasUrls()) { - *p_handled = true; - *p_allowed = true; - return; - } + if (p_source->hasUrls()) { + *p_handled = true; + *p_allowed = true; + return; + } } -void MarkdownEditor::handleInsertFromMimeData(const QMimeData *p_source, bool *p_handled) -{ - if (!m_shouldTriggerRichPaste) { - // Default paste. - // Give tips about the Rich Paste and Parse to Markdown And Paste features. - VNoteX::getInst().showStatusMessageShort( - tr("For advanced paste, try the \"Rich Paste\" and \"Parse to Markdown and Paste\" on the editor's context menu")); - return; - } +void MarkdownEditor::handleInsertFromMimeData(const QMimeData *p_source, bool *p_handled) { + if (!m_shouldTriggerRichPaste) { + // Default paste. + // Give tips about the Rich Paste and Parse to Markdown And Paste features. + VNoteX::getInst().showStatusMessageShort( + tr("For advanced paste, try the \"Rich Paste\" and \"Parse to Markdown and Paste\" on the " + "editor's context menu")); + return; + } - m_shouldTriggerRichPaste = false; + m_shouldTriggerRichPaste = false; - if (processHtmlFromMimeData(p_source)) { - *p_handled = true; - return; - } + if (processHtmlFromMimeData(p_source)) { + *p_handled = true; + return; + } - if (processImageFromMimeData(p_source)) { - *p_handled = true; - return; - } + if (processImageFromMimeData(p_source)) { + *p_handled = true; + return; + } - if (processUrlFromMimeData(p_source)) { - *p_handled = true; - return; - } + if (processUrlFromMimeData(p_source)) { + *p_handled = true; + return; + } - if (processMultipleUrlsFromMimeData(p_source)) { - *p_handled = true; - return; - } + if (processMultipleUrlsFromMimeData(p_source)) { + *p_handled = true; + return; + } } -bool MarkdownEditor::processHtmlFromMimeData(const QMimeData *p_source) -{ - if (!p_source->hasHtml()) { - return false; - } +bool MarkdownEditor::processHtmlFromMimeData(const QMimeData *p_source) { + if (!p_source->hasHtml()) { + return false; + } - const QString html(p_source->html()); + const QString html(p_source->html()); - // Process . - QRegularExpression reg("]*)src=\"([^\"]+)\"([^>]*)>"); - QRegularExpressionMatch match; - if (html.indexOf(reg, 0, &match) != -1 && HtmlUtils::hasOnlyImgTag(html)) { - if (p_source->hasImage()) { - // Both image data and URL are embedded. - SelectDialog dialog(tr("Insert From Clipboard"), this); - dialog.addSelection(tr("Insert From URL"), 0); - dialog.addSelection(tr("Insert From Image Data"), 1); - dialog.addSelection(tr("Insert As Image Link"), 2); - - if (dialog.exec() == QDialog::Accepted) { - int selection = dialog.getSelection(); - if (selection == 1) { - // Insert from image data. - insertImageFromMimeData(p_source); - return true; - } else if (selection == 2) { - // Insert as link. - auto imageLink = vte::MarkdownUtils::generateImageLink("", match.captured(2), ""); - m_textEdit->insertPlainText(imageLink); - return true; - } - } else { - return true; - } - } - - insertImageFromUrl(match.captured(2)); + // Process . + QRegularExpression reg("]*)src=\"([^\"]+)\"([^>]*)>"); + QRegularExpressionMatch match; + if (html.indexOf(reg, 0, &match) != -1 && HtmlUtils::hasOnlyImgTag(html)) { + if (p_source->hasImage()) { + // Both image data and URL are embedded. + SelectDialog dialog(tr("Insert From Clipboard"), this); + dialog.addSelection(tr("Insert From URL"), 0); + dialog.addSelection(tr("Insert From Image Data"), 1); + dialog.addSelection(tr("Insert As Image Link"), 2); + + if (dialog.exec() == QDialog::Accepted) { + int selection = dialog.getSelection(); + if (selection == 1) { + // Insert from image data. + insertImageFromMimeData(p_source); + return true; + } else if (selection == 2) { + // Insert as link. + auto imageLink = vte::MarkdownUtils::generateImageLink("", match.captured(2), ""); + m_textEdit->insertPlainText(imageLink); + return true; + } + } else { return true; + } } - return false; -} - -bool MarkdownEditor::processImageFromMimeData(const QMimeData *p_source) -{ - if (!p_source->hasImage()) { - return false; - } - - // Image url in the clipboard. - if (p_source->hasText()) { - SelectDialog dialog(tr("Insert From Clipboard"), this); - dialog.addSelection(tr("Insert As Image"), 0); - dialog.addSelection(tr("Insert As Text"), 1); - dialog.addSelection(tr("Insert As Image Link"), 2); - - if (dialog.exec() == QDialog::Accepted) { - int selection = dialog.getSelection(); - if (selection == 1) { - // Insert as text. - Q_ASSERT(p_source->hasText() && p_source->hasImage()); - m_textEdit->insertFromMimeDataOfBase(p_source); - return true; - } else if (selection == 2) { - // Insert as link. - auto imageLink = vte::MarkdownUtils::generateImageLink("", p_source->text(), ""); - m_textEdit->insertPlainText(imageLink); - return true; - } - } else { - return true; - } - } - - insertImageFromMimeData(p_source); + insertImageFromUrl(match.captured(2)); return true; -} + } -bool MarkdownEditor::processUrlFromMimeData(const QMimeData *p_source) -{ - const auto urls = p_source->urls(); - if (urls.size() > 1) { - return false; - } + return false; +} - QUrl url; - if (p_source->hasUrls()) { - if (urls.size() == 1) { - url = urls[0]; - } - } else if (p_source->hasText()) { - // Try to get URL from text. - const QString text = p_source->text(); - if (QFileInfo::exists(text)) { - url = QUrl::fromLocalFile(text); - } else { - url.setUrl(text); - if (url.scheme() != QStringLiteral("https") && url.scheme() != QStringLiteral("http")) { - url.clear(); - } - } - } +bool MarkdownEditor::processImageFromMimeData(const QMimeData *p_source) { + if (!p_source->hasImage()) { + return false; + } - if (!url.isValid()) { - return false; - } + // Image url in the clipboard. + if (p_source->hasText()) { + SelectDialog dialog(tr("Insert From Clipboard"), this); + dialog.addSelection(tr("Insert As Image"), 0); + dialog.addSelection(tr("Insert As Text"), 1); + dialog.addSelection(tr("Insert As Image Link"), 2); - const bool isImage = PathUtils::isImageUrl(PathUtils::urlToPath(url)); - QString localFile = url.toLocalFile(); - if (!url.isLocalFile() || !QFileInfo::exists(localFile)) { - localFile.clear(); + if (dialog.exec() == QDialog::Accepted) { + int selection = dialog.getSelection(); + if (selection == 1) { + // Insert as text. + Q_ASSERT(p_source->hasText() && p_source->hasImage()); + m_textEdit->insertFromMimeDataOfBase(p_source); + return true; + } else if (selection == 2) { + // Insert as link. + auto imageLink = vte::MarkdownUtils::generateImageLink("", p_source->text(), ""); + m_textEdit->insertPlainText(imageLink); + return true; + } + } else { + return true; } + } - bool isTextFile = false; - if (!isImage && !localFile.isEmpty()) { - const auto mimeType = QMimeDatabase().mimeTypeForFile(localFile); - if (mimeType.isValid() && mimeType.inherits(QStringLiteral("text/plain"))) { - isTextFile = true; - } - } + insertImageFromMimeData(p_source); + return true; +} - SelectDialog dialog(tr("Insert From Clipboard"), this); - if (isImage) { - dialog.addSelection(tr("Insert As Image"), 0); - dialog.addSelection(tr("Insert As Image Link"), 1); - if (!localFile.isEmpty()) { - dialog.addSelection(tr("Insert As Relative Image Link"), 7); - } +bool MarkdownEditor::processUrlFromMimeData(const QMimeData *p_source) { + const auto urls = p_source->urls(); + if (urls.size() > 1) { + return false; + } + + QUrl url; + if (p_source->hasUrls()) { + if (urls.size() == 1) { + url = urls[0]; + } + } else if (p_source->hasText()) { + // Try to get URL from text. + const QString text = p_source->text(); + if (QFileInfo::exists(text)) { + url = QUrl::fromLocalFile(text); + } else { + url.setUrl(text); + if (url.scheme() != QStringLiteral("https") && url.scheme() != QStringLiteral("http")) { + url.clear(); + } } + } - dialog.addSelection(tr("Insert As Link"), 2); + if (!url.isValid()) { + return false; + } + + const bool isImage = PathUtils::isImageUrl(PathUtils::urlToPath(url)); + QString localFile = url.toLocalFile(); + if (!url.isLocalFile() || !QFileInfo::exists(localFile)) { + localFile.clear(); + } + + bool isTextFile = false; + if (!isImage && !localFile.isEmpty()) { + const auto mimeType = QMimeDatabase().mimeTypeForFile(localFile); + if (mimeType.isValid() && mimeType.inherits(QStringLiteral("text/plain"))) { + isTextFile = true; + } + } + + SelectDialog dialog(tr("Insert From Clipboard"), this); + if (isImage) { + dialog.addSelection(tr("Insert As Image"), 0); + dialog.addSelection(tr("Insert As Image Link"), 1); if (!localFile.isEmpty()) { - dialog.addSelection(tr("Insert As Relative Link"), 3); - - if (m_buffer->isAttachmentSupported() && !m_buffer->isAttachment(localFile) && !PathUtils::isDir(localFile)) { - dialog.addSelection(tr("Attach And Insert Link"), 6); - } - } - - dialog.addSelection(tr("Insert As Text"), 4); - if (!localFile.isEmpty() && isTextFile) { - dialog.addSelection(tr("Insert File Content"), 5); - } - - // FIXME: After calling dialog.exec(), p_source->hasUrl() returns false. - if (dialog.exec() == QDialog::Accepted) { - bool relativeLink = false; - switch (dialog.getSelection()) { - case 0: - { - // Insert As Image. - insertImageFromUrl(PathUtils::urlToPath(url)); - return true; - } - - case 7: - // Insert As Relative Image Link. - relativeLink = true; - Q_FALLTHROUGH(); - - case 1: - { - // Insert As Image Link. - QString urlInLink; - if (relativeLink) { - urlInLink = getRelativeLink(localFile); - } else { - urlInLink = url.toString(QUrl::EncodeSpaces); - } - - enterInsertModeIfApplicable(); - const auto imageLink = vte::MarkdownUtils::generateImageLink("", urlInLink, ""); - m_textEdit->insertPlainText(imageLink); - return true; - } - - case 6: - { - // Attach And Insert Link. - QStringList fileList; - fileList << localFile; - fileList = m_buffer->addAttachment(QString(), fileList); - - // Update localFile to point to the attachment file. - localFile = fileList[0]; - Q_FALLTHROUGH(); - } - - case 3: - // Insert As Relative link. - relativeLink = true; - Q_FALLTHROUGH(); - - case 2: - { - // Insert As Link. - QString linkText; - if (!localFile.isEmpty()) { - linkText = QFileInfo(localFile).fileName(); - } - - QString linkUrl; - if (relativeLink) { - Q_ASSERT(!localFile.isEmpty()); - linkUrl = getRelativeLink(localFile); - } else { - linkUrl = url.toString(QUrl::EncodeSpaces); - } - - LinkInsertDialog linkDialog(tr("Insert Link"), linkText, linkUrl, false, this); - if (linkDialog.exec() == QDialog::Accepted) { - linkText = linkDialog.getLinkText(); - linkUrl = linkDialog.getLinkUrl(); - - enterInsertModeIfApplicable(); - vte::MarkdownUtils::typeLink(m_textEdit, linkText, linkUrl); - } - - return true; - } + dialog.addSelection(tr("Insert As Relative Image Link"), 7); + } + } + + dialog.addSelection(tr("Insert As Link"), 2); + if (!localFile.isEmpty()) { + dialog.addSelection(tr("Insert As Relative Link"), 3); + + if (m_buffer->isAttachmentSupported() && !m_buffer->isAttachment(localFile) && + !PathUtils::isDir(localFile)) { + dialog.addSelection(tr("Attach And Insert Link"), 6); + } + } + + dialog.addSelection(tr("Insert As Text"), 4); + if (!localFile.isEmpty() && isTextFile) { + dialog.addSelection(tr("Insert File Content"), 5); + } + + // FIXME: After calling dialog.exec(), p_source->hasUrl() returns false. + if (dialog.exec() == QDialog::Accepted) { + bool relativeLink = false; + switch (dialog.getSelection()) { + case 0: { + // Insert As Image. + insertImageFromUrl(PathUtils::urlToPath(url)); + return true; + } + + case 7: + // Insert As Relative Image Link. + relativeLink = true; + Q_FALLTHROUGH(); + + case 1: { + // Insert As Image Link. + QString urlInLink; + if (relativeLink) { + urlInLink = getRelativeLink(localFile); + } else { + urlInLink = url.toString(QUrl::EncodeSpaces); + } + + enterInsertModeIfApplicable(); + const auto imageLink = vte::MarkdownUtils::generateImageLink("", urlInLink, ""); + m_textEdit->insertPlainText(imageLink); + return true; + } + + case 6: { + // Attach And Insert Link. + QStringList fileList; + fileList << localFile; + fileList = m_buffer->addAttachment(QString(), fileList); + + // Update localFile to point to the attachment file. + localFile = fileList[0]; + Q_FALLTHROUGH(); + } + + case 3: + // Insert As Relative link. + relativeLink = true; + Q_FALLTHROUGH(); + + case 2: { + // Insert As Link. + QString linkText; + if (!localFile.isEmpty()) { + linkText = QFileInfo(localFile).fileName(); + } + + QString linkUrl; + if (relativeLink) { + Q_ASSERT(!localFile.isEmpty()); + linkUrl = getRelativeLink(localFile); + } else { + linkUrl = url.toString(QUrl::EncodeSpaces); + } + + LinkInsertDialog linkDialog(tr("Insert Link"), linkText, linkUrl, false, this); + if (linkDialog.exec() == QDialog::Accepted) { + linkText = linkDialog.getLinkText(); + linkUrl = linkDialog.getLinkUrl(); - case 4: - { - // Insert As Text. - enterInsertModeIfApplicable(); - if (p_source->hasText()) { - m_textEdit->insertPlainText(p_source->text()); - } else { - m_textEdit->insertPlainText(url.toString()); - } - - return true; - } - - case 5: - { - // Insert File Content. - Q_ASSERT(!localFile.isEmpty() && isTextFile); - enterInsertModeIfApplicable(); - m_textEdit->insertPlainText(FileUtils::readTextFile(localFile)); - return true; - } + enterInsertModeIfApplicable(); + vte::MarkdownUtils::typeLink(m_textEdit, linkText, linkUrl); + } - default: - Q_ASSERT(false); - break; - } - } else { - // Nothing happens. - return true; + return true; } - return false; -} + case 4: { + // Insert As Text. + enterInsertModeIfApplicable(); + if (p_source->hasText()) { + m_textEdit->insertPlainText(p_source->text()); + } else { + m_textEdit->insertPlainText(url.toString()); + } -bool MarkdownEditor::processMultipleUrlsFromMimeData(const QMimeData *p_source) { - const auto urls = p_source->urls(); - if (urls.size() <= 1) { - return false; + return true; } - bool isProcessed = false; - // Judgment if all QMimeData are images. - bool isAllImage = true; - for (const QUrl &url : urls) { - if (!PathUtils::isImageUrl(PathUtils::urlToPath(url))) { - isAllImage = false; - break; - } + case 5: { + // Insert File Content. + Q_ASSERT(!localFile.isEmpty() && isTextFile); + enterInsertModeIfApplicable(); + m_textEdit->insertPlainText(FileUtils::readTextFile(localFile)); + return true; } - SelectDialog dialog(tr("Insert From Clipboard (%n items)", "", urls.size()), this); - if (isAllImage) { - dialog.addSelection(tr("Insert As Image"), 0); - } - if (m_buffer->isAttachmentSupported()) { - dialog.addSelection(tr("Attach And Insert Link"), 1); + default: + Q_ASSERT(false); + break; } - dialog.setMinimumWidth(400); + } else { + // Nothing happens. + return true; + } - if (dialog.exec() == QDialog::Accepted) { - switch (dialog.getSelection()) { - case 0: - { - // Insert As Image. - for (const QUrl &url : urls) { - insertImageFromUrl(PathUtils::urlToPath(url), true); - m_textEdit->insertPlainText("\n\n"); - } - isProcessed = true; - break; - } - case 1: - { - // Attach And Insert Link. - QStringList fileList; - for (const QUrl &url : urls) { - fileList << url.toLocalFile(); - } - fileList = m_buffer->addAttachment(QString(), fileList); - enterInsertModeIfApplicable(); - for (int i = 0; i < fileList.length(); ++i) { - vte::MarkdownUtils::typeLink( - m_textEdit, QFileInfo(fileList[i]).fileName(), - getRelativeLink(fileList[i])); - - m_textEdit->insertPlainText("\n\n"); - } - isProcessed = true; - break; - } - } - } + return false; +} - return isProcessed; +bool MarkdownEditor::processMultipleUrlsFromMimeData(const QMimeData *p_source) { + const auto urls = p_source->urls(); + if (urls.size() <= 1) { + return false; + } + + bool isProcessed = false; + // Judgment if all QMimeData are images. + bool isAllImage = true; + for (const QUrl &url : urls) { + if (!PathUtils::isImageUrl(PathUtils::urlToPath(url))) { + isAllImage = false; + break; + } + } + + SelectDialog dialog(tr("Insert From Clipboard (%n items)", "", urls.size()), this); + if (isAllImage) { + dialog.addSelection(tr("Insert As Image"), 0); + } + if (m_buffer->isAttachmentSupported()) { + dialog.addSelection(tr("Attach And Insert Link"), 1); + } + dialog.setMinimumWidth(400); + + if (dialog.exec() == QDialog::Accepted) { + switch (dialog.getSelection()) { + case 0: { + // Insert As Image. + for (const QUrl &url : urls) { + insertImageFromUrl(PathUtils::urlToPath(url), true); + m_textEdit->insertPlainText("\n\n"); + } + isProcessed = true; + break; + } + case 1: { + // Attach And Insert Link. + QStringList fileList; + for (const QUrl &url : urls) { + fileList << url.toLocalFile(); + } + fileList = m_buffer->addAttachment(QString(), fileList); + enterInsertModeIfApplicable(); + for (int i = 0; i < fileList.length(); ++i) { + vte::MarkdownUtils::typeLink(m_textEdit, QFileInfo(fileList[i]).fileName(), + getRelativeLink(fileList[i])); + + m_textEdit->insertPlainText("\n\n"); + } + isProcessed = true; + break; + } + } + } + + return isProcessed; } -void MarkdownEditor::insertImageFromMimeData(const QMimeData *p_source) -{ - QImage image = qvariant_cast(p_source->imageData()); - if (image.isNull()) { - return; - } +void MarkdownEditor::insertImageFromMimeData(const QMimeData *p_source) { + QImage image = qvariant_cast(p_source->imageData()); + if (image.isNull()) { + return; + } - ImageInsertDialog dialog(tr("Insert Image From Clipboard"), "", "", "", false, this); - dialog.setImage(image); - if (dialog.exec() == QDialog::Accepted) { - enterInsertModeIfApplicable(); - insertImageToBufferFromData(dialog.getImageTitle(), - dialog.getImageAltText(), - image, - dialog.getScaledWidth()); - } + ImageInsertDialog dialog(tr("Insert Image From Clipboard"), "", "", "", false, this); + dialog.setImage(image); + if (dialog.exec() == QDialog::Accepted) { + enterInsertModeIfApplicable(); + insertImageToBufferFromData(dialog.getImageTitle(), dialog.getImageAltText(), image, + dialog.getScaledWidth()); + } } -void MarkdownEditor::insertImageFromUrl(const QString &p_url, bool p_quiet) -{ - if (p_quiet) { - insertImageToBufferFromLocalFile("", "", p_url, 0); - } else { - ImageInsertDialog dialog(tr("Insert Image From URL"), "", "", "", false, this); - dialog.setImagePath(p_url); - if (dialog.exec() == QDialog::Accepted) { - enterInsertModeIfApplicable(); - if (dialog.getImageSource() == ImageInsertDialog::Source::LocalFile) { - insertImageToBufferFromLocalFile(dialog.getImageTitle(), - dialog.getImageAltText(), - dialog.getImagePath(), - dialog.getScaledWidth()); - } else { - auto image = dialog.getImage(); - if (!image.isNull()) { - insertImageToBufferFromData(dialog.getImageTitle(), - dialog.getImageAltText(), - image, - dialog.getScaledWidth()); - } - } +void MarkdownEditor::insertImageFromUrl(const QString &p_url, bool p_quiet) { + if (p_quiet) { + insertImageToBufferFromLocalFile("", "", p_url, 0); + } else { + ImageInsertDialog dialog(tr("Insert Image From URL"), "", "", "", false, this); + dialog.setImagePath(p_url); + if (dialog.exec() == QDialog::Accepted) { + enterInsertModeIfApplicable(); + if (dialog.getImageSource() == ImageInsertDialog::Source::LocalFile) { + insertImageToBufferFromLocalFile(dialog.getImageTitle(), dialog.getImageAltText(), + dialog.getImagePath(), dialog.getScaledWidth()); + } else { + auto image = dialog.getImage(); + if (!image.isNull()) { + insertImageToBufferFromData(dialog.getImageTitle(), dialog.getImageAltText(), image, + dialog.getScaledWidth()); } + } } + } } -QString MarkdownEditor::getRelativeLink(const QString &p_path) -{ - if (PathUtils::isLocalFile(p_path)) { - auto relativePath = PathUtils::relativePath(PathUtils::parentDirPath(m_buffer->getContentPath()), p_path); - auto link = PathUtils::encodeSpacesInPath(QDir::fromNativeSeparators(relativePath)); - if (m_config.getPrependDotInRelativeLink()) { - PathUtils::prependDotIfRelative(link); - } - - return link; - } else { - return p_path; +QString MarkdownEditor::getRelativeLink(const QString &p_path) { + if (PathUtils::isLocalFile(p_path)) { + auto relativePath = + PathUtils::relativePath(PathUtils::parentDirPath(m_buffer->getContentPath()), p_path); + auto link = PathUtils::encodeSpacesInPath(QDir::fromNativeSeparators(relativePath)); + if (m_config.getPrependDotInRelativeLink()) { + PathUtils::prependDotIfRelative(link); } -} -const QVector &MarkdownEditor::getHeadings() const -{ - return m_headings; + return link; + } else { + return p_path; + } } -int MarkdownEditor::getCurrentHeadingIndex() const -{ - int blockNumber = m_textEdit->textCursor().blockNumber(); - return getHeadingIndexByBlockNumber(blockNumber); +const QVector &MarkdownEditor::getHeadings() const { return m_headings; } + +int MarkdownEditor::getCurrentHeadingIndex() const { + int blockNumber = m_textEdit->textCursor().blockNumber(); + return getHeadingIndexByBlockNumber(blockNumber); } -void MarkdownEditor::updateHeadings(const QVector &p_headerRegions) -{ - bool needUpdateSectionNumber = false; - if (isReadOnly()) { - m_sectionNumberEnabled = false; - } else { - needUpdateSectionNumber = m_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Edit; - if (m_overriddenSectionNumber != OverrideState::NoOverride) { - needUpdateSectionNumber = m_overriddenSectionNumber == OverrideState::ForceEnable; - } - if (needUpdateSectionNumber) { - m_sectionNumberEnabled = true; - } else if (m_sectionNumberEnabled) { - // On -> Off. We still need to do the clean up. - needUpdateSectionNumber = true; - m_sectionNumberEnabled = false; - } +void MarkdownEditor::updateHeadings(const QVector &p_headerRegions) { + bool needUpdateSectionNumber = false; + if (isReadOnly()) { + m_sectionNumberEnabled = false; + } else { + needUpdateSectionNumber = + m_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Edit; + if (m_overriddenSectionNumber != OverrideState::NoOverride) { + needUpdateSectionNumber = m_overriddenSectionNumber == OverrideState::ForceEnable; + } + if (needUpdateSectionNumber) { + m_sectionNumberEnabled = true; + } else if (m_sectionNumberEnabled) { + // On -> Off. We still need to do the clean up. + needUpdateSectionNumber = true; + m_sectionNumberEnabled = false; } + } - QVector headings; - headings.reserve(p_headerRegions.size()); + QVector headings; + headings.reserve(p_headerRegions.size()); - // Assume that each block contains only one line. - // Only support # syntax for now. - auto doc = document(); - for (auto const ® : p_headerRegions) { - auto block = doc->findBlock(reg.m_startPos); - if (!block.isValid()) { - continue; - } + // Assume that each block contains only one line. + // Only support # syntax for now. + auto doc = document(); + for (auto const ® : p_headerRegions) { + auto block = doc->findBlock(reg.m_startPos); + if (!block.isValid()) { + continue; + } - if (!block.contains(reg.m_endPos - 1)) { - qWarning() << "header accross multiple blocks, starting from block" << block.blockNumber() << block.text(); - } + if (!block.contains(reg.m_endPos - 1)) { + qWarning() << "header accross multiple blocks, starting from block" << block.blockNumber() + << block.text(); + } - auto match = vte::MarkdownUtils::matchHeader(block.text()); - if (match.m_matched) { - Heading heading(match.m_header, - match.m_level, - match.m_sequence, - block.blockNumber()); - headings.append(heading); - } + auto match = vte::MarkdownUtils::matchHeader(block.text()); + if (match.m_matched) { + Heading heading(match.m_header, match.m_level, match.m_sequence, block.blockNumber()); + headings.append(heading); } + } - OutlineProvider::makePerfectHeadings(headings, m_headings); + OutlineProvider::makePerfectHeadings(headings, m_headings); - if (needUpdateSectionNumber) { - // Use a timer to kick off the update to let user have time to undo. - m_sectionNumberTimer->start(); - } + if (needUpdateSectionNumber) { + // Use a timer to kick off the update to let user have time to undo. + m_sectionNumberTimer->start(); + } - emit headingsChanged(); + emit headingsChanged(); - emit currentHeadingChanged(); + emit currentHeadingChanged(); } -int MarkdownEditor::getHeadingIndexByBlockNumber(int p_blockNumber) const -{ - if (m_headings.isEmpty()) { - return -1; - } - - int left = 0, right = m_headings.size() - 1; - while (left < right) { - int mid = left + (right - left + 1) / 2; - int val = m_headings[mid].m_blockNumber; - if (val == -1) { - // Search to right. - for (int i = mid + 1; i <= right; ++i) { - if (m_headings[i].m_blockNumber != -1) { - mid = i; - val = m_headings[i].m_blockNumber; - break; - } - } - - if (val == -1) { - // Search to left. - for (int i = mid - 1; i >= left; --i) { - if (m_headings[i].m_blockNumber != -1) { - mid = i; - val = m_headings[i].m_blockNumber; - break; - } - } - } - } - - if (val == -1) { - // No more valid values. +int MarkdownEditor::getHeadingIndexByBlockNumber(int p_blockNumber) const { + if (m_headings.isEmpty()) { + return -1; + } + + int left = 0, right = m_headings.size() - 1; + while (left < right) { + int mid = left + (right - left + 1) / 2; + int val = m_headings[mid].m_blockNumber; + if (val == -1) { + // Search to right. + for (int i = mid + 1; i <= right; ++i) { + if (m_headings[i].m_blockNumber != -1) { + mid = i; + val = m_headings[i].m_blockNumber; + break; + } + } + + if (val == -1) { + // Search to left. + for (int i = mid - 1; i >= left; --i) { + if (m_headings[i].m_blockNumber != -1) { + mid = i; + val = m_headings[i].m_blockNumber; break; + } } + } + } - if (val == p_blockNumber) { - return mid; - } else if (val > p_blockNumber) { - // Skip the -1 headings. - // Bad case: [0, 2, 3, 43, 44, -1, 46, 60]. - // If not skipped, [left, right] will be stuck at [4, 5]. - right = mid - 1; - while (right >= left && m_headings[right].m_blockNumber == -1) { - --right; - } - } else { - left = mid; - } + if (val == -1) { + // No more valid values. + break; } - if (m_headings[left].m_blockNumber <= p_blockNumber && m_headings[left].m_blockNumber != -1) { - return left; + if (val == p_blockNumber) { + return mid; + } else if (val > p_blockNumber) { + // Skip the -1 headings. + // Bad case: [0, 2, 3, 43, 44, -1, 46, 60]. + // If not skipped, [left, right] will be stuck at [4, 5]. + right = mid - 1; + while (right >= left && m_headings[right].m_blockNumber == -1) { + --right; + } + } else { + left = mid; } + } - return -1; + if (m_headings[left].m_blockNumber <= p_blockNumber && m_headings[left].m_blockNumber != -1) { + return left; + } + + return -1; } -void MarkdownEditor::scrollToHeading(int p_idx) -{ - if (p_idx < 0 || p_idx >= m_headings.size()) { - return; - } +void MarkdownEditor::scrollToHeading(int p_idx) { + if (p_idx < 0 || p_idx >= m_headings.size()) { + return; + } - if (m_headings[p_idx].m_blockNumber == -1) { - return; - } + if (m_headings[p_idx].m_blockNumber == -1) { + return; + } - scrollToLine(m_headings[p_idx].m_blockNumber, true); + scrollToLine(m_headings[p_idx].m_blockNumber, true); } -void MarkdownEditor::handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, QScopedPointer *p_menu) -{ - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); +void MarkdownEditor::handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, + QScopedPointer *p_menu) { + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - *p_handled = true; - p_menu->reset(m_textEdit->createStandardContextMenu(p_event->pos())); - auto menu = p_menu->data(); - - const auto actions = menu->actions(); - QAction *firstAct = actions.isEmpty() ? nullptr : actions.first(); - // QAction *copyAct = WidgetUtils::findActionByObjectName(actions, "edit-copy"); - QAction *pasteAct = WidgetUtils::findActionByObjectName(actions, "edit-paste"); - - const bool hasSelection = m_textEdit->hasSelection(); - - if (!hasSelection) { - auto readAct = new QAction(tr("&Read"), menu); - WidgetUtils::addActionShortcutText(readAct, editorConfig.getShortcut(EditorConfig::Shortcut::EditRead)); - connect(readAct, &QAction::triggered, - this, &MarkdownEditor::readRequested); - menu->insertAction(firstAct, readAct); - if (firstAct) { - menu->insertSeparator(firstAct); - } + *p_handled = true; + p_menu->reset(m_textEdit->createStandardContextMenu(p_event->pos())); + auto menu = p_menu->data(); - prependContextSensitiveMenu(menu, p_event->pos()); - } - - if (pasteAct && pasteAct->isEnabled()) { - QClipboard *clipboard = QApplication::clipboard(); - const QMimeData *mimeData = clipboard->mimeData(); - - // Rich Paste or Plain Text Paste. - const bool richPasteByDefault = editorConfig.getMarkdownEditorConfig().getRichPasteByDefaultEnabled(); - auto altPasteAct = new QAction(richPasteByDefault ? tr("Paste as Plain Text") : tr("Rich Paste"), menu); - WidgetUtils::addActionShortcutText(altPasteAct, - editorConfig.getShortcut(EditorConfig::Shortcut::AltPaste)); - connect(altPasteAct, &QAction::triggered, - this, &MarkdownEditor::altPaste); - WidgetUtils::insertActionAfter(menu, pasteAct, altPasteAct); - - if (mimeData->hasHtml()) { - // Parse to Markdown and Paste. - auto parsePasteAct = new QAction(tr("Parse to Markdown and Paste"), menu); - WidgetUtils::addActionShortcutText(parsePasteAct, - editorConfig.getShortcut(EditorConfig::Shortcut::ParseToMarkdownAndPaste)); - connect(parsePasteAct, &QAction::triggered, - this, &MarkdownEditor::parseToMarkdownAndPaste); - WidgetUtils::insertActionAfter(menu, altPasteAct, parsePasteAct); - } - } + const auto actions = menu->actions(); + QAction *firstAct = actions.isEmpty() ? nullptr : actions.first(); + // QAction *copyAct = WidgetUtils::findActionByObjectName(actions, "edit-copy"); + QAction *pasteAct = WidgetUtils::findActionByObjectName(actions, "edit-paste"); - { - menu->addSeparator(); + const bool hasSelection = m_textEdit->hasSelection(); - auto snippetAct = menu->addAction(tr("Insert Snippet"), this, &MarkdownEditor::applySnippetRequested); - WidgetUtils::addActionShortcutText(snippetAct, - editorConfig.getShortcut(EditorConfig::Shortcut::ApplySnippet)); + if (!hasSelection) { + auto readAct = new QAction(tr("&Read"), menu); + WidgetUtils::addActionShortcutText(readAct, + editorConfig.getShortcut(EditorConfig::Shortcut::EditRead)); + connect(readAct, &QAction::triggered, this, &MarkdownEditor::readRequested); + menu->insertAction(firstAct, readAct); + if (firstAct) { + menu->insertSeparator(firstAct); } - if (!hasSelection) { - appendImageHostMenu(menu); - } - - appendSpellCheckMenu(p_event, menu); -} + prependContextSensitiveMenu(menu, p_event->pos()); + } -void MarkdownEditor::altPaste() -{ - const bool richPasteByDefault = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getRichPasteByDefaultEnabled(); + if (pasteAct && pasteAct->isEnabled()) { + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); - if (richPasteByDefault) { - // Paste as plain text. - m_plainTextPasteAsked = true; - m_richPasteAsked = false; - } else { - // Rich paste. - m_plainTextPasteAsked = false; - m_richPasteAsked = true; - } + // Rich Paste or Plain Text Paste. + const bool richPasteByDefault = + editorConfig.getMarkdownEditorConfig().getRichPasteByDefaultEnabled(); + auto altPasteAct = + new QAction(richPasteByDefault ? tr("Paste as Plain Text") : tr("Rich Paste"), menu); + WidgetUtils::addActionShortcutText(altPasteAct, + editorConfig.getShortcut(EditorConfig::Shortcut::AltPaste)); + connect(altPasteAct, &QAction::triggered, this, &MarkdownEditor::altPaste); + WidgetUtils::insertActionAfter(menu, pasteAct, altPasteAct); + + if (mimeData->hasHtml()) { + // Parse to Markdown and Paste. + auto parsePasteAct = new QAction(tr("Parse to Markdown and Paste"), menu); + WidgetUtils::addActionShortcutText( + parsePasteAct, editorConfig.getShortcut(EditorConfig::Shortcut::ParseToMarkdownAndPaste)); + connect(parsePasteAct, &QAction::triggered, this, &MarkdownEditor::parseToMarkdownAndPaste); + WidgetUtils::insertActionAfter(menu, altPasteAct, parsePasteAct); + } + } + + { + menu->addSeparator(); + + auto snippetAct = + menu->addAction(tr("Insert Snippet"), this, &MarkdownEditor::applySnippetRequested); + WidgetUtils::addActionShortcutText( + snippetAct, editorConfig.getShortcut(EditorConfig::Shortcut::ApplySnippet)); + } + + if (!hasSelection) { + appendImageHostMenu(menu); + } + + appendSpellCheckMenu(p_event, menu); +} - // handleCanInsertFromMimeData() is called before this function. Call it manually. - if (m_textEdit->canPaste()) { - m_textEdit->paste(); - } +void MarkdownEditor::altPaste() { + const bool richPasteByDefault = ConfigMgr::getInst() + .getEditorConfig() + .getMarkdownEditorConfig() + .getRichPasteByDefaultEnabled(); - m_plainTextPasteAsked = false; + if (richPasteByDefault) { + // Paste as plain text. + m_plainTextPasteAsked = true; m_richPasteAsked = false; -} + } else { + // Rich paste. + m_plainTextPasteAsked = false; + m_richPasteAsked = true; + } -void MarkdownEditor::setupShortcuts() -{ - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - - // Alt paste. - { - auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::Shortcut::AltPaste), - this); - if (shortcut) { - connect(shortcut, &QShortcut::activated, - this, &MarkdownEditor::altPaste); - } - } + // handleCanInsertFromMimeData() is called before this function. Call it manually. + if (m_textEdit->canPaste()) { + m_textEdit->paste(); + } - // Parse to Markdown and Paste. - { - auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::Shortcut::ParseToMarkdownAndPaste), - this); - if (shortcut) { - connect(shortcut, &QShortcut::activated, - this, &MarkdownEditor::parseToMarkdownAndPaste); - } - } + m_plainTextPasteAsked = false; + m_richPasteAsked = false; } -void MarkdownEditor::parseToMarkdownAndPaste() -{ - if (isReadOnly()) { - return; +void MarkdownEditor::setupShortcuts() { + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + + // Alt paste. + { + auto shortcut = WidgetUtils::createShortcut( + editorConfig.getShortcut(EditorConfig::Shortcut::AltPaste), this); + if (shortcut) { + connect(shortcut, &QShortcut::activated, this, &MarkdownEditor::altPaste); } + } - QClipboard *clipboard = QApplication::clipboard(); - const QMimeData *mimeData = clipboard->mimeData(); - QString html(mimeData->html()); - if (!html.isEmpty()) { - emit htmlToMarkdownRequested(0, ++m_timeStamp, html); + // Parse to Markdown and Paste. + { + auto shortcut = WidgetUtils::createShortcut( + editorConfig.getShortcut(EditorConfig::Shortcut::ParseToMarkdownAndPaste), this); + if (shortcut) { + connect(shortcut, &QShortcut::activated, this, &MarkdownEditor::parseToMarkdownAndPaste); } + } } -void MarkdownEditor::handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text) -{ - Q_UNUSED(p_id); - if (m_timeStamp == p_timeStamp && !p_text.isEmpty()) { - QString text(p_text); +void MarkdownEditor::parseToMarkdownAndPaste() { + if (isReadOnly()) { + return; + } + + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + QString html(mimeData->html()); + if (!html.isEmpty()) { + emit htmlToMarkdownRequested(0, ++m_timeStamp, html); + } +} - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - if (editorConfig.getFetchImagesInParseAndPaste()) { - fetchImagesToLocalAndReplace(text); - } +void MarkdownEditor::handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, + const QString &p_text) { + Q_UNUSED(p_id); + if (m_timeStamp == p_timeStamp && !p_text.isEmpty()) { + QString text(p_text); - insertText(text); + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); + if (editorConfig.getFetchImagesInParseAndPaste()) { + fetchImagesToLocalAndReplace(text); } + + insertText(text); + } } -static QString purifyImageTitle(QString p_title) -{ - return p_title.remove(QRegularExpression("[\\r\\n\\[\\]]")); +static QString purifyImageTitle(QString p_title) { + return p_title.remove(QRegularExpression("[\\r\\n\\[\\]]")); } -void MarkdownEditor::fetchImagesToLocalAndReplace(QString &p_text) -{ - auto regs = vte::MarkdownUtils::fetchImageRegionsViaParser(p_text); - if (regs.isEmpty()) { - return; - } +void MarkdownEditor::fetchImagesToLocalAndReplace(QString &p_text) { + auto regs = vte::MarkdownUtils::fetchImageRegionsViaParser(p_text); + if (regs.isEmpty()) { + return; + } - // Sort it in ascending order. - std::sort(regs.begin(), regs.end()); + // Sort it in ascending order. + std::sort(regs.begin(), regs.end()); - QProgressDialog proDlg(tr("Fetching images to local..."), - tr("Abort"), - 0, - regs.size(), - this); - proDlg.setWindowModality(Qt::WindowModal); - proDlg.setWindowTitle(tr("Fetch Images To Local")); + QProgressDialog proDlg(tr("Fetching images to local..."), tr("Abort"), 0, regs.size(), this); + proDlg.setWindowModality(Qt::WindowModal); + proDlg.setWindowTitle(tr("Fetch Images To Local")); - QRegularExpression zhihuRegExp("^https?://www\\.zhihu\\.com/equation\\?tex=(.+)$"); + QRegularExpression zhihuRegExp("^https?://www\\.zhihu\\.com/equation\\?tex=(.+)$"); - QRegularExpression regExp(vte::MarkdownUtils::c_imageLinkRegExp); - for (int i = regs.size() - 1; i >= 0; --i) { - proDlg.setValue(regs.size() - 1 - i); - if (proDlg.wasCanceled()) { - break; - } + QRegularExpression regExp(vte::MarkdownUtils::c_imageLinkRegExp); + for (int i = regs.size() - 1; i >= 0; --i) { + proDlg.setValue(regs.size() - 1 - i); + if (proDlg.wasCanceled()) { + break; + } - const auto ® = regs[i]; - QString linkText = p_text.mid(reg.m_startPos, reg.m_endPos - reg.m_startPos); - QRegularExpressionMatch match; - if (linkText.indexOf(regExp, 0, &match) == -1) { - continue; - } + const auto ® = regs[i]; + QString linkText = p_text.mid(reg.m_startPos, reg.m_endPos - reg.m_startPos); + QRegularExpressionMatch match; + if (linkText.indexOf(regExp, 0, &match) == -1) { + continue; + } - qDebug() << "fetching image link" << linkText; + qDebug() << "fetching image link" << linkText; - const QString imageTitle = purifyImageTitle(match.captured(1).trimmed()); - QString imageUrl = match.captured(2).trimmed(); + const QString imageTitle = purifyImageTitle(match.captured(1).trimmed()); + QString imageUrl = match.captured(2).trimmed(); - const int maxUrlLength = 100; - QString urlToDisplay(imageUrl); - if (urlToDisplay.size() > maxUrlLength) { - urlToDisplay = urlToDisplay.left(maxUrlLength) + "..."; - } - proDlg.setLabelText(tr("Fetching image (%1)").arg(urlToDisplay)); - - // Handle equation from zhihu.com like http://www.zhihu.com/equation?tex=P. - QRegularExpressionMatch zhihuMatch; - if (imageUrl.indexOf(zhihuRegExp, 0, &zhihuMatch) != -1) { - QString tex = zhihuMatch.captured(1).trimmed(); - - // Remove the +. - tex.replace(QChar('+'), " "); - - tex = QUrl::fromPercentEncoding(tex.toUtf8()); - if (tex.isEmpty()) { - continue; - } - - tex = "$" + tex + "$"; - p_text.replace(reg.m_startPos, - reg.m_endPos - reg.m_startPos, - tex); - continue; - } + const int maxUrlLength = 100; + QString urlToDisplay(imageUrl); + if (urlToDisplay.size() > maxUrlLength) { + urlToDisplay = urlToDisplay.left(maxUrlLength) + "..."; + } + proDlg.setLabelText(tr("Fetching image (%1)").arg(urlToDisplay)); - // Only handle absolute file path or network path. - QString srcImagePath; - QFileInfo info(WebUtils::purifyUrl(imageUrl)); - - // For network image. - QScopedPointer tmpFile; - - if (info.exists()) { - if (info.isAbsolute()) { - // Absolute local path. - srcImagePath = info.absoluteFilePath(); - } - } else { - // Network path. - // Prepend the protocol if missing. - if (imageUrl.startsWith(QStringLiteral("//"))) { - imageUrl.prepend(QStringLiteral("https:")); - } - QByteArray data = vte::NetworkAccess::request(QUrl(imageUrl)).m_data; - if (!data.isEmpty()) { - // Prefer the suffix from the real data. - auto suffix = ImageUtils::guessImageSuffix(data); - if (suffix.isEmpty()) { - suffix = info.suffix(); - } else if (info.suffix() != suffix) { - qWarning() << "guess a different suffix from image data" << info.suffix() << suffix; - } - tmpFile.reset(FileUtils::createTemporaryFile(suffix)); - if (tmpFile->open() && tmpFile->write(data) > -1) { - srcImagePath = tmpFile->fileName(); - } - - // Need to close it explicitly to flush cache of small file. - tmpFile->close(); - } - } + // Handle equation from zhihu.com like http://www.zhihu.com/equation?tex=P. + QRegularExpressionMatch zhihuMatch; + if (imageUrl.indexOf(zhihuRegExp, 0, &zhihuMatch) != -1) { + QString tex = zhihuMatch.captured(1).trimmed(); - if (srcImagePath.isEmpty()) { - continue; - } + // Remove the +. + tex.replace(QChar('+'), " "); - // Insert image without inserting text. - QString urlInLink; - bool ret = insertImageToBufferFromLocalFile(imageTitle, - QString(), - srcImagePath, - 0, - 0, - false, - &urlInLink); - if (!ret || urlInLink.isEmpty()) { - continue; - } + tex = QUrl::fromPercentEncoding(tex.toUtf8()); + if (tex.isEmpty()) { + continue; + } - // Replace URL in link. - QString newLink = QStringLiteral("![%1](%2%3%4)") - .arg(imageTitle, urlInLink, match.captured(3), match.captured(6)); - p_text.replace(reg.m_startPos, - reg.m_endPos - reg.m_startPos, - newLink); + tex = "$" + tex + "$"; + p_text.replace(reg.m_startPos, reg.m_endPos - reg.m_startPos, tex); + continue; } - proDlg.setValue(regs.size()); -} + // Only handle absolute file path or network path. + QString srcImagePath; + QFileInfo info(WebUtils::purifyUrl(imageUrl)); -static bool updateHeadingSectionNumber(QTextCursor &p_cursor, - const QTextBlock &p_block, - const QString &p_sectionNumber, - bool p_endingDot) -{ - if (!p_block.isValid()) { - return false; - } - - QString text = p_block.text(); - auto match = vte::MarkdownUtils::matchHeader(text); - Q_ASSERT(match.m_matched); - - bool isSequence = false; - if (!match.m_sequence.isEmpty()) { - // Check if this sequence is the real sequence matching current style. - if (match.m_sequence.endsWith('.')) { - isSequence = p_endingDot; - } else { - isSequence = !p_endingDot; + // For network image. + QScopedPointer tmpFile; + + if (info.exists()) { + if (info.isAbsolute()) { + // Absolute local path. + srcImagePath = info.absoluteFilePath(); + } + } else { + // Network path. + // Prepend the protocol if missing. + if (imageUrl.startsWith(QStringLiteral("//"))) { + imageUrl.prepend(QStringLiteral("https:")); + } + QByteArray data = vte::NetworkAccess::request(QUrl(imageUrl)).m_data; + if (!data.isEmpty()) { + // Prefer the suffix from the real data. + auto suffix = ImageUtils::guessImageSuffix(data); + if (suffix.isEmpty()) { + suffix = info.suffix(); + } else if (info.suffix() != suffix) { + qWarning() << "guess a different suffix from image data" << info.suffix() << suffix; + } + tmpFile.reset(FileUtils::createTemporaryFile(suffix)); + if (tmpFile->open() && tmpFile->write(data) > -1) { + srcImagePath = tmpFile->fileName(); } - } - int start = match.m_level + 1; - int end = match.m_level + match.m_spacesAfterMarker; - if (isSequence) { - end += match.m_sequence.size() + match.m_spacesAfterSequence; + // Need to close it explicitly to flush cache of small file. + tmpFile->close(); + } } - Q_ASSERT(start <= end); + if (srcImagePath.isEmpty()) { + continue; + } - p_cursor.setPosition(p_block.position() + start); - if (start != end) { - p_cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor); + // Insert image without inserting text. + QString urlInLink; + bool ret = insertImageToBufferFromLocalFile(imageTitle, QString(), srcImagePath, 0, 0, false, + &urlInLink); + if (!ret || urlInLink.isEmpty()) { + continue; } - if (p_sectionNumber.isEmpty()) { - p_cursor.removeSelectedText(); + // Replace URL in link. + QString newLink = QStringLiteral("![%1](%2%3%4)") + .arg(imageTitle, urlInLink, match.captured(3), match.captured(6)); + p_text.replace(reg.m_startPos, reg.m_endPos - reg.m_startPos, newLink); + } + + proDlg.setValue(regs.size()); +} + +static bool updateHeadingSectionNumber(QTextCursor &p_cursor, const QTextBlock &p_block, + const QString &p_sectionNumber, bool p_endingDot) { + if (!p_block.isValid()) { + return false; + } + + QString text = p_block.text(); + auto match = vte::MarkdownUtils::matchHeader(text); + Q_ASSERT(match.m_matched); + + bool isSequence = false; + if (!match.m_sequence.isEmpty()) { + // Check if this sequence is the real sequence matching current style. + if (match.m_sequence.endsWith('.')) { + isSequence = p_endingDot; } else { - p_cursor.insertText(p_sectionNumber + ' '); + isSequence = !p_endingDot; } - return true; + } + + int start = match.m_level + 1; + int end = match.m_level + match.m_spacesAfterMarker; + if (isSequence) { + end += match.m_sequence.size() + match.m_spacesAfterSequence; + } + + Q_ASSERT(start <= end); + + p_cursor.setPosition(p_block.position() + start); + if (start != end) { + p_cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor); + } + + if (p_sectionNumber.isEmpty()) { + p_cursor.removeSelectedText(); + } else { + p_cursor.insertText(p_sectionNumber + ' '); + } + return true; } -bool MarkdownEditor::updateSectionNumber(const QVector &p_headings) -{ - SectionNumber sectionNumber(7, 0); - int baseLevel = m_config.getSectionNumberBaseLevel(); - if (baseLevel < 1 || baseLevel > 6) { - baseLevel = 1; - } - - bool changed = false; - bool endingDot = m_config.getSectionNumberStyle() == MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot; - auto doc = document(); - QTextCursor cursor(doc); - cursor.beginEditBlock(); - for (const auto &heading : p_headings) { - OutlineProvider::increaseSectionNumber(sectionNumber, heading.m_level, baseLevel); - auto sectionStr = m_sectionNumberEnabled ? OutlineProvider::joinSectionNumber(sectionNumber, endingDot) : QString(); - if (heading.m_blockNumber > -1 && sectionStr != heading.m_sectionNumber) { - if (updateHeadingSectionNumber(cursor, - doc->findBlockByNumber(heading.m_blockNumber), - sectionStr, - endingDot)) { - changed = true; - } - } - } - cursor.endEditBlock(); +bool MarkdownEditor::updateSectionNumber(const QVector &p_headings) { + SectionNumber sectionNumber(7, 0); + int baseLevel = m_config.getSectionNumberBaseLevel(); + if (baseLevel < 1 || baseLevel > 6) { + baseLevel = 1; + } + + bool changed = false; + bool endingDot = + m_config.getSectionNumberStyle() == MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot; + auto doc = document(); + QTextCursor cursor(doc); + cursor.beginEditBlock(); + for (const auto &heading : p_headings) { + OutlineProvider::increaseSectionNumber(sectionNumber, heading.m_level, baseLevel); + auto sectionStr = m_sectionNumberEnabled + ? OutlineProvider::joinSectionNumber(sectionNumber, endingDot) + : QString(); + if (heading.m_blockNumber > -1 && sectionStr != heading.m_sectionNumber) { + if (updateHeadingSectionNumber(cursor, doc->findBlockByNumber(heading.m_blockNumber), + sectionStr, endingDot)) { + changed = true; + } + } + } + cursor.endEditBlock(); + + return changed; +} - return changed; +void MarkdownEditor::overrideSectionNumber(OverrideState p_state) { + if (m_overriddenSectionNumber == p_state) { + return; + } + + m_overriddenSectionNumber = p_state; + getHighlighter()->updateHighlight(); } -void MarkdownEditor::overrideSectionNumber(OverrideState p_state) -{ - if (m_overriddenSectionNumber == p_state) { - return; - } +void MarkdownEditor::updateFromConfig(bool p_initialized) { + if (m_config.getTextEditorConfig().getZoomDelta() != 0) { + zoom(m_config.getTextEditorConfig().getZoomDelta()); + } - m_overriddenSectionNumber = p_state; + if (p_initialized) { getHighlighter()->updateHighlight(); + } } -void MarkdownEditor::updateFromConfig(bool p_initialized) -{ - if (m_config.getTextEditorConfig().getZoomDelta() != 0) { - zoom(m_config.getTextEditorConfig().getZoomDelta()); - } +void MarkdownEditor::setupTableHelper() { + m_tableHelper = new MarkdownTableHelper(this, this); + connect(getHighlighter(), &vte::PegMarkdownHighlighter::tableBlocksUpdated, m_tableHelper, + &MarkdownTableHelper::updateTableBlocks); +} - if (p_initialized) { - getHighlighter()->updateHighlight(); - } +QRgb MarkdownEditor::getPreviewBackground() const { + auto th = theme(); + const auto &fmt = th->editorStyle(vte::Theme::EditorStyle::Preview); + return fmt.m_backgroundColor; } -void MarkdownEditor::setupTableHelper() -{ - m_tableHelper = new MarkdownTableHelper(this, this); - connect(getHighlighter(), &vte::PegMarkdownHighlighter::tableBlocksUpdated, - m_tableHelper, &MarkdownTableHelper::updateTableBlocks); +void MarkdownEditor::setImageHost(ImageHost *p_host) { + // It may be different than the global default image host. + m_imageHost = p_host; } -QRgb MarkdownEditor::getPreviewBackground() const -{ - auto th = theme(); - const auto &fmt = th->editorStyle(vte::Theme::EditorStyle::Preview); - return fmt.m_backgroundColor; +static QString generateImageHostFileName(const Buffer *p_buffer, const QString &p_destFileName) { + auto destPath = ImageHostUtils::generateRelativePath(p_buffer); + if (destPath.isEmpty()) { + destPath = p_destFileName; + } else { + destPath += "/" + p_destFileName; + } + return destPath; } -void MarkdownEditor::setImageHost(ImageHost *p_host) -{ - // It may be different than the global default image host. - m_imageHost = p_host; +QString MarkdownEditor::saveToImageHost(const QByteArray &p_imageData, + const QString &p_destFileName) { + Q_ASSERT(m_imageHost); + + const auto destPath = generateImageHostFileName(m_buffer, p_destFileName); + + QString errMsg; + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + auto targetUrl = m_imageHost->create(p_imageData, destPath, errMsg); + QApplication::restoreOverrideCursor(); + + if (targetUrl.isEmpty()) { + MessageBoxHelper::notify(MessageBoxHelper::Warning, + tr("Failed to upload image to image host (%1) as (%2).") + .arg(m_imageHost->getName(), destPath), + QString(), errMsg, this); + } + + return targetUrl; } -static QString generateImageHostFileName(const Buffer *p_buffer, const QString &p_destFileName) -{ - auto destPath = ImageHostUtils::generateRelativePath(p_buffer); - if (destPath.isEmpty()) { - destPath = p_destFileName; - } else { - destPath += "/" + p_destFileName; - } - return destPath; +void MarkdownEditor::appendImageHostMenu(QMenu *p_menu) { + p_menu->addSeparator(); + auto subMenu = p_menu->addMenu(tr("Upload Images To Image Host")); + + const auto &hosts = ImageHostMgr::getInst().getImageHosts(); + if (hosts.isEmpty()) { + auto act = subMenu->addAction(tr("None")); + act->setEnabled(false); + return; + } + + for (const auto &host : hosts) { + auto act = subMenu->addAction(host->getName(), this, &MarkdownEditor::uploadImagesToImageHost); + act->setData(host->getName()); + } } -QString MarkdownEditor::saveToImageHost(const QByteArray &p_imageData, const QString &p_destFileName) -{ - Q_ASSERT(m_imageHost); +void MarkdownEditor::uploadImagesToImageHost() { + auto act = static_cast(sender()); + auto host = ImageHostMgr::getInst().find(act->data().toString()); + Q_ASSERT(host); - const auto destPath = generateImageHostFileName(m_buffer, p_destFileName); + // Only LocalRelativeInternal images. + // Descending order of the link position. + auto images = vte::MarkdownUtils::fetchImagesFromMarkdownText( + m_buffer->getContent(), m_buffer->getResourcePath(), + vte::MarkdownLink::TypeFlag::LocalRelativeInternal); + if (images.isEmpty()) { + return; + } - QString errMsg; + QProgressDialog proDlg(tr("Uploading local images..."), tr("Abort"), 0, images.size(), this); + proDlg.setWindowModality(Qt::WindowModal); + proDlg.setWindowTitle(tr("Upload Images To Image Host")); - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - auto targetUrl = m_imageHost->create(p_imageData, destPath, errMsg); - QApplication::restoreOverrideCursor(); + QHash uploadedImages; - if (targetUrl.isEmpty()) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to upload image to image host (%1) as (%2).").arg(m_imageHost->getName(), destPath), - QString(), - errMsg, - this); + int cnt = 0; + auto cursor = m_textEdit->textCursor(); + cursor.beginEditBlock(); + for (int i = 0; i < images.size(); ++i) { + const auto &link = images[i]; + + auto it = uploadedImages.find(link.m_path); + if (it != uploadedImages.end()) { + cursor.setPosition(link.m_urlInLinkPos); + cursor.setPosition(link.m_urlInLinkPos + link.m_urlInLink.size(), QTextCursor::KeepAnchor); + cursor.insertText(it.value()); + continue; } - return targetUrl; -} + proDlg.setValue(i + 1); + if (proDlg.wasCanceled()) { + break; + } + proDlg.setLabelText(tr("Upload image (%1)").arg(link.m_path)); -void MarkdownEditor::appendImageHostMenu(QMenu *p_menu) -{ - p_menu->addSeparator(); - auto subMenu = p_menu->addMenu(tr("Upload Images To Image Host")); + Q_ASSERT(i == 0 || link.m_urlInLinkPos < images[i - 1].m_urlInLinkPos); - const auto &hosts = ImageHostMgr::getInst().getImageHosts(); - if (hosts.isEmpty()) { - auto act = subMenu->addAction(tr("None")); - act->setEnabled(false); - return; + QByteArray ba; + try { + ba = FileUtils::readFile(link.m_path); + } catch (Exception &e) { + MessageBoxHelper::notify( + MessageBoxHelper::Warning, + tr("Failed to read local image file (%1) (%2).").arg(link.m_path, e.what()), this); + continue; } - for (const auto &host : hosts) { - auto act = subMenu->addAction(host->getName(), - this, - &MarkdownEditor::uploadImagesToImageHost); - act->setData(host->getName()); + if (ba.isEmpty()) { + qWarning() << "Skipped uploading empty image" << link.m_path; + continue; } -} -void MarkdownEditor::uploadImagesToImageHost() -{ - auto act = static_cast(sender()); - auto host = ImageHostMgr::getInst().find(act->data().toString()); - Q_ASSERT(host); - - // Only LocalRelativeInternal images. - // Descending order of the link position. - auto images = vte::MarkdownUtils::fetchImagesFromMarkdownText(m_buffer->getContent(), - m_buffer->getResourcePath(), - vte::MarkdownLink::TypeFlag::LocalRelativeInternal); - if (images.isEmpty()) { - return; + const auto destPath = generateImageHostFileName(m_buffer, PathUtils::fileName(link.m_path)); + QString errMsg; + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + const auto targetUrl = host->create(ba, destPath, errMsg); + QApplication::restoreOverrideCursor(); + + if (targetUrl.isEmpty()) { + MessageBoxHelper::notify( + MessageBoxHelper::Warning, + tr("Failed to upload image to image host (%1) as (%2).").arg(host->getName(), destPath), + QString(), errMsg, this); + continue; } - QProgressDialog proDlg(tr("Uploading local images..."), - tr("Abort"), - 0, - images.size(), - this); - proDlg.setWindowModality(Qt::WindowModal); - proDlg.setWindowTitle(tr("Upload Images To Image Host")); - - QHash uploadedImages; - - int cnt = 0; - auto cursor = m_textEdit->textCursor(); - cursor.beginEditBlock(); - for (int i = 0; i < images.size(); ++i) { - const auto &link = images[i]; - - auto it = uploadedImages.find(link.m_path); - if (it != uploadedImages.end()) { - cursor.setPosition(link.m_urlInLinkPos); - cursor.setPosition(link.m_urlInLinkPos + link.m_urlInLink.size(), QTextCursor::KeepAnchor); - cursor.insertText(it.value()); - continue; - } + // Update the link URL. + cursor.setPosition(link.m_urlInLinkPos); + cursor.setPosition(link.m_urlInLinkPos + link.m_urlInLink.size(), QTextCursor::KeepAnchor); + cursor.insertText(targetUrl); + uploadedImages.insert(link.m_path, targetUrl); + ++cnt; + } + cursor.endEditBlock(); - proDlg.setValue(i + 1); - if (proDlg.wasCanceled()) { - break; - } - proDlg.setLabelText(tr("Upload image (%1)").arg(link.m_path)); - - Q_ASSERT(i == 0 || link.m_urlInLinkPos < images[i - 1].m_urlInLinkPos); - - QByteArray ba; - try { - ba = FileUtils::readFile(link.m_path); - } catch (Exception &e) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to read local image file (%1) (%2).").arg(link.m_path, e.what()), - this); - continue; - } + proDlg.setValue(images.size()); - if (ba.isEmpty()) { - qWarning() << "Skipped uploading empty image" << link.m_path; - continue; - } + if (cnt > 0) { + m_textEdit->setTextCursor(cursor); + } +} - const auto destPath = generateImageHostFileName(m_buffer, PathUtils::fileName(link.m_path)); - QString errMsg; - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - const auto targetUrl = host->create(ba, destPath, errMsg); - QApplication::restoreOverrideCursor(); - - if (targetUrl.isEmpty()) { - MessageBoxHelper::notify(MessageBoxHelper::Warning, - tr("Failed to upload image to image host (%1) as (%2).").arg(host->getName(), destPath), - QString(), - errMsg, - this); - continue; - } +void MarkdownEditor::prependContextSensitiveMenu(QMenu *p_menu, const QPoint &p_pos) { + auto cursor = m_textEdit->cursorForPosition(p_pos); + const int pos = cursor.position(); + const auto block = cursor.block(); - // Update the link URL. - cursor.setPosition(link.m_urlInLinkPos); - cursor.setPosition(link.m_urlInLinkPos + link.m_urlInLink.size(), QTextCursor::KeepAnchor); - cursor.insertText(targetUrl); - uploadedImages.insert(link.m_path, targetUrl); - ++cnt; - } - cursor.endEditBlock(); + Q_ASSERT(!p_menu->isEmpty()); + auto firstAct = p_menu->actions().at(0); - proDlg.setValue(images.size()); + bool ret = prependImageMenu(p_menu, firstAct, pos, block); + if (ret) { + return; + } - if (cnt > 0) { - m_textEdit->setTextCursor(cursor); - } + ret = prependLinkMenu(p_menu, firstAct, pos, block); + if (ret) { + return; + } + + if (prependInPlacePreviewMenu(p_menu, firstAct, pos, block)) { + p_menu->insertSeparator(firstAct); + } } -void MarkdownEditor::prependContextSensitiveMenu(QMenu *p_menu, const QPoint &p_pos) -{ - auto cursor = m_textEdit->cursorForPosition(p_pos); - const int pos = cursor.position(); - const auto block = cursor.block(); +bool MarkdownEditor::prependImageMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block) { + const auto text = p_block.text(); - Q_ASSERT(!p_menu->isEmpty()); - auto firstAct = p_menu->actions().at(0); + if (!vte::MarkdownUtils::hasImageLink(text)) { + return false; + } - bool ret = prependImageMenu(p_menu, firstAct, pos, block); - if (ret) { - return; - } + QString imgPath; - ret = prependLinkMenu(p_menu, firstAct, pos, block); - if (ret) { - return; + const auto ®ions = getHighlighter()->getImageRegions(); + for (const auto ® : regions) { + if (!reg.contains(p_cursorPos) && + (!reg.contains(p_cursorPos - 1) || p_cursorPos != p_block.position() + text.size())) { + continue; } - if (prependInPlacePreviewMenu(p_menu, firstAct, pos, block)) { - p_menu->insertSeparator(firstAct); + if (reg.m_endPos > p_block.position() + text.size()) { + return true; } -} - -bool MarkdownEditor::prependImageMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block) -{ - const auto text = p_block.text(); - if (!vte::MarkdownUtils::hasImageLink(text)) { - return false; + const auto linkText = + text.mid(reg.m_startPos - p_block.position(), reg.m_endPos - reg.m_startPos); + int linkWidth = 0; + int linkHeight = 0; + const auto shortUrl = vte::MarkdownUtils::fetchImageLinkUrl(linkText, linkWidth, linkHeight); + if (shortUrl.isEmpty()) { + return true; } - QString imgPath; + imgPath = vte::MarkdownUtils::linkUrlToPath(getBasePath(), shortUrl); + break; + } - const auto ®ions = getHighlighter()->getImageRegions(); - for (const auto ® : regions) { - if (!reg.contains(p_cursorPos) && (!reg.contains(p_cursorPos - 1) || p_cursorPos != p_block.position() + text.size())) { - continue; - } - - if (reg.m_endPos > p_block.position() + text.size()) { - return true; - } + { + auto act = new QAction(tr("View Image"), p_menu); + connect(act, &QAction::triggered, p_menu, + [imgPath]() { WidgetUtils::openUrlByDesktop(PathUtils::pathToUrl(imgPath)); }); + p_menu->insertAction(p_before, act); + } - const auto linkText = text.mid(reg.m_startPos - p_block.position(), reg.m_endPos - reg.m_startPos); - int linkWidth = 0; - int linkHeight = 0; - const auto shortUrl = vte::MarkdownUtils::fetchImageLinkUrl(linkText, linkWidth, linkHeight); - if (shortUrl.isEmpty()) { - return true; - } + { + auto act = new QAction(tr("Copy Image URL"), p_menu); + connect(act, &QAction::triggered, p_menu, + [imgPath]() { ClipboardUtils::setLinkToClipboard(imgPath); }); + p_menu->insertAction(p_before, act); + } + + if (QFileInfo::exists(imgPath)) { + // Local image. + auto act = new QAction(tr("Copy Image"), p_menu); + connect(act, &QAction::triggered, p_menu, [imgPath]() { + auto clipboard = QApplication::clipboard(); + clipboard->clear(); + + // Copy local GIF to clipboard to ensure no frame loss + if (imgPath.endsWith(QStringLiteral(".gif"), Qt::CaseInsensitive) && + FileUtils::existsCaseInsensitive(imgPath)) { + ClipboardUtils::setLocalFileToClipboard(clipboard, imgPath, QClipboard::Clipboard); + return; + } - imgPath = vte::MarkdownUtils::linkUrlToPath(getBasePath(), shortUrl); - break; - } - - { - auto act = new QAction(tr("View Image"), p_menu); - connect(act, &QAction::triggered, - p_menu, [imgPath]() { - WidgetUtils::openUrlByDesktop(PathUtils::pathToUrl(imgPath)); - }); - p_menu->insertAction(p_before, act); - } - - { - auto act = new QAction(tr("Copy Image URL"), p_menu); - connect(act, &QAction::triggered, - p_menu, [imgPath]() { - ClipboardUtils::setLinkToClipboard(imgPath); - }); - p_menu->insertAction(p_before, act); - } - - if (QFileInfo::exists(imgPath)) { - // Local image. - auto act = new QAction(tr("Copy Image"), p_menu); - connect(act, &QAction::triggered, - p_menu, [imgPath]() { - auto clipboard = QApplication::clipboard(); - clipboard->clear(); - - // Copy local GIF to clipboard to ensure no frame loss - if (imgPath.endsWith(QStringLiteral(".gif"), Qt::CaseInsensitive) && FileUtils::existsCaseInsensitive(imgPath)) { - ClipboardUtils::setLocalFileToClipboard(clipboard, imgPath, QClipboard::Clipboard); - return ; - } - - auto img = FileUtils::imageFromFile(imgPath); - if (!img.isNull()) { - ClipboardUtils::setImageToClipboard(clipboard, img); - } - }); - p_menu->insertAction(p_before, act); - } else { - // Online image. - prependInPlacePreviewMenu(p_menu, p_before, p_cursorPos, p_block); - } + auto img = FileUtils::imageFromFile(imgPath); + if (!img.isNull()) { + ClipboardUtils::setImageToClipboard(clipboard, img); + } + }); + p_menu->insertAction(p_before, act); + } else { + // Online image. + prependInPlacePreviewMenu(p_menu, p_before, p_cursorPos, p_block); + } - p_menu->insertSeparator(p_before); + p_menu->insertSeparator(p_before); - return true; + return true; } -bool MarkdownEditor::prependInPlacePreviewMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block) -{ - auto data = vte::TextBlockData::get(p_block); - if (!data) { - return false; - } - - auto previewData = data->getBlockPreviewData(); - if (!previewData) { - return false; - } +bool MarkdownEditor::prependInPlacePreviewMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block) { + auto data = vte::TextBlockData::get(p_block); + if (!data) { + return false; + } - QPixmap image; - QRgb background = 0; - const int pib = p_cursorPos - p_block.position(); - for (const auto &info : previewData->getPreviewData()) { - const auto *imageData = info->getImageData(); - if (!imageData) { - continue; - } + auto previewData = data->getBlockPreviewData(); + if (!previewData) { + return false; + } - if (imageData->contains(pib) || (imageData->contains(pib - 1) && pib == p_block.length() - 1)) { - const auto *img = findImageFromDocumentResourceMgr(imageData->m_imageName); - if (img) { - image = *img; - background = imageData->m_backgroundColor; - } - break; - } + QPixmap image; + QRgb background = 0; + const int pib = p_cursorPos - p_block.position(); + for (const auto &info : previewData->getPreviewData()) { + const auto *imageData = info->getImageData(); + if (!imageData) { + continue; } - if (image.isNull()) { - return false; + if (imageData->contains(pib) || (imageData->contains(pib - 1) && pib == p_block.length() - 1)) { + const auto *img = findImageFromDocumentResourceMgr(imageData->m_imageName); + if (img) { + image = *img; + background = imageData->m_backgroundColor; + } + break; } + } - auto act = new QAction(tr("Copy In-Place Preview"), p_menu); - connect(act, &QAction::triggered, - p_menu, [this, image, background]() { - QColor color(background); - if (background == 0) { - color = m_textEdit->palette().color(QPalette::Base); - } - QImage img(image.size(), QImage::Format_ARGB32); - img.fill(color); - QPainter painter(&img); - painter.drawPixmap(img.rect(), image); + if (image.isNull()) { + return false; + } - auto clipboard = QApplication::clipboard(); - clipboard->clear(); - ClipboardUtils::setImageToClipboard(clipboard, img); - }); + auto act = new QAction(tr("Copy In-Place Preview"), p_menu); + connect(act, &QAction::triggered, p_menu, [this, image, background]() { + QColor color(background); + if (background == 0) { + color = m_textEdit->palette().color(QPalette::Base); + } + QImage img(image.size(), QImage::Format_ARGB32); + img.fill(color); + QPainter painter(&img); + painter.drawPixmap(img.rect(), image); - p_menu->insertAction(p_before, act); + auto clipboard = QApplication::clipboard(); + clipboard->clear(); + ClipboardUtils::setImageToClipboard(clipboard, img); + }); - return true; + p_menu->insertAction(p_before, act); + + return true; } -bool MarkdownEditor::prependLinkMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block) -{ - const auto text = p_block.text(); - - QRegularExpression regExp(vte::MarkdownUtils::c_linkRegExp); - QString linkText; - const int pib = p_cursorPos - p_block.position(); - auto matchIter = regExp.globalMatch(text); - while (matchIter.hasNext()) { - auto match = matchIter.next(); - if (pib >= match.capturedStart() && pib < match.capturedEnd()) { - linkText = match.captured(2); - break; - } - } +bool MarkdownEditor::prependLinkMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block) { + const auto text = p_block.text(); - if (linkText.isEmpty()) { - return false; + QRegularExpression regExp(vte::MarkdownUtils::c_linkRegExp); + QString linkText; + const int pib = p_cursorPos - p_block.position(); + auto matchIter = regExp.globalMatch(text); + while (matchIter.hasNext()) { + auto match = matchIter.next(); + if (pib >= match.capturedStart() && pib < match.capturedEnd()) { + linkText = match.captured(2); + break; } + } + + if (linkText.isEmpty()) { + return false; + } - const auto linkUrl = vte::MarkdownUtils::linkUrlToPath(getBasePath(), linkText); + const auto linkUrl = vte::MarkdownUtils::linkUrlToPath(getBasePath(), linkText); - { - auto act = new QAction(tr("Open Link"), p_menu); - connect(act, &QAction::triggered, - p_menu, [linkUrl]() { - emit VNoteX::getInst().openFileRequested(linkUrl, QSharedPointer::create()); - }); - p_menu->insertAction(p_before, act); - } + { + auto act = new QAction(tr("Open Link"), p_menu); + connect(act, &QAction::triggered, p_menu, [linkUrl]() { + emit VNoteX::getInst().openFileRequested(linkUrl, + QSharedPointer::create()); + }); + p_menu->insertAction(p_before, act); + } - { - auto act = new QAction(tr("Copy Link"), p_menu); - connect(act, &QAction::triggered, - p_menu, [linkUrl]() { - ClipboardUtils::setLinkToClipboard(linkUrl); - }); - p_menu->insertAction(p_before, act); - } + { + auto act = new QAction(tr("Copy Link"), p_menu); + connect(act, &QAction::triggered, p_menu, + [linkUrl]() { ClipboardUtils::setLinkToClipboard(linkUrl); }); + p_menu->insertAction(p_before, act); + } - p_menu->insertSeparator(p_before); + p_menu->insertSeparator(p_before); - return true; + return true; } diff --git a/src/widgets/editors/markdowneditor.h b/src/widgets/editors/markdowneditor.h index 02b7ddfac3..543c9715ab 100644 --- a/src/widgets/editors/markdowneditor.h +++ b/src/widgets/editors/markdowneditor.h @@ -3,8 +3,8 @@ #include -#include #include +#include #include @@ -12,229 +12,218 @@ class QMimeData; class QMenu; class QTimer; -namespace vte -{ - class MarkdownEditorConfig; +namespace vte { +class MarkdownEditorConfig; } -namespace vnotex -{ - class PreviewHelper; - class Buffer; - class MarkdownEditorConfig; - class MarkdownTableHelper; - class ImageHost; +namespace vnotex { +class PreviewHelper; +class Buffer; +class MarkdownEditorConfig; +class MarkdownTableHelper; +class ImageHost; - class MarkdownEditor : public vte::VMarkdownEditor - { - Q_OBJECT - public: - struct Heading - { - Heading() = default; +class MarkdownEditor : public vte::VMarkdownEditor { + Q_OBJECT +public: + struct Heading { + Heading() = default; - Heading(const QString &p_name, - int p_level, - const QString &p_sectionNumber = QString(), - int p_blockNumber = -1); + Heading(const QString &p_name, int p_level, const QString &p_sectionNumber = QString(), + int p_blockNumber = -1); - QString m_name; + QString m_name; - int m_level = -1; + int m_level = -1; - // 1.2. . - QString m_sectionNumber; + // 1.2. . + QString m_sectionNumber; - int m_blockNumber = -1; - }; + int m_blockNumber = -1; + }; - MarkdownEditor(const MarkdownEditorConfig &p_config, - const QSharedPointer &p_editorConfig, - const QSharedPointer &p_editorParas, - QWidget *p_parent = nullptr); + MarkdownEditor(const MarkdownEditorConfig &p_config, + const QSharedPointer &p_editorConfig, + const QSharedPointer &p_editorParas, + QWidget *p_parent = nullptr); - virtual ~MarkdownEditor(); + virtual ~MarkdownEditor(); - void setPreviewHelper(PreviewHelper *p_helper); + void setPreviewHelper(PreviewHelper *p_helper); - void setBuffer(Buffer *p_buffer); + void setBuffer(Buffer *p_buffer); - // @p_level: [0, 6], 0 for none. - void typeHeading(int p_level); + // @p_level: [0, 6], 0 for none. + void typeHeading(int p_level); - void typeBold(); + void typeBold(); - void typeItalic(); + void typeItalic(); - void typeStrikethrough(); + void typeStrikethrough(); - void typeMark(); + void typeMark(); - void typeUnorderedList(); + void typeUnorderedList(); - void typeOrderedList(); + void typeOrderedList(); - void typeTodoList(bool p_checked); + void typeTodoList(bool p_checked); - void typeCode(); + void typeCode(); - void typeCodeBlock(); + void typeCodeBlock(); - void typeMath(); + void typeMath(); - void typeMathBlock(); + void typeMathBlock(); - void typeQuote(); + void typeQuote(); - void typeLink(); + void typeLink(); - void typeImage(); + void typeImage(); - void typeTable(); + void typeTable(); - const QVector &getHeadings() const; - int getCurrentHeadingIndex() const; + const QVector &getHeadings() const; + int getCurrentHeadingIndex() const; - void scrollToHeading(int p_idx); + void scrollToHeading(int p_idx); - void overrideSectionNumber(OverrideState p_state); + void overrideSectionNumber(OverrideState p_state); - void updateFromConfig(bool p_initialized = true); + void updateFromConfig(bool p_initialized = true); - QRgb getPreviewBackground() const; + QRgb getPreviewBackground() const; - void setImageHost(ImageHost *p_host); + void setImageHost(ImageHost *p_host); - public slots: - void handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text); +public slots: + void handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text); - signals: - void headingsChanged(); +signals: + void headingsChanged(); - void currentHeadingChanged(); + void currentHeadingChanged(); - void htmlToMarkdownRequested(quint64 p_id, TimeStamp p_timeStamp, const QString &p_html); + void htmlToMarkdownRequested(quint64 p_id, TimeStamp p_timeStamp, const QString &p_html); - void readRequested(); + void readRequested(); - void applySnippetRequested(); + void applySnippetRequested(); - private slots: - void handleCanInsertFromMimeData(const QMimeData *p_source, bool *p_handled, bool *p_allowed); +private slots: + void handleCanInsertFromMimeData(const QMimeData *p_source, bool *p_handled, bool *p_allowed); - void handleInsertFromMimeData(const QMimeData *p_source, bool *p_handled); + void handleInsertFromMimeData(const QMimeData *p_source, bool *p_handled); - void handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, QScopedPointer *p_menu); + void handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, + QScopedPointer *p_menu); - void altPaste(); + void altPaste(); - void parseToMarkdownAndPaste(); + void parseToMarkdownAndPaste(); - private: - // @p_scaledWidth: 0 for not overridden. - // @p_insertText: whether insert text into the buffer after inserting image file. - // @p_urlInLink: store the url in link if not null. - bool insertImageToBufferFromLocalFile(const QString &p_title, - const QString &p_altText, - const QString &p_srcImagePath, - int p_scaledWidth = 0, - int p_scaledHeight = 0, - bool p_insertText = true, - QString *p_urlInLink = nullptr); +private: + // @p_scaledWidth: 0 for not overridden. + // @p_insertText: whether insert text into the buffer after inserting image file. + // @p_urlInLink: store the url in link if not null. + bool insertImageToBufferFromLocalFile(const QString &p_title, const QString &p_altText, + const QString &p_srcImagePath, int p_scaledWidth = 0, + int p_scaledHeight = 0, bool p_insertText = true, + QString *p_urlInLink = nullptr); - bool insertImageToBufferFromData(const QString &p_title, - const QString &p_altText, - const QImage &p_image, - int p_scaledWidth = 0, - int p_scaledHeight = 0); + bool insertImageToBufferFromData(const QString &p_title, const QString &p_altText, + const QImage &p_image, int p_scaledWidth = 0, + int p_scaledHeight = 0); - void insertImageLink(const QString &p_title, - const QString &p_altText, - const QString &p_destImagePath, - int p_scaledWidth, - int p_scaledHeight, - bool p_insertText = true, - QString *p_urlInLink = nullptr); + void insertImageLink(const QString &p_title, const QString &p_altText, + const QString &p_destImagePath, int p_scaledWidth, int p_scaledHeight, + bool p_insertText = true, QString *p_urlInLink = nullptr); - // Return true if it is processed. - bool processHtmlFromMimeData(const QMimeData *p_source); + // Return true if it is processed. + bool processHtmlFromMimeData(const QMimeData *p_source); - // Return true if it is processed. - bool processImageFromMimeData(const QMimeData *p_source); + // Return true if it is processed. + bool processImageFromMimeData(const QMimeData *p_source); - // Return true if it is processed. - bool processUrlFromMimeData(const QMimeData *p_source); + // Return true if it is processed. + bool processUrlFromMimeData(const QMimeData *p_source); - // Return true if it is processed. - bool processMultipleUrlsFromMimeData(const QMimeData *p_source); + // Return true if it is processed. + bool processMultipleUrlsFromMimeData(const QMimeData *p_source); - void insertImageFromMimeData(const QMimeData *p_source); + void insertImageFromMimeData(const QMimeData *p_source); - void insertImageFromUrl(const QString &p_url, bool p_quiet = false); + void insertImageFromUrl(const QString &p_url, bool p_quiet = false); - QString getRelativeLink(const QString &p_path); + QString getRelativeLink(const QString &p_path); - // Update section number. - // Update headings outline. - void updateHeadings(const QVector &p_headerRegions); + // Update section number. + // Update headings outline. + void updateHeadings(const QVector &p_headerRegions); - int getHeadingIndexByBlockNumber(int p_blockNumber) const; + int getHeadingIndexByBlockNumber(int p_blockNumber) const; - void setupShortcuts(); + void setupShortcuts(); - void fetchImagesToLocalAndReplace(QString &p_text); + void fetchImagesToLocalAndReplace(QString &p_text); - // Return true if there is change. - bool updateSectionNumber(const QVector &p_headings); + // Return true if there is change. + bool updateSectionNumber(const QVector &p_headings); - void setupTableHelper(); + void setupTableHelper(); - // Return the dest file path of the image on success. - QString saveToImageHost(const QByteArray &p_imageData, const QString &p_destFileName); + // Return the dest file path of the image on success. + QString saveToImageHost(const QByteArray &p_imageData, const QString &p_destFileName); - void appendImageHostMenu(QMenu *p_menu); + void appendImageHostMenu(QMenu *p_menu); - void uploadImagesToImageHost(); + void uploadImagesToImageHost(); - void prependContextSensitiveMenu(QMenu *p_menu, const QPoint &p_pos); + void prependContextSensitiveMenu(QMenu *p_menu, const QPoint &p_pos); - bool prependImageMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block); + bool prependImageMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block); - bool prependInPlacePreviewMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block); + bool prependInPlacePreviewMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block); - bool prependLinkMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, const QTextBlock &p_block); + bool prependLinkMenu(QMenu *p_menu, QAction *p_before, int p_cursorPos, + const QTextBlock &p_block); - static QString generateImageFileNameToInsertAs(const QString &p_title, const QString &p_suffix); + static QString generateImageFileNameToInsertAs(const QString &p_title, const QString &p_suffix); - const MarkdownEditorConfig &m_config; + const MarkdownEditorConfig &m_config; - Buffer *m_buffer = nullptr; + Buffer *m_buffer = nullptr; - QVector m_headings; + QVector m_headings; - // TimeStamp used as sequence number to interact with Web side. - TimeStamp m_timeStamp = 0; + // TimeStamp used as sequence number to interact with Web side. + TimeStamp m_timeStamp = 0; - QTimer *m_headingTimer = nullptr; + QTimer *m_headingTimer = nullptr; - QTimer *m_sectionNumberTimer = nullptr; + QTimer *m_sectionNumberTimer = nullptr; - // Used to detect the config change and do a clean up. - bool m_sectionNumberEnabled = false; + // Used to detect the config change and do a clean up. + bool m_sectionNumberEnabled = false; - OverrideState m_overriddenSectionNumber = OverrideState::NoOverride; + OverrideState m_overriddenSectionNumber = OverrideState::NoOverride; - // Managed by QObject. - MarkdownTableHelper *m_tableHelper = nullptr; + // Managed by QObject. + MarkdownTableHelper *m_tableHelper = nullptr; - ImageHost *m_imageHost = nullptr; + ImageHost *m_imageHost = nullptr; - bool m_shouldTriggerRichPaste = false; + bool m_shouldTriggerRichPaste = false; - bool m_richPasteAsked = false; + bool m_richPasteAsked = false; - bool m_plainTextPasteAsked = false; - }; -} + bool m_plainTextPasteAsked = false; +}; +} // namespace vnotex #endif // MARKDOWNEDITOR_H diff --git a/src/widgets/editors/markdowntable.cpp b/src/widgets/editors/markdowntable.cpp index 06ffc3b2ab..cddc30b3a8 100644 --- a/src/widgets/editors/markdowntable.cpp +++ b/src/widgets/editors/markdowntable.cpp @@ -1,42 +1,35 @@ #include "markdowntable.h" -#include #include +#include using namespace vnotex; -void MarkdownTable::Cell::clear() -{ - m_offset = -1; - m_length = 0; - m_text.clear(); - m_formattedText.clear(); - m_cursorCoreOffset = -1; - m_deleted = false; +void MarkdownTable::Cell::clear() { + m_offset = -1; + m_length = 0; + m_text.clear(); + m_formattedText.clear(); + m_cursorCoreOffset = -1; + m_deleted = false; } -bool MarkdownTable::Row::isValid() const -{ - return !m_cells.isEmpty(); -} +bool MarkdownTable::Row::isValid() const { return !m_cells.isEmpty(); } -void MarkdownTable::Row::clear() -{ - m_block = QTextBlock(); - m_preText.clear(); - m_cells.clear(); +void MarkdownTable::Row::clear() { + m_block = QTextBlock(); + m_preText.clear(); + m_cells.clear(); } -QString MarkdownTable::Row::toString() const -{ - QString cells; - for (auto & cell : m_cells) { - cells += QStringLiteral(" (%1, %2 [%3])").arg(cell.m_offset) - .arg(cell.m_length) - .arg(cell.m_text); - } +QString MarkdownTable::Row::toString() const { + QString cells; + for (auto &cell : m_cells) { + cells += + QStringLiteral(" (%1, %2 [%3])").arg(cell.m_offset).arg(cell.m_length).arg(cell.m_text); + } - return QStringLiteral("row %1 %2").arg(m_block.blockNumber()).arg(cells); + return QStringLiteral("row %1 %2").arg(m_block.blockNumber()).arg(cells); } qreal MarkdownTable::s_spaceWidth = -1; @@ -51,731 +44,680 @@ const QString MarkdownTable::c_defaultDelimiter = "---"; const QChar MarkdownTable::c_borderChar = '|'; -enum -{ - HeaderRowIndex = 0, - DelimiterRowIndex = 1 -}; +enum { HeaderRowIndex = 0, DelimiterRowIndex = 1 }; MarkdownTable::MarkdownTable(QTextEdit *p_textEdit, const vte::peg::TableBlock &p_block) - : m_textEdit(p_textEdit) -{ - parseTableBlock(p_block); + : m_textEdit(p_textEdit) { + parseTableBlock(p_block); } MarkdownTable::MarkdownTable(QTextEdit *p_textEdit, int p_bodyRow, int p_col, Alignment p_alignment) - : m_textEdit(p_textEdit), - m_isNew(true) -{ - Q_ASSERT(p_bodyRow >= 0 && p_col > 0); - m_rows.resize(p_bodyRow + 2); - - // PreText for each row. - QString preText; - const QTextCursor cursor = m_textEdit->textCursor(); - Q_ASSERT(cursor.atBlockEnd()); - if (!cursor.atBlockStart()) { - preText = cursor.block().text(); - } - - QString delimiterCore(c_defaultDelimiter); - switch (p_alignment) { - case Alignment::Left: - delimiterCore[0] = ':'; - break; - - case Alignment::Center: - delimiterCore[0] = ':'; - delimiterCore[delimiterCore.size() - 1] = ':'; - break; - - case Alignment::Right: - delimiterCore[delimiterCore.size() - 1] = ':'; - break; - - default: - break; - } - const QString delimiterCell = generateFormattedText(delimiterCore, 0); - const QString contentCell = generateFormattedText(QString(c_defaultDelimiter.size(), QLatin1Char(' ')), 0); + : m_textEdit(p_textEdit), m_isNew(true) { + Q_ASSERT(p_bodyRow >= 0 && p_col > 0); + m_rows.resize(p_bodyRow + 2); + + // PreText for each row. + QString preText; + const QTextCursor cursor = m_textEdit->textCursor(); + Q_ASSERT(cursor.atBlockEnd()); + if (!cursor.atBlockStart()) { + preText = cursor.block().text(); + } + + QString delimiterCore(c_defaultDelimiter); + switch (p_alignment) { + case Alignment::Left: + delimiterCore[0] = ':'; + break; + + case Alignment::Center: + delimiterCore[0] = ':'; + delimiterCore[delimiterCore.size() - 1] = ':'; + break; + + case Alignment::Right: + delimiterCore[delimiterCore.size() - 1] = ':'; + break; + + default: + break; + } + const QString delimiterCell = generateFormattedText(delimiterCore, 0); + const QString contentCell = + generateFormattedText(QString(c_defaultDelimiter.size(), QLatin1Char(' ')), 0); + + for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) { + auto &row = m_rows[rowIdx]; + row.m_preText = preText; + row.m_cells.resize(p_col); + + const QString &content = isDelimiterRow(rowIdx) ? delimiterCell : contentCell; + for (auto &cell : row.m_cells) { + cell.m_text = content; + } + } +} - for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) { - auto &row = m_rows[rowIdx]; - row.m_preText = preText; - row.m_cells.resize(p_col); +bool MarkdownTable::isValid() const { + return header() && header()->isValid() && delimiter() && delimiter()->isValid(); +} - const QString &content = isDelimiterRow(rowIdx) ? delimiterCell : contentCell; - for (auto &cell : row.m_cells) { - cell.m_text = content; - } - } +void MarkdownTable::format() { + if (!isValid()) { + return; + } + + const QTextCursor cursor = m_textEdit->textCursor(); + int curRowIdx = cursor.blockNumber() - m_rows[0].m_block.blockNumber(); + int curPib = -1; + if (curRowIdx < 0 || curRowIdx >= m_rows.size()) { + curRowIdx = -1; + } else { + curPib = cursor.positionInBlock(); + } + + int nrCols = calculateColumnCount(); + pruneColumns(nrCols); + + for (int i = 0; i < nrCols; ++i) { + formatColumn(i, curRowIdx, curPib); + } } -bool MarkdownTable::isValid() const -{ - return header() && header()->isValid() && delimiter() && delimiter()->isValid(); +void MarkdownTable::write() { + if (m_isNew) { + writeNewTable(); + } else { + writeTable(); + } } -void MarkdownTable::format() -{ - if (!isValid()) { - return; - } +void MarkdownTable::parseTableBlock(const vte::peg::TableBlock &p_block) { + auto doc = m_textEdit->document(); - const QTextCursor cursor = m_textEdit->textCursor(); - int curRowIdx = cursor.blockNumber() - m_rows[0].m_block.blockNumber(); - int curPib = -1; - if (curRowIdx < 0 || curRowIdx >= m_rows.size()) { - curRowIdx = -1; - } else { - curPib = cursor.positionInBlock(); - } + QTextBlock block = doc->findBlock(p_block.m_startPos); + if (!block.isValid()) { + return; + } - int nrCols = calculateColumnCount(); - pruneColumns(nrCols); + int lastBlockNumber = doc->findBlock(p_block.m_endPos - 1).blockNumber(); + if (lastBlockNumber == -1) { + return; + } - for (int i = 0; i < nrCols; ++i) { - formatColumn(i, curRowIdx, curPib); - } -} + const QVector &borders = p_block.m_borders; + if (borders.isEmpty()) { + return; + } -void MarkdownTable::write() -{ - if (m_isNew) { - writeNewTable(); - } else { - writeTable(); - } -} + int numRows = lastBlockNumber - block.blockNumber() + 1; + if (numRows <= DelimiterRowIndex) { + return; + } -void MarkdownTable::parseTableBlock(const vte::peg::TableBlock &p_block) -{ - auto doc = m_textEdit->document(); + initWidths(block, borders[0]); - QTextBlock block = doc->findBlock(p_block.m_startPos); - if (!block.isValid()) { - return; + int borderIdx = 0; + m_rows.reserve(numRows); + for (int i = 0; i < numRows; ++i) { + m_rows.append(Row()); + if (!parseRow(block, borders, borderIdx, m_rows.last())) { + clear(); + return; } - int lastBlockNumber = doc->findBlock(p_block.m_endPos - 1).blockNumber(); - if (lastBlockNumber == -1) { - return; - } + qDebug() << "row" << i << m_rows.last().toString(); - const QVector &borders = p_block.m_borders; - if (borders.isEmpty()) { - return; - } + block = block.next(); + } +} - int numRows = lastBlockNumber - block.blockNumber() + 1; - if (numRows <= DelimiterRowIndex) { - return; +void MarkdownTable::clear() { m_rows.clear(); } + +void MarkdownTable::initWidths(const QTextBlock &p_block, int p_borderPos) { + if (s_spaceWidth != -1) { + return; + } + + QFont font = m_textEdit->font(); + int pib = p_borderPos - p_block.position(); + auto fmts = p_block.layout()->formats(); + for (const auto &fmt : fmts) { + if (fmt.start <= pib && fmt.start + fmt.length > pib) { + // Hit. + if (!fmt.format.fontFamily().isEmpty()) { + font = fmt.format.font(); + break; + } } + } - initWidths(block, borders[0]); - - int borderIdx = 0; - m_rows.reserve(numRows); - for (int i = 0; i < numRows; ++i) { - m_rows.append(Row()); - if (!parseRow(block, borders, borderIdx, m_rows.last())) { - clear(); - return; - } + QFontMetricsF fmf(font); + s_spaceWidth = fmf.horizontalAdvance(' '); + s_minusWidth = fmf.horizontalAdvance('-'); + s_colonWidth = fmf.horizontalAdvance(':'); + s_defaultDelimiterWidth = fmf.horizontalAdvance(c_defaultDelimiter); - qDebug() << "row" << i << m_rows.last().toString(); - - block = block.next(); - } + qDebug() << "smart table widths" << font.family() << s_spaceWidth << s_minusWidth << s_colonWidth + << s_defaultDelimiterWidth; } -void MarkdownTable::clear() -{ - m_rows.clear(); -} +bool MarkdownTable::parseRow(const QTextBlock &p_block, const QVector &p_borders, + int &p_borderIdx, Row &p_row) const { + if (!p_block.isValid() || p_borderIdx >= p_borders.size()) { + return false; + } -void MarkdownTable::initWidths(const QTextBlock &p_block, int p_borderPos) -{ - if (s_spaceWidth != -1) { - return; - } + p_row.m_block = p_block; - QFont font = m_textEdit->font(); - int pib = p_borderPos - p_block.position(); - auto fmts = p_block.layout()->formats(); - for (const auto &fmt : fmts) { - if (fmt.start <= pib && fmt.start + fmt.length > pib) { - // Hit. - if (!fmt.format.fontFamily().isEmpty()) { - font = fmt.format.font(); - break; - } - } - } + QString text = p_block.text(); + int startPos = p_block.position(); + int endPos = startPos + text.length(); - QFontMetricsF fmf(font); - s_spaceWidth = fmf.horizontalAdvance(' '); - s_minusWidth = fmf.horizontalAdvance('-'); - s_colonWidth = fmf.horizontalAdvance(':'); - s_defaultDelimiterWidth = fmf.horizontalAdvance(c_defaultDelimiter); + if (p_borders[p_borderIdx] < startPos || p_borders[p_borderIdx] >= endPos) { + return false; + } - qDebug() << "smart table widths" << font.family() << s_spaceWidth << s_minusWidth << s_colonWidth << s_defaultDelimiterWidth; -} + // Get pre text. + int firstCellOffset = p_borders[p_borderIdx] - startPos; + if (text[firstCellOffset] != c_borderChar) { + return false; + } + p_row.m_preText = text.left(firstCellOffset); -bool MarkdownTable::parseRow(const QTextBlock &p_block, - const QVector &p_borders, - int &p_borderIdx, - Row &p_row) const -{ - if (!p_block.isValid() || p_borderIdx >= p_borders.size()) { - return false; + for (; p_borderIdx < p_borders.size(); ++p_borderIdx) { + int border = p_borders[p_borderIdx]; + if (border >= endPos) { + break; } - p_row.m_block = p_block; - - QString text = p_block.text(); - int startPos = p_block.position(); - int endPos = startPos + text.length(); - - if (p_borders[p_borderIdx] < startPos - || p_borders[p_borderIdx] >= endPos) { - return false; + int offset = border - startPos; + if (text[offset] != c_borderChar) { + return false; } - // Get pre text. - int firstCellOffset = p_borders[p_borderIdx] - startPos; - if (text[firstCellOffset] != c_borderChar) { - return false; + int nextIdx = p_borderIdx + 1; + if (nextIdx >= p_borders.size() || p_borders[nextIdx] >= endPos) { + // The last border of this row. + ++p_borderIdx; + break; } - p_row.m_preText = text.left(firstCellOffset); - - for (; p_borderIdx < p_borders.size(); ++p_borderIdx) { - int border = p_borders[p_borderIdx]; - if (border >= endPos) { - break; - } - int offset = border - startPos; - if (text[offset] != c_borderChar) { - return false; - } - - int nextIdx = p_borderIdx + 1; - if (nextIdx >= p_borders.size() || p_borders[nextIdx] >= endPos) { - // The last border of this row. - ++p_borderIdx; - break; - } - - int nextOffset = p_borders[nextIdx] - startPos; - if (text[nextOffset] != c_borderChar) { - return false; - } + int nextOffset = p_borders[nextIdx] - startPos; + if (text[nextOffset] != c_borderChar) { + return false; + } - // Got one cell. - Cell cell; - cell.m_offset = offset; - cell.m_length = nextOffset - offset; - cell.m_text = text.mid(cell.m_offset, cell.m_length); + // Got one cell. + Cell cell; + cell.m_offset = offset; + cell.m_length = nextOffset - offset; + cell.m_text = text.mid(cell.m_offset, cell.m_length); - p_row.m_cells.append(cell); - } + p_row.m_cells.append(cell); + } - return true; + return true; } -const MarkdownTable::Row *MarkdownTable::header() const -{ - if (m_rows.size() <= HeaderRowIndex) { - return nullptr; - } +const MarkdownTable::Row *MarkdownTable::header() const { + if (m_rows.size() <= HeaderRowIndex) { + return nullptr; + } - return &m_rows[HeaderRowIndex]; + return &m_rows[HeaderRowIndex]; } -const MarkdownTable::Row *MarkdownTable::delimiter() const -{ - if (m_rows.size() <= DelimiterRowIndex) { - return nullptr; - } +const MarkdownTable::Row *MarkdownTable::delimiter() const { + if (m_rows.size() <= DelimiterRowIndex) { + return nullptr; + } - return &m_rows[DelimiterRowIndex]; + return &m_rows[DelimiterRowIndex]; } -int MarkdownTable::calculateColumnCount() const -{ - // We use the width of the header as the width of the table. - // With this, we could add or remove one column by just changing the header row. - return header()->m_cells.size(); +int MarkdownTable::calculateColumnCount() const { + // We use the width of the header as the width of the table. + // With this, we could add or remove one column by just changing the header row. + return header()->m_cells.size(); } -void MarkdownTable::pruneColumns(int p_nrCols) -{ - for (auto &row : m_rows) { - for (int i = p_nrCols; i < row.m_cells.size(); ++i) { - row.m_cells[i].m_deleted = true; - } +void MarkdownTable::pruneColumns(int p_nrCols) { + for (auto &row : m_rows) { + for (int i = p_nrCols; i < row.m_cells.size(); ++i) { + row.m_cells[i].m_deleted = true; } + } } -void MarkdownTable::formatColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib) -{ - QVector cells; - // Target width of this column. - qreal targetWidth = 0; - fetchCellInfoOfColumn(p_idx, p_cursorRowIdx, p_cursorPib, cells, targetWidth); - - // Get the alignment of this column. - const auto align = getColumnAlignment(p_idx); - - // Calculate the formatted text of each cell. - for (int rowIdx = 0; rowIdx < cells.size(); ++rowIdx) { - const auto &info = cells[rowIdx]; - auto &row = m_rows[rowIdx]; - if (row.m_cells.size() <= p_idx) { - row.m_cells.resize(p_idx + 1); - } - auto &cell = row.m_cells[p_idx]; - Q_ASSERT(cell.m_formattedText.isEmpty()); - Q_ASSERT(cell.m_cursorCoreOffset == -1); - - // Record the cursor position. - if (rowIdx == p_cursorRowIdx) { - if (cell.m_offset <= p_cursorPib && cell.m_offset + cell.m_length > p_cursorPib) { - // Cursor in this cell. - int offset = p_cursorPib - cell.m_offset; - offset = offset - info.m_coreOffset; - if (offset > info.m_coreLength) { - offset = info.m_coreLength; - } else if (offset < 0) { - offset = 0; - } - - cell.m_cursorCoreOffset = offset; - } +void MarkdownTable::formatColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib) { + QVector cells; + // Target width of this column. + qreal targetWidth = 0; + fetchCellInfoOfColumn(p_idx, p_cursorRowIdx, p_cursorPib, cells, targetWidth); + + // Get the alignment of this column. + const auto align = getColumnAlignment(p_idx); + + // Calculate the formatted text of each cell. + for (int rowIdx = 0; rowIdx < cells.size(); ++rowIdx) { + const auto &info = cells[rowIdx]; + auto &row = m_rows[rowIdx]; + if (row.m_cells.size() <= p_idx) { + row.m_cells.resize(p_idx + 1); + } + auto &cell = row.m_cells[p_idx]; + Q_ASSERT(cell.m_formattedText.isEmpty()); + Q_ASSERT(cell.m_cursorCoreOffset == -1); + + // Record the cursor position. + if (rowIdx == p_cursorRowIdx) { + if (cell.m_offset <= p_cursorPib && cell.m_offset + cell.m_length > p_cursorPib) { + // Cursor in this cell. + int offset = p_cursorPib - cell.m_offset; + offset = offset - info.m_coreOffset; + if (offset > info.m_coreLength) { + offset = info.m_coreLength; + } else if (offset < 0) { + offset = 0; } - if (isDelimiterRow(rowIdx)) { - if (!isDelimiterCellWellFormatted(cell, info, targetWidth)) { - QString core; - int delta = s_minusWidth - 1; - switch (align) { - case Alignment::None: - { - int coreLength = static_cast((targetWidth + delta) / s_minusWidth); - core = QString(coreLength, '-'); - break; - } - - case Alignment::Left: - { - int coreLength = static_cast((targetWidth - s_colonWidth + delta) / s_minusWidth); - core = QStringLiteral(":"); - core += QString(coreLength, '-'); - break; - } - - case Alignment::Center: - { - int coreLength = static_cast((targetWidth - 2 * s_colonWidth + delta) / s_minusWidth); - core = QStringLiteral(":"); - core += QString(coreLength, '-'); - core += QStringLiteral(":"); - break; - } - - case Alignment::Right: - { - int coreLength = static_cast((targetWidth - s_colonWidth + delta) / s_minusWidth); - core = QString(coreLength, '-'); - core += QStringLiteral(":"); - break; - } - - default: - Q_ASSERT(false); - break; - } - - cell.m_formattedText = generateFormattedText(core, 0); - if (cell.m_text == cell.m_formattedText) { - // Avoid infinite change. - cell.m_formattedText.clear(); - } - } - } else { - Alignment fakeAlign = align; - if (fakeAlign == Alignment::None) { - // For Alignment::None, we make the header align center while - // content cells align left. - if (isHeaderRow(rowIdx)) { - fakeAlign = Alignment::Center; - } else { - fakeAlign = Alignment::Left; - } - } - - if (!isCellWellFormatted(row, cell, info, targetWidth, fakeAlign)) { - QString core = cell.m_text.mid(info.m_coreOffset, info.m_coreLength); - int nr = static_cast((targetWidth - info.m_coreWidth + s_spaceWidth - 1) / s_spaceWidth); - cell.m_formattedText = generateFormattedText(core, nr, fakeAlign); - - // For cells crossing lines and having spaces at the end of one line, - // Qt will collapse those spaces, which make it not well formatted. - if (cell.m_text == cell.m_formattedText) { - cell.m_formattedText.clear(); - } - } - } + cell.m_cursorCoreOffset = offset; + } } -} -void MarkdownTable::fetchCellInfoOfColumn(int p_idx, - int p_cursorRowIdx, - int p_cursorPib, - QVector &p_cellsInfo, - qreal &p_targetWidth) const -{ - p_targetWidth = s_defaultDelimiterWidth; - p_cellsInfo.resize(m_rows.size()); - - // Fetch the trimmed core content and its width. - for (int i = 0; i < m_rows.size(); ++i) { - const auto &row = m_rows[i]; - auto &info = p_cellsInfo[i]; - - if (row.m_cells.size() <= p_idx) { - // Need to add a new cell later. - continue; + if (isDelimiterRow(rowIdx)) { + if (!isDelimiterCellWellFormatted(cell, info, targetWidth)) { + QString core; + int delta = s_minusWidth - 1; + switch (align) { + case Alignment::None: { + int coreLength = static_cast((targetWidth + delta) / s_minusWidth); + core = QString(coreLength, '-'); + break; } - // Get the info of this cell. - const auto &cell = row.m_cells[p_idx]; - int first = fetchCoreOffset(cell.m_text); - if (first == -1) { - // Empty cell. - continue; - } - info.m_coreOffset = first; - - // If the cursor is in this cell, then we should treat the core length at least not - // less than the cursor position even if there is trailing spaces before the cursor. - int last = cell.m_length - 1; - for (; last >= first; --last) { - if ((p_cursorRowIdx == i && p_cursorPib - cell.m_offset - 1 == last) || cell.m_text[last] != ' ') { - // Found the last of core content. - info.m_coreLength = last - first + 1; - break; - } + case Alignment::Left: { + int coreLength = static_cast((targetWidth - s_colonWidth + delta) / s_minusWidth); + core = QStringLiteral(":"); + core += QString(coreLength, '-'); + break; } - // Calculate the core width. - info.m_coreWidth = calculateTextWidth(row.m_block, - cell.m_offset + info.m_coreOffset, - info.m_coreLength); - // Delimiter row's width should not be considered. - if (info.m_coreWidth > p_targetWidth && !isDelimiterRow(i)) { - p_targetWidth = info.m_coreWidth; + case Alignment::Center: { + int coreLength = + static_cast((targetWidth - 2 * s_colonWidth + delta) / s_minusWidth); + core = QStringLiteral(":"); + core += QString(coreLength, '-'); + core += QStringLiteral(":"); + break; } - } -} -bool MarkdownTable::isDelimiterRow(int p_idx) const -{ - return p_idx == DelimiterRowIndex; -} - -qreal MarkdownTable::calculateTextWidth(const QTextBlock &p_block, int p_pib, int p_length) const -{ - // The block may cross multiple lines. - qreal textWidth = 0; - QTextLayout *layout = p_block.layout(); - QTextLine line = layout->lineForTextPosition(p_pib); - while (line.isValid()) { - int lineEnd = line.textStart() + line.textLength(); - if (lineEnd >= p_pib + p_length) { - // The last line. - textWidth += line.cursorToX(p_pib + p_length) - line.cursorToX(p_pib); - break; - } else { - // Cross lines. - textWidth += line.cursorToX(lineEnd) - line.cursorToX(p_pib); - - // Move to next line. - p_length = p_length - (lineEnd - p_pib); - p_pib = lineEnd; - line = layout->lineForTextPosition(p_pib + 1); + case Alignment::Right: { + int coreLength = static_cast((targetWidth - s_colonWidth + delta) / s_minusWidth); + core = QString(coreLength, '-'); + core += QStringLiteral(":"); + break; } - } - - return textWidth > 0 ? textWidth : -1; -} -Alignment MarkdownTable::getColumnAlignment(int p_idx) const -{ - auto row = delimiter(); - if (row->m_cells.size() <= p_idx) { - return Alignment::None; - } + default: + Q_ASSERT(false); + break; + } - QString core = row->m_cells[p_idx].m_text.mid(1).trimmed(); - Q_ASSERT(!core.isEmpty()); - bool leftColon = core[0] == ':'; - bool rightColon = core[core.size() - 1] == ':'; - if (leftColon) { - if (rightColon) { - return Alignment::Center; - } else { - return Alignment::Left; + cell.m_formattedText = generateFormattedText(core, 0); + if (cell.m_text == cell.m_formattedText) { + // Avoid infinite change. + cell.m_formattedText.clear(); } + } } else { - if (rightColon) { - return Alignment::Right; + Alignment fakeAlign = align; + if (fakeAlign == Alignment::None) { + // For Alignment::None, we make the header align center while + // content cells align left. + if (isHeaderRow(rowIdx)) { + fakeAlign = Alignment::Center; } else { - return Alignment::None; + fakeAlign = Alignment::Left; } + } + + if (!isCellWellFormatted(row, cell, info, targetWidth, fakeAlign)) { + QString core = cell.m_text.mid(info.m_coreOffset, info.m_coreLength); + int nr = + static_cast((targetWidth - info.m_coreWidth + s_spaceWidth - 1) / s_spaceWidth); + cell.m_formattedText = generateFormattedText(core, nr, fakeAlign); + + // For cells crossing lines and having spaces at the end of one line, + // Qt will collapse those spaces, which make it not well formatted. + if (cell.m_text == cell.m_formattedText) { + cell.m_formattedText.clear(); + } + } } + } } -static bool equalWidth(int p_a, int p_b, int p_margin = 5) -{ - return qAbs(p_a - p_b) <= p_margin; -} - -bool MarkdownTable::isDelimiterCellWellFormatted(const Cell &p_cell, - const CellInfo &p_info, - qreal p_targetWidth) const -{ - // We could use core width here for delimiter cell. - if (!equalWidth(p_info.m_coreWidth, p_targetWidth, s_minusWidth / 2)) { - return false; +void MarkdownTable::fetchCellInfoOfColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib, + QVector &p_cellsInfo, + qreal &p_targetWidth) const { + p_targetWidth = s_defaultDelimiterWidth; + p_cellsInfo.resize(m_rows.size()); + + // Fetch the trimmed core content and its width. + for (int i = 0; i < m_rows.size(); ++i) { + const auto &row = m_rows[i]; + auto &info = p_cellsInfo[i]; + + if (row.m_cells.size() <= p_idx) { + // Need to add a new cell later. + continue; + } + + // Get the info of this cell. + const auto &cell = row.m_cells[p_idx]; + int first = fetchCoreOffset(cell.m_text); + if (first == -1) { + // Empty cell. + continue; + } + info.m_coreOffset = first; + + // If the cursor is in this cell, then we should treat the core length at least not + // less than the cursor position even if there is trailing spaces before the cursor. + int last = cell.m_length - 1; + for (; last >= first; --last) { + if ((p_cursorRowIdx == i && p_cursorPib - cell.m_offset - 1 == last) || + cell.m_text[last] != ' ') { + // Found the last of core content. + info.m_coreLength = last - first + 1; + break; + } } - const QString &text = p_cell.m_text; - if (text.size() < 4) { - return false; + // Calculate the core width. + info.m_coreWidth = + calculateTextWidth(row.m_block, cell.m_offset + info.m_coreOffset, info.m_coreLength); + // Delimiter row's width should not be considered. + if (info.m_coreWidth > p_targetWidth && !isDelimiterRow(i)) { + p_targetWidth = info.m_coreWidth; } + } +} - if (text[1] != ' ' || text[text.size() - 1] != ' ') { - return false; - } +bool MarkdownTable::isDelimiterRow(int p_idx) const { return p_idx == DelimiterRowIndex; } + +qreal MarkdownTable::calculateTextWidth(const QTextBlock &p_block, int p_pib, int p_length) const { + // The block may cross multiple lines. + qreal textWidth = 0; + QTextLayout *layout = p_block.layout(); + QTextLine line = layout->lineForTextPosition(p_pib); + while (line.isValid()) { + int lineEnd = line.textStart() + line.textLength(); + if (lineEnd >= p_pib + p_length) { + // The last line. + textWidth += line.cursorToX(p_pib + p_length) - line.cursorToX(p_pib); + break; + } else { + // Cross lines. + textWidth += line.cursorToX(lineEnd) - line.cursorToX(p_pib); - if (text[2] == ' ' || text[text.size() - 2] == ' ') { - return false; + // Move to next line. + p_length = p_length - (lineEnd - p_pib); + p_pib = lineEnd; + line = layout->lineForTextPosition(p_pib + 1); } + } - return true; + return textWidth > 0 ? textWidth : -1; } -QString MarkdownTable::generateFormattedText(const QString &p_core, - int p_nrSpaces, - Alignment p_align) const -{ - Q_ASSERT(p_align != Alignment::None); - - // Align left. - int leftSpaces = 0; - int rightSpaces = p_nrSpaces; - - if (p_align == Alignment::Center) { - leftSpaces = p_nrSpaces / 2; - rightSpaces = p_nrSpaces - leftSpaces; - } else if (p_align == Alignment::Right) { - leftSpaces = p_nrSpaces; - rightSpaces = 0; +Alignment MarkdownTable::getColumnAlignment(int p_idx) const { + auto row = delimiter(); + if (row->m_cells.size() <= p_idx) { + return Alignment::None; + } + + QString core = row->m_cells[p_idx].m_text.mid(1).trimmed(); + Q_ASSERT(!core.isEmpty()); + bool leftColon = core[0] == ':'; + bool rightColon = core[core.size() - 1] == ':'; + if (leftColon) { + if (rightColon) { + return Alignment::Center; + } else { + return Alignment::Left; } - - return QStringLiteral("%1 %2%3%4 ").arg(c_borderChar, - QString(leftSpaces, ' '), - p_core, - QString(rightSpaces, ' ')); + } else { + if (rightColon) { + return Alignment::Right; + } else { + return Alignment::None; + } + } } -bool MarkdownTable::isHeaderRow(int p_idx) const -{ - return p_idx == HeaderRowIndex; -} +static bool equalWidth(int p_a, int p_b, int p_margin = 5) { return qAbs(p_a - p_b) <= p_margin; } -bool MarkdownTable::isCellWellFormatted(const Row &p_row, - const Cell &p_cell, - const CellInfo &p_info, - int p_targetWidth, - Alignment p_align) const -{ - Q_ASSERT(p_align != Alignment::None); - const QString &text = p_cell.m_text; - if (text.size() < 4) { - return false; - } +bool MarkdownTable::isDelimiterCellWellFormatted(const Cell &p_cell, const CellInfo &p_info, + qreal p_targetWidth) const { + // We could use core width here for delimiter cell. + if (!equalWidth(p_info.m_coreWidth, p_targetWidth, s_minusWidth / 2)) { + return false; + } - if (text[1] != ' ' || text[text.size() - 1] != ' ') { - return false; - } + const QString &text = p_cell.m_text; + if (text.size() < 4) { + return false; + } - // Skip alignment check of empty cell. - if (p_info.m_coreOffset > 0) { - int leftSpaces = p_info.m_coreOffset - 2; - int rightSpaces = text.size() - p_info.m_coreOffset - p_info.m_coreLength - 1; - switch (p_align) { - case Alignment::Left: - if (leftSpaces > 0) { - return false; - } + if (text[1] != ' ' || text[text.size() - 1] != ' ') { + return false; + } - break; + if (text[2] == ' ' || text[text.size() - 2] == ' ') { + return false; + } - case Alignment::Center: - if (qAbs(leftSpaces - rightSpaces) > 1) { - return false; - } + return true; +} - break; +QString MarkdownTable::generateFormattedText(const QString &p_core, int p_nrSpaces, + Alignment p_align) const { + Q_ASSERT(p_align != Alignment::None); - case Alignment::Right: - if (rightSpaces > 0) { - return false; - } + // Align left. + int leftSpaces = 0; + int rightSpaces = p_nrSpaces; - break; + if (p_align == Alignment::Center) { + leftSpaces = p_nrSpaces / 2; + rightSpaces = p_nrSpaces - leftSpaces; + } else if (p_align == Alignment::Right) { + leftSpaces = p_nrSpaces; + rightSpaces = 0; + } - default: - Q_ASSERT(false); - break; - } - } + return QStringLiteral("%1 %2%3%4 ") + .arg(c_borderChar, QString(leftSpaces, ' '), p_core, QString(rightSpaces, ' ')); +} - // Calculate the width of the text without two spaces around. - int cellWidth = calculateTextWidth(p_row.m_block, - p_cell.m_offset + 2, - p_cell.m_length - 3); - if (!equalWidth(cellWidth, p_targetWidth, s_spaceWidth / 2)) { +bool MarkdownTable::isHeaderRow(int p_idx) const { return p_idx == HeaderRowIndex; } + +bool MarkdownTable::isCellWellFormatted(const Row &p_row, const Cell &p_cell, + const CellInfo &p_info, int p_targetWidth, + Alignment p_align) const { + Q_ASSERT(p_align != Alignment::None); + const QString &text = p_cell.m_text; + if (text.size() < 4) { + return false; + } + + if (text[1] != ' ' || text[text.size() - 1] != ' ') { + return false; + } + + // Skip alignment check of empty cell. + if (p_info.m_coreOffset > 0) { + int leftSpaces = p_info.m_coreOffset - 2; + int rightSpaces = text.size() - p_info.m_coreOffset - p_info.m_coreLength - 1; + switch (p_align) { + case Alignment::Left: + if (leftSpaces > 0) { return false; - } + } - return true; -} - -void MarkdownTable::writeTable() -{ - bool changed = false; - // Use cursor(QTextDocument) to handle the corner case when cursor locates at the end of one row. - QTextCursor cursor(m_textEdit->document()); - int cursorBlock = -1, cursorPib = -1; - bool cursorHit = false; - - // Write the table row by row. - for (const auto &row : m_rows) { - bool needChange = false; - for (const auto &cell : row.m_cells) { - if (!cell.m_formattedText.isEmpty() || cell.m_deleted) { - needChange = true; - break; - } - } + break; - if (!needChange) { - continue; - } + case Alignment::Center: + if (qAbs(leftSpaces - rightSpaces) > 1) { + return false; + } - if (!changed) { - changed = true; - const QTextCursor curCursor = m_textEdit->textCursor(); - cursorBlock = curCursor.blockNumber(); - cursorPib = curCursor.positionInBlock(); - cursor.beginEditBlock(); - } + break; - // Construct the block text. - QString newBlockText(row.m_preText); - for (const auto &cell : row.m_cells) { - if (cell.m_deleted) { - continue; - } - - int pos = newBlockText.size(); - if (cell.m_formattedText.isEmpty()) { - newBlockText += cell.m_text; - } else { - newBlockText += cell.m_formattedText; - } - - if (cell.m_cursorCoreOffset > -1) { - // Cursor in this cell. - cursorHit = true; - // We need to calculate the new core offset of this cell. - // For delimiter row, this way won't work, but that is fine. - int coreOffset = fetchCoreOffset(cell.m_formattedText.isEmpty() ? cell.m_text : cell.m_formattedText); - cursorPib = pos + cell.m_cursorCoreOffset + coreOffset; - if (cursorPib >= newBlockText.size()) { - cursorPib = newBlockText.size() - 1; - } - } - } + case Alignment::Right: + if (rightSpaces > 0) { + return false; + } - newBlockText += c_borderChar; + break; - // Replace the whole block. - cursor.setPosition(row.m_block.position()); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.insertText(newBlockText); + default: + Q_ASSERT(false); + break; } + } + + // Calculate the width of the text without two spaces around. + int cellWidth = calculateTextWidth(p_row.m_block, p_cell.m_offset + 2, p_cell.m_length - 3); + if (!equalWidth(cellWidth, p_targetWidth, s_spaceWidth / 2)) { + return false; + } - if (changed) { - qDebug() << "write formatted table with cursor block" << cursorBlock; - cursor.endEditBlock(); - - // Restore the cursor. - if (cursorHit) { - QTextBlock block = m_textEdit->document()->findBlockByNumber(cursorBlock); - if (block.isValid()) { - int pos = block.position() + cursorPib; - auto curCursor = m_textEdit->textCursor(); - curCursor.setPosition(pos); - m_textEdit->setTextCursor(curCursor); - } + return true; +} + +void MarkdownTable::writeTable() { + bool changed = false; + // Use cursor(QTextDocument) to handle the corner case when cursor locates at the end of one row. + QTextCursor cursor(m_textEdit->document()); + int cursorBlock = -1, cursorPib = -1; + bool cursorHit = false; + + // Write the table row by row. + for (const auto &row : m_rows) { + bool needChange = false; + for (const auto &cell : row.m_cells) { + if (!cell.m_formattedText.isEmpty() || cell.m_deleted) { + needChange = true; + break; + } + } + + if (!needChange) { + continue; + } + + if (!changed) { + changed = true; + const QTextCursor curCursor = m_textEdit->textCursor(); + cursorBlock = curCursor.blockNumber(); + cursorPib = curCursor.positionInBlock(); + cursor.beginEditBlock(); + } + + // Construct the block text. + QString newBlockText(row.m_preText); + for (const auto &cell : row.m_cells) { + if (cell.m_deleted) { + continue; + } + + int pos = newBlockText.size(); + if (cell.m_formattedText.isEmpty()) { + newBlockText += cell.m_text; + } else { + newBlockText += cell.m_formattedText; + } + + if (cell.m_cursorCoreOffset > -1) { + // Cursor in this cell. + cursorHit = true; + // We need to calculate the new core offset of this cell. + // For delimiter row, this way won't work, but that is fine. + int coreOffset = + fetchCoreOffset(cell.m_formattedText.isEmpty() ? cell.m_text : cell.m_formattedText); + cursorPib = pos + cell.m_cursorCoreOffset + coreOffset; + if (cursorPib >= newBlockText.size()) { + cursorPib = newBlockText.size() - 1; } + } } + + newBlockText += c_borderChar; + + // Replace the whole block. + cursor.setPosition(row.m_block.position()); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + cursor.insertText(newBlockText); + } + + if (changed) { + qDebug() << "write formatted table with cursor block" << cursorBlock; + cursor.endEditBlock(); + + // Restore the cursor. + if (cursorHit) { + QTextBlock block = m_textEdit->document()->findBlockByNumber(cursorBlock); + if (block.isValid()) { + int pos = block.position() + cursorPib; + auto curCursor = m_textEdit->textCursor(); + curCursor.setPosition(pos); + m_textEdit->setTextCursor(curCursor); + } + } + } } -void MarkdownTable::writeNewTable() -{ - // Generate the text of the whole table. - QString tableText; - for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) { - const auto &row = m_rows[rowIdx]; - tableText += row.m_preText; - for (const auto &cell : row.m_cells) { - if (cell.m_deleted) { - continue; - } - - tableText += cell.m_text; - } +void MarkdownTable::writeNewTable() { + // Generate the text of the whole table. + QString tableText; + for (int rowIdx = 0; rowIdx < m_rows.size(); ++rowIdx) { + const auto &row = m_rows[rowIdx]; + tableText += row.m_preText; + for (const auto &cell : row.m_cells) { + if (cell.m_deleted) { + continue; + } + + tableText += cell.m_text; + } - tableText += c_borderChar; + tableText += c_borderChar; - if (rowIdx < m_rows.size() - 1) { - tableText += '\n'; - } + if (rowIdx < m_rows.size() - 1) { + tableText += '\n'; } + } - QTextCursor cursor = m_textEdit->textCursor(); - int pos = cursor.position() + 2; - cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.insertText(tableText); - cursor.setPosition(pos); - m_textEdit->setTextCursor(cursor); + QTextCursor cursor = m_textEdit->textCursor(); + int pos = cursor.position() + 2; + cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + cursor.insertText(tableText); + cursor.setPosition(pos); + m_textEdit->setTextCursor(cursor); } -int MarkdownTable::fetchCoreOffset(const QString &p_cellText) -{ - // [0] is the border char. To find the offset of the core content. - for (int i = 1; i < p_cellText.size(); ++i) { - if (p_cellText[i] != ' ') { - return i; - } +int MarkdownTable::fetchCoreOffset(const QString &p_cellText) { + // [0] is the border char. To find the offset of the core content. + for (int i = 1; i < p_cellText.size(); ++i) { + if (p_cellText[i] != ' ') { + return i; } + } - return -1; + return -1; } diff --git a/src/widgets/editors/markdowntable.h b/src/widgets/editors/markdowntable.h index 092e2b48d8..565525efe1 100644 --- a/src/widgets/editors/markdowntable.h +++ b/src/widgets/editors/markdowntable.h @@ -10,156 +10,141 @@ class QTextEdit; -namespace vnotex -{ - class MarkdownTable - { - public: - MarkdownTable(QTextEdit *p_textEdit, const vte::peg::TableBlock &p_block); +namespace vnotex { +class MarkdownTable { +public: + MarkdownTable(QTextEdit *p_textEdit, const vte::peg::TableBlock &p_block); - MarkdownTable(QTextEdit *p_textEdit, int p_bodyRow, int p_col, Alignment p_alignment); + MarkdownTable(QTextEdit *p_textEdit, int p_bodyRow, int p_col, Alignment p_alignment); - bool isValid() const; + bool isValid() const; - void format(); + void format(); - void write(); + void write(); - private: - struct Cell - { - void clear(); +private: + struct Cell { + void clear(); - // Start offset within block, including the starting border |. - int m_offset = -1; + // Start offset within block, including the starting border |. + int m_offset = -1; - // Length of this cell, till next border |. - int m_length = 0; + // Length of this cell, till next border |. + int m_length = 0; - // Text like "| vnote ". - QString m_text; + // Text like "| vnote ". + QString m_text; - // Formatted text, such as "| vnote ". - // It is empty if it does not need formatted. - QString m_formattedText; + // Formatted text, such as "| vnote ". + // It is empty if it does not need formatted. + QString m_formattedText; - // If cursor is within this cell, this will not be -1. - int m_cursorCoreOffset = -1; + // If cursor is within this cell, this will not be -1. + int m_cursorCoreOffset = -1; - // Whether this cell need to be deleted. - bool m_deleted = false; - }; + // Whether this cell need to be deleted. + bool m_deleted = false; + }; - struct Row - { - bool isValid() const; + struct Row { + bool isValid() const; - void clear(); + void clear(); - QString toString() const; + QString toString() const; - QTextBlock m_block; + QTextBlock m_block; - // Text before (the first cell of) table row. - QString m_preText; + // Text before (the first cell of) table row. + QString m_preText; - QVector m_cells; - }; + QVector m_cells; + }; - // Used to hold info about a cell when formatting a column. - struct CellInfo - { - // The offset of the core content within the cell. - // Will be 0 if it is an empty cell. - int m_coreOffset = 0; + // Used to hold info about a cell when formatting a column. + struct CellInfo { + // The offset of the core content within the cell. + // Will be 0 if it is an empty cell. + int m_coreOffset = 0; - // The length of the core content. - // Will be 0 if it is an empty cell. - int m_coreLength = 0; + // The length of the core content. + // Will be 0 if it is an empty cell. + int m_coreLength = 0; - // Pixel width of the core content. - qreal m_coreWidth = 0; - }; + // Pixel width of the core content. + qreal m_coreWidth = 0; + }; - void parseTableBlock(const vte::peg::TableBlock &p_block); + void parseTableBlock(const vte::peg::TableBlock &p_block); - void clear(); + void clear(); - void initWidths(const QTextBlock &p_block, int p_borderPos); + void initWidths(const QTextBlock &p_block, int p_borderPos); - // Parse one row into @p_row and move @p_borderIdx forward. - bool parseRow(const QTextBlock &p_block, - const QVector &p_borders, - int &p_borderIdx, - Row &p_row) const; + // Parse one row into @p_row and move @p_borderIdx forward. + bool parseRow(const QTextBlock &p_block, const QVector &p_borders, int &p_borderIdx, + Row &p_row) const; - const Row *header() const; + const Row *header() const; - const Row *delimiter() const; + const Row *delimiter() const; - int calculateColumnCount() const; + int calculateColumnCount() const; - // Prune columns beyond the header row that should be deleted. - void pruneColumns(int p_nrCols); + // Prune columns beyond the header row that should be deleted. + void pruneColumns(int p_nrCols); - void formatColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib); + void formatColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib); - void fetchCellInfoOfColumn(int p_idx, - int p_cursorRowIdx, - int p_cursorPib, - QVector &p_cellsInfo, - qreal &p_targetWidth) const; + void fetchCellInfoOfColumn(int p_idx, int p_cursorRowIdx, int p_cursorPib, + QVector &p_cellsInfo, qreal &p_targetWidth) const; - bool isHeaderRow(int p_idx) const; + bool isHeaderRow(int p_idx) const; - bool isDelimiterRow(int p_idx) const; + bool isDelimiterRow(int p_idx) const; - qreal calculateTextWidth(const QTextBlock &p_block, int p_pib, int p_length) const; + qreal calculateTextWidth(const QTextBlock &p_block, int p_pib, int p_length) const; - Alignment getColumnAlignment(int p_idx) const; + Alignment getColumnAlignment(int p_idx) const; - bool isDelimiterCellWellFormatted(const Cell &p_cell, - const CellInfo &p_info, - qreal p_targetWidth) const; + bool isDelimiterCellWellFormatted(const Cell &p_cell, const CellInfo &p_info, + qreal p_targetWidth) const; - // @p_nrSpaces: number of spaces to fill core content. - QString generateFormattedText(const QString &p_core, - int p_nrSpaces, - Alignment p_align = Alignment::Left) const; + // @p_nrSpaces: number of spaces to fill core content. + QString generateFormattedText(const QString &p_core, int p_nrSpaces, + Alignment p_align = Alignment::Left) const; - bool isCellWellFormatted(const Row &p_row, - const Cell &p_cell, - const CellInfo &p_info, - int p_targetWidth, - Alignment p_align) const; + bool isCellWellFormatted(const Row &p_row, const Cell &p_cell, const CellInfo &p_info, + int p_targetWidth, Alignment p_align) const; - void writeTable(); + void writeTable(); - void writeNewTable(); + void writeNewTable(); - // Return -1 if it is an empty cell. - static int fetchCoreOffset(const QString &p_cellText); + // Return -1 if it is an empty cell. + static int fetchCoreOffset(const QString &p_cellText); - QTextEdit *m_textEdit = nullptr; + QTextEdit *m_textEdit = nullptr; - // Whether this table is a new table or not. - bool m_isNew = false; + // Whether this table is a new table or not. + bool m_isNew = false; - // Header, delimiter, and body. - QVector m_rows; + // Header, delimiter, and body. + QVector m_rows; - static qreal s_spaceWidth; + static qreal s_spaceWidth; - static qreal s_minusWidth; + static qreal s_minusWidth; - static qreal s_colonWidth; + static qreal s_colonWidth; - static qreal s_defaultDelimiterWidth; + static qreal s_defaultDelimiterWidth; - static const QString c_defaultDelimiter; + static const QString c_defaultDelimiter; - static const QChar c_borderChar; - }; -} + static const QChar c_borderChar; +}; +} // namespace vnotex #endif // MARKDOWNTABLE_H diff --git a/src/widgets/editors/markdowntablehelper.cpp b/src/widgets/editors/markdowntablehelper.cpp index 5a0ea42192..dd76b5b0d3 100644 --- a/src/widgets/editors/markdowntablehelper.cpp +++ b/src/widgets/editors/markdowntablehelper.cpp @@ -1,121 +1,111 @@ #include "markdowntablehelper.h" -#include -#include #include +#include +#include -#include #include +#include #include -#include #include +#include using namespace vnotex; MarkdownTableHelper::MarkdownTableHelper(vte::VTextEditor *p_editor, QObject *p_parent) - : QObject(p_parent), - m_editor(p_editor) -{ -} + : QObject(p_parent), m_editor(p_editor) {} -bool MarkdownTableHelper::isSmartTableEnabled() const -{ - return ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getSmartTableEnabled(); +bool MarkdownTableHelper::isSmartTableEnabled() const { + return ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getSmartTableEnabled(); } -QTimer *MarkdownTableHelper::getTimer() -{ - if (!m_timer) { - m_timer = new QTimer(this); - m_timer->setSingleShot(true); - m_timer->setInterval(ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getSmartTableInterval()); - connect(m_timer, &QTimer::timeout, - this, &MarkdownTableHelper::formatTable); - - connect(m_editor->getTextEdit(), &QTextEdit::cursorPositionChanged, - this, [this]() { - if (m_timer->isActive()) { - // Defer the formatting. - m_timer->start(); - } - }); - } - - return m_timer; +QTimer *MarkdownTableHelper::getTimer() { + if (!m_timer) { + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + m_timer->setInterval( + ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getSmartTableInterval()); + connect(m_timer, &QTimer::timeout, this, &MarkdownTableHelper::formatTable); + + connect(m_editor->getTextEdit(), &QTextEdit::cursorPositionChanged, this, [this]() { + if (m_timer->isActive()) { + // Defer the formatting. + m_timer->start(); + } + }); + } + + return m_timer; } -void MarkdownTableHelper::formatTable() -{ - if (!isSmartTableEnabled()) { - return; - } +void MarkdownTableHelper::formatTable() { + if (!isSmartTableEnabled()) { + return; + } - if (!m_block.isValid()) { - return; - } + if (!m_block.isValid()) { + return; + } + MarkdownTable table(m_editor->getTextEdit(), m_block); + if (!table.isValid()) { + return; + } - MarkdownTable table(m_editor->getTextEdit(), m_block); - if (!table.isValid()) { - return; - } + table.format(); - table.format(); - - table.write(); + table.write(); } -void MarkdownTableHelper::updateTableBlocks(const QVector &p_blocks) -{ - if (!isSmartTableEnabled()) { - return; - } +void MarkdownTableHelper::updateTableBlocks(const QVector &p_blocks) { + if (!isSmartTableEnabled()) { + return; + } - getTimer()->stop(); + getTimer()->stop(); - if (m_editor->isReadOnly() || !m_editor->isModified()) { - return; - } + if (m_editor->isReadOnly() || !m_editor->isModified()) { + return; + } - int idx = currentCursorTableBlock(p_blocks); - if (idx == -1) { - return; - } + int idx = currentCursorTableBlock(p_blocks); + if (idx == -1) { + return; + } - m_block = p_blocks[idx]; - getTimer()->start(); + m_block = p_blocks[idx]; + getTimer()->start(); } -int MarkdownTableHelper::currentCursorTableBlock(const QVector &p_blocks) const -{ - // Binary search. - int curPos = m_editor->getTextEdit()->textCursor().position(); - - int first = 0, last = p_blocks.size() - 1; - while (first <= last) { - int mid = (first + last) / 2; - const auto &block = p_blocks[mid]; - if (block.m_startPos <= curPos && block.m_endPos >= curPos) { - return mid; - } - - if (block.m_startPos > curPos) { - last = mid - 1; - } else { - first = mid + 1; - } +int MarkdownTableHelper::currentCursorTableBlock( + const QVector &p_blocks) const { + // Binary search. + int curPos = m_editor->getTextEdit()->textCursor().position(); + + int first = 0, last = p_blocks.size() - 1; + while (first <= last) { + int mid = (first + last) / 2; + const auto &block = p_blocks[mid]; + if (block.m_startPos <= curPos && block.m_endPos >= curPos) { + return mid; } - return -1; + if (block.m_startPos > curPos) { + last = mid - 1; + } else { + first = mid + 1; + } + } + + return -1; } -void MarkdownTableHelper::insertTable(int p_bodyRow, int p_col, Alignment p_alignment) -{ - MarkdownTable table(m_editor->getTextEdit(), p_bodyRow, p_col, p_alignment); - if (!table.isValid()) { - return; - } +void MarkdownTableHelper::insertTable(int p_bodyRow, int p_col, Alignment p_alignment) { + MarkdownTable table(m_editor->getTextEdit(), p_bodyRow, p_col, p_alignment); + if (!table.isValid()) { + return; + } - table.write(); + table.write(); } diff --git a/src/widgets/editors/markdowntablehelper.h b/src/widgets/editors/markdowntablehelper.h index efc66e62d0..e7ea12bceb 100644 --- a/src/widgets/editors/markdowntablehelper.h +++ b/src/widgets/editors/markdowntablehelper.h @@ -7,41 +7,38 @@ class QTimer; -namespace vte -{ - class VTextEditor; +namespace vte { +class VTextEditor; } -namespace vnotex -{ - class MarkdownTableHelper : public QObject - { - Q_OBJECT - public: - MarkdownTableHelper(vte::VTextEditor *p_editor, QObject *p_parent = nullptr); +namespace vnotex { +class MarkdownTableHelper : public QObject { + Q_OBJECT +public: + MarkdownTableHelper(vte::VTextEditor *p_editor, QObject *p_parent = nullptr); - void insertTable(int p_bodyRow, int p_col, Alignment p_alignment); + void insertTable(int p_bodyRow, int p_col, Alignment p_alignment); - public slots: - void updateTableBlocks(const QVector &p_blocks); +public slots: + void updateTableBlocks(const QVector &p_blocks); - private: - // Return the block index which contains the cursor. - int currentCursorTableBlock(const QVector &p_blocks) const; +private: + // Return the block index which contains the cursor. + int currentCursorTableBlock(const QVector &p_blocks) const; - void formatTable(); + void formatTable(); - bool isSmartTableEnabled() const; + bool isSmartTableEnabled() const; - QTimer *getTimer(); + QTimer *getTimer(); - vte::VTextEditor *m_editor = nullptr; + vte::VTextEditor *m_editor = nullptr; - // Use getTimer() to access. - QTimer *m_timer = nullptr; + // Use getTimer() to access. + QTimer *m_timer = nullptr; - vte::peg::TableBlock m_block; - }; -} + vte::peg::TableBlock m_block; +}; +} // namespace vnotex #endif // MARKDOWNTABLEHELPER_H diff --git a/src/widgets/editors/markdownviewer.cpp b/src/widgets/editors/markdownviewer.cpp index bfbe76d3c3..8de4ff7156 100644 --- a/src/widgets/editors/markdownviewer.cpp +++ b/src/widgets/editors/markdownviewer.cpp @@ -1,23 +1,23 @@ #include "markdownviewer.h" -#include +#include #include #include -#include #include #include +#include #include +#include "../viewwindow.h" +#include "../widgetsfactory.h" #include "markdownvieweradapter.h" #include "previewhelper.h" +#include +#include #include #include #include #include -#include -#include -#include "../widgetsfactory.h" -#include "../viewwindow.h" using namespace vnotex; @@ -28,430 +28,388 @@ static const char *c_propertyImageUrlAltered = "CopiedImageUrlAltered"; // Indicate whether this clipboard change is triggered by cross copy. static const char *c_propertyCrossCopy = "CrossCopy"; -MarkdownViewer::MarkdownViewer(MarkdownViewerAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent) - : MarkdownViewer(p_adapter, nullptr, p_background, p_zoomFactor, p_parent) -{ -} +MarkdownViewer::MarkdownViewer(MarkdownViewerAdapter *p_adapter, const QColor &p_background, + qreal p_zoomFactor, QWidget *p_parent) + : MarkdownViewer(p_adapter, nullptr, p_background, p_zoomFactor, p_parent) {} -MarkdownViewer::MarkdownViewer(MarkdownViewerAdapter *p_adapter, - const ViewWindow *p_viewWindow, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent) - : WebViewer(p_background, p_zoomFactor, p_parent), - m_adapter(p_adapter), - m_viewWindow(p_viewWindow) -{ - m_adapter->setParent(this); - - auto channel = new QWebChannel(this); - channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); - - page()->setWebChannel(channel); - - connect(QApplication::clipboard(), &QClipboard::changed, - this, &MarkdownViewer::handleClipboardChanged); - - connect(m_adapter, &MarkdownViewerAdapter::keyPressed, - this, &MarkdownViewer::handleWebKeyPress); - - connect(m_adapter, &MarkdownViewerAdapter::zoomed, - this, [this](bool p_zoomIn) { - p_zoomIn ? zoomIn() : zoomOut(); - }); - - connect(m_adapter, &MarkdownViewerAdapter::crossCopyReady, - this, [](quint64 p_id, quint64 p_timeStamp, const QString &p_html) { - Q_UNUSED(p_id); - Q_UNUSED(p_timeStamp); - std::unique_ptr mimeData(new QMimeData()); - mimeData->setHtml(p_html); - ClipboardUtils::setMimeDataToClipboard(QApplication::clipboard(), mimeData.release()); - }); - - settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); -} +MarkdownViewer::MarkdownViewer(MarkdownViewerAdapter *p_adapter, const ViewWindow *p_viewWindow, + const QColor &p_background, qreal p_zoomFactor, QWidget *p_parent) + : WebViewer(p_background, p_zoomFactor, p_parent), m_adapter(p_adapter), + m_viewWindow(p_viewWindow) { + m_adapter->setParent(this); + + auto channel = new QWebChannel(this); + channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); + + page()->setWebChannel(channel); + + connect(QApplication::clipboard(), &QClipboard::changed, this, + &MarkdownViewer::handleClipboardChanged); -MarkdownViewerAdapter *MarkdownViewer::adapter() const -{ - return m_adapter; + connect(m_adapter, &MarkdownViewerAdapter::keyPressed, this, &MarkdownViewer::handleWebKeyPress); + + connect(m_adapter, &MarkdownViewerAdapter::zoomed, this, + [this](bool p_zoomIn) { p_zoomIn ? zoomIn() : zoomOut(); }); + + connect(m_adapter, &MarkdownViewerAdapter::crossCopyReady, this, + [](quint64 p_id, quint64 p_timeStamp, const QString &p_html) { + Q_UNUSED(p_id); + Q_UNUSED(p_timeStamp); + std::unique_ptr mimeData(new QMimeData()); + mimeData->setHtml(p_html); + ClipboardUtils::setMimeDataToClipboard(QApplication::clipboard(), mimeData.release()); + }); + + settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); } -void MarkdownViewer::setPreviewHelper(PreviewHelper *p_previewHelper) -{ - connect(p_previewHelper, &PreviewHelper::graphPreviewRequested, - this, [this, p_previewHelper](quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_lang, - const QString &p_text) { - if (m_adapter->isReady()) { - m_adapter->graphPreviewRequested(p_id, p_timeStamp, p_lang, p_text); - } else { - p_previewHelper->handleGraphPreviewData(MarkdownViewerAdapter::PreviewData()); - } - }); - connect(p_previewHelper, &PreviewHelper::mathPreviewRequested, - this, [this, p_previewHelper](quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_text) { - if (m_adapter->isReady()) { - m_adapter->mathPreviewRequested(p_id, p_timeStamp, p_text); - } else { - p_previewHelper->handleMathPreviewData(MarkdownViewerAdapter::PreviewData()); - } - }); - connect(m_adapter, &MarkdownViewerAdapter::graphPreviewDataReady, - p_previewHelper, &PreviewHelper::handleGraphPreviewData); - connect(m_adapter, &MarkdownViewerAdapter::mathPreviewDataReady, - p_previewHelper, &PreviewHelper::handleMathPreviewData); +MarkdownViewerAdapter *MarkdownViewer::adapter() const { return m_adapter; } + +void MarkdownViewer::setPreviewHelper(PreviewHelper *p_previewHelper) { + connect(p_previewHelper, &PreviewHelper::graphPreviewRequested, this, + [this, p_previewHelper](quint64 p_id, TimeStamp p_timeStamp, const QString &p_lang, + const QString &p_text) { + if (m_adapter->isReady()) { + m_adapter->graphPreviewRequested(p_id, p_timeStamp, p_lang, p_text); + } else { + p_previewHelper->handleGraphPreviewData(MarkdownViewerAdapter::PreviewData()); + } + }); + connect(p_previewHelper, &PreviewHelper::mathPreviewRequested, this, + [this, p_previewHelper](quint64 p_id, TimeStamp p_timeStamp, const QString &p_text) { + if (m_adapter->isReady()) { + m_adapter->mathPreviewRequested(p_id, p_timeStamp, p_text); + } else { + p_previewHelper->handleMathPreviewData(MarkdownViewerAdapter::PreviewData()); + } + }); + connect(m_adapter, &MarkdownViewerAdapter::graphPreviewDataReady, p_previewHelper, + &PreviewHelper::handleGraphPreviewData); + connect(m_adapter, &MarkdownViewerAdapter::mathPreviewDataReady, p_previewHelper, + &PreviewHelper::handleMathPreviewData); } -void MarkdownViewer::contextMenuEvent(QContextMenuEvent *p_event) -{ +void MarkdownViewer::contextMenuEvent(QContextMenuEvent *p_event) { #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - QMenu* menu(page()->createStandardContextMenu()); + QMenu *menu(page()->createStandardContextMenu()); #else - QMenu* menu(createStandardContextMenu()); + QMenu *menu(createStandardContextMenu()); #endif - const QList actions = menu->actions(); + const QList actions = menu->actions(); #if defined(Q_OS_WIN) - if (!m_copyImageUrlActionHooked) { - // "Copy Image URL" action will put the encoded URL to the clipboard as text - // and the URL as URLs. If the URL contains Chinese, OneNote or Word could not - // recognize it. - // We need to change it to only-space-encoded text. - QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); - if (actions.contains(copyImageUrlAct)) { - connect(copyImageUrlAct, &QAction::triggered, - this, &MarkdownViewer::handleCopyImageUrlAction); - m_copyImageUrlActionHooked = true; - } + if (!m_copyImageUrlActionHooked) { + // "Copy Image URL" action will put the encoded URL to the clipboard as text + // and the URL as URLs. If the URL contains Chinese, OneNote or Word could not + // recognize it. + // We need to change it to only-space-encoded text. + QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); + if (actions.contains(copyImageUrlAct)) { + connect(copyImageUrlAct, &QAction::triggered, this, + &MarkdownViewer::handleCopyImageUrlAction); + m_copyImageUrlActionHooked = true; } + } #endif - if (!hasSelection() && m_viewWindow && m_viewWindow->getMode() == ViewWindowMode::Read) { - auto firstAct = actions.isEmpty() ? nullptr : actions[0]; - auto editAct = new QAction(tr("&Edit"), menu); - WidgetUtils::addActionShortcutText(editAct, - ConfigMgr::getInst().getEditorConfig().getShortcut(EditorConfig::Shortcut::EditRead)); - connect(editAct, &QAction::triggered, - this, &MarkdownViewer::editRequested); - menu->insertAction(firstAct, editAct); - if (firstAct) { - menu->insertSeparator(firstAct); - } + if (!hasSelection() && m_viewWindow && m_viewWindow->getMode() == ViewWindowMode::Read) { + auto firstAct = actions.isEmpty() ? nullptr : actions[0]; + auto editAct = new QAction(tr("&Edit"), menu); + WidgetUtils::addActionShortcutText(editAct, ConfigMgr::getInst().getEditorConfig().getShortcut( + EditorConfig::Shortcut::EditRead)); + connect(editAct, &QAction::triggered, this, &MarkdownViewer::editRequested); + menu->insertAction(firstAct, editAct); + if (firstAct) { + menu->insertSeparator(firstAct); } - - // We need to replace the "Copy Image" action: - // - the default one use the fully-encoded URL to fetch the image while - // Windows seems to not recognize it. - // - We need to remove the html to let it be recognized by some web pages. - { - auto defaultCopyImageAct = pageAction(QWebEnginePage::CopyImageToClipboard); - if (actions.contains(defaultCopyImageAct)) { - QAction *copyImageAct = new QAction(defaultCopyImageAct->text(), menu); - copyImageAct->setToolTip(defaultCopyImageAct->toolTip()); - connect(copyImageAct, &QAction::triggered, - this, &MarkdownViewer::copyImage); - menu->insertAction(defaultCopyImageAct, copyImageAct); - defaultCopyImageAct->setVisible(false); - } + } + + // We need to replace the "Copy Image" action: + // - the default one use the fully-encoded URL to fetch the image while + // Windows seems to not recognize it. + // - We need to remove the html to let it be recognized by some web pages. + { + auto defaultCopyImageAct = pageAction(QWebEnginePage::CopyImageToClipboard); + if (actions.contains(defaultCopyImageAct)) { + QAction *copyImageAct = new QAction(defaultCopyImageAct->text(), menu); + copyImageAct->setToolTip(defaultCopyImageAct->toolTip()); + connect(copyImageAct, &QAction::triggered, this, &MarkdownViewer::copyImage); + menu->insertAction(defaultCopyImageAct, copyImageAct); + defaultCopyImageAct->setVisible(false); } + } - { - auto copyAct = pageAction(QWebEnginePage::Copy); - if (actions.contains(copyAct)) { - setupCrossCopyMenu(menu, copyAct); - } + { + auto copyAct = pageAction(QWebEnginePage::Copy); + if (actions.contains(copyAct)) { + setupCrossCopyMenu(menu, copyAct); } + } - hideUnusedActions(menu); + hideUnusedActions(menu); - p_event->accept(); + p_event->accept(); - bool valid = false; - for (auto act : menu->actions()) { - // There may be one action visible with text being empty. - if (act->isVisible() && !act->text().isEmpty()) { - valid = true; - break; - } + bool valid = false; + for (auto act : menu->actions()) { + // There may be one action visible with text being empty. + if (act->isVisible() && !act->text().isEmpty()) { + valid = true; + break; } + } - if (valid) { - menu->exec(p_event->globalPos()); - } + if (valid) { + menu->exec(p_event->globalPos()); + } - // For Qt 6, the menu is set with WA_DeleteOnClose. + // For Qt 6, the menu is set with WA_DeleteOnClose. #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - delete menu; + delete menu; #endif } -void MarkdownViewer::handleCopyImageUrlAction() -{ - // To avoid failure of setting clipboard mime data. - QCoreApplication::processEvents(); - - QClipboard *clipboard = QApplication::clipboard(); - const QMimeData *mimeData = clipboard->mimeData(); - clipboard->setProperty(c_propertyImageUrlAltered, false); - if (clipboard->ownsClipboard() - && mimeData->hasText() - && mimeData->hasUrls()) { - QString text = mimeData->text(); - QList urls = mimeData->urls(); - if (urls.size() == 1 - && urls[0].isLocalFile() - && urls[0].toEncoded() == text) { - QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces); - if (spaceOnlyText != text) { - // Set new mime data. - QMimeData *data = new QMimeData(); - data->setUrls(urls); - data->setText(spaceOnlyText); - ClipboardUtils::setMimeDataToClipboard(clipboard, data, QClipboard::Clipboard); - clipboard->setProperty(c_propertyImageUrlAltered, true); - qDebug() << "clipboard copy image URL altered" << spaceOnlyText; - } - } +void MarkdownViewer::handleCopyImageUrlAction() { + // To avoid failure of setting clipboard mime data. + QCoreApplication::processEvents(); + + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + clipboard->setProperty(c_propertyImageUrlAltered, false); + if (clipboard->ownsClipboard() && mimeData->hasText() && mimeData->hasUrls()) { + QString text = mimeData->text(); + QList urls = mimeData->urls(); + if (urls.size() == 1 && urls[0].isLocalFile() && urls[0].toEncoded() == text) { + QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces); + if (spaceOnlyText != text) { + // Set new mime data. + QMimeData *data = new QMimeData(); + data->setUrls(urls); + data->setText(spaceOnlyText); + ClipboardUtils::setMimeDataToClipboard(clipboard, data, QClipboard::Clipboard); + clipboard->setProperty(c_propertyImageUrlAltered, true); + qDebug() << "clipboard copy image URL altered" << spaceOnlyText; + } } + } } -void MarkdownViewer::copyImage() -{ +void MarkdownViewer::copyImage() { #if defined(Q_OS_WIN) - Q_ASSERT(m_copyImageUrlActionHooked); - // triggerPageAction(QWebEnginePage::CopyImageUrlToClipboard) will not really - // trigger the corresponding action. It just do the stuff directly. - QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); - copyImageUrlAct->trigger(); - - QCoreApplication::processEvents(); + Q_ASSERT(m_copyImageUrlActionHooked); + // triggerPageAction(QWebEnginePage::CopyImageUrlToClipboard) will not really + // trigger the corresponding action. It just do the stuff directly. + QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); + copyImageUrlAct->trigger(); - QClipboard *clipboard = QApplication::clipboard(); - if (clipboard->property(c_propertyImageUrlAltered).toBool()) { - const QMimeData *mimeData = clipboard->mimeData(); - QString imgPath; - if (mimeData->hasUrls()) { - QList urls = mimeData->urls(); - if (!urls.isEmpty() && urls[0].isLocalFile()) { - imgPath = urls[0].toLocalFile(); - } - } - - if (!imgPath.isEmpty()) { - QImage img = FileUtils::imageFromFile(imgPath); - if (!img.isNull()) { - m_copyImageTriggered = false; - ClipboardUtils::setImageToClipboard(clipboard, img, QClipboard::Clipboard); - return; - } - } - } -#endif + QCoreApplication::processEvents(); - m_copyImageTriggered = true; - - // Fall back. - triggerPageAction(QWebEnginePage::CopyImageToClipboard); -} - -void MarkdownViewer::handleClipboardChanged(QClipboard::Mode p_mode) -{ - if (!hasFocus() || p_mode != QClipboard::Clipboard) { - return; - } - - QClipboard *clipboard = QApplication::clipboard(); - if (!clipboard->ownsClipboard()) { - return; + QClipboard *clipboard = QApplication::clipboard(); + if (clipboard->property(c_propertyImageUrlAltered).toBool()) { + const QMimeData *mimeData = clipboard->mimeData(); + QString imgPath; + if (mimeData->hasUrls()) { + QList urls = mimeData->urls(); + if (!urls.isEmpty() && urls[0].isLocalFile()) { + imgPath = urls[0].toLocalFile(); + } } - const QMimeData *mimeData = clipboard->mimeData(); - if (m_copyImageTriggered) { + if (!imgPath.isEmpty()) { + QImage img = FileUtils::imageFromFile(imgPath); + if (!img.isNull()) { m_copyImageTriggered = false; - removeHtmlFromImageData(clipboard, mimeData); + ClipboardUtils::setImageToClipboard(clipboard, img, QClipboard::Clipboard); return; + } } + } +#endif - if (clipboard->property(c_propertyCrossCopy).toBool()) { - clipboard->setProperty(c_propertyCrossCopy, false); - if (mimeData->hasHtml() && !mimeData->hasImage() && !m_crossCopyTarget.isEmpty()) { - crossCopy(m_crossCopyTarget, url().toString(), mimeData->html()); - } - } + m_copyImageTriggered = true; + + // Fall back. + triggerPageAction(QWebEnginePage::CopyImageToClipboard); } -void MarkdownViewer::removeHtmlFromImageData(QClipboard *p_clipboard, - const QMimeData *p_mimeData) -{ - if (!p_mimeData->hasImage()) { - return; +void MarkdownViewer::handleClipboardChanged(QClipboard::Mode p_mode) { + if (!hasFocus() || p_mode != QClipboard::Clipboard) { + return; + } + + QClipboard *clipboard = QApplication::clipboard(); + if (!clipboard->ownsClipboard()) { + return; + } + + const QMimeData *mimeData = clipboard->mimeData(); + if (m_copyImageTriggered) { + m_copyImageTriggered = false; + removeHtmlFromImageData(clipboard, mimeData); + return; + } + + if (clipboard->property(c_propertyCrossCopy).toBool()) { + clipboard->setProperty(c_propertyCrossCopy, false); + if (mimeData->hasHtml() && !mimeData->hasImage() && !m_crossCopyTarget.isEmpty()) { + crossCopy(m_crossCopyTarget, url().toString(), mimeData->html()); } + } +} - if (p_mimeData->hasHtml()) { - qDebug() << "remove HTML from image QMimeData" << p_mimeData->html(); - QMimeData *data = new QMimeData(); - data->setImageData(p_mimeData->imageData()); - ClipboardUtils::setMimeDataToClipboard(p_clipboard, data, QClipboard::Clipboard); - } +void MarkdownViewer::removeHtmlFromImageData(QClipboard *p_clipboard, const QMimeData *p_mimeData) { + if (!p_mimeData->hasImage()) { + return; + } + + if (p_mimeData->hasHtml()) { + qDebug() << "remove HTML from image QMimeData" << p_mimeData->html(); + QMimeData *data = new QMimeData(); + data->setImageData(p_mimeData->imageData()); + ClipboardUtils::setMimeDataToClipboard(p_clipboard, data, QClipboard::Clipboard); + } } -void MarkdownViewer::hideUnusedActions(QMenu *p_menu) -{ - Q_UNUSED(p_menu); +void MarkdownViewer::hideUnusedActions(QMenu *p_menu) { + Q_UNUSED(p_menu); - QList unusedActions; + QList unusedActions; - // QWebEnginePage uses different actions of Back/Forward/Reload before Qt 5.15. - // [Woboq](https://code.woboq.org/qt5/qtwebengine/src/webenginewidgets/api/qwebenginepage.cpp.html#1652) - // We tell these three actions by name. + // QWebEnginePage uses different actions of Back/Forward/Reload before Qt 5.15. + // [Woboq](https://code.woboq.org/qt5/qtwebengine/src/webenginewidgets/api/qwebenginepage.cpp.html#1652) + // We tell these three actions by name. #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) - const QStringList actionNames({QWebEnginePage::tr("&Back"), - QWebEnginePage::tr("&Forward"), - QWebEnginePage::tr("&Reload")}); - - const QList actions = p_menu->actions(); - for (auto it : actions) { - if (actionNames.contains(it->text())) { - unusedActions.append(it); - } + const QStringList actionNames( + {QWebEnginePage::tr("&Back"), QWebEnginePage::tr("&Forward"), QWebEnginePage::tr("&Reload")}); + + const QList actions = p_menu->actions(); + for (auto it : actions) { + if (actionNames.contains(it->text())) { + unusedActions.append(it); } + } #endif - QVector pageActions = { QWebEnginePage::SavePage, - QWebEnginePage::ViewSource, - QWebEnginePage::DownloadImageToDisk, - QWebEnginePage::DownloadLinkToDisk, - QWebEnginePage::OpenLinkInThisWindow, - QWebEnginePage::OpenLinkInNewBackgroundTab, - QWebEnginePage::OpenLinkInNewTab, - QWebEnginePage::OpenLinkInNewWindow, + QVector pageActions = {QWebEnginePage::SavePage, + QWebEnginePage::ViewSource, + QWebEnginePage::DownloadImageToDisk, + QWebEnginePage::DownloadLinkToDisk, + QWebEnginePage::OpenLinkInThisWindow, + QWebEnginePage::OpenLinkInNewBackgroundTab, + QWebEnginePage::OpenLinkInNewTab, + QWebEnginePage::OpenLinkInNewWindow, #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - QWebEnginePage::Forward, - QWebEnginePage::Back, - QWebEnginePage::Reload + QWebEnginePage::Forward, + QWebEnginePage::Back, + QWebEnginePage::Reload #endif - }; + }; - for (auto pageAct : pageActions) { - auto act = pageAction(pageAct); - unusedActions.append(act); - } + for (auto pageAct : pageActions) { + auto act = pageAction(pageAct); + unusedActions.append(act); + } - for (auto it : unusedActions) { - if (it) { - it->setVisible(false); - } + for (auto it : unusedActions) { + if (it) { + it->setVisible(false); } + } } -void MarkdownViewer::handleWebKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta) -{ - Q_UNUSED(p_shift); - Q_UNUSED(p_meta); - switch (p_key) { - // Esc - case 27: - break; - - // Dash - case 189: - if (p_ctrl) { - // Zoom out. - zoomOut(); - } - break; - - // Equal - case 187: - if (p_ctrl) { - // Zoom in. - zoomIn(); - } - break; - - // 0 - case 48: - if (p_ctrl) { - // Recover zoom. - restoreZoom(); - } - break; - - default: - break; +void MarkdownViewer::handleWebKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta) { + Q_UNUSED(p_shift); + Q_UNUSED(p_meta); + switch (p_key) { + // Esc + case 27: + break; + + // Dash + case 189: + if (p_ctrl) { + // Zoom out. + zoomOut(); } -} + break; -void MarkdownViewer::zoomOut() -{ - qreal factor = zoomFactor(); - if (factor > 0.1) { - factor -= 0.1; - setZoomFactor(factor); - emit zoomFactorChanged(factor); + // Equal + case 187: + if (p_ctrl) { + // Zoom in. + zoomIn(); } + break; + + // 0 + case 48: + if (p_ctrl) { + // Recover zoom. + restoreZoom(); + } + break; + + default: + break; + } } -void MarkdownViewer::zoomIn() -{ - qreal factor = zoomFactor(); - factor += 0.1; +void MarkdownViewer::zoomOut() { + qreal factor = zoomFactor(); + if (factor > 0.1) { + factor -= 0.1; setZoomFactor(factor); emit zoomFactorChanged(factor); + } } -void MarkdownViewer::restoreZoom() -{ - setZoomFactor(1); - emit zoomFactorChanged(1); +void MarkdownViewer::zoomIn() { + qreal factor = zoomFactor(); + factor += 0.1; + setZoomFactor(factor); + emit zoomFactorChanged(factor); } -void MarkdownViewer::setupCrossCopyMenu(QMenu *p_menu, QAction *p_copyAct) -{ - const auto &targets = m_adapter->getCrossCopyTargets(); - if (targets.isEmpty()) { - return; - } +void MarkdownViewer::restoreZoom() { + setZoomFactor(1); + emit zoomFactorChanged(1); +} - auto subMenu = WidgetsFactory::createMenu(tr("Cross Copy"), p_menu); +void MarkdownViewer::setupCrossCopyMenu(QMenu *p_menu, QAction *p_copyAct) { + const auto &targets = m_adapter->getCrossCopyTargets(); + if (targets.isEmpty()) { + return; + } - for (const auto &target : targets) { - auto act = subMenu->addAction(m_adapter->getCrossCopyTargetDisplayName(target)); - act->setData(target); - } + auto subMenu = WidgetsFactory::createMenu(tr("Cross Copy"), p_menu); - connect(subMenu, &QMenu::triggered, - this, [this](QAction *p_act) { - // selectedText() will return a plain text, so we trigger the Copy action here. - m_crossCopyTarget = p_act->data().toString(); + for (const auto &target : targets) { + auto act = subMenu->addAction(m_adapter->getCrossCopyTargetDisplayName(target)); + act->setData(target); + } - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setProperty(c_propertyCrossCopy, true); - // Will handle the remaining logics in handleClipboardChanged(). - triggerPageAction(QWebEnginePage::Copy); - }); + connect(subMenu, &QMenu::triggered, this, [this](QAction *p_act) { + // selectedText() will return a plain text, so we trigger the Copy action here. + m_crossCopyTarget = p_act->data().toString(); - auto menuAct = p_menu->insertMenu(p_copyAct, subMenu); - p_menu->removeAction(p_copyAct); - p_menu->insertAction(menuAct, p_copyAct); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setProperty(c_propertyCrossCopy, true); + // Will handle the remaining logics in handleClipboardChanged(). + triggerPageAction(QWebEnginePage::Copy); + }); + + auto menuAct = p_menu->insertMenu(p_copyAct, subMenu); + p_menu->removeAction(p_copyAct); + p_menu->insertAction(menuAct, p_copyAct); } -void MarkdownViewer::crossCopy(const QString &p_target, const QString &p_baseUrl, const QString &p_html) -{ - emit m_adapter->crossCopyRequested(0, 0, p_target, p_baseUrl, p_html); +void MarkdownViewer::crossCopy(const QString &p_target, const QString &p_baseUrl, + const QString &p_html) { + emit m_adapter->crossCopyRequested(0, 0, p_target, p_baseUrl, p_html); } -void MarkdownViewer::saveContent(const std::function &p_callback) -{ - page()->runJavaScript("document.getElementById('vx-content').textContent", [p_callback](const QVariant &v) { - p_callback(v.toString()); - }); +void MarkdownViewer::saveContent(const std::function &p_callback) { + page()->runJavaScript("document.getElementById('vx-content').textContent", + [p_callback](const QVariant &v) { p_callback(v.toString()); }); } diff --git a/src/widgets/editors/markdownviewer.h b/src/widgets/editors/markdownviewer.h index 9d0ffd04bf..d99e18b502 100644 --- a/src/widgets/editors/markdownviewer.h +++ b/src/widgets/editors/markdownviewer.h @@ -5,84 +5,77 @@ #include -namespace vnotex -{ - class MarkdownViewerAdapter; - class PreviewHelper; - class ViewWindow; +namespace vnotex { +class MarkdownViewerAdapter; +class PreviewHelper; +class ViewWindow; - class MarkdownViewer : public WebViewer - { - Q_OBJECT - public: - // @p_adapter will be managed by MarkdownViewer. - MarkdownViewer(MarkdownViewerAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent = nullptr); +class MarkdownViewer : public WebViewer { + Q_OBJECT +public: + // @p_adapter will be managed by MarkdownViewer. + MarkdownViewer(MarkdownViewerAdapter *p_adapter, const QColor &p_background, qreal p_zoomFactor, + QWidget *p_parent = nullptr); - MarkdownViewer(MarkdownViewerAdapter *p_adapter, - const ViewWindow *p_viewWindow, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent = nullptr); + MarkdownViewer(MarkdownViewerAdapter *p_adapter, const ViewWindow *p_viewWindow, + const QColor &p_background, qreal p_zoomFactor, QWidget *p_parent = nullptr); - MarkdownViewerAdapter *adapter() const; + MarkdownViewerAdapter *adapter() const; - void setPreviewHelper(PreviewHelper *p_previewHelper); + void setPreviewHelper(PreviewHelper *p_previewHelper); - void saveContent(const std::function &p_callback); + void saveContent(const std::function &p_callback); - signals: - void zoomFactorChanged(qreal p_factor); +signals: + void zoomFactorChanged(qreal p_factor); - void editRequested(); + void editRequested(); - protected: - void contextMenuEvent(QContextMenuEvent *p_event) Q_DECL_OVERRIDE; +protected: + void contextMenuEvent(QContextMenuEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void handleClipboardChanged(QClipboard::Mode p_mode); +private slots: + void handleClipboardChanged(QClipboard::Mode p_mode); - void handleWebKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta); + void handleWebKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta); - private: - void handleCopyImageUrlAction(); +private: + void handleCopyImageUrlAction(); - // Copy the clicked image. - // Used to replace the default CopyImageToClipboard action. - void copyImage(); + // Copy the clicked image. + // Used to replace the default CopyImageToClipboard action. + void copyImage(); - void removeHtmlFromImageData(QClipboard *p_clipboard, const QMimeData *p_mimeData); + void removeHtmlFromImageData(QClipboard *p_clipboard, const QMimeData *p_mimeData); - void hideUnusedActions(QMenu *p_menu); + void hideUnusedActions(QMenu *p_menu); - void zoomOut(); + void zoomOut(); - void zoomIn(); + void zoomIn(); - void restoreZoom(); + void restoreZoom(); - void setupCrossCopyMenu(QMenu *p_menu, QAction *p_copyAct); + void setupCrossCopyMenu(QMenu *p_menu, QAction *p_copyAct); - // @p_baseUrl: if it is a folder, please end it with '/'. It is not used now in web side. - void crossCopy(const QString &p_target, const QString &p_baseUrl, const QString &p_html); + // @p_baseUrl: if it is a folder, please end it with '/'. It is not used now in web side. + void crossCopy(const QString &p_target, const QString &p_baseUrl, const QString &p_html); - // Managed by QObject. - MarkdownViewerAdapter *m_adapter = nullptr; + // Managed by QObject. + MarkdownViewerAdapter *m_adapter = nullptr; - // Nullable. - const ViewWindow *m_viewWindow = nullptr; + // Nullable. + const ViewWindow *m_viewWindow = nullptr; - // Whether this view has hooked the Copy Image Url action. - bool m_copyImageUrlActionHooked = false; + // Whether this view has hooked the Copy Image Url action. + bool m_copyImageUrlActionHooked = false; - // Whether CopyImage action has been triggered. - bool m_copyImageTriggered = false; + // Whether CopyImage action has been triggered. + bool m_copyImageTriggered = false; - // Target name of cross copy going to execute. - QString m_crossCopyTarget; - }; -} + // Target name of cross copy going to execute. + QString m_crossCopyTarget; +}; +} // namespace vnotex #endif // MARKDOWNVIEWER_H diff --git a/src/widgets/editors/markdownvieweradapter.cpp b/src/widgets/editors/markdownvieweradapter.cpp index 831b627f07..8feffe8654 100644 --- a/src/widgets/editors/markdownvieweradapter.cpp +++ b/src/widgets/editors/markdownvieweradapter.cpp @@ -3,406 +3,325 @@ #include #include "../outlineprovider.h" -#include "plantumlhelper.h" #include "graphvizhelper.h" +#include "plantumlhelper.h" #include using namespace vnotex; MarkdownViewerAdapter::Position::Position(int p_lineNumber, const QString &p_anchor) - : m_lineNumber(p_lineNumber), - m_anchor(p_anchor) -{ -} + : m_lineNumber(p_lineNumber), m_anchor(p_anchor) {} -QJsonObject MarkdownViewerAdapter::Position::toJson() const -{ - QJsonObject obj; - obj["lineNumber"] = m_lineNumber; - obj["anchor"] = m_anchor; - return obj; +QJsonObject MarkdownViewerAdapter::Position::toJson() const { + QJsonObject obj; + obj["lineNumber"] = m_lineNumber; + obj["anchor"] = m_anchor; + return obj; } -MarkdownViewerAdapter::PreviewData::PreviewData(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QByteArray &p_data, +MarkdownViewerAdapter::PreviewData::PreviewData(quint64 p_id, TimeStamp p_timeStamp, + const QString &p_format, const QByteArray &p_data, bool p_needScale) - : m_id(p_id), - m_timeStamp(p_timeStamp), - m_format(p_format), - m_data(p_data), - m_needScale(p_needScale) -{ -} + : m_id(p_id), m_timeStamp(p_timeStamp), m_format(p_format), m_data(p_data), + m_needScale(p_needScale) {} MarkdownViewerAdapter::Heading::Heading(const QString &p_name, int p_level, const QString &p_anchor) - : m_name(p_name), - m_level(p_level), - m_anchor(p_anchor) -{ -} - -MarkdownViewerAdapter::Heading MarkdownViewerAdapter::Heading::fromJson(const QJsonObject &p_obj) -{ - return Heading(p_obj.value(QStringLiteral("name")).toString(), - p_obj.value(QStringLiteral("level")).toInt(), - p_obj.value(QStringLiteral("anchor")).toString()); -} - -MarkdownViewerAdapter::CssRuleStyle MarkdownViewerAdapter::CssRuleStyle::fromJson(const QJsonObject &p_obj) -{ - CssRuleStyle style; - style.m_selector = p_obj[QStringLiteral("selector")].toString(); - style.m_color = p_obj[QStringLiteral("color")].toString(); - style.m_backgroundColor = p_obj[QStringLiteral("backgroundColor")].toString(); - style.m_fontWeight = p_obj[QStringLiteral("fontWeight")].toString(); - style.m_fontStyle = p_obj[QStringLiteral("fontStyle")].toString(); - return style; -} - -QTextCharFormat MarkdownViewerAdapter::CssRuleStyle::toTextCharFormat() const -{ - QTextCharFormat fmt; - if (!m_color.isEmpty()) { - fmt.setForeground(Utils::toColor(m_color)); - } - if (!m_backgroundColor.isEmpty()) { - fmt.setBackground(QColor(m_color)); - } - if (m_fontWeight.contains(QStringLiteral("bold"))) { - fmt.setFontWeight(QFont::Bold); - } - if (m_fontStyle.contains(QStringLiteral("italic"))) { - fmt.setFontItalic(true); - } - return fmt; -} - -MarkdownViewerAdapter::MarkdownViewerAdapter(QObject *p_parent) - : WebViewAdapter(p_parent) -{ -} - -MarkdownViewerAdapter::~MarkdownViewerAdapter() -{ -} - -void MarkdownViewerAdapter::setText(int p_revision, - const QString &p_text, - int p_lineNumber) -{ - if (p_revision == m_revision && p_revision != 0) { - // Only sync line number position. - scrollToPosition(Position(p_lineNumber, "")); - return; - } - - if (isReady()) { - m_revision = p_revision; - emit textUpdated(p_text); - scrollToPosition(Position(p_lineNumber, "")); - } else { - pendAction(std::bind(QOverload::of(&MarkdownViewerAdapter::setText), - this, - p_revision, - p_text, - p_lineNumber)); - } -} - -void MarkdownViewerAdapter::setText(const QString &p_text, int p_lineNumber) -{ - setText(0, p_text, p_lineNumber); -} - -void MarkdownViewerAdapter::scrollToLine(int p_lineNumber) -{ - if (p_lineNumber == -1) { - return; - } - - if (isReady()) { - m_topLineNumber = p_lineNumber; - emit editLineNumberUpdated(p_lineNumber); - } else { - pendAction(std::bind(&MarkdownViewerAdapter::scrollToLine, this, p_lineNumber)); - } -} - -void MarkdownViewerAdapter::setTopLineNumber(int p_lineNumber) -{ - if (m_topLineNumber == p_lineNumber) { - return; - } - + : m_name(p_name), m_level(p_level), m_anchor(p_anchor) {} + +MarkdownViewerAdapter::Heading MarkdownViewerAdapter::Heading::fromJson(const QJsonObject &p_obj) { + return Heading(p_obj.value(QStringLiteral("name")).toString(), + p_obj.value(QStringLiteral("level")).toInt(), + p_obj.value(QStringLiteral("anchor")).toString()); +} + +MarkdownViewerAdapter::CssRuleStyle +MarkdownViewerAdapter::CssRuleStyle::fromJson(const QJsonObject &p_obj) { + CssRuleStyle style; + style.m_selector = p_obj[QStringLiteral("selector")].toString(); + style.m_color = p_obj[QStringLiteral("color")].toString(); + style.m_backgroundColor = p_obj[QStringLiteral("backgroundColor")].toString(); + style.m_fontWeight = p_obj[QStringLiteral("fontWeight")].toString(); + style.m_fontStyle = p_obj[QStringLiteral("fontStyle")].toString(); + return style; +} + +QTextCharFormat MarkdownViewerAdapter::CssRuleStyle::toTextCharFormat() const { + QTextCharFormat fmt; + if (!m_color.isEmpty()) { + fmt.setForeground(Utils::toColor(m_color)); + } + if (!m_backgroundColor.isEmpty()) { + fmt.setBackground(QColor(m_color)); + } + if (m_fontWeight.contains(QStringLiteral("bold"))) { + fmt.setFontWeight(QFont::Bold); + } + if (m_fontStyle.contains(QStringLiteral("italic"))) { + fmt.setFontItalic(true); + } + return fmt; +} + +MarkdownViewerAdapter::MarkdownViewerAdapter(QObject *p_parent) : WebViewAdapter(p_parent) {} + +MarkdownViewerAdapter::~MarkdownViewerAdapter() {} + +void MarkdownViewerAdapter::setText(int p_revision, const QString &p_text, int p_lineNumber) { + if (p_revision == m_revision && p_revision != 0) { + // Only sync line number position. + scrollToPosition(Position(p_lineNumber, "")); + return; + } + + if (isReady()) { + m_revision = p_revision; + emit textUpdated(p_text); + scrollToPosition(Position(p_lineNumber, "")); + } else { + pendAction(std::bind(QOverload::of(&MarkdownViewerAdapter::setText), + this, p_revision, p_text, p_lineNumber)); + } +} + +void MarkdownViewerAdapter::setText(const QString &p_text, int p_lineNumber) { + setText(0, p_text, p_lineNumber); +} + +void MarkdownViewerAdapter::scrollToLine(int p_lineNumber) { + if (p_lineNumber == -1) { + return; + } + + if (isReady()) { m_topLineNumber = p_lineNumber; + emit editLineNumberUpdated(p_lineNumber); + } else { + pendAction(std::bind(&MarkdownViewerAdapter::scrollToLine, this, p_lineNumber)); + } } -void MarkdownViewerAdapter::scrollToPosition(const Position &p_pos) -{ - if (p_pos.m_lineNumber >= 0) { - scrollToLine(p_pos.m_lineNumber); - } else { - // Anchor. - scrollToAnchor(p_pos.m_anchor); - } -} +void MarkdownViewerAdapter::setTopLineNumber(int p_lineNumber) { + if (m_topLineNumber == p_lineNumber) { + return; + } -int MarkdownViewerAdapter::getTopLineNumber() const -{ - return m_topLineNumber; + m_topLineNumber = p_lineNumber; } -void MarkdownViewerAdapter::setGraphPreviewData(quint64 p_id, - quint64 p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_base64, - bool p_needScale) -{ - auto ba = p_data.toUtf8(); - if (p_base64 && !ba.isEmpty()) { - ba = QByteArray::fromBase64(ba); - } - emit graphPreviewDataReady(PreviewData(p_id, p_timeStamp, p_format, ba, p_needScale)); -} - -void MarkdownViewerAdapter::setMathPreviewData(quint64 p_id, - quint64 p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_base64, - bool p_needScale) -{ - auto ba = p_data.toUtf8(); - if (p_base64 && !ba.isEmpty()) { - ba = QByteArray::fromBase64(ba); - } - emit mathPreviewDataReady(PreviewData(p_id, p_timeStamp, p_format, ba, p_needScale)); -} - -void MarkdownViewerAdapter::setHeadings(const QJsonArray &p_headings) -{ - QVector headings; - headings.reserve(p_headings.size()); - for (auto const &arr : p_headings) { - headings.push_back(MarkdownViewerAdapter::Heading::fromJson(arr.toObject())); - } - - OutlineProvider::makePerfectHeadings(headings, m_headings); - m_currentHeadingIndex = -1; - - emit headingsChanged(); +void MarkdownViewerAdapter::scrollToPosition(const Position &p_pos) { + if (p_pos.m_lineNumber >= 0) { + scrollToLine(p_pos.m_lineNumber); + } else { + // Anchor. + scrollToAnchor(p_pos.m_anchor); + } } -void MarkdownViewerAdapter::setCurrentHeadingAnchor(int p_index, const QString &p_anchor) -{ - m_currentHeadingIndex = -1; - if (p_index > -1) { - for (int i = p_index; i < m_headings.size(); ++i) { - if (m_headings[i].m_anchor == p_anchor) { - m_currentHeadingIndex = i; - break; - } - } - } +int MarkdownViewerAdapter::getTopLineNumber() const { return m_topLineNumber; } - emit currentHeadingChanged(); +void MarkdownViewerAdapter::setGraphPreviewData(quint64 p_id, quint64 p_timeStamp, + const QString &p_format, const QString &p_data, + bool p_base64, bool p_needScale) { + auto ba = p_data.toUtf8(); + if (p_base64 && !ba.isEmpty()) { + ba = QByteArray::fromBase64(ba); + } + emit graphPreviewDataReady(PreviewData(p_id, p_timeStamp, p_format, ba, p_needScale)); } -const QVector &MarkdownViewerAdapter::getHeadings() const -{ - return m_headings; +void MarkdownViewerAdapter::setMathPreviewData(quint64 p_id, quint64 p_timeStamp, + const QString &p_format, const QString &p_data, + bool p_base64, bool p_needScale) { + auto ba = p_data.toUtf8(); + if (p_base64 && !ba.isEmpty()) { + ba = QByteArray::fromBase64(ba); + } + emit mathPreviewDataReady(PreviewData(p_id, p_timeStamp, p_format, ba, p_needScale)); } -int MarkdownViewerAdapter::getCurrentHeadingIndex() const -{ - return m_currentHeadingIndex; -} +void MarkdownViewerAdapter::setHeadings(const QJsonArray &p_headings) { + QVector headings; + headings.reserve(p_headings.size()); + for (auto const &arr : p_headings) { + headings.push_back(MarkdownViewerAdapter::Heading::fromJson(arr.toObject())); + } -void MarkdownViewerAdapter::scrollToHeading(int p_idx) -{ - if (p_idx < 0 || p_idx >= m_headings.size()) { - return; - } + OutlineProvider::makePerfectHeadings(headings, m_headings); + m_currentHeadingIndex = -1; - if (m_headings[p_idx].m_anchor.isEmpty()) { - return; - } - - scrollToPosition(Position(-1, m_headings[p_idx].m_anchor)); + emit headingsChanged(); } -void MarkdownViewerAdapter::scrollToAnchor(const QString &p_anchor) -{ - if (p_anchor.isEmpty()) { - return; +void MarkdownViewerAdapter::setCurrentHeadingAnchor(int p_index, const QString &p_anchor) { + m_currentHeadingIndex = -1; + if (p_index > -1) { + for (int i = p_index; i < m_headings.size(); ++i) { + if (m_headings[i].m_anchor == p_anchor) { + m_currentHeadingIndex = i; + break; + } } - Q_ASSERT(isReady()); - m_currentHeadingIndex = -1; - emit anchorScrollRequested(p_anchor); -} + } -void MarkdownViewerAdapter::scroll(bool p_up) -{ - emit scrollRequested(p_up); + emit currentHeadingChanged(); } -void MarkdownViewerAdapter::setKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta) -{ - emit keyPressed(p_key, p_ctrl, p_shift, p_meta); +const QVector &MarkdownViewerAdapter::getHeadings() const { + return m_headings; } -void MarkdownViewerAdapter::zoom(bool p_zoomIn) -{ - emit zoomed(p_zoomIn); -} +int MarkdownViewerAdapter::getCurrentHeadingIndex() const { return m_currentHeadingIndex; } -void MarkdownViewerAdapter::setMarkdownFromHtml(quint64 p_id, quint64 p_timeStamp, const QString &p_text) -{ - emit htmlToMarkdownReady(p_id, p_timeStamp, p_text); -} +void MarkdownViewerAdapter::scrollToHeading(int p_idx) { + if (p_idx < 0 || p_idx >= m_headings.size()) { + return; + } -void MarkdownViewerAdapter::setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, const QString &p_html) -{ - emit highlightCodeBlockReady(p_idx, p_timeStamp, p_html); -} + if (m_headings[p_idx].m_anchor.isEmpty()) { + return; + } -void MarkdownViewerAdapter::setCrossCopyTargets(const QJsonArray &p_targets) -{ - m_crossCopyTargets.clear(); - for (const auto &target : p_targets) { - m_crossCopyTargets << target.toString(); - } + scrollToPosition(Position(-1, m_headings[p_idx].m_anchor)); } -const QStringList &MarkdownViewerAdapter::getCrossCopyTargets() const -{ - return m_crossCopyTargets; +void MarkdownViewerAdapter::scrollToAnchor(const QString &p_anchor) { + if (p_anchor.isEmpty()) { + return; + } + Q_ASSERT(isReady()); + m_currentHeadingIndex = -1; + emit anchorScrollRequested(p_anchor); } -QString MarkdownViewerAdapter::getCrossCopyTargetDisplayName(const QString &p_target) const -{ - static QMap maps; - if (maps.isEmpty()) { - maps.insert("No Background", tr("No Background")); - maps.insert("Evernote", tr("Evernote")); - maps.insert("OneNote", tr("OneNote")); - maps.insert("Microsoft Word", tr("Microsoft Word")); - maps.insert("WeChat Public Account Editor", tr("WeChat Public Account Editor")); - maps.insert("Raw HTML", tr("Raw HTML")); - } +void MarkdownViewerAdapter::scroll(bool p_up) { emit scrollRequested(p_up); } - auto it = maps.find(p_target); - if (it != maps.end()) { - return *it; - } - qWarning() << "missing cross copy target" << p_target; - return p_target; +void MarkdownViewerAdapter::setKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta) { + emit keyPressed(p_key, p_ctrl, p_shift, p_meta); } -void MarkdownViewerAdapter::setCrossCopyResult(quint64 p_id, quint64 p_timeStamp, const QString &p_html) -{ - emit crossCopyReady(p_id, p_timeStamp, p_html); -} +void MarkdownViewerAdapter::zoom(bool p_zoomIn) { emit zoomed(p_zoomIn); } -void MarkdownViewerAdapter::setWorkFinished() -{ - emit workFinished(); +void MarkdownViewerAdapter::setMarkdownFromHtml(quint64 p_id, quint64 p_timeStamp, + const QString &p_text) { + emit htmlToMarkdownReady(p_id, p_timeStamp, p_text); } -void MarkdownViewerAdapter::saveContent() -{ - emit contentRequested(); +void MarkdownViewerAdapter::setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, + const QString &p_html) { + emit highlightCodeBlockReady(p_idx, p_timeStamp, p_html); } -void MarkdownViewerAdapter::setSavedContent(const QString &p_headContent, - const QString &p_styleContent, - const QString &p_content, - const QString &p_bodyClassList) -{ - emit contentReady(p_headContent, p_styleContent, p_content, p_bodyClassList); +void MarkdownViewerAdapter::setCrossCopyTargets(const QJsonArray &p_targets) { + m_crossCopyTargets.clear(); + for (const auto &target : p_targets) { + m_crossCopyTargets << target.toString(); + } } -void MarkdownViewerAdapter::reset() -{ - m_revision = 0; - setReady(false); - m_topLineNumber = -1; - m_headings.clear(); - m_currentHeadingIndex = -1; - m_crossCopyTargets.clear(); -} +const QStringList &MarkdownViewerAdapter::getCrossCopyTargets() const { return m_crossCopyTargets; } -void MarkdownViewerAdapter::renderGraph(quint64 p_id, - quint64 p_index, - const QString &p_format, - const QString &p_lang, - const QString &p_text) -{ - if (p_text.isEmpty()) { - emit graphRenderDataReady(p_id, p_index, p_format, QString()); - return; - } +QString MarkdownViewerAdapter::getCrossCopyTargetDisplayName(const QString &p_target) const { + static QMap maps; + if (maps.isEmpty()) { + maps.insert("No Background", tr("No Background")); + maps.insert("Evernote", tr("Evernote")); + maps.insert("OneNote", tr("OneNote")); + maps.insert("Microsoft Word", tr("Microsoft Word")); + maps.insert("WeChat Public Account Editor", tr("WeChat Public Account Editor")); + maps.insert("Raw HTML", tr("Raw HTML")); + } - if (p_lang == QStringLiteral("puml")) { - PlantUmlHelper::getInst().process(p_id, - p_index, - p_format, - p_text, - this, - [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { - emit graphRenderDataReady(id, timeStamp, format, data); - }); - } else if (p_lang == QStringLiteral("dot")) { - GraphvizHelper::getInst().process(p_id, - p_index, - p_format, - p_text, - this, - [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { - emit graphRenderDataReady(id, timeStamp, format, data); - }); - } else { - Q_ASSERT(false); - } + auto it = maps.find(p_target); + if (it != maps.end()) { + return *it; + } + qWarning() << "missing cross copy target" << p_target; + return p_target; } -void MarkdownViewerAdapter::highlightCodeBlock(int p_idx, quint64 p_timeStamp, const QString &p_text) -{ - if (isReady()) { - emit highlightCodeBlockRequested(p_idx, p_timeStamp, p_text); - } else { - pendAction(std::bind(&MarkdownViewerAdapter::highlightCodeBlock, this, p_idx, p_timeStamp, p_text)); - } +void MarkdownViewerAdapter::setCrossCopyResult(quint64 p_id, quint64 p_timeStamp, + const QString &p_html) { + emit crossCopyReady(p_id, p_timeStamp, p_html); } -void MarkdownViewerAdapter::setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles) -{ - QVector ruleStyles; - ruleStyles.reserve(p_styles.size()); - for (int i = 0; i < p_styles.size(); ++i) { - ruleStyles.push_back(CssRuleStyle::fromJson(p_styles[i].toObject())); - } - - invokeCallback(p_id, &ruleStyles); -} +void MarkdownViewerAdapter::setWorkFinished() { emit workFinished(); } -void MarkdownViewerAdapter::fetchStylesFromStyleSheet(const QString &p_styleSheet, - const std::function *)> &p_callback) -{ - if (p_styleSheet.isEmpty()) { - p_callback(nullptr); - return; - } +void MarkdownViewerAdapter::saveContent() { emit contentRequested(); } - if (isReady()) { - const quint64 id = addCallback([p_callback](void *data) { - p_callback(reinterpret_cast *>(data)); +void MarkdownViewerAdapter::setSavedContent(const QString &p_headContent, + const QString &p_styleContent, const QString &p_content, + const QString &p_bodyClassList) { + emit contentReady(p_headContent, p_styleContent, p_content, p_bodyClassList); +} + +void MarkdownViewerAdapter::reset() { + m_revision = 0; + setReady(false); + m_topLineNumber = -1; + m_headings.clear(); + m_currentHeadingIndex = -1; + m_crossCopyTargets.clear(); +} + +void MarkdownViewerAdapter::renderGraph(quint64 p_id, quint64 p_index, const QString &p_format, + const QString &p_lang, const QString &p_text) { + if (p_text.isEmpty()) { + emit graphRenderDataReady(p_id, p_index, p_format, QString()); + return; + } + + if (p_lang == QStringLiteral("puml")) { + PlantUmlHelper::getInst().process( + p_id, p_index, p_format, p_text, this, + [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { + emit graphRenderDataReady(id, timeStamp, format, data); }); - emit parseStyleSheetRequested(id, p_styleSheet); - } else { - pendAction(std::bind(&MarkdownViewerAdapter::fetchStylesFromStyleSheet, this, p_styleSheet, p_callback)); - } + } else if (p_lang == QStringLiteral("dot")) { + GraphvizHelper::getInst().process( + p_id, p_index, p_format, p_text, this, + [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { + emit graphRenderDataReady(id, timeStamp, format, data); + }); + } else { + Q_ASSERT(false); + } +} + +void MarkdownViewerAdapter::highlightCodeBlock(int p_idx, quint64 p_timeStamp, + const QString &p_text) { + if (isReady()) { + emit highlightCodeBlockRequested(p_idx, p_timeStamp, p_text); + } else { + pendAction( + std::bind(&MarkdownViewerAdapter::highlightCodeBlock, this, p_idx, p_timeStamp, p_text)); + } +} + +void MarkdownViewerAdapter::setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles) { + QVector ruleStyles; + ruleStyles.reserve(p_styles.size()); + for (int i = 0; i < p_styles.size(); ++i) { + ruleStyles.push_back(CssRuleStyle::fromJson(p_styles[i].toObject())); + } + + invokeCallback(p_id, &ruleStyles); +} + +void MarkdownViewerAdapter::fetchStylesFromStyleSheet( + const QString &p_styleSheet, + const std::function *)> &p_callback) { + if (p_styleSheet.isEmpty()) { + p_callback(nullptr); + return; + } + + if (isReady()) { + const quint64 id = addCallback([p_callback](void *data) { + p_callback(reinterpret_cast *>(data)); + }); + emit parseStyleSheetRequested(id, p_styleSheet); + } else { + pendAction(std::bind(&MarkdownViewerAdapter::fetchStylesFromStyleSheet, this, p_styleSheet, + p_callback)); + } } diff --git a/src/widgets/editors/markdownvieweradapter.h b/src/widgets/editors/markdownvieweradapter.h index 63f101da32..0e8095d5f6 100644 --- a/src/widgets/editors/markdownvieweradapter.h +++ b/src/widgets/editors/markdownvieweradapter.h @@ -3,267 +3,236 @@ #include "webviewadapter.h" -#include +#include #include #include -#include +#include #include #include -namespace vnotex -{ - // Adapter and interface between CPP and JS. - class MarkdownViewerAdapter : public WebViewAdapter - { - Q_OBJECT - public: - struct Position - { - Position() = default; +namespace vnotex { +// Adapter and interface between CPP and JS. +class MarkdownViewerAdapter : public WebViewAdapter { + Q_OBJECT +public: + struct Position { + Position() = default; - Position(int p_lineNumber, const QString &p_anchor); + Position(int p_lineNumber, const QString &p_anchor); - QJsonObject toJson() const; + QJsonObject toJson() const; - int m_lineNumber = -1; + int m_lineNumber = -1; - QString m_anchor; - }; + QString m_anchor; + }; - struct PreviewData - { - PreviewData() = default; + struct PreviewData { + PreviewData() = default; - PreviewData(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QByteArray &p_data, - bool p_needScale); + PreviewData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, + const QByteArray &p_data, bool p_needScale); - quint64 m_id = 0; + quint64 m_id = 0; - quint64 m_timeStamp = 0; + quint64 m_timeStamp = 0; - QString m_format; + QString m_format; - QByteArray m_data; + QByteArray m_data; - bool m_needScale = false; - }; + bool m_needScale = false; + }; - struct Heading - { - Heading() = default; + struct Heading { + Heading() = default; - Heading(const QString &p_name, int p_level, const QString &p_anchor = QString()); + Heading(const QString &p_name, int p_level, const QString &p_anchor = QString()); - static Heading fromJson(const QJsonObject &p_obj); + static Heading fromJson(const QJsonObject &p_obj); - QString m_name; + QString m_name; - int m_level = -1; + int m_level = -1; - QString m_anchor; - }; + QString m_anchor; + }; - struct CssRuleStyle - { - QTextCharFormat toTextCharFormat() const; + struct CssRuleStyle { + QTextCharFormat toTextCharFormat() const; - static CssRuleStyle fromJson(const QJsonObject &p_obj); + static CssRuleStyle fromJson(const QJsonObject &p_obj); - QString m_selector; + QString m_selector; - QString m_color; + QString m_color; - QString m_backgroundColor; + QString m_backgroundColor; - QString m_fontWeight; + QString m_fontWeight; - QString m_fontStyle; - }; + QString m_fontStyle; + }; - explicit MarkdownViewerAdapter(QObject *p_parent = nullptr); + explicit MarkdownViewerAdapter(QObject *p_parent = nullptr); - virtual ~MarkdownViewerAdapter(); + virtual ~MarkdownViewerAdapter(); - // @p_lineNumber: the line number needed to sync, -1 for invalid. - void setText(int p_revision, - const QString &p_text, - int p_lineNumber); + // @p_lineNumber: the line number needed to sync, -1 for invalid. + void setText(int p_revision, const QString &p_text, int p_lineNumber); - // @p_lineNumber: the line number needed to sync, -1 for invalid. - void setText(const QString &p_text, int p_lineNumber = -1); + // @p_lineNumber: the line number needed to sync, -1 for invalid. + void setText(const QString &p_text, int p_lineNumber = -1); - void scrollToPosition(const Position &p_pos); + void scrollToPosition(const Position &p_pos); - int getTopLineNumber() const; + int getTopLineNumber() const; - const QVector &getHeadings() const; - int getCurrentHeadingIndex() const; + const QVector &getHeadings() const; + int getCurrentHeadingIndex() const; - void scrollToHeading(int p_idx); + void scrollToHeading(int p_idx); - void scroll(bool p_up); + void scroll(bool p_up); - const QStringList &getCrossCopyTargets() const; + const QStringList &getCrossCopyTargets() const; - QString getCrossCopyTargetDisplayName(const QString &p_target) const; + QString getCrossCopyTargetDisplayName(const QString &p_target) const; - void saveContent(); + void saveContent(); - // Should be called before WebViewer.setHtml(). - void reset(); + // Should be called before WebViewer.setHtml(). + void reset(); - void highlightCodeBlock(int p_idx, quint64 p_timeStamp, const QString &p_text); + void highlightCodeBlock(int p_idx, quint64 p_timeStamp, const QString &p_text); - // Parse style sheet and fetch the styles. - void fetchStylesFromStyleSheet(const QString &p_styleSheet, - const std::function *)> &p_callback); + // Parse style sheet and fetch the styles. + void + fetchStylesFromStyleSheet(const QString &p_styleSheet, + const std::function *)> &p_callback); - // Functions to be called from web side. - public slots: - void setWorkFinished(); + // Functions to be called from web side. +public slots: + void setWorkFinished(); - // The line number at the top. - void setTopLineNumber(int p_lineNumber); + // The line number at the top. + void setTopLineNumber(int p_lineNumber); - // Web sets back the preview result. - void setGraphPreviewData(quint64 p_id, - quint64 p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_base64 = false, - bool p_needScale = false); + // Web sets back the preview result. + void setGraphPreviewData(quint64 p_id, quint64 p_timeStamp, const QString &p_format, + const QString &p_data, bool p_base64 = false, bool p_needScale = false); - // Web sets back the preview result. - void setMathPreviewData(quint64 p_id, - quint64 p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_base64 = false, - bool p_needScale = false); + // Web sets back the preview result. + void setMathPreviewData(quint64 p_id, quint64 p_timeStamp, const QString &p_format, + const QString &p_data, bool p_base64 = false, bool p_needScale = false); - // Set the headings. - void setHeadings(const QJsonArray &p_headings); + // Set the headings. + void setHeadings(const QJsonArray &p_headings); - // Set current heading anchor. - void setCurrentHeadingAnchor(int p_index, const QString &p_anchor); + // Set current heading anchor. + void setCurrentHeadingAnchor(int p_index, const QString &p_anchor); - void setKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta); + void setKeyPress(int p_key, bool p_ctrl, bool p_shift, bool p_meta); - void zoom(bool p_zoomIn); + void zoom(bool p_zoomIn); - // Set back the result of htmlToMarkdown() call. - void setMarkdownFromHtml(quint64 p_id, quint64 p_timeStamp, const QString &p_text); + // Set back the result of htmlToMarkdown() call. + void setMarkdownFromHtml(quint64 p_id, quint64 p_timeStamp, const QString &p_text); - void setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, const QString &p_html); + void setCodeBlockHighlightHtml(int p_idx, quint64 p_timeStamp, const QString &p_html); - void setCrossCopyTargets(const QJsonArray &p_targets); + void setCrossCopyTargets(const QJsonArray &p_targets); - void setCrossCopyResult(quint64 p_id, quint64 p_timeStamp, const QString &p_html); + void setCrossCopyResult(quint64 p_id, quint64 p_timeStamp, const QString &p_html); - void setSavedContent(const QString &p_headContent, const QString &p_styleContent, const QString &p_content, const QString &p_bodyClassList); + void setSavedContent(const QString &p_headContent, const QString &p_styleContent, + const QString &p_content, const QString &p_bodyClassList); - // Call local CPP code to render graph. - void renderGraph(quint64 p_id, - quint64 p_index, - const QString &p_format, - const QString &p_lang, - const QString &p_text); + // Call local CPP code to render graph. + void renderGraph(quint64 p_id, quint64 p_index, const QString &p_format, const QString &p_lang, + const QString &p_text); - void setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles); + void setStyleSheetStyles(quint64 p_id, const QJsonArray &p_styles); - // Signals to be connected at web side. - signals: - // Current Markdown text is updated. - void textUpdated(const QString &p_text); + // Signals to be connected at web side. +signals: + // Current Markdown text is updated. + void textUpdated(const QString &p_text); - // Current editor line number is updated. - void editLineNumberUpdated(int p_lineNumber); + // Current editor line number is updated. + void editLineNumberUpdated(int p_lineNumber); - // Request to preview graph. - void graphPreviewRequested(quint64 p_id, - quint64 p_timeStamp, - const QString &p_lang, - const QString &p_text); + // Request to preview graph. + void graphPreviewRequested(quint64 p_id, quint64 p_timeStamp, const QString &p_lang, + const QString &p_text); - // Request to preview math. - void mathPreviewRequested(quint64 p_id, - quint64 p_timeStamp, - const QString &p_text); + // Request to preview math. + void mathPreviewRequested(quint64 p_id, quint64 p_timeStamp, const QString &p_text); - void anchorScrollRequested(const QString &p_anchor); + void anchorScrollRequested(const QString &p_anchor); - void scrollRequested(bool p_up); + void scrollRequested(bool p_up); - void htmlToMarkdownRequested(quint64 p_id, quint64 p_timeStamp, const QString &p_html); + void htmlToMarkdownRequested(quint64 p_id, quint64 p_timeStamp, const QString &p_html); - void crossCopyRequested(quint64 p_id, - quint64 p_timeStamp, - const QString &p_target, - const QString &p_baseUrl, - const QString &p_html); + void crossCopyRequested(quint64 p_id, quint64 p_timeStamp, const QString &p_target, + const QString &p_baseUrl, const QString &p_html); - // Request to get the whole HTML content. - void contentRequested(); + // Request to get the whole HTML content. + void contentRequested(); - void graphRenderDataReady(quint64 p_id, - quint64 p_index, - const QString &p_format, - const QString &p_data); + void graphRenderDataReady(quint64 p_id, quint64 p_index, const QString &p_format, + const QString &p_data); - void highlightCodeBlockRequested(int p_idx, quint64 p_timeStamp, const QString &p_text); + void highlightCodeBlockRequested(int p_idx, quint64 p_timeStamp, const QString &p_text); - void parseStyleSheetRequested(quint64 p_id, const QString &p_styleSheet); + void parseStyleSheetRequested(quint64 p_id, const QString &p_styleSheet); - // Signals to be connected at cpp side. - signals: - void graphPreviewDataReady(const PreviewData &p_data); + // Signals to be connected at cpp side. +signals: + void graphPreviewDataReady(const PreviewData &p_data); - void mathPreviewDataReady(const PreviewData &p_data); + void mathPreviewDataReady(const PreviewData &p_data); - // All rendering work has finished. - void workFinished(); + // All rendering work has finished. + void workFinished(); - void headingsChanged(); + void headingsChanged(); - void currentHeadingChanged(); + void currentHeadingChanged(); - void keyPressed(int p_key, bool p_ctrl, bool p_shift, bool p_meta); + void keyPressed(int p_key, bool p_ctrl, bool p_shift, bool p_meta); - void zoomed(bool p_zoomIn); + void zoomed(bool p_zoomIn); - void htmlToMarkdownReady(quint64 p_id, quint64 p_timeStamp, const QString &p_text); + void htmlToMarkdownReady(quint64 p_id, quint64 p_timeStamp, const QString &p_text); - void crossCopyReady(quint64 p_id, quint64 p_timeStamp, const QString &p_html); + void crossCopyReady(quint64 p_id, quint64 p_timeStamp, const QString &p_html); - void contentReady(const QString &p_headContent, - const QString &p_styleContent, - const QString &p_content, - const QString &p_bodyClassList); + void contentReady(const QString &p_headContent, const QString &p_styleContent, + const QString &p_content, const QString &p_bodyClassList); - void highlightCodeBlockReady(int p_idx, quint64 p_timeStamp, const QString &p_html); + void highlightCodeBlockReady(int p_idx, quint64 p_timeStamp, const QString &p_html); - private: - void scrollToLine(int p_lineNumber); +private: + void scrollToLine(int p_lineNumber); - void scrollToAnchor(const QString &p_anchor); + void scrollToAnchor(const QString &p_anchor); - int m_revision = 0; + int m_revision = 0; - // Source line number of the top element node at web side. - int m_topLineNumber = -1; + // Source line number of the top element node at web side. + int m_topLineNumber = -1; - // Headings from web side. - QVector m_headings; + // Headings from web side. + QVector m_headings; - int m_currentHeadingIndex = -1; + int m_currentHeadingIndex = -1; - // Targets supported by cross copy. Set by web. - QStringList m_crossCopyTargets; - }; -} + // Targets supported by cross copy. Set by web. + QStringList m_crossCopyTargets; +}; +} // namespace vnotex #endif // MARKDOWNVIEWERADAPTER_H diff --git a/src/widgets/editors/mindmapeditor.cpp b/src/widgets/editors/mindmapeditor.cpp index 33c587d9f0..37a3a8a9fa 100644 --- a/src/widgets/editors/mindmapeditor.cpp +++ b/src/widgets/editors/mindmapeditor.cpp @@ -6,39 +6,25 @@ using namespace vnotex; -MindMapEditor::MindMapEditor(MindMapEditorAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent) - : WebViewer(p_background, p_zoomFactor, p_parent), - m_adapter(p_adapter) -{ - setAcceptDrops(true); - - m_adapter->setParent(this); - connect(m_adapter, &MindMapEditorAdapter::contentsChanged, - this, [this]() { - m_modified = true; - emit contentsChanged(); - }); - - auto channel = new QWebChannel(this); - channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); - - page()->setWebChannel(channel); -} +MindMapEditor::MindMapEditor(MindMapEditorAdapter *p_adapter, const QColor &p_background, + qreal p_zoomFactor, QWidget *p_parent) + : WebViewer(p_background, p_zoomFactor, p_parent), m_adapter(p_adapter) { + setAcceptDrops(true); -MindMapEditorAdapter *MindMapEditor::adapter() const -{ - return m_adapter; -} + m_adapter->setParent(this); + connect(m_adapter, &MindMapEditorAdapter::contentsChanged, this, [this]() { + m_modified = true; + emit contentsChanged(); + }); -void MindMapEditor::setModified(bool p_modified) -{ - m_modified = p_modified; -} + auto channel = new QWebChannel(this); + channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); -bool MindMapEditor::isModified() const -{ - return m_modified; + page()->setWebChannel(channel); } + +MindMapEditorAdapter *MindMapEditor::adapter() const { return m_adapter; } + +void MindMapEditor::setModified(bool p_modified) { m_modified = p_modified; } + +bool MindMapEditor::isModified() const { return m_modified; } diff --git a/src/widgets/editors/mindmapeditor.h b/src/widgets/editors/mindmapeditor.h index 1b255a7348..bf554d4599 100644 --- a/src/widgets/editors/mindmapeditor.h +++ b/src/widgets/editors/mindmapeditor.h @@ -3,33 +3,29 @@ #include "../webviewer.h" -namespace vnotex -{ - class MindMapEditorAdapter; - - class MindMapEditor : public WebViewer - { - Q_OBJECT - public: - MindMapEditor(MindMapEditorAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent = nullptr); - - MindMapEditorAdapter *adapter() const; - - void setModified(bool p_modified); - bool isModified() const; - - signals: - void contentsChanged(); - - private: - // Managed by QObject. - MindMapEditorAdapter *m_adapter = nullptr; - - bool m_modified = false; - }; -} +namespace vnotex { +class MindMapEditorAdapter; + +class MindMapEditor : public WebViewer { + Q_OBJECT +public: + MindMapEditor(MindMapEditorAdapter *p_adapter, const QColor &p_background, qreal p_zoomFactor, + QWidget *p_parent = nullptr); + + MindMapEditorAdapter *adapter() const; + + void setModified(bool p_modified); + bool isModified() const; + +signals: + void contentsChanged(); + +private: + // Managed by QObject. + MindMapEditorAdapter *m_adapter = nullptr; + + bool m_modified = false; +}; +} // namespace vnotex #endif // MINDMAPEDITOR_H diff --git a/src/widgets/editors/mindmapeditoradapter.cpp b/src/widgets/editors/mindmapeditoradapter.cpp index 551bdd1274..0a3a775f17 100644 --- a/src/widgets/editors/mindmapeditoradapter.cpp +++ b/src/widgets/editors/mindmapeditoradapter.cpp @@ -2,63 +2,55 @@ using namespace vnotex; -MindMapEditorAdapter::MindMapEditorAdapter(QObject *p_parent) - : WebViewAdapter(p_parent) -{ - qDebug() << "MindMapEditorAdapter: Constructor called"; +MindMapEditorAdapter::MindMapEditorAdapter(QObject *p_parent) : WebViewAdapter(p_parent) { + qDebug() << "MindMapEditorAdapter: Constructor called"; } -void MindMapEditorAdapter::setData(const QString &p_data) -{ - if (isReady()) { - emit dataUpdated(p_data); - } else { - pendAction(std::bind(&MindMapEditorAdapter::setData, this, p_data)); - } +void MindMapEditorAdapter::setData(const QString &p_data) { + if (isReady()) { + emit dataUpdated(p_data); + } else { + pendAction(std::bind(&MindMapEditorAdapter::setData, this, p_data)); + } } -void MindMapEditorAdapter::saveData(const std::function &p_callback) -{ - if (isReady()) { - const quint64 id = addCallback([p_callback](void *data) { - p_callback(*reinterpret_cast(data)); - }); - emit saveDataRequested(id); - } else { - pendAction(std::bind(&MindMapEditorAdapter::saveData, this, p_callback)); - } +void MindMapEditorAdapter::saveData(const std::function &p_callback) { + if (isReady()) { + const quint64 id = addCallback( + [p_callback](void *data) { p_callback(*reinterpret_cast(data)); }); + emit saveDataRequested(id); + } else { + pendAction(std::bind(&MindMapEditorAdapter::saveData, this, p_callback)); + } } -void MindMapEditorAdapter::setSavedData(quint64 p_id, const QString &p_data) -{ - invokeCallback(p_id, (void *)&p_data); +void MindMapEditorAdapter::setSavedData(quint64 p_id, const QString &p_data) { + invokeCallback(p_id, (void *)&p_data); } -void MindMapEditorAdapter::notifyContentsChanged() -{ - emit contentsChanged(); -} +void MindMapEditorAdapter::notifyContentsChanged() { emit contentsChanged(); } + +void MindMapEditorAdapter::urlClicked(const QString &p_url) { + if (p_url.isEmpty()) { + qWarning() << "MindMapEditorAdapter::urlClicked: URL is empty"; + return; + } -void MindMapEditorAdapter::urlClicked(const QString &p_url) -{ - if (p_url.isEmpty()) { - qWarning() << "MindMapEditorAdapter::urlClicked: URL is empty"; - return; - } + qDebug() << "MindMapEditorAdapter::urlClicked: Emitting urlClickRequested signal with URL:" + << p_url; - qDebug() << "MindMapEditorAdapter::urlClicked: Emitting urlClickRequested signal with URL:" << p_url; - - emit urlClickRequested(p_url); + emit urlClickRequested(p_url); } -void MindMapEditorAdapter::urlClickedWithDirection(const QString &p_url, const QString &p_direction) -{ - if (p_url.isEmpty()) { - qWarning() << "MindMapEditorAdapter::urlClickedWithDirection: URL is empty"; - return; - } +void MindMapEditorAdapter::urlClickedWithDirection(const QString &p_url, + const QString &p_direction) { + if (p_url.isEmpty()) { + qWarning() << "MindMapEditorAdapter::urlClickedWithDirection: URL is empty"; + return; + } + + qDebug() << "MindMapEditorAdapter::urlClickedWithDirection: URL:" << p_url + << "Direction:" << p_direction; - qDebug() << "MindMapEditorAdapter::urlClickedWithDirection: URL:" << p_url << "Direction:" << p_direction; - - emit urlClickWithDirectionRequested(p_url, p_direction); + emit urlClickWithDirectionRequested(p_url, p_direction); } diff --git a/src/widgets/editors/mindmapeditoradapter.h b/src/widgets/editors/mindmapeditoradapter.h index 4938ae2acd..0723df8e06 100644 --- a/src/widgets/editors/mindmapeditoradapter.h +++ b/src/widgets/editors/mindmapeditoradapter.h @@ -3,55 +3,53 @@ #include "webviewadapter.h" -#include #include +#include #include -namespace vnotex -{ - // Adapter and interface between CPP and JS for MindMap. - class MindMapEditorAdapter : public WebViewAdapter - { - Q_OBJECT - public: - explicit MindMapEditorAdapter(QObject *p_parent = nullptr); +namespace vnotex { +// Adapter and interface between CPP and JS for MindMap. +class MindMapEditorAdapter : public WebViewAdapter { + Q_OBJECT +public: + explicit MindMapEditorAdapter(QObject *p_parent = nullptr); - ~MindMapEditorAdapter() = default; + ~MindMapEditorAdapter() = default; - void setData(const QString &p_data); + void setData(const QString &p_data); - void saveData(const std::function &p_callback); + void saveData(const std::function &p_callback); - // Functions to be called from web side. - public slots: - void setSavedData(quint64 p_id, const QString &p_data); + // Functions to be called from web side. +public slots: + void setSavedData(quint64 p_id, const QString &p_data); - void notifyContentsChanged(); + void notifyContentsChanged(); - // 处理来自JavaScript的URL点击事件 - void urlClicked(const QString &p_url); + // 处理来自JavaScript的URL点击事件 + void urlClicked(const QString &p_url); - // 处理来自JavaScript的带方向的URL点击事件 - void urlClickedWithDirection(const QString &p_url, const QString &p_direction); + // 处理来自JavaScript的带方向的URL点击事件 + void urlClickedWithDirection(const QString &p_url, const QString &p_direction); - // Signals to be connected at web side. - signals: - void dataUpdated(const QString& p_data); + // Signals to be connected at web side. +signals: + void dataUpdated(const QString &p_data); - void saveDataRequested(quint64 p_id); + void saveDataRequested(quint64 p_id); - signals: - void contentsChanged(); +signals: + void contentsChanged(); - // 发出URL点击信号,供其他组件处理 - void urlClickRequested(const QString &p_url); + // 发出URL点击信号,供其他组件处理 + void urlClickRequested(const QString &p_url); - // 发出带方向的URL点击信号 - void urlClickWithDirectionRequested(const QString &p_url, const QString &p_direction); + // 发出带方向的URL点击信号 + void urlClickWithDirectionRequested(const QString &p_url, const QString &p_direction); - private: - }; -} +private: +}; +} // namespace vnotex #endif // MINDMAPEDITORADAPTER_H diff --git a/src/widgets/editors/pdfviewer.cpp b/src/widgets/editors/pdfviewer.cpp index cae889159c..682be2d93e 100644 --- a/src/widgets/editors/pdfviewer.cpp +++ b/src/widgets/editors/pdfviewer.cpp @@ -6,22 +6,15 @@ using namespace vnotex; -PdfViewer::PdfViewer(PdfViewerAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, +PdfViewer::PdfViewer(PdfViewerAdapter *p_adapter, const QColor &p_background, qreal p_zoomFactor, QWidget *p_parent) - : WebViewer(p_background, p_zoomFactor, p_parent), - m_adapter(p_adapter) -{ - m_adapter->setParent(this); + : WebViewer(p_background, p_zoomFactor, p_parent), m_adapter(p_adapter) { + m_adapter->setParent(this); - auto channel = new QWebChannel(this); - channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); + auto channel = new QWebChannel(this); + channel->registerObject(QStringLiteral("vxAdapter"), m_adapter); - page()->setWebChannel(channel); + page()->setWebChannel(channel); } -PdfViewerAdapter *PdfViewer::adapter() const -{ - return m_adapter; -} +PdfViewerAdapter *PdfViewer::adapter() const { return m_adapter; } diff --git a/src/widgets/editors/pdfviewer.h b/src/widgets/editors/pdfviewer.h index 789518f4a1..dfa0a33238 100644 --- a/src/widgets/editors/pdfviewer.h +++ b/src/widgets/editors/pdfviewer.h @@ -3,25 +3,21 @@ #include "../webviewer.h" -namespace vnotex -{ - class PdfViewerAdapter; +namespace vnotex { +class PdfViewerAdapter; - class PdfViewer : public WebViewer - { - Q_OBJECT - public: - PdfViewer(PdfViewerAdapter *p_adapter, - const QColor &p_background, - qreal p_zoomFactor, - QWidget *p_parent = nullptr); +class PdfViewer : public WebViewer { + Q_OBJECT +public: + PdfViewer(PdfViewerAdapter *p_adapter, const QColor &p_background, qreal p_zoomFactor, + QWidget *p_parent = nullptr); - PdfViewerAdapter *adapter() const; + PdfViewerAdapter *adapter() const; - private: - // Managed by QObject. - PdfViewerAdapter *m_adapter = nullptr; - }; -} +private: + // Managed by QObject. + PdfViewerAdapter *m_adapter = nullptr; +}; +} // namespace vnotex #endif // PDFVIEWER_H diff --git a/src/widgets/editors/pdfvieweradapter.cpp b/src/widgets/editors/pdfvieweradapter.cpp index 606fe2cb67..18e1195cce 100644 --- a/src/widgets/editors/pdfvieweradapter.cpp +++ b/src/widgets/editors/pdfvieweradapter.cpp @@ -2,18 +2,14 @@ using namespace vnotex; -PdfViewerAdapter::PdfViewerAdapter(QObject *p_parent) - : WebViewAdapter(p_parent) -{ -} +PdfViewerAdapter::PdfViewerAdapter(QObject *p_parent) : WebViewAdapter(p_parent) {} -void PdfViewerAdapter::setUrl(const QString &p_url) -{ - // TODO: Not supported yet. - Q_ASSERT(false); - if (isReady()) { - emit urlUpdated(p_url); - } else { - pendAction(std::bind(&PdfViewerAdapter::setUrl, this, p_url)); - } +void PdfViewerAdapter::setUrl(const QString &p_url) { + // TODO: Not supported yet. + Q_ASSERT(false); + if (isReady()) { + emit urlUpdated(p_url); + } else { + pendAction(std::bind(&PdfViewerAdapter::setUrl, this, p_url)); + } } diff --git a/src/widgets/editors/pdfvieweradapter.h b/src/widgets/editors/pdfvieweradapter.h index cf198e89a0..83e369897c 100644 --- a/src/widgets/editors/pdfvieweradapter.h +++ b/src/widgets/editors/pdfvieweradapter.h @@ -3,26 +3,24 @@ #include "webviewadapter.h" -namespace vnotex -{ - // Adapter and interface between CPP and JS for PDF. - class PdfViewerAdapter : public WebViewAdapter - { - Q_OBJECT - public: - explicit PdfViewerAdapter(QObject *p_parent = nullptr); +namespace vnotex { +// Adapter and interface between CPP and JS for PDF. +class PdfViewerAdapter : public WebViewAdapter { + Q_OBJECT +public: + explicit PdfViewerAdapter(QObject *p_parent = nullptr); - ~PdfViewerAdapter() = default; + ~PdfViewerAdapter() = default; - void setUrl(const QString &p_url); + void setUrl(const QString &p_url); - // Functions to be called from web side. - public slots: + // Functions to be called from web side. +public slots: - // Signals to be connected at web side. - signals: - void urlUpdated(const QString &p_url); - }; -} + // Signals to be connected at web side. +signals: + void urlUpdated(const QString &p_url); +}; +} // namespace vnotex #endif // PDFVIEWERADAPTER_H diff --git a/src/widgets/editors/plantumlhelper.cpp b/src/widgets/editors/plantumlhelper.cpp index 1de3b09c25..25b1ca3244 100644 --- a/src/widgets/editors/plantumlhelper.cpp +++ b/src/widgets/editors/plantumlhelper.cpp @@ -3,109 +3,98 @@ #include #include -#include -#include #include #include #include +#include +#include using namespace vnotex; -PlantUmlHelper &PlantUmlHelper::getInst() -{ - static bool initialized = false; - static PlantUmlHelper inst; - if (!initialized) { - initialized = true; - const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); - inst.update(markdownEditorConfig.getPlantUmlJar(), - markdownEditorConfig.getGraphvizExe(), - markdownEditorConfig.getPlantUmlCommand()); - } - return inst; +PlantUmlHelper &PlantUmlHelper::getInst() { + static bool initialized = false; + static PlantUmlHelper inst; + if (!initialized) { + initialized = true; + const auto &markdownEditorConfig = + ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig(); + inst.update(markdownEditorConfig.getPlantUmlJar(), markdownEditorConfig.getGraphvizExe(), + markdownEditorConfig.getPlantUmlCommand()); + } + return inst; } -void PlantUmlHelper::update(const QString &p_plantUmlJarFile, - const QString &p_graphvizFile, - const QString &p_overriddenCommand) -{ - m_overriddenCommand = p_overriddenCommand; - if (m_overriddenCommand.isEmpty()) { - prepareProgramAndArgs(p_plantUmlJarFile, p_graphvizFile, m_program, m_args); - } else { - m_program.clear(); - m_args.clear(); - } - - checkValidProgram(); - - clearCache(); +void PlantUmlHelper::update(const QString &p_plantUmlJarFile, const QString &p_graphvizFile, + const QString &p_overriddenCommand) { + m_overriddenCommand = p_overriddenCommand; + if (m_overriddenCommand.isEmpty()) { + prepareProgramAndArgs(p_plantUmlJarFile, p_graphvizFile, m_program, m_args); + } else { + m_program.clear(); + m_args.clear(); + } + + checkValidProgram(); + + clearCache(); } void PlantUmlHelper::prepareProgramAndArgs(const QString &p_plantUmlJarFile, - const QString &p_graphvizFile, - QString &p_program, - QStringList &p_args) -{ - p_program.clear(); - p_args.clear(); + const QString &p_graphvizFile, QString &p_program, + QStringList &p_args) { + p_program.clear(); + p_args.clear(); #if defined(Q_OS_WIN) - p_program = "java"; + p_program = "java"; #else - p_program = "/bin/sh"; - p_args << "-c"; - p_args << "java"; + p_program = "/bin/sh"; + p_args << "-c"; + p_args << "java"; #endif #if defined(Q_OS_MACOS) - p_args << "-Djava.awt.headless=true"; + p_args << "-Djava.awt.headless=true"; #endif - p_args << "-jar" << QDir::toNativeSeparators(PathUtils::absolutePath(p_plantUmlJarFile)); + p_args << "-jar" << QDir::toNativeSeparators(PathUtils::absolutePath(p_plantUmlJarFile)); - p_args << "-charset" << "UTF-8"; + p_args << "-charset" << "UTF-8"; - if (!p_graphvizFile.isEmpty()) { - p_args << "-graphvizdot" << QDir::toNativeSeparators(PathUtils::absolutePath(p_graphvizFile)); - } + if (!p_graphvizFile.isEmpty()) { + p_args << "-graphvizdot" << QDir::toNativeSeparators(PathUtils::absolutePath(p_graphvizFile)); + } - p_args << "-pipe"; + p_args << "-pipe"; } -QPair PlantUmlHelper::testPlantUml(const QString &p_plantUmlJarFile) -{ - auto ret = qMakePair(false, QString()); +QPair PlantUmlHelper::testPlantUml(const QString &p_plantUmlJarFile) { + auto ret = qMakePair(false, QString()); - QString program; - QStringList args; - prepareProgramAndArgs(p_plantUmlJarFile, QString(), program, args); + QString program; + QStringList args; + prepareProgramAndArgs(p_plantUmlJarFile, QString(), program, args); - args << "-tsvg"; - args = getArgsToUse(args); + args << "-tsvg"; + args = getArgsToUse(args); - const QString testGraph("VNote->Markdown : Hello"); + const QString testGraph("VNote->Markdown : Hello"); - int exitCode = -1; - QByteArray outData; - QByteArray errData; - auto state = ProcessUtils::start(program, - args, - testGraph.toUtf8(), - exitCode, - outData, - errData); - ret.first = (state == ProcessUtils::Succeeded) && (exitCode == 0); + int exitCode = -1; + QByteArray outData; + QByteArray errData; + auto state = ProcessUtils::start(program, args, testGraph.toUtf8(), exitCode, outData, errData); + ret.first = (state == ProcessUtils::Succeeded) && (exitCode == 0); - ret.second = QStringLiteral("%1 %2\n\nExitcode: %3\n\nOutput: %4\n\nError: %5") - .arg(program, args.join(' '), QString::number(exitCode), QString::fromLocal8Bit(outData), QString::fromLocal8Bit(errData)); + ret.second = QStringLiteral("%1 %2\n\nExitcode: %3\n\nOutput: %4\n\nError: %5") + .arg(program, args.join(' '), QString::number(exitCode), + QString::fromLocal8Bit(outData), QString::fromLocal8Bit(errData)); - return ret; + return ret; } -QStringList PlantUmlHelper::getFormatArgs(const QString &p_format) -{ - QStringList args; - args << ("-t" + p_format); - return args; +QStringList PlantUmlHelper::getFormatArgs(const QString &p_format) { + QStringList args; + args << ("-t" + p_format); + return args; } diff --git a/src/widgets/editors/plantumlhelper.h b/src/widgets/editors/plantumlhelper.h index de7dba5066..94a9cb3b40 100644 --- a/src/widgets/editors/plantumlhelper.h +++ b/src/widgets/editors/plantumlhelper.h @@ -3,29 +3,24 @@ #include "graphhelper.h" -namespace vnotex -{ - class PlantUmlHelper : public GraphHelper - { - public: - void update(const QString &p_plantUmlJarFile, - const QString &p_graphvizFile, - const QString &p_overriddenCommand); - - static PlantUmlHelper &getInst(); - - static QPair testPlantUml(const QString &p_plantUmlJarFile); - - private: - PlantUmlHelper() = default; - - QStringList getFormatArgs(const QString &p_format) Q_DECL_OVERRIDE; - - static void prepareProgramAndArgs(const QString &p_plantUmlJarFile, - const QString &p_graphvizFile, - QString &p_program, - QStringList &p_args); - }; -} +namespace vnotex { +class PlantUmlHelper : public GraphHelper { +public: + void update(const QString &p_plantUmlJarFile, const QString &p_graphvizFile, + const QString &p_overriddenCommand); + + static PlantUmlHelper &getInst(); + + static QPair testPlantUml(const QString &p_plantUmlJarFile); + +private: + PlantUmlHelper() = default; + + QStringList getFormatArgs(const QString &p_format) Q_DECL_OVERRIDE; + + static void prepareProgramAndArgs(const QString &p_plantUmlJarFile, const QString &p_graphvizFile, + QString &p_program, QStringList &p_args); +}; +} // namespace vnotex #endif // PLANTUMLHELPER_H diff --git a/src/widgets/editors/previewhelper.cpp b/src/widgets/editors/previewhelper.cpp index 44e10a5313..8738bc1fbe 100644 --- a/src/widgets/editors/previewhelper.cpp +++ b/src/widgets/editors/previewhelper.cpp @@ -1,8 +1,8 @@ #include "previewhelper.h" #include -#include #include +#include #include #include @@ -10,537 +10,468 @@ #include +#include "graphvizhelper.h" #include "markdowneditor.h" #include "plantumlhelper.h" -#include "graphvizhelper.h" using namespace vnotex; -PreviewHelper::CodeBlockPreviewData::CodeBlockPreviewData(const vte::peg::FencedCodeBlock &p_codeBlock) - : m_startBlock(p_codeBlock.m_startBlock), - m_endBlock(p_codeBlock.m_endBlock), - m_lang(p_codeBlock.m_lang) -{ -} +PreviewHelper::CodeBlockPreviewData::CodeBlockPreviewData( + const vte::peg::FencedCodeBlock &p_codeBlock) + : m_startBlock(p_codeBlock.m_startBlock), m_endBlock(p_codeBlock.m_endBlock), + m_lang(p_codeBlock.m_lang) {} void PreviewHelper::CodeBlockPreviewData::updateInplacePreview(QTextDocument *p_doc, const QPixmap &p_image, const QString &p_imageName, QRgb p_background, - int p_tabStopWidth) -{ - const auto block = p_doc->findBlockByNumber(m_endBlock); - if (block.isValid()) { - m_inplacePreview.reset(new vte::PreviewItem()); - m_inplacePreview->m_startPos = block.position(); - m_inplacePreview->m_endPos = m_inplacePreview->m_startPos + block.length(); - m_inplacePreview->m_blockPos = m_inplacePreview->m_startPos; - m_inplacePreview->m_blockNumber = m_endBlock; - m_inplacePreview->m_padding = vte::PreviewMgr::calculateBlockMargin(block, p_tabStopWidth); - m_inplacePreview->m_name = p_imageName; - m_inplacePreview->m_backgroundColor = p_background; - m_inplacePreview->m_isBlockwise = true; - m_inplacePreview->m_image = p_image; - } else { - m_inplacePreview.clear(); - } + int p_tabStopWidth) { + const auto block = p_doc->findBlockByNumber(m_endBlock); + if (block.isValid()) { + m_inplacePreview.reset(new vte::PreviewItem()); + m_inplacePreview->m_startPos = block.position(); + m_inplacePreview->m_endPos = m_inplacePreview->m_startPos + block.length(); + m_inplacePreview->m_blockPos = m_inplacePreview->m_startPos; + m_inplacePreview->m_blockNumber = m_endBlock; + m_inplacePreview->m_padding = vte::PreviewMgr::calculateBlockMargin(block, p_tabStopWidth); + m_inplacePreview->m_name = p_imageName; + m_inplacePreview->m_backgroundColor = p_background; + m_inplacePreview->m_isBlockwise = true; + m_inplacePreview->m_image = p_image; + } else { + m_inplacePreview.clear(); + } } PreviewHelper::MathBlockPreviewData::MathBlockPreviewData(const vte::peg::MathBlock &p_mathBlock) - : m_blockNumber(p_mathBlock.m_blockNumber), - m_previewedAsBlock(p_mathBlock.m_previewedAsBlock), - m_index(p_mathBlock.m_index), - m_length(p_mathBlock.m_length) -{ -} + : m_blockNumber(p_mathBlock.m_blockNumber), m_previewedAsBlock(p_mathBlock.m_previewedAsBlock), + m_index(p_mathBlock.m_index), m_length(p_mathBlock.m_length) {} void PreviewHelper::MathBlockPreviewData::updateInplacePreview(QTextDocument *p_doc, const QPixmap &p_image, const QString &p_imageName, - int p_tabStopWidth) -{ - const auto block = p_doc->findBlockByNumber(m_blockNumber); - if (block.isValid()) { - m_inplacePreview.reset(new vte::PreviewItem()); - m_inplacePreview->m_startPos = block.position() + m_index; - m_inplacePreview->m_endPos = m_inplacePreview->m_startPos + m_length; - m_inplacePreview->m_blockPos = block.position(); - m_inplacePreview->m_blockNumber = m_blockNumber; - m_inplacePreview->m_padding = vte::PreviewMgr::calculateBlockMargin(block, p_tabStopWidth); - m_inplacePreview->m_name = p_imageName; - m_inplacePreview->m_isBlockwise = m_previewedAsBlock; - m_inplacePreview->m_image = p_image; - } else { - m_inplacePreview.clear(); - } + int p_tabStopWidth) { + const auto block = p_doc->findBlockByNumber(m_blockNumber); + if (block.isValid()) { + m_inplacePreview.reset(new vte::PreviewItem()); + m_inplacePreview->m_startPos = block.position() + m_index; + m_inplacePreview->m_endPos = m_inplacePreview->m_startPos + m_length; + m_inplacePreview->m_blockPos = block.position(); + m_inplacePreview->m_blockNumber = m_blockNumber; + m_inplacePreview->m_padding = vte::PreviewMgr::calculateBlockMargin(block, p_tabStopWidth); + m_inplacePreview->m_name = p_imageName; + m_inplacePreview->m_isBlockwise = m_previewedAsBlock; + m_inplacePreview->m_image = p_image; + } else { + m_inplacePreview.clear(); + } } int PreviewHelper::GraphPreviewData::s_imageIndex = 0; -PreviewHelper::GraphPreviewData::GraphPreviewData(TimeStamp p_timeStamp, - const QString &p_format, - const QByteArray &p_data, - QRgb p_background, +PreviewHelper::GraphPreviewData::GraphPreviewData(TimeStamp p_timeStamp, const QString &p_format, + const QByteArray &p_data, QRgb p_background, qreal p_scaleFactor) - : m_timeStamp(p_timeStamp), - m_background(p_background) -{ - if (p_data.isEmpty()) { - return; - } + : m_timeStamp(p_timeStamp), m_background(p_background) { + if (p_data.isEmpty()) { + return; + } + + m_name = QString::number(++s_imageIndex); - m_name = QString::number(++s_imageIndex); - - bool needScale = p_scaleFactor > 1.01; - if (needScale) { - if (p_format == QStringLiteral("svg")) { - m_image = Utils::svgToPixmap(p_data, p_background, p_scaleFactor); - } else { - QPixmap tmpImg; - tmpImg.loadFromData(p_data, p_format.toLocal8Bit().data()); - m_image = tmpImg.scaledToWidth(tmpImg.width() * p_scaleFactor, Qt::SmoothTransformation); - } + bool needScale = p_scaleFactor > 1.01; + if (needScale) { + if (p_format == QStringLiteral("svg")) { + m_image = Utils::svgToPixmap(p_data, p_background, p_scaleFactor); } else { - m_image.loadFromData(p_data, p_format.toLocal8Bit().data()); + QPixmap tmpImg; + tmpImg.loadFromData(p_data, p_format.toLocal8Bit().data()); + m_image = tmpImg.scaledToWidth(tmpImg.width() * p_scaleFactor, Qt::SmoothTransformation); } + } else { + m_image.loadFromData(p_data, p_format.toLocal8Bit().data()); + } } -bool PreviewHelper::GraphPreviewData::isNull() const -{ - return m_timeStamp == 0; -} +bool PreviewHelper::GraphPreviewData::isNull() const { return m_timeStamp == 0; } PreviewHelper::PreviewHelper(MarkdownEditor *p_editor, QObject *p_parent) : QObject(p_parent), - m_inplacePreviewSources(SourceFlag::FlowChart - | SourceFlag::Mermaid - | SourceFlag::WaveDrom - | SourceFlag::PlantUml - | SourceFlag::Graphviz - | SourceFlag::Math), - m_codeBlockCache(100, nullptr), - m_mathBlockCache(100, nullptr) -{ - setMarkdownEditor(p_editor); - - const int interval = 1000; - m_codeBlockTimer = new QTimer(this); - m_codeBlockTimer->setSingleShot(true); - m_codeBlockTimer->setInterval(interval); - connect(m_codeBlockTimer, &QTimer::timeout, - this, &PreviewHelper::handleCodeBlocksUpdate); - - m_mathBlockTimer = new QTimer(this); - m_mathBlockTimer->setSingleShot(true); - m_mathBlockTimer->setInterval(interval); - connect(m_mathBlockTimer, &QTimer::timeout, - this, &PreviewHelper::handleMathBlocksUpdate); + m_inplacePreviewSources(SourceFlag::FlowChart | SourceFlag::Mermaid | SourceFlag::WaveDrom | + SourceFlag::PlantUml | SourceFlag::Graphviz | SourceFlag::Math), + m_codeBlockCache(100, nullptr), m_mathBlockCache(100, nullptr) { + setMarkdownEditor(p_editor); + + const int interval = 1000; + m_codeBlockTimer = new QTimer(this); + m_codeBlockTimer->setSingleShot(true); + m_codeBlockTimer->setInterval(interval); + connect(m_codeBlockTimer, &QTimer::timeout, this, &PreviewHelper::handleCodeBlocksUpdate); + + m_mathBlockTimer = new QTimer(this); + m_mathBlockTimer->setSingleShot(true); + m_mathBlockTimer->setInterval(interval); + connect(m_mathBlockTimer, &QTimer::timeout, this, &PreviewHelper::handleMathBlocksUpdate); } void PreviewHelper::codeBlocksUpdated(vte::TimeStamp p_timeStamp, - const QVector &p_codeBlocks) -{ - Q_UNUSED(p_timeStamp); - if (!m_inplacePreviewCodeBlocksEnabled) { - return; - } - - m_pendingCodeBlocks = p_codeBlocks; - m_codeBlockTimer->start(); + const QVector &p_codeBlocks) { + Q_UNUSED(p_timeStamp); + if (!m_inplacePreviewCodeBlocksEnabled) { + return; + } + + m_pendingCodeBlocks = p_codeBlocks; + m_codeBlockTimer->start(); } -void PreviewHelper::handleCodeBlocksUpdate() -{ - ++m_codeBlockTimeStamp; - m_codeBlocksData.clear(); - - QVector needPreviewBlocks; - - for (int i = 0; i < m_pendingCodeBlocks.size(); ++i) { - const auto &cb = m_pendingCodeBlocks[i]; - - const auto needPreview = isLangNeedPreview(cb.m_lang); - if (!needPreview.first && !needPreview.second) { - continue; - } - - m_codeBlocksData.append(CodeBlockPreviewData(cb)); - const int blockPreviewIdx = m_codeBlocksData.size() - 1; - - bool cacheHit = false; - auto &cachedData = m_codeBlockCache.get(cb.m_text); - if (cachedData) { - cacheHit = true; - cachedData->m_timeStamp = m_codeBlockTimeStamp; - m_codeBlocksData[blockPreviewIdx].updateInplacePreview(m_document, - cachedData->m_image, - cachedData->m_name, - cachedData->m_background, - m_tabStopWidth); - } - - if (m_inplacePreviewCodeBlocksEnabled && needPreview.first && !cacheHit) { - m_codeBlocksData[blockPreviewIdx].m_text = cb.m_text; - needPreviewBlocks.push_back(blockPreviewIdx); - } +void PreviewHelper::handleCodeBlocksUpdate() { + ++m_codeBlockTimeStamp; + m_codeBlocksData.clear(); + + QVector needPreviewBlocks; + + for (int i = 0; i < m_pendingCodeBlocks.size(); ++i) { + const auto &cb = m_pendingCodeBlocks[i]; + + const auto needPreview = isLangNeedPreview(cb.m_lang); + if (!needPreview.first && !needPreview.second) { + continue; } - for (auto idx : needPreviewBlocks) { - inplacePreviewCodeBlock(idx); + m_codeBlocksData.append(CodeBlockPreviewData(cb)); + const int blockPreviewIdx = m_codeBlocksData.size() - 1; + + bool cacheHit = false; + auto &cachedData = m_codeBlockCache.get(cb.m_text); + if (cachedData) { + cacheHit = true; + cachedData->m_timeStamp = m_codeBlockTimeStamp; + m_codeBlocksData[blockPreviewIdx].updateInplacePreview( + m_document, cachedData->m_image, cachedData->m_name, cachedData->m_background, + m_tabStopWidth); } - updateEditorInplacePreviewCodeBlock(); + if (m_inplacePreviewCodeBlocksEnabled && needPreview.first && !cacheHit) { + m_codeBlocksData[blockPreviewIdx].m_text = cb.m_text; + needPreviewBlocks.push_back(blockPreviewIdx); + } + } + + for (auto idx : needPreviewBlocks) { + inplacePreviewCodeBlock(idx); + } - m_pendingCodeBlocks.clear(); + updateEditorInplacePreviewCodeBlock(); + + m_pendingCodeBlocks.clear(); } -bool PreviewHelper::checkPreviewSourceLang(SourceFlag p_flag, const QString &p_lang) const -{ - switch (p_flag) { - case SourceFlag::FlowChart: - return p_lang == QStringLiteral("flow") || p_lang == QStringLiteral("flowchart"); +bool PreviewHelper::checkPreviewSourceLang(SourceFlag p_flag, const QString &p_lang) const { + switch (p_flag) { + case SourceFlag::FlowChart: + return p_lang == QStringLiteral("flow") || p_lang == QStringLiteral("flowchart"); - case SourceFlag::WaveDrom: - return p_lang == QStringLiteral("wavedrom"); + case SourceFlag::WaveDrom: + return p_lang == QStringLiteral("wavedrom"); - case SourceFlag::Mermaid: - return p_lang == QStringLiteral("mermaid"); + case SourceFlag::Mermaid: + return p_lang == QStringLiteral("mermaid"); - case SourceFlag::PlantUml: - return p_lang == QStringLiteral("puml") || p_lang == QStringLiteral("plantuml"); + case SourceFlag::PlantUml: + return p_lang == QStringLiteral("puml") || p_lang == QStringLiteral("plantuml"); - case SourceFlag::Graphviz: - return p_lang == QStringLiteral("dot") || p_lang == QStringLiteral("graphviz"); + case SourceFlag::Graphviz: + return p_lang == QStringLiteral("dot") || p_lang == QStringLiteral("graphviz"); - case SourceFlag::Math: - return p_lang == QStringLiteral("mathjax"); - } + case SourceFlag::Math: + return p_lang == QStringLiteral("mathjax"); + } - return false; + return false; } -QPair PreviewHelper::isLangNeedPreview(const QString &p_lang) const -{ - QPair res(false, false); - if ((isInplacePreviewSourceEnabled(SourceFlag::FlowChart) && checkPreviewSourceLang(SourceFlag::FlowChart, p_lang)) - || (isInplacePreviewSourceEnabled(SourceFlag::WaveDrom) && checkPreviewSourceLang(SourceFlag::WaveDrom, p_lang)) - || (isInplacePreviewSourceEnabled(SourceFlag::Mermaid) && checkPreviewSourceLang(SourceFlag::Mermaid, p_lang)) - || (isInplacePreviewSourceEnabled(SourceFlag::PlantUml) && checkPreviewSourceLang(SourceFlag::PlantUml, p_lang)) - || (isInplacePreviewSourceEnabled(SourceFlag::Graphviz) && checkPreviewSourceLang(SourceFlag::Graphviz, p_lang)) - || (isInplacePreviewSourceEnabled(SourceFlag::Math) && checkPreviewSourceLang(SourceFlag::Math, p_lang))) { - res.first = res.second = true; - } - return res; +QPair PreviewHelper::isLangNeedPreview(const QString &p_lang) const { + QPair res(false, false); + if ((isInplacePreviewSourceEnabled(SourceFlag::FlowChart) && + checkPreviewSourceLang(SourceFlag::FlowChart, p_lang)) || + (isInplacePreviewSourceEnabled(SourceFlag::WaveDrom) && + checkPreviewSourceLang(SourceFlag::WaveDrom, p_lang)) || + (isInplacePreviewSourceEnabled(SourceFlag::Mermaid) && + checkPreviewSourceLang(SourceFlag::Mermaid, p_lang)) || + (isInplacePreviewSourceEnabled(SourceFlag::PlantUml) && + checkPreviewSourceLang(SourceFlag::PlantUml, p_lang)) || + (isInplacePreviewSourceEnabled(SourceFlag::Graphviz) && + checkPreviewSourceLang(SourceFlag::Graphviz, p_lang)) || + (isInplacePreviewSourceEnabled(SourceFlag::Math) && + checkPreviewSourceLang(SourceFlag::Math, p_lang))) { + res.first = res.second = true; + } + return res; } -bool PreviewHelper::isInplacePreviewSourceEnabled(SourceFlag p_flag) const -{ - return m_inplacePreviewSources & p_flag; +bool PreviewHelper::isInplacePreviewSourceEnabled(SourceFlag p_flag) const { + return m_inplacePreviewSources & p_flag; } -void PreviewHelper::inplacePreviewCodeBlock(int p_blockPreviewIdx) -{ - const auto &blockData = m_codeBlocksData[p_blockPreviewIdx]; - Q_ASSERT(!blockData.m_text.isEmpty()); - if (checkPreviewSourceLang(SourceFlag::FlowChart, blockData.m_lang) - || checkPreviewSourceLang(SourceFlag::WaveDrom, blockData.m_lang) - || checkPreviewSourceLang(SourceFlag::Mermaid, blockData.m_lang) - || (checkPreviewSourceLang(SourceFlag::PlantUml, blockData.m_lang) && m_webPlantUmlEnabled) - || (checkPreviewSourceLang(SourceFlag::Graphviz, blockData.m_lang) && m_webGraphvizEnabled) - || checkPreviewSourceLang(SourceFlag::Math, blockData.m_lang)) { - emit graphPreviewRequested(p_blockPreviewIdx, - m_codeBlockTimeStamp, - blockData.m_lang, - vte::TextUtils::removeCodeBlockFence(blockData.m_text)); - return; - } - - if (!m_webPlantUmlEnabled && checkPreviewSourceLang(SourceFlag::PlantUml, blockData.m_lang)) { - // Local PlantUml. - PlantUmlHelper::getInst().process(static_cast(p_blockPreviewIdx), - m_codeBlockTimeStamp, - QStringLiteral("svg"), - vte::TextUtils::removeCodeBlockFence(blockData.m_text), - this, - [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { - handleLocalData(id, timeStamp, format, data, true); - }); - return; - } - - if (!m_webGraphvizEnabled && checkPreviewSourceLang(SourceFlag::Graphviz, blockData.m_lang)) { - // Local PlantUml. - GraphvizHelper::getInst().process(static_cast(p_blockPreviewIdx), - m_codeBlockTimeStamp, - QStringLiteral("svg"), - vte::TextUtils::removeCodeBlockFence(blockData.m_text), - this, - [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { - handleLocalData(id, timeStamp, format, data, false); - }); - return; - } +void PreviewHelper::inplacePreviewCodeBlock(int p_blockPreviewIdx) { + const auto &blockData = m_codeBlocksData[p_blockPreviewIdx]; + Q_ASSERT(!blockData.m_text.isEmpty()); + if (checkPreviewSourceLang(SourceFlag::FlowChart, blockData.m_lang) || + checkPreviewSourceLang(SourceFlag::WaveDrom, blockData.m_lang) || + checkPreviewSourceLang(SourceFlag::Mermaid, blockData.m_lang) || + (checkPreviewSourceLang(SourceFlag::PlantUml, blockData.m_lang) && m_webPlantUmlEnabled) || + (checkPreviewSourceLang(SourceFlag::Graphviz, blockData.m_lang) && m_webGraphvizEnabled) || + checkPreviewSourceLang(SourceFlag::Math, blockData.m_lang)) { + emit graphPreviewRequested(p_blockPreviewIdx, m_codeBlockTimeStamp, blockData.m_lang, + vte::TextUtils::removeCodeBlockFence(blockData.m_text)); + return; + } + + if (!m_webPlantUmlEnabled && checkPreviewSourceLang(SourceFlag::PlantUml, blockData.m_lang)) { + // Local PlantUml. + PlantUmlHelper::getInst().process( + static_cast(p_blockPreviewIdx), m_codeBlockTimeStamp, QStringLiteral("svg"), + vte::TextUtils::removeCodeBlockFence(blockData.m_text), this, + [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { + handleLocalData(id, timeStamp, format, data, true); + }); + return; + } + + if (!m_webGraphvizEnabled && checkPreviewSourceLang(SourceFlag::Graphviz, blockData.m_lang)) { + // Local PlantUml. + GraphvizHelper::getInst().process( + static_cast(p_blockPreviewIdx), m_codeBlockTimeStamp, QStringLiteral("svg"), + vte::TextUtils::removeCodeBlockFence(blockData.m_text), this, + [this](quint64 id, TimeStamp timeStamp, const QString &format, const QString &data) { + handleLocalData(id, timeStamp, format, data, false); + }); + return; + } } -void PreviewHelper::handleGraphPreviewData(const MarkdownViewerAdapter::PreviewData &p_data) -{ - if (p_data.m_timeStamp != m_codeBlockTimeStamp) { - return; - } - if (p_data.m_id >= static_cast(m_codeBlocksData.size()) || p_data.m_data.isEmpty()) { - updateEditorInplacePreviewCodeBlock(); - return; - } - - auto &blockData = m_codeBlocksData[p_data.m_id]; - const bool forcedBackground = needForcedBackground(blockData.m_lang); - auto previewData = QSharedPointer::create(p_data.m_timeStamp, - p_data.m_format, - p_data.m_data, - forcedBackground ? m_editor->getPreviewBackground() : 0, - p_data.m_needScale ? getEditorScaleFactor() : 1); - m_codeBlockCache.set(blockData.m_text, previewData); - blockData.m_text.clear(); - - blockData.updateInplacePreview(m_document, - previewData->m_image, - previewData->m_name, - previewData->m_background, - m_tabStopWidth); - +void PreviewHelper::handleGraphPreviewData(const MarkdownViewerAdapter::PreviewData &p_data) { + if (p_data.m_timeStamp != m_codeBlockTimeStamp) { + return; + } + if (p_data.m_id >= static_cast(m_codeBlocksData.size()) || p_data.m_data.isEmpty()) { updateEditorInplacePreviewCodeBlock(); + return; + } + + auto &blockData = m_codeBlocksData[p_data.m_id]; + const bool forcedBackground = needForcedBackground(blockData.m_lang); + auto previewData = QSharedPointer::create( + p_data.m_timeStamp, p_data.m_format, p_data.m_data, + forcedBackground ? m_editor->getPreviewBackground() : 0, + p_data.m_needScale ? getEditorScaleFactor() : 1); + m_codeBlockCache.set(blockData.m_text, previewData); + blockData.m_text.clear(); + + blockData.updateInplacePreview(m_document, previewData->m_image, previewData->m_name, + previewData->m_background, m_tabStopWidth); + + updateEditorInplacePreviewCodeBlock(); } -void PreviewHelper::updateEditorInplacePreviewCodeBlock() -{ - QSet obsoleteBlocks; - QVector> previewItems; - previewItems.reserve(m_codeBlocksData.size()); - for (const auto &blockData : m_codeBlocksData) { - if (blockData.m_inplacePreview) { - if (!blockData.m_inplacePreview->m_image.isNull()) { - previewItems.append(blockData.m_inplacePreview); - } else { - obsoleteBlocks.insert(blockData.m_inplacePreview->m_blockNumber); - } - } else { - obsoleteBlocks.insert(blockData.m_endBlock); - } +void PreviewHelper::updateEditorInplacePreviewCodeBlock() { + QSet obsoleteBlocks; + QVector> previewItems; + previewItems.reserve(m_codeBlocksData.size()); + for (const auto &blockData : m_codeBlocksData) { + if (blockData.m_inplacePreview) { + if (!blockData.m_inplacePreview->m_image.isNull()) { + previewItems.append(blockData.m_inplacePreview); + } else { + obsoleteBlocks.insert(blockData.m_inplacePreview->m_blockNumber); + } + } else { + obsoleteBlocks.insert(blockData.m_endBlock); } + } - if (previewItems.isEmpty() && m_previousInplacePreviewCodeBlockSize == 0) { - return; - } + if (previewItems.isEmpty() && m_previousInplacePreviewCodeBlockSize == 0) { + return; + } - emit inplacePreviewCodeBlockUpdated(previewItems); + emit inplacePreviewCodeBlockUpdated(previewItems); - m_previousInplacePreviewCodeBlockSize = previewItems.size(); + m_previousInplacePreviewCodeBlockSize = previewItems.size(); - if (!obsoleteBlocks.isEmpty()) { - emit potentialObsoletePreviewBlocksUpdated(obsoleteBlocks.values()); - } + if (!obsoleteBlocks.isEmpty()) { + emit potentialObsoletePreviewBlocksUpdated(obsoleteBlocks.values()); + } - m_codeBlockCache.setCapacityHint(m_codeBlocksData.size()); + m_codeBlockCache.setCapacityHint(m_codeBlocksData.size()); } -void PreviewHelper::setMarkdownEditor(MarkdownEditor *p_editor) -{ - Q_ASSERT(!m_editor); - m_editor = p_editor; - if (m_editor) { - m_document = m_editor->document(); - m_tabStopWidth = m_editor->getConfig().m_tabStopWidth; - } +void PreviewHelper::setMarkdownEditor(MarkdownEditor *p_editor) { + Q_ASSERT(!m_editor); + m_editor = p_editor; + if (m_editor) { + m_document = m_editor->document(); + m_tabStopWidth = m_editor->getConfig().m_tabStopWidth; + } } -void PreviewHelper::mathBlocksUpdated(const QVector &p_mathBlocks) -{ - if (!m_inplacePreviewMathBlocksEnabled || !isInplacePreviewSourceEnabled(SourceFlag::Math)) { - return; - } +void PreviewHelper::mathBlocksUpdated(const QVector &p_mathBlocks) { + if (!m_inplacePreviewMathBlocksEnabled || !isInplacePreviewSourceEnabled(SourceFlag::Math)) { + return; + } - m_pendingMathBlocks = p_mathBlocks; - m_mathBlockTimer->start(); + m_pendingMathBlocks = p_mathBlocks; + m_mathBlockTimer->start(); } -void PreviewHelper::handleMathBlocksUpdate() -{ - ++m_mathBlockTimeStamp; - m_mathBlocksData.clear(); - m_mathBlocksData.reserve(m_pendingMathBlocks.size()); - - bool needUpdateEditorInplacePreview = true; - - for (const auto &mb : m_pendingMathBlocks) { - m_mathBlocksData.append(MathBlockPreviewData(mb)); - const int blockPreviewIdx = m_mathBlocksData.size() - 1; - - bool cacheHit = false; - auto &cachedData = m_mathBlockCache.get(mb.m_text); - if (cachedData) { - cacheHit = true; - cachedData->m_timeStamp = m_mathBlockTimeStamp; - m_mathBlocksData[blockPreviewIdx].updateInplacePreview(m_document, - cachedData->m_image, - cachedData->m_name, - m_tabStopWidth); - } - - if (!cacheHit) { - needUpdateEditorInplacePreview = false; - m_mathBlocksData[blockPreviewIdx].m_text = mb.m_text; - inplacePreviewMathBlock(blockPreviewIdx); - } +void PreviewHelper::handleMathBlocksUpdate() { + ++m_mathBlockTimeStamp; + m_mathBlocksData.clear(); + m_mathBlocksData.reserve(m_pendingMathBlocks.size()); + + bool needUpdateEditorInplacePreview = true; + + for (const auto &mb : m_pendingMathBlocks) { + m_mathBlocksData.append(MathBlockPreviewData(mb)); + const int blockPreviewIdx = m_mathBlocksData.size() - 1; + + bool cacheHit = false; + auto &cachedData = m_mathBlockCache.get(mb.m_text); + if (cachedData) { + cacheHit = true; + cachedData->m_timeStamp = m_mathBlockTimeStamp; + m_mathBlocksData[blockPreviewIdx].updateInplacePreview(m_document, cachedData->m_image, + cachedData->m_name, m_tabStopWidth); } - if (needUpdateEditorInplacePreview) { - updateEditorInplacePreviewMathBlock(); + if (!cacheHit) { + needUpdateEditorInplacePreview = false; + m_mathBlocksData[blockPreviewIdx].m_text = mb.m_text; + inplacePreviewMathBlock(blockPreviewIdx); } + } - m_pendingMathBlocks.clear(); + if (needUpdateEditorInplacePreview) { + updateEditorInplacePreviewMathBlock(); + } + + m_pendingMathBlocks.clear(); } -void PreviewHelper::inplacePreviewMathBlock(int p_blockPreviewIdx) -{ - const auto &blockData = m_mathBlocksData[p_blockPreviewIdx]; - Q_ASSERT(!blockData.m_text.isEmpty()); - emit mathPreviewRequested(p_blockPreviewIdx, m_mathBlockTimeStamp, blockData.m_text); +void PreviewHelper::inplacePreviewMathBlock(int p_blockPreviewIdx) { + const auto &blockData = m_mathBlocksData[p_blockPreviewIdx]; + Q_ASSERT(!blockData.m_text.isEmpty()); + emit mathPreviewRequested(p_blockPreviewIdx, m_mathBlockTimeStamp, blockData.m_text); } -void PreviewHelper::updateEditorInplacePreviewMathBlock() -{ - QSet obsoleteBlocks; - QVector> previewItems; - previewItems.reserve(m_mathBlocksData.size()); - for (const auto &blockData : m_mathBlocksData) { - if (blockData.m_inplacePreview) { - if (!blockData.m_inplacePreview->m_image.isNull()) { - previewItems.append(blockData.m_inplacePreview); - } else { - obsoleteBlocks.insert(blockData.m_inplacePreview->m_blockNumber); - } - } else { - obsoleteBlocks.insert(blockData.m_blockNumber); - } +void PreviewHelper::updateEditorInplacePreviewMathBlock() { + QSet obsoleteBlocks; + QVector> previewItems; + previewItems.reserve(m_mathBlocksData.size()); + for (const auto &blockData : m_mathBlocksData) { + if (blockData.m_inplacePreview) { + if (!blockData.m_inplacePreview->m_image.isNull()) { + previewItems.append(blockData.m_inplacePreview); + } else { + obsoleteBlocks.insert(blockData.m_inplacePreview->m_blockNumber); + } + } else { + obsoleteBlocks.insert(blockData.m_blockNumber); } + } - if (previewItems.isEmpty() && m_previousInplacePreviewMathBlockSize == 0) { - return; - } + if (previewItems.isEmpty() && m_previousInplacePreviewMathBlockSize == 0) { + return; + } - emit inplacePreviewMathBlockUpdated(previewItems); + emit inplacePreviewMathBlockUpdated(previewItems); - m_previousInplacePreviewMathBlockSize = previewItems.size(); + m_previousInplacePreviewMathBlockSize = previewItems.size(); - if (!obsoleteBlocks.isEmpty()) { - emit potentialObsoletePreviewBlocksUpdated(obsoleteBlocks.values()); - } + if (!obsoleteBlocks.isEmpty()) { + emit potentialObsoletePreviewBlocksUpdated(obsoleteBlocks.values()); + } - m_mathBlockCache.setCapacityHint(m_mathBlocksData.size()); + m_mathBlockCache.setCapacityHint(m_mathBlocksData.size()); } -void PreviewHelper::handleMathPreviewData(const MarkdownViewerAdapter::PreviewData &p_data) -{ - if (p_data.m_timeStamp != m_mathBlockTimeStamp) { - return; - } - if (p_data.m_id >= static_cast(m_mathBlocksData.size()) || p_data.m_data.isEmpty()) { - updateEditorInplacePreviewMathBlock(); - return; - } +void PreviewHelper::handleMathPreviewData(const MarkdownViewerAdapter::PreviewData &p_data) { + if (p_data.m_timeStamp != m_mathBlockTimeStamp) { + return; + } + if (p_data.m_id >= static_cast(m_mathBlocksData.size()) || p_data.m_data.isEmpty()) { + updateEditorInplacePreviewMathBlock(); + return; + } - auto &blockData = m_mathBlocksData[p_data.m_id]; - auto previewData = QSharedPointer::create(p_data.m_timeStamp, - p_data.m_format, - p_data.m_data, - 0, - p_data.m_needScale ? getEditorScaleFactor() : 1); - m_mathBlockCache.set(blockData.m_text, previewData); - blockData.m_text.clear(); + auto &blockData = m_mathBlocksData[p_data.m_id]; + auto previewData = + QSharedPointer::create(p_data.m_timeStamp, p_data.m_format, p_data.m_data, + 0, p_data.m_needScale ? getEditorScaleFactor() : 1); + m_mathBlockCache.set(blockData.m_text, previewData); + blockData.m_text.clear(); - blockData.updateInplacePreview(m_document, - previewData->m_image, - previewData->m_name, - m_tabStopWidth); + blockData.updateInplacePreview(m_document, previewData->m_image, previewData->m_name, + m_tabStopWidth); - updateEditorInplacePreviewMathBlock(); + updateEditorInplacePreviewMathBlock(); } -qreal PreviewHelper::getEditorScaleFactor() const -{ - if (m_editor) { - return m_editor->getConfig().m_scaleFactor; - } +qreal PreviewHelper::getEditorScaleFactor() const { + if (m_editor) { + return m_editor->getConfig().m_scaleFactor; + } - return 1; + return 1; } -void PreviewHelper::setWebPlantUmlEnabled(bool p_enabled) -{ - m_webPlantUmlEnabled = p_enabled; -} +void PreviewHelper::setWebPlantUmlEnabled(bool p_enabled) { m_webPlantUmlEnabled = p_enabled; } -void PreviewHelper::setWebGraphvizEnabled(bool p_enabled) -{ - m_webGraphvizEnabled = p_enabled; -} +void PreviewHelper::setWebGraphvizEnabled(bool p_enabled) { m_webGraphvizEnabled = p_enabled; } -void PreviewHelper::handleLocalData(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_forcedBackground) -{ - if (p_timeStamp != m_codeBlockTimeStamp) { - return; - } +void PreviewHelper::handleLocalData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, + const QString &p_data, bool p_forcedBackground) { + if (p_timeStamp != m_codeBlockTimeStamp) { + return; + } - Q_UNUSED(p_format); - Q_ASSERT(p_format == QStringLiteral("svg")); + Q_UNUSED(p_format); + Q_ASSERT(p_format == QStringLiteral("svg")); - if (p_id >= static_cast(m_codeBlocksData.size()) || p_data.isEmpty()) { - updateEditorInplacePreviewCodeBlock(); - return; - } + if (p_id >= static_cast(m_codeBlocksData.size()) || p_data.isEmpty()) { + updateEditorInplacePreviewCodeBlock(); + return; + } - auto &blockData = m_codeBlocksData[p_id]; - auto previewData = QSharedPointer::create(p_timeStamp, - p_format, - p_data.toUtf8(), - p_forcedBackground ? m_editor->getPreviewBackground() : 0, - getEditorScaleFactor()); - m_codeBlockCache.set(blockData.m_text, previewData); - blockData.m_text.clear(); - - blockData.updateInplacePreview(m_document, - previewData->m_image, - previewData->m_name, - previewData->m_background, - m_tabStopWidth); + auto &blockData = m_codeBlocksData[p_id]; + auto previewData = QSharedPointer::create( + p_timeStamp, p_format, p_data.toUtf8(), + p_forcedBackground ? m_editor->getPreviewBackground() : 0, getEditorScaleFactor()); + m_codeBlockCache.set(blockData.m_text, previewData); + blockData.m_text.clear(); - updateEditorInplacePreviewCodeBlock(); + blockData.updateInplacePreview(m_document, previewData->m_image, previewData->m_name, + previewData->m_background, m_tabStopWidth); + + updateEditorInplacePreviewCodeBlock(); } -bool PreviewHelper::needForcedBackground(const QString &p_lang) const -{ - if (checkPreviewSourceLang(SourceFlag::PlantUml, p_lang)) { - return true; - } +bool PreviewHelper::needForcedBackground(const QString &p_lang) const { + if (checkPreviewSourceLang(SourceFlag::PlantUml, p_lang)) { + return true; + } - return false; + return false; } -void PreviewHelper::setInplacePreviewSources(SourceFlags p_srcs) -{ - m_inplacePreviewSources = p_srcs; +void PreviewHelper::setInplacePreviewSources(SourceFlags p_srcs) { + m_inplacePreviewSources = p_srcs; } -void PreviewHelper::setInplacePreviewCodeBlocksEnabled(bool p_enabled) -{ - m_inplacePreviewCodeBlocksEnabled = p_enabled; +void PreviewHelper::setInplacePreviewCodeBlocksEnabled(bool p_enabled) { + m_inplacePreviewCodeBlocksEnabled = p_enabled; } -void PreviewHelper::setInplacePreviewMathBlocksEnabled(bool p_enabled) -{ - m_inplacePreviewMathBlocksEnabled = p_enabled; +void PreviewHelper::setInplacePreviewMathBlocksEnabled(bool p_enabled) { + m_inplacePreviewMathBlocksEnabled = p_enabled; } diff --git a/src/widgets/editors/previewhelper.h b/src/widgets/editors/previewhelper.h index be8a742ab2..b1e61d15d3 100644 --- a/src/widgets/editors/previewhelper.h +++ b/src/widgets/editors/previewhelper.h @@ -9,240 +9,221 @@ #include #include -#include #include "markdownvieweradapter.h" +#include class QTimer; class QTextDocument; -namespace vnotex -{ - class MarkdownEditor; +namespace vnotex { +class MarkdownEditor; - // Helper to manage in-place preview and focus preview. - class PreviewHelper : public QObject - { - Q_OBJECT - public: - enum SourceFlag - { - FlowChart = 0x1, - Mermaid = 0x2, - WaveDrom = 0x4, - PlantUml = 0x8, - Graphviz = 0x10, - Math = 0x20 - }; - Q_DECLARE_FLAGS(SourceFlags, SourceFlag); +// Helper to manage in-place preview and focus preview. +class PreviewHelper : public QObject { + Q_OBJECT +public: + enum SourceFlag { + FlowChart = 0x1, + Mermaid = 0x2, + WaveDrom = 0x4, + PlantUml = 0x8, + Graphviz = 0x10, + Math = 0x20 + }; + Q_DECLARE_FLAGS(SourceFlags, SourceFlag); - PreviewHelper(MarkdownEditor *p_editor, QObject *p_parent = nullptr); + PreviewHelper(MarkdownEditor *p_editor, QObject *p_parent = nullptr); - void setMarkdownEditor(MarkdownEditor *p_editor); + void setMarkdownEditor(MarkdownEditor *p_editor); - void setWebPlantUmlEnabled(bool p_enabled); + void setWebPlantUmlEnabled(bool p_enabled); - void setWebGraphvizEnabled(bool p_enabled); + void setWebGraphvizEnabled(bool p_enabled); - void setInplacePreviewSources(SourceFlags p_srcs); + void setInplacePreviewSources(SourceFlags p_srcs); - void setInplacePreviewCodeBlocksEnabled(bool p_enabled); + void setInplacePreviewCodeBlocksEnabled(bool p_enabled); - void setInplacePreviewMathBlocksEnabled(bool p_enabled); + void setInplacePreviewMathBlocksEnabled(bool p_enabled); - public slots: - void codeBlocksUpdated(vte::TimeStamp p_timeStamp, - const QVector &p_codeBlocks); +public slots: + void codeBlocksUpdated(vte::TimeStamp p_timeStamp, + const QVector &p_codeBlocks); - void mathBlocksUpdated(const QVector &p_mathBlocks); + void mathBlocksUpdated(const QVector &p_mathBlocks); - void handleGraphPreviewData(const MarkdownViewerAdapter::PreviewData &p_data); + void handleGraphPreviewData(const MarkdownViewerAdapter::PreviewData &p_data); - void handleMathPreviewData(const MarkdownViewerAdapter::PreviewData &p_data); + void handleMathPreviewData(const MarkdownViewerAdapter::PreviewData &p_data); - signals: - // Request to preview graph. - // There must be a corresponding call to handleGraphPreviewData(). - void graphPreviewRequested(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_lang, - const QString &p_text); +signals: + // Request to preview graph. + // There must be a corresponding call to handleGraphPreviewData(). + void graphPreviewRequested(quint64 p_id, TimeStamp p_timeStamp, const QString &p_lang, + const QString &p_text); - // Request to preview math. - // There must be a corresponding call to handleMathPreviewData(). - void mathPreviewRequested(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_text); + // Request to preview math. + // There must be a corresponding call to handleMathPreviewData(). + void mathPreviewRequested(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text); - // Request to do in-place preview for @p_previewItems. - void inplacePreviewCodeBlockUpdated(const QVector> &p_previewItems); + // Request to do in-place preview for @p_previewItems. + void + inplacePreviewCodeBlockUpdated(const QVector> &p_previewItems); - // Request to do in-place preview for @p_previewItems. - void inplacePreviewMathBlockUpdated(const QVector> &p_previewItems); + // Request to do in-place preview for @p_previewItems. + void + inplacePreviewMathBlockUpdated(const QVector> &p_previewItems); - void potentialObsoletePreviewBlocksUpdated(const QList &p_blocks); + void potentialObsoletePreviewBlocksUpdated(const QList &p_blocks); - private: - // Preview data of each related code block. - struct CodeBlockPreviewData - { - CodeBlockPreviewData() = default; +private: + // Preview data of each related code block. + struct CodeBlockPreviewData { + CodeBlockPreviewData() = default; - CodeBlockPreviewData(const vte::peg::FencedCodeBlock &p_codeBlock); + CodeBlockPreviewData(const vte::peg::FencedCodeBlock &p_codeBlock); - void updateInplacePreview(QTextDocument *p_doc, - const QPixmap &p_image, - const QString &p_imageName, - QRgb p_background, - int p_tabStopWidth); + void updateInplacePreview(QTextDocument *p_doc, const QPixmap &p_image, + const QString &p_imageName, QRgb p_background, int p_tabStopWidth); - // Start and end block of the fenced code block. - int m_startBlock = 0; - int m_endBlock = 0; + // Start and end block of the fenced code block. + int m_startBlock = 0; + int m_endBlock = 0; - QString m_lang; + QString m_lang; - // Including the fence text. - // Will be filled only when preview is needed. - QString m_text; + // Including the fence text. + // Will be filled only when preview is needed. + QString m_text; - QSharedPointer m_inplacePreview; - }; + QSharedPointer m_inplacePreview; + }; - struct MathBlockPreviewData - { - MathBlockPreviewData() = default; + struct MathBlockPreviewData { + MathBlockPreviewData() = default; - MathBlockPreviewData(const vte::peg::MathBlock &p_mathBlock); + MathBlockPreviewData(const vte::peg::MathBlock &p_mathBlock); - void updateInplacePreview(QTextDocument *p_doc, - const QPixmap &p_image, - const QString &p_imageName, - int p_tabStopWidth); + void updateInplacePreview(QTextDocument *p_doc, const QPixmap &p_image, + const QString &p_imageName, int p_tabStopWidth); - // Block number for in-place preview. - int m_blockNumber = -1; + // Block number for in-place preview. + int m_blockNumber = -1; - // Whether it should be previewed as block or not. - bool m_previewedAsBlock = false; + // Whether it should be previewed as block or not. + bool m_previewedAsBlock = false; - // Start index wihtin block with number m_blockNumber, including the start mark. - int m_index = -1; + // Start index wihtin block with number m_blockNumber, including the start mark. + int m_index = -1; - // Length of this math in block with number m_blockNumber, including the end mark. - int m_length = -1; + // Length of this math in block with number m_blockNumber, including the end mark. + int m_length = -1; - // Including the guarding marks. - // Will be filled only when preview is needed. - QString m_text; + // Including the guarding marks. + // Will be filled only when preview is needed. + QString m_text; - QSharedPointer m_inplacePreview; - }; + QSharedPointer m_inplacePreview; + }; - // Data of the preview result. - struct GraphPreviewData - { - GraphPreviewData() = default; + // Data of the preview result. + struct GraphPreviewData { + GraphPreviewData() = default; - GraphPreviewData(TimeStamp p_timeStamp, - const QString &p_format, - const QByteArray &p_data, - QRgb p_background = 0x0, - qreal p_scaleFactor = 1); + GraphPreviewData(TimeStamp p_timeStamp, const QString &p_format, const QByteArray &p_data, + QRgb p_background = 0x0, qreal p_scaleFactor = 1); - bool isNull() const; + bool isNull() const; - TimeStamp m_timeStamp = 0; + TimeStamp m_timeStamp = 0; - QPixmap m_image; + QPixmap m_image; - // Name of the image for identification in resource manager. - QString m_name; + // Name of the image for identification in resource manager. + QString m_name; - // Background color to override. - // 0x0 indicates it is not specified. - QRgb m_background = 0x0; + // Background color to override. + // 0x0 indicates it is not specified. + QRgb m_background = 0x0; - // An increasing index to used as the image name. - static int s_imageIndex; - }; + // An increasing index to used as the image name. + static int s_imageIndex; + }; - // Return . - QPair isLangNeedPreview(const QString &p_lang) const; + // Return . + QPair isLangNeedPreview(const QString &p_lang) const; - bool isInplacePreviewSourceEnabled(SourceFlag p_flag) const; + bool isInplacePreviewSourceEnabled(SourceFlag p_flag) const; - bool checkPreviewSourceLang(SourceFlag p_flag, const QString &p_lang) const; + bool checkPreviewSourceLang(SourceFlag p_flag, const QString &p_lang) const; - // Inplace preview code block m_codeBlocksData[@p_blockPreviewIdx]. - void inplacePreviewCodeBlock(int p_blockPreviewIdx); + // Inplace preview code block m_codeBlocksData[@p_blockPreviewIdx]. + void inplacePreviewCodeBlock(int p_blockPreviewIdx); - void inplacePreviewMathBlock(int p_blockPreviewIdx); + void inplacePreviewMathBlock(int p_blockPreviewIdx); - void updateEditorInplacePreviewCodeBlock(); + void updateEditorInplacePreviewCodeBlock(); - void updateEditorInplacePreviewMathBlock(); + void updateEditorInplacePreviewMathBlock(); - void handleLocalData(quint64 p_id, - TimeStamp p_timeStamp, - const QString &p_format, - const QString &p_data, - bool p_forcedBackground); + void handleLocalData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_format, + const QString &p_data, bool p_forcedBackground); - qreal getEditorScaleFactor() const; + qreal getEditorScaleFactor() const; - bool needForcedBackground(const QString &p_lang) const; + bool needForcedBackground(const QString &p_lang) const; - void handleCodeBlocksUpdate(); + void handleCodeBlocksUpdate(); - void handleMathBlocksUpdate(); + void handleMathBlocksUpdate(); - MarkdownEditor *m_editor = nullptr; + MarkdownEditor *m_editor = nullptr; - QTextDocument *m_document = nullptr; + QTextDocument *m_document = nullptr; - // Need to init it in the constructor. - SourceFlags m_inplacePreviewSources; + // Need to init it in the constructor. + SourceFlags m_inplacePreviewSources; - bool m_inplacePreviewCodeBlocksEnabled = true; + bool m_inplacePreviewCodeBlocksEnabled = true; - bool m_inplacePreviewMathBlocksEnabled = true; + bool m_inplacePreviewMathBlocksEnabled = true; - TimeStamp m_codeBlockTimeStamp = 0; + TimeStamp m_codeBlockTimeStamp = 0; - TimeStamp m_mathBlockTimeStamp = 0; + TimeStamp m_mathBlockTimeStamp = 0; - // Sorted by startBlock in ascending order. - QVector m_codeBlocksData; + // Sorted by startBlock in ascending order. + QVector m_codeBlocksData; - QVector m_mathBlocksData; + QVector m_mathBlocksData; - // Tab stop width of the editor, used for block margin calculation. - int m_tabStopWidth = 4; + // Tab stop width of the editor, used for block margin calculation. + int m_tabStopWidth = 4; - // To record the size of previous inplace preview of code block. - int m_previousInplacePreviewCodeBlockSize = 0; + // To record the size of previous inplace preview of code block. + int m_previousInplacePreviewCodeBlockSize = 0; - // To record the size of previous inplace preview of math block. - int m_previousInplacePreviewMathBlockSize = 0; + // To record the size of previous inplace preview of math block. + int m_previousInplacePreviewMathBlockSize = 0; - // {text} -> GraphPreviewData. - vte::LruCache> m_codeBlockCache; + // {text} -> GraphPreviewData. + vte::LruCache> m_codeBlockCache; - vte::LruCache> m_mathBlockCache; + vte::LruCache> m_mathBlockCache; - bool m_webPlantUmlEnabled = true; + bool m_webPlantUmlEnabled = true; - bool m_webGraphvizEnabled = true; + bool m_webGraphvizEnabled = true; - QVector m_pendingCodeBlocks; + QVector m_pendingCodeBlocks; - QTimer *m_codeBlockTimer = nullptr; + QTimer *m_codeBlockTimer = nullptr; - QVector m_pendingMathBlocks; + QVector m_pendingMathBlocks; - QTimer *m_mathBlockTimer = nullptr; - }; -} + QTimer *m_mathBlockTimer = nullptr; +}; +} // namespace vnotex Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::PreviewHelper::SourceFlags) diff --git a/src/widgets/editors/statuswidget.cpp b/src/widgets/editors/statuswidget.cpp index d1e508b6f5..c00a14f1dc 100644 --- a/src/widgets/editors/statuswidget.cpp +++ b/src/widgets/editors/statuswidget.cpp @@ -1,74 +1,66 @@ #include "statuswidget.h" -#include +#include #include #include -#include +#include using namespace vnotex; -StatusWidget::StatusWidget(QWidget *p_parent) - : QWidget(p_parent) -{ - m_mainLayout = new QStackedLayout(this); - m_mainLayout->setContentsMargins(0, 0, 0, 0); - m_mainLayout->setSpacing(0); +StatusWidget::StatusWidget(QWidget *p_parent) : QWidget(p_parent) { + m_mainLayout = new QStackedLayout(this); + m_mainLayout->setContentsMargins(0, 0, 0, 0); + m_mainLayout->setSpacing(0); - m_messageLabel = new QLabel(this); - m_messageLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - m_mainLayout->addWidget(m_messageLabel); + m_messageLabel = new QLabel(this); + m_messageLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_mainLayout->addWidget(m_messageLabel); - m_messageTimer = new QTimer(this); - m_messageTimer->setSingleShot(true); - connect(m_messageTimer, &QTimer::timeout, - this, &StatusWidget::clearMessage); + m_messageTimer = new QTimer(this); + m_messageTimer->setSingleShot(true); + connect(m_messageTimer, &QTimer::timeout, this, &StatusWidget::clearMessage); } -StatusWidget::~StatusWidget() -{ - if (m_editorWidget) { - m_editorWidget->setParent(nullptr); - } +StatusWidget::~StatusWidget() { + if (m_editorWidget) { + m_editorWidget->setParent(nullptr); + } } -void StatusWidget::showMessage(const QString &p_msg, int p_milliseconds) -{ - if (p_msg.isEmpty()) { - clearMessage(); - return; - } +void StatusWidget::showMessage(const QString &p_msg, int p_milliseconds) { + if (p_msg.isEmpty()) { + clearMessage(); + return; + } - m_messageLabel->setText(p_msg); - m_mainLayout->setCurrentWidget(m_messageLabel); + m_messageLabel->setText(p_msg); + m_mainLayout->setCurrentWidget(m_messageLabel); - if (p_milliseconds > 0) { - m_messageTimer->start(p_milliseconds); - } + if (p_milliseconds > 0) { + m_messageTimer->start(p_milliseconds); + } } -void StatusWidget::setEditorStatusWidget(const QSharedPointer &p_editorWidget) -{ - Q_ASSERT(!m_editorWidget); - m_editorWidget = p_editorWidget; - m_mainLayout->addWidget(m_editorWidget.data()); - m_mainLayout->setCurrentWidget(m_editorWidget.data()); +void StatusWidget::setEditorStatusWidget(const QSharedPointer &p_editorWidget) { + Q_ASSERT(!m_editorWidget); + m_editorWidget = p_editorWidget; + m_mainLayout->addWidget(m_editorWidget.data()); + m_mainLayout->setCurrentWidget(m_editorWidget.data()); } -void StatusWidget::resizeEvent(QResizeEvent *p_event) -{ - QWidget::resizeEvent(p_event); +void StatusWidget::resizeEvent(QResizeEvent *p_event) { + QWidget::resizeEvent(p_event); - int maxWidth = width() - 10; - if (maxWidth <= 0) { - maxWidth = width(); - } - m_messageLabel->setMaximumWidth(maxWidth); + int maxWidth = width() - 10; + if (maxWidth <= 0) { + maxWidth = width(); + } + m_messageLabel->setMaximumWidth(maxWidth); } -void StatusWidget::clearMessage() -{ - m_messageLabel->clear(); - if (m_editorWidget) { - m_mainLayout->setCurrentWidget(m_editorWidget.data()); - } +void StatusWidget::clearMessage() { + m_messageLabel->clear(); + if (m_editorWidget) { + m_mainLayout->setCurrentWidget(m_editorWidget.data()); + } } diff --git a/src/widgets/editors/statuswidget.h b/src/widgets/editors/statuswidget.h index 1e93e4f011..4e7e59ae8b 100644 --- a/src/widgets/editors/statuswidget.h +++ b/src/widgets/editors/statuswidget.h @@ -1,44 +1,42 @@ #ifndef STATUSWIDGET_H #define STATUSWIDGET_H -#include #include +#include class QLabel; class QTimer; class QStackedLayout; -namespace vnotex -{ - // A status widget wrapper for ViewWindow. - class StatusWidget : public QWidget - { - Q_OBJECT - public: - explicit StatusWidget(QWidget *p_parent = nullptr); +namespace vnotex { +// A status widget wrapper for ViewWindow. +class StatusWidget : public QWidget { + Q_OBJECT +public: + explicit StatusWidget(QWidget *p_parent = nullptr); - ~StatusWidget(); + ~StatusWidget(); - void showMessage(const QString &p_msg, int p_milliseconds = 3000); + void showMessage(const QString &p_msg, int p_milliseconds = 3000); - void setEditorStatusWidget(const QSharedPointer &p_editorWidget); + void setEditorStatusWidget(const QSharedPointer &p_editorWidget); - protected: - void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE; +protected: + void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE; - private: - void clearMessage(); +private: + void clearMessage(); - QStackedLayout *m_mainLayout = nullptr; + QStackedLayout *m_mainLayout = nullptr; - QLabel *m_messageLabel = nullptr; + QLabel *m_messageLabel = nullptr; - QTimer *m_messageTimer = nullptr; + QTimer *m_messageTimer = nullptr; - // Use shared pointer here to hold the widget. - // Should detach the widget in destructor. - QSharedPointer m_editorWidget; - }; -} + // Use shared pointer here to hold the widget. + // Should detach the widget in destructor. + QSharedPointer m_editorWidget; +}; +} // namespace vnotex #endif // STATUSWIDGET_H diff --git a/src/widgets/editors/texteditor.cpp b/src/widgets/editors/texteditor.cpp index ccca2d7eea..c5395c83eb 100644 --- a/src/widgets/editors/texteditor.cpp +++ b/src/widgets/editors/texteditor.cpp @@ -13,27 +13,27 @@ using namespace vnotex; TextEditor::TextEditor(const QSharedPointer &p_config, - const QSharedPointer &p_paras, - QWidget *p_parent) - : vte::VTextEditor(p_config, p_paras, p_parent) -{ - connect(m_textEdit, &vte::VTextEdit::contextMenuEventRequested, - this, &TextEditor::handleContextMenuEvent); + const QSharedPointer &p_paras, QWidget *p_parent) + : vte::VTextEditor(p_config, p_paras, p_parent) { + connect(m_textEdit, &vte::VTextEdit::contextMenuEventRequested, this, + &TextEditor::handleContextMenuEvent); } -void TextEditor::handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, QScopedPointer *p_menu) -{ - *p_handled = true; - p_menu->reset(m_textEdit->createStandardContextMenu(p_event->pos())); - auto menu = p_menu->data(); +void TextEditor::handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, + QScopedPointer *p_menu) { + *p_handled = true; + p_menu->reset(m_textEdit->createStandardContextMenu(p_event->pos())); + auto menu = p_menu->data(); - { - menu->addSeparator(); + { + menu->addSeparator(); - auto snippetAct = menu->addAction(tr("Insert Snippet"), this, &TextEditor::applySnippetRequested); - WidgetUtils::addActionShortcutText(snippetAct, - ConfigMgr::getInst().getEditorConfig().getShortcut(EditorConfig::Shortcut::ApplySnippet)); - } + auto snippetAct = + menu->addAction(tr("Insert Snippet"), this, &TextEditor::applySnippetRequested); + WidgetUtils::addActionShortcutText( + snippetAct, + ConfigMgr::getInst().getEditorConfig().getShortcut(EditorConfig::Shortcut::ApplySnippet)); + } - appendSpellCheckMenu(p_event, menu); + appendSpellCheckMenu(p_event, menu); } diff --git a/src/widgets/editors/texteditor.h b/src/widgets/editors/texteditor.h index 36391204c8..6a7c1dbea4 100644 --- a/src/widgets/editors/texteditor.h +++ b/src/widgets/editors/texteditor.h @@ -3,22 +3,20 @@ #include -namespace vnotex -{ - class TextEditor : public vte::VTextEditor - { - Q_OBJECT - public: - TextEditor(const QSharedPointer &p_config, - const QSharedPointer &p_paras, - QWidget *p_parent = nullptr); +namespace vnotex { +class TextEditor : public vte::VTextEditor { + Q_OBJECT +public: + TextEditor(const QSharedPointer &p_config, + const QSharedPointer &p_paras, QWidget *p_parent = nullptr); - signals: - void applySnippetRequested(); +signals: + void applySnippetRequested(); - private slots: - void handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, QScopedPointer *p_menu); - }; -} +private slots: + void handleContextMenuEvent(QContextMenuEvent *p_event, bool *p_handled, + QScopedPointer *p_menu); +}; +} // namespace vnotex #endif // TEXTEDITOR_H diff --git a/src/widgets/editors/webviewadapter.cpp b/src/widgets/editors/webviewadapter.cpp index a07b594857..638cd55596 100644 --- a/src/widgets/editors/webviewadapter.cpp +++ b/src/widgets/editors/webviewadapter.cpp @@ -4,89 +4,77 @@ using namespace vnotex; -QJsonObject WebViewAdapter::FindOption::toJson() const -{ - QJsonObject obj; - obj["findBackward"] = m_findBackward; - obj["caseSensitive"] = m_caseSensitive; - obj["wholeWordOnly"] = m_wholeWordOnly; - obj["regularExpression"] = m_regularExpression; - return obj; +QJsonObject WebViewAdapter::FindOption::toJson() const { + QJsonObject obj; + obj["findBackward"] = m_findBackward; + obj["caseSensitive"] = m_caseSensitive; + obj["wholeWordOnly"] = m_wholeWordOnly; + obj["regularExpression"] = m_regularExpression; + return obj; } -WebViewAdapter::WebViewAdapter(QObject *p_parent) - : QObject(p_parent) -{ -} +WebViewAdapter::WebViewAdapter(QObject *p_parent) : QObject(p_parent) {} -void WebViewAdapter::setReady(bool p_ready) -{ - if (m_ready == p_ready) { - return; - } +void WebViewAdapter::setReady(bool p_ready) { + if (m_ready == p_ready) { + return; + } - m_ready = p_ready; - if (m_ready) { - for (auto &act : m_pendingActions) { - act(); - } - m_pendingActions.clear(); - emit ready(); - } else { - m_pendingActions.clear(); + m_ready = p_ready; + if (m_ready) { + for (auto &act : m_pendingActions) { + act(); } + m_pendingActions.clear(); + emit ready(); + } else { + m_pendingActions.clear(); + } } -void WebViewAdapter::pendAction(const std::function &p_func) -{ - Q_ASSERT(!m_ready); - m_pendingActions.append(p_func); +void WebViewAdapter::pendAction(const std::function &p_func) { + Q_ASSERT(!m_ready); + m_pendingActions.append(p_func); } -bool WebViewAdapter::isReady() const -{ - return m_ready; -} +bool WebViewAdapter::isReady() const { return m_ready; } -void WebViewAdapter::invokeCallback(quint64 p_id, void *p_data) -{ - m_callbackPool.call(p_id, p_data); +void WebViewAdapter::invokeCallback(quint64 p_id, void *p_data) { + m_callbackPool.call(p_id, p_data); } -quint64 WebViewAdapter::addCallback(const CallbackPool::Callback &p_callback) -{ - return m_callbackPool.add(p_callback); +quint64 WebViewAdapter::addCallback(const CallbackPool::Callback &p_callback) { + return m_callbackPool.add(p_callback); } -void WebViewAdapter::findText(const QStringList &p_texts, FindOptions p_options, int p_currentMatchLine) -{ - FindOption opts; - if (p_options & vnotex::FindOption::FindBackward) { - opts.m_findBackward = true; - } - if (p_options & vnotex::FindOption::CaseSensitive) { - opts.m_caseSensitive = true; - } - if (p_options & vnotex::FindOption::WholeWordOnly) { - opts.m_wholeWordOnly = true; - } - if (p_options & vnotex::FindOption::RegularExpression) { - opts.m_regularExpression = true; - } +void WebViewAdapter::findText(const QStringList &p_texts, FindOptions p_options, + int p_currentMatchLine) { + FindOption opts; + if (p_options & vnotex::FindOption::FindBackward) { + opts.m_findBackward = true; + } + if (p_options & vnotex::FindOption::CaseSensitive) { + opts.m_caseSensitive = true; + } + if (p_options & vnotex::FindOption::WholeWordOnly) { + opts.m_wholeWordOnly = true; + } + if (p_options & vnotex::FindOption::RegularExpression) { + opts.m_regularExpression = true; + } - if (isReady()) { - emit findTextRequested(p_texts, opts.toJson(), p_currentMatchLine); - } else { - pendAction([this, p_texts, opts, p_currentMatchLine]() { - // FIXME: highlights will be clear once the page is ready. Add a delay here. - Utils::sleepWait(1000); - emit findTextRequested(p_texts, opts.toJson(), p_currentMatchLine); - }); - } + if (isReady()) { + emit findTextRequested(p_texts, opts.toJson(), p_currentMatchLine); + } else { + pendAction([this, p_texts, opts, p_currentMatchLine]() { + // FIXME: highlights will be clear once the page is ready. Add a delay here. + Utils::sleepWait(1000); + emit findTextRequested(p_texts, opts.toJson(), p_currentMatchLine); + }); + } } -void WebViewAdapter::setFindText(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex) -{ - emit findTextReady(p_texts, p_totalMatches, p_currentMatchIndex); +void WebViewAdapter::setFindText(const QStringList &p_texts, int p_totalMatches, + int p_currentMatchIndex) { + emit findTextReady(p_texts, p_totalMatches, p_currentMatchIndex); } - diff --git a/src/widgets/editors/webviewadapter.h b/src/widgets/editors/webviewadapter.h index 624212cd6f..ec63dce17a 100644 --- a/src/widgets/editors/webviewadapter.h +++ b/src/widgets/editors/webviewadapter.h @@ -5,67 +5,65 @@ #include -#include #include +#include -namespace vnotex -{ - // Base class of adapter and interface between CPP and JS for WebView. - class WebViewAdapter : public QObject - { - Q_OBJECT - public: - explicit WebViewAdapter(QObject *p_parent = nullptr); +namespace vnotex { +// Base class of adapter and interface between CPP and JS for WebView. +class WebViewAdapter : public QObject { + Q_OBJECT +public: + explicit WebViewAdapter(QObject *p_parent = nullptr); - bool isReady() const; + bool isReady() const; - void findText(const QStringList &p_texts, FindOptions p_options, int p_currentMatchLine = -1); + void findText(const QStringList &p_texts, FindOptions p_options, int p_currentMatchLine = -1); - // Functions to be called from web side. - public slots: - void setReady(bool p_ready); + // Functions to be called from web side. +public slots: + void setReady(bool p_ready); - void setFindText(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex); + void setFindText(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex); - // Signals to be connected at cpp side. - signals: - void ready(); + // Signals to be connected at cpp side. +signals: + void ready(); - void findTextReady(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex); + void findTextReady(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex); - // Signals to be connected at web side. - signals: - void findTextRequested(const QStringList &p_texts, const QJsonObject &p_options, int p_currentMatchLine); + // Signals to be connected at web side. +signals: + void findTextRequested(const QStringList &p_texts, const QJsonObject &p_options, + int p_currentMatchLine); - protected: - void pendAction(const std::function &p_func); +protected: + void pendAction(const std::function &p_func); - void invokeCallback(quint64 p_id, void *p_data); + void invokeCallback(quint64 p_id, void *p_data); - quint64 addCallback(const CallbackPool::Callback &p_callback); + quint64 addCallback(const CallbackPool::Callback &p_callback); - private: - struct FindOption - { - QJsonObject toJson() const; +private: + struct FindOption { + QJsonObject toJson() const; - bool m_findBackward = false; + bool m_findBackward = false; - bool m_caseSensitive = false; + bool m_caseSensitive = false; - bool m_wholeWordOnly = false; + bool m_wholeWordOnly = false; - bool m_regularExpression = false; - }; + bool m_regularExpression = false; + }; - // Whether web side is ready. - bool m_ready = false; + // Whether web side is ready. + bool m_ready = false; - // Pending actions for the editor once it is ready. - QVector> m_pendingActions; + // Pending actions for the editor once it is ready. + QVector> m_pendingActions; - CallbackPool m_callbackPool; - }; -} + CallbackPool m_callbackPool; +}; +} // namespace vnotex #endif // WEBVIEWADAPTER_H diff --git a/src/widgets/editreaddiscardaction.cpp b/src/widgets/editreaddiscardaction.cpp index 6b1ee96dad..07743ea884 100644 --- a/src/widgets/editreaddiscardaction.cpp +++ b/src/widgets/editreaddiscardaction.cpp @@ -1,58 +1,39 @@ #include "editreaddiscardaction.h" -#include #include +#include #include "widgetsfactory.h" using namespace vnotex; -EditReadDiscardAction::EditReadDiscardAction(const QIcon &p_editIcon, - const QString &p_editText, - const QIcon &p_readIcon, - const QString &p_readText, +EditReadDiscardAction::EditReadDiscardAction(const QIcon &p_editIcon, const QString &p_editText, + const QIcon &p_readIcon, const QString &p_readText, const QIcon &p_discardIcon, - const QString &p_discardText, - QObject *p_parent) - : BiAction(p_editIcon, - p_editText, - p_readIcon, - p_readText, - p_parent) -{ - m_readMenu.reset(WidgetsFactory::createMenu(nullptr)); - m_discardAct = m_readMenu->addAction(p_discardIcon, - p_discardText, - m_readMenu.data(), - [this]() { - emit triggered(Action::Discard); - }); - setStateMenu(State::Alternative, m_readMenu.data()); - - connect(this, &BiAction::triggered, - this, [this]() { - switch (previousState()) { - case State::Default: - emit triggered(Action::Edit); - break; - - case State::Alternative: - emit triggered(Action::Read); - break; - - default: - Q_ASSERT(false); - break; - } - }); + const QString &p_discardText, QObject *p_parent) + : BiAction(p_editIcon, p_editText, p_readIcon, p_readText, p_parent) { + m_readMenu.reset(WidgetsFactory::createMenu(nullptr)); + m_discardAct = m_readMenu->addAction(p_discardIcon, p_discardText, m_readMenu.data(), + [this]() { emit triggered(Action::Discard); }); + setStateMenu(State::Alternative, m_readMenu.data()); + + connect(this, &BiAction::triggered, this, [this]() { + switch (previousState()) { + case State::Default: + emit triggered(Action::Edit); + break; + + case State::Alternative: + emit triggered(Action::Read); + break; + + default: + Q_ASSERT(false); + break; + } + }); } -EditReadDiscardAction::~EditReadDiscardAction() -{ +EditReadDiscardAction::~EditReadDiscardAction() {} -} - -QAction *EditReadDiscardAction::getDiscardAction() const -{ - return m_discardAct; -} +QAction *EditReadDiscardAction::getDiscardAction() const { return m_discardAct; } diff --git a/src/widgets/editreaddiscardaction.h b/src/widgets/editreaddiscardaction.h index bdced1d573..f28485174a 100644 --- a/src/widgets/editreaddiscardaction.h +++ b/src/widgets/editreaddiscardaction.h @@ -5,39 +5,28 @@ #include -namespace vnotex -{ - class EditReadDiscardAction : public BiAction - { - Q_OBJECT - public: - enum Action - { - Edit, - Read, - Discard - }; - - EditReadDiscardAction(const QIcon &p_editIcon, - const QString &p_editText, - const QIcon &p_readIcon, - const QString &p_readText, - const QIcon &p_discardIcon, - const QString &p_discardText, - QObject *p_parent = nullptr); - - ~EditReadDiscardAction(); - - QAction *getDiscardAction() const; - - signals: - void triggered(Action p_act); - - private: - QScopedPointer m_readMenu; - - QAction *m_discardAct = nullptr; - }; -} +namespace vnotex { +class EditReadDiscardAction : public BiAction { + Q_OBJECT +public: + enum Action { Edit, Read, Discard }; + + EditReadDiscardAction(const QIcon &p_editIcon, const QString &p_editText, const QIcon &p_readIcon, + const QString &p_readText, const QIcon &p_discardIcon, + const QString &p_discardText, QObject *p_parent = nullptr); + + ~EditReadDiscardAction(); + + QAction *getDiscardAction() const; + +signals: + void triggered(Action p_act); + +private: + QScopedPointer m_readMenu; + + QAction *m_discardAct = nullptr; +}; +} // namespace vnotex #endif // EDITREADDISCARDACTION_H diff --git a/src/widgets/filesystemviewer.cpp b/src/widgets/filesystemviewer.cpp index f0add9998c..be26ec1525 100644 --- a/src/widgets/filesystemviewer.cpp +++ b/src/widgets/filesystemviewer.cpp @@ -1,242 +1,215 @@ #include "filesystemviewer.h" -#include -#include -#include #include -#include +#include +#include #include +#include +#include -#include -#include -#include -#include -#include -#include "widgetsfactory.h" #include "dialogs/filepropertiesdialog.h" #include "treeview.h" +#include "widgetsfactory.h" +#include +#include +#include +#include +#include using namespace vnotex; -FileSystemViewer::FileSystemViewer(QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(); -} - -void FileSystemViewer::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); +FileSystemViewer::FileSystemViewer(QWidget *p_parent) : QWidget(p_parent) { setupUI(); } + +void FileSystemViewer::setupUI() { + auto mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + + auto fileModel = new QFileSystemModel(this); + + m_viewer = new TreeView(this); + m_viewer->setModel(fileModel); + m_viewer->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_viewer->setHeaderHidden(true); + // Show only the Name column. + for (int i = 1; i < fileModel->columnCount(); ++i) { + m_viewer->hideColumn(i); + } + + 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)) { + QStringList files; + files << this->fileModel()->filePath(p_index); + emit openFiles(files); + } + }); + connect(m_viewer->selectionModel(), &QItemSelectionModel::selectionChanged, this, + &FileSystemViewer::selectionChanged); - auto fileModel = new QFileSystemModel(this); + auto index = fileModel->setRootPath(QDir::homePath()); + m_viewer->setRootIndex(index); - m_viewer = new TreeView(this); - m_viewer->setModel(fileModel); - m_viewer->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_viewer->setHeaderHidden(true); - // Show only the Name column. - for (int i = 1; i < fileModel->columnCount(); ++i) { - m_viewer->hideColumn(i); - } + mainLayout->addWidget(m_viewer); - if (m_contextMenuEnabled) { - m_viewer->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_viewer, &QTreeView::customContextMenuRequested, - this, &FileSystemViewer::handleContextMenuRequested); - } + setFocusProxy(m_viewer); - connect(m_viewer, &QTreeView::activated, - this, [this](const QModelIndex &p_index) { - if (!this->fileModel()->isDir(p_index)) { - QStringList files; - files << this->fileModel()->filePath(p_index); - emit openFiles(files); - } - }); - connect(m_viewer->selectionModel(), &QItemSelectionModel::selectionChanged, - this, &FileSystemViewer::selectionChanged); - - auto index = fileModel->setRootPath(QDir::homePath()); - m_viewer->setRootIndex(index); - - mainLayout->addWidget(m_viewer); - - setFocusProxy(m_viewer); - - connect(m_viewer, &QTreeView::expanded, - this, &FileSystemViewer::resizeTreeToContents); - connect(m_viewer, &QTreeView::collapsed, - this, &FileSystemViewer::resizeTreeToContents); - connect(fileModel, &QFileSystemModel::directoryLoaded, - this, &FileSystemViewer::resizeTreeToContents); + connect(m_viewer, &QTreeView::expanded, this, &FileSystemViewer::resizeTreeToContents); + connect(m_viewer, &QTreeView::collapsed, this, &FileSystemViewer::resizeTreeToContents); + connect(fileModel, &QFileSystemModel::directoryLoaded, this, + &FileSystemViewer::resizeTreeToContents); } -void FileSystemViewer::resizeTreeToContents() -{ - m_viewer->resizeColumnToContents(0); -} +void FileSystemViewer::resizeTreeToContents() { m_viewer->resizeColumnToContents(0); } -QFileSystemModel *FileSystemViewer::fileModel() const -{ - return static_cast(m_viewer->model()); +QFileSystemModel *FileSystemViewer::fileModel() const { + return static_cast(m_viewer->model()); } -int FileSystemViewer::selectedCount() const -{ - return m_viewer->selectionModel()->selectedRows().size(); +int FileSystemViewer::selectedCount() const { + return m_viewer->selectionModel()->selectedRows().size(); } -QModelIndex FileSystemViewer::getSelectedIndex() const -{ - const auto modelIndexList = m_viewer->selectionModel()->selectedRows(); - return modelIndexList.size() == 1 ? modelIndexList[0] : QModelIndex(); +QModelIndex FileSystemViewer::getSelectedIndex() const { + const auto modelIndexList = m_viewer->selectionModel()->selectedRows(); + return modelIndexList.size() == 1 ? modelIndexList[0] : QModelIndex(); } -void FileSystemViewer::setRootPath(const QString &p_rootPath) -{ - auto model = fileModel(); - auto index = model->setRootPath(p_rootPath); - if (!index.isValid()) { - qWarning() << "failed to set root path to" << p_rootPath; - index = model->setRootPath(""); - } +void FileSystemViewer::setRootPath(const QString &p_rootPath) { + auto model = fileModel(); + auto index = model->setRootPath(p_rootPath); + if (!index.isValid()) { + qWarning() << "failed to set root path to" << p_rootPath; + index = model->setRootPath(""); + } - m_viewer->setRootIndex(index); - resizeTreeToContents(); + m_viewer->setRootIndex(index); + resizeTreeToContents(); } -QString FileSystemViewer::rootPath() const -{ - return fileModel()->rootPath(); -} +QString FileSystemViewer::rootPath() const { return fileModel()->rootPath(); } -QStringList FileSystemViewer::getSelectedPaths() const -{ - const auto modelIndexList = m_viewer->selectionModel()->selectedRows(); - auto model = fileModel(); - QStringList filePaths; - for (const auto &index : modelIndexList) { - filePaths << model->filePath(index); - } +QStringList FileSystemViewer::getSelectedPaths() const { + const auto modelIndexList = m_viewer->selectionModel()->selectedRows(); + auto model = fileModel(); + QStringList filePaths; + for (const auto &index : modelIndexList) { + filePaths << model->filePath(index); + } - return filePaths; + return filePaths; } -void FileSystemViewer::createContextMenuOnItem(QMenu *p_menu) -{ - auto act = createAction(Action::Open, p_menu); - p_menu->addAction(act); - - act = createAction(Action::Delete, p_menu); - p_menu->addAction(act); +void FileSystemViewer::createContextMenuOnItem(QMenu *p_menu) { + auto act = createAction(Action::Open, p_menu); + p_menu->addAction(act); - if (selectedCount() == 1) { - act = createAction(Action::CopyPath, p_menu); - p_menu->addAction(act); + act = createAction(Action::Delete, p_menu); + p_menu->addAction(act); - act = createAction(Action::Properties, p_menu); - p_menu->addAction(act); - } -} + if (selectedCount() == 1) { + act = createAction(Action::CopyPath, p_menu); + p_menu->addAction(act); -QAction *FileSystemViewer::createAction(Action p_act, QObject *p_parent) -{ - QAction *act = nullptr; - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - switch (p_act) { - case Action::Open: - act = new QAction(tr("&Open"), p_parent); - connect(act, &QAction::triggered, - this, [this]() { - auto paths = getSelectedPaths(); - Q_ASSERT(paths.size() > 0); - emit openFiles(paths); - }); - break; - - case Action::Delete: - act = new QAction(tr("&Delete"), p_parent); - connect(act, &QAction::triggered, - this, [this]() { - auto paths = getSelectedPaths(); - emit removeFiles(paths); - }); - break; - - case Action::Properties: - act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile("properties.svg")), - tr("&Properties"), - p_parent); - connect(act, &QAction::triggered, - this, [this]() { - auto paths = getSelectedPaths(); - Q_ASSERT(paths.size() == 1); - FilePropertiesDialog dialog(paths[0], this); - int ret = dialog.exec(); - if (ret) { - auto newName = dialog.getFileName(); - if (newName != PathUtils::fileName(paths[0])) { - // Rename. - emit renameFile(paths[0], newName); - } - } - }); - break; - - case Action::CopyPath: - act = new QAction(tr("Cop&y Path"), p_parent); - connect(act, &QAction::triggered, - this, [this]() { - auto paths = getSelectedPaths(); - Q_ASSERT(paths.size() == 1); - ClipboardUtils::setTextToClipboard(paths[0]); - VNoteX::getInst().showStatusMessageShort(tr("Copied path: %1").arg(paths[0])); - }); - break; - } - return act; + act = createAction(Action::Properties, p_menu); + p_menu->addAction(act); + } } -void FileSystemViewer::scrollToAndSelect(const QStringList &p_paths) -{ - auto selectionModel = m_viewer->selectionModel(); - selectionModel->clear(); - - bool isFirst = true; - auto model = fileModel(); - for (const auto &pa : p_paths) { - auto index = model->index(pa); - if (index.isValid()) { - if (isFirst) { - m_viewer->scrollTo(index); - isFirst = false; - } - selectionModel->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); +QAction *FileSystemViewer::createAction(Action p_act, QObject *p_parent) { + QAction *act = nullptr; + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + switch (p_act) { + case Action::Open: + act = new QAction(tr("&Open"), p_parent); + connect(act, &QAction::triggered, this, [this]() { + auto paths = getSelectedPaths(); + Q_ASSERT(paths.size() > 0); + emit openFiles(paths); + }); + break; + + case Action::Delete: + act = new QAction(tr("&Delete"), p_parent); + connect(act, &QAction::triggered, this, [this]() { + auto paths = getSelectedPaths(); + emit removeFiles(paths); + }); + break; + + case Action::Properties: + act = new QAction(IconUtils::fetchIconWithDisabledState(themeMgr.getIconFile("properties.svg")), + tr("&Properties"), p_parent); + connect(act, &QAction::triggered, this, [this]() { + auto paths = getSelectedPaths(); + Q_ASSERT(paths.size() == 1); + FilePropertiesDialog dialog(paths[0], this); + int ret = dialog.exec(); + if (ret) { + auto newName = dialog.getFileName(); + if (newName != PathUtils::fileName(paths[0])) { + // Rename. + emit renameFile(paths[0], newName); } - } + } + }); + break; + + case Action::CopyPath: + act = new QAction(tr("Cop&y Path"), p_parent); + connect(act, &QAction::triggered, this, [this]() { + auto paths = getSelectedPaths(); + Q_ASSERT(paths.size() == 1); + ClipboardUtils::setTextToClipboard(paths[0]); + VNoteX::getInst().showStatusMessageShort(tr("Copied path: %1").arg(paths[0])); + }); + break; + } + return act; } -void FileSystemViewer::handleContextMenuRequested(const QPoint &p_pos) -{ - QScopedPointer menu(WidgetsFactory::createMenu()); +void FileSystemViewer::scrollToAndSelect(const QStringList &p_paths) { + auto selectionModel = m_viewer->selectionModel(); + selectionModel->clear(); - auto index = m_viewer->indexAt(p_pos); + bool isFirst = true; + auto model = fileModel(); + for (const auto &pa : p_paths) { + auto index = model->index(pa); if (index.isValid()) { - auto selectionModel = m_viewer->selectionModel(); - if (!selectionModel->isSelected(index)) { - // Must select entire row since we use selectedRows() to count. - selectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - } + if (isFirst) { + m_viewer->scrollTo(index); + isFirst = false; + } + selectionModel->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } + } +} - m_viewer->update(); +void FileSystemViewer::handleContextMenuRequested(const QPoint &p_pos) { + QScopedPointer menu(WidgetsFactory::createMenu()); - createContextMenuOnItem(menu.data()); + auto index = m_viewer->indexAt(p_pos); + if (index.isValid()) { + auto selectionModel = m_viewer->selectionModel(); + if (!selectionModel->isSelected(index)) { + // Must select entire row since we use selectedRows() to count. + selectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | + QItemSelectionModel::Rows); } m_viewer->update(); - if (!menu->isEmpty()) { - menu->exec(m_viewer->mapToGlobal(p_pos)); - } + createContextMenuOnItem(menu.data()); + } + + m_viewer->update(); + + if (!menu->isEmpty()) { + menu->exec(m_viewer->mapToGlobal(p_pos)); + } } diff --git a/src/widgets/filesystemviewer.h b/src/widgets/filesystemviewer.h index 88276ffe50..3dd7a456d3 100644 --- a/src/widgets/filesystemviewer.h +++ b/src/widgets/filesystemviewer.h @@ -1,71 +1,64 @@ #ifndef FILESYSTEMVIEWER_H #define FILESYSTEMVIEWER_H -#include #include +#include class QTreeView; class QFileSystemModel; class QMenu; -namespace vnotex -{ - class FileSystemViewer : public QWidget - { - Q_OBJECT - public: - explicit FileSystemViewer(QWidget *p_parent = nullptr); +namespace vnotex { +class FileSystemViewer : public QWidget { + Q_OBJECT +public: + explicit FileSystemViewer(QWidget *p_parent = nullptr); - int selectedCount() const; + int selectedCount() const; - void setRootPath(const QString &p_rootPath); + void setRootPath(const QString &p_rootPath); - QString rootPath() const; + QString rootPath() const; - QStringList getSelectedPaths() const; + QStringList getSelectedPaths() const; - void scrollToAndSelect(const QStringList &p_paths); + void scrollToAndSelect(const QStringList &p_paths); - signals: - void renameFile(const QString &p_path, const QString &p_name); +signals: + void renameFile(const QString &p_path, const QString &p_name); - // Should detect children relationship. - void removeFiles(const QStringList &p_paths); + // Should detect children relationship. + void removeFiles(const QStringList &p_paths); - void openFiles(const QStringList &p_paths); + void openFiles(const QStringList &p_paths); - void selectionChanged(); + void selectionChanged(); - private slots: - // Resize the first column. - void resizeTreeToContents(); +private slots: + // Resize the first column. + void resizeTreeToContents(); - void handleContextMenuRequested(const QPoint &p_pos); + void handleContextMenuRequested(const QPoint &p_pos); - private: - enum Action { - Open, - Delete, - Properties, - CopyPath - }; +private: + enum Action { Open, Delete, Properties, CopyPath }; - void setupUI(); + void setupUI(); - QFileSystemModel *fileModel() const; + QFileSystemModel *fileModel() const; - // Valid only when there is only one selected index. - QModelIndex getSelectedIndex() const; + // Valid only when there is only one selected index. + QModelIndex getSelectedIndex() const; - void createContextMenuOnItem(QMenu *p_menu); + void createContextMenuOnItem(QMenu *p_menu); - QAction *createAction(Action p_act, QObject *p_parent); + QAction *createAction(Action p_act, QObject *p_parent); - // Managed by QObject. - QTreeView *m_viewer = nullptr; + // Managed by QObject. + QTreeView *m_viewer = nullptr; - bool m_contextMenuEnabled = false; - }; -} + bool m_contextMenuEnabled = false; +}; +} // namespace vnotex #endif // FILESYSTEMVIEWER_H diff --git a/src/widgets/findandreplacewidget.cpp b/src/widgets/findandreplacewidget.cpp index 8b2b220fd2..cb03fdf02e 100644 --- a/src/widgets/findandreplacewidget.cpp +++ b/src/widgets/findandreplacewidget.cpp @@ -1,343 +1,315 @@ #include "findandreplacewidget.h" -#include -#include -#include -#include -#include -#include #include #include +#include +#include #include +#include +#include #include +#include +#include #include "lineedit.h" -#include "widgetsfactory.h" -#include -#include -#include -#include #include "propertydefs.h" +#include "widgetsfactory.h" #include #include +#include +#include +#include +#include #include using namespace vnotex; -FindAndReplaceWidget::FindAndReplaceWidget(QWidget *p_parent) - : QWidget(p_parent) -{ - m_findTextTimer = new QTimer(this); - m_findTextTimer->setSingleShot(true); - m_findTextTimer->setInterval(500); - connect(m_findTextTimer, &QTimer::timeout, - this, [this]() { - emit findTextChanged(getFindText(), getOptions()); - }); - - setupUI(); - - auto options = ConfigMgr::getInst().getWidgetConfig().getFindAndReplaceOptions(); - setFindOptions(options); -} - -void FindAndReplaceWidget::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - - // Title. - { - auto titleLayout = new QHBoxLayout(); - titleLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addLayout(titleLayout); - - auto label = new QLabel(tr("Find And Replace"), this); - titleLayout->addWidget(label); - - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - auto iconFile = themeMgr.getIconFile(QStringLiteral("close.svg")); - auto closeBtn = new QToolButton(this); - closeBtn->setProperty(PropertyDefs::c_actionToolButton, true); - titleLayout->addWidget(closeBtn); - - auto closeAct = new QAction(IconUtils::fetchIcon(iconFile), QString(), closeBtn); - closeAct->setToolTip(tr("Close")); - closeBtn->setDefaultAction(closeAct); - connect(closeAct, &QAction::triggered, - this, &FindAndReplaceWidget::close); - } - - auto gridLayout = new QGridLayout(); - gridLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addLayout(gridLayout); - - // Find. - { - auto label = new QLabel(tr("Find:"), this); - - m_findLineEdit = WidgetsFactory::createLineEdit(this); - m_findLineEdit->setPlaceholderText(tr("Search")); - m_findLineEdit->setClearButtonEnabled(true); - connect(m_findLineEdit, &QLineEdit::textChanged, - m_findTextTimer, QOverload<>::of(&QTimer::start)); - - setFocusProxy(m_findLineEdit); - - const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); - - auto findNextBtn = new QPushButton(tr("Find &Next"), this); - WidgetUtils::addButtonShortcutText(findNextBtn, editorConfig.getShortcut(EditorConfig::FindNext)); - findNextBtn->setDefault(true); - connect(findNextBtn, &QPushButton::clicked, - this, &FindAndReplaceWidget::findNext); +FindAndReplaceWidget::FindAndReplaceWidget(QWidget *p_parent) : QWidget(p_parent) { + m_findTextTimer = new QTimer(this); + m_findTextTimer->setSingleShot(true); + m_findTextTimer->setInterval(500); + connect(m_findTextTimer, &QTimer::timeout, this, + [this]() { emit findTextChanged(getFindText(), getOptions()); }); - auto findPrevBtn = new QPushButton(tr("Find &Previous"), this); - WidgetUtils::addButtonShortcutText(findPrevBtn, editorConfig.getShortcut(EditorConfig::FindPrevious)); - connect(findPrevBtn, &QPushButton::clicked, - this, &FindAndReplaceWidget::findPrevious); + setupUI(); - gridLayout->addWidget(label, 0, 0); - gridLayout->addWidget(m_findLineEdit, 0, 1); - gridLayout->addWidget(findNextBtn, 0, 2); - gridLayout->addWidget(findPrevBtn, 0, 3); - } - - // Replace. - { - auto label = new QLabel(tr("Replace with:"), this); - - m_replaceLineEdit = WidgetsFactory::createLineEdit(this); - m_replaceLineEdit->setPlaceholderText(tr("\\1, \\2 for back reference in regular expression")); - m_replaceRelatedWidgets.push_back(m_replaceLineEdit); - - auto replaceBtn = new QPushButton(tr("Replace"), this); - connect(replaceBtn, &QPushButton::clicked, - this, &FindAndReplaceWidget::replace); - m_replaceRelatedWidgets.push_back(replaceBtn); - - auto replaceFindBtn = new QPushButton(tr("Replace And Find"), this); - connect(replaceFindBtn, &QPushButton::clicked, - this, &FindAndReplaceWidget::replaceAndFind); - m_replaceRelatedWidgets.push_back(replaceFindBtn); - - auto replaceAllBtn = new QPushButton(tr("Replace All"), this); - connect(replaceAllBtn, &QPushButton::clicked, - this, &FindAndReplaceWidget::replaceAll); - m_replaceRelatedWidgets.push_back(replaceAllBtn); - - gridLayout->addWidget(label, 1, 0); - gridLayout->addWidget(m_replaceLineEdit, 1, 1); - gridLayout->addWidget(replaceBtn, 1, 2); - gridLayout->addWidget(replaceFindBtn, 1, 3); - gridLayout->addWidget(replaceAllBtn, 1, 4); - } - - // Options. - { - auto optionLayout = new QHBoxLayout(); - optionLayout->setContentsMargins(0, 0, 0, 0); - gridLayout->addLayout(optionLayout, 2, 1, 1, 4); - - m_caseSensitiveCheckBox = WidgetsFactory::createCheckBox(tr("&Case sensitive"), this); - connect(m_caseSensitiveCheckBox, &QCheckBox::stateChanged, - this, &FindAndReplaceWidget::updateFindOptions); - optionLayout->addWidget(m_caseSensitiveCheckBox); - - m_wholeWordOnlyCheckBox = WidgetsFactory::createCheckBox(tr("&Whole word only"), this); - connect(m_wholeWordOnlyCheckBox, &QCheckBox::stateChanged, - this, &FindAndReplaceWidget::updateFindOptions); - optionLayout->addWidget(m_wholeWordOnlyCheckBox); - - m_regularExpressionCheckBox = WidgetsFactory::createCheckBox(tr("Re&gular expression"), this); - connect(m_regularExpressionCheckBox, &QCheckBox::stateChanged, - this, &FindAndReplaceWidget::updateFindOptions); - optionLayout->addWidget(m_regularExpressionCheckBox); - - m_incrementalSearchCheckBox = WidgetsFactory::createCheckBox(tr("&Incremental search"), this); - connect(m_incrementalSearchCheckBox, &QCheckBox::stateChanged, - this, &FindAndReplaceWidget::updateFindOptions); - optionLayout->addWidget(m_incrementalSearchCheckBox); - - optionLayout->addStretch(); - } + auto options = ConfigMgr::getInst().getWidgetConfig().getFindAndReplaceOptions(); + setFindOptions(options); } -void FindAndReplaceWidget::close() -{ - hide(); - emit closed(); +void FindAndReplaceWidget::setupUI() { + auto mainLayout = new QVBoxLayout(this); + + // Title. + { + auto titleLayout = new QHBoxLayout(); + titleLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addLayout(titleLayout); + + auto label = new QLabel(tr("Find And Replace"), this); + titleLayout->addWidget(label); + + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + auto iconFile = themeMgr.getIconFile(QStringLiteral("close.svg")); + auto closeBtn = new QToolButton(this); + closeBtn->setProperty(PropertyDefs::c_actionToolButton, true); + titleLayout->addWidget(closeBtn); + + auto closeAct = new QAction(IconUtils::fetchIcon(iconFile), QString(), closeBtn); + closeAct->setToolTip(tr("Close")); + closeBtn->setDefaultAction(closeAct); + connect(closeAct, &QAction::triggered, this, &FindAndReplaceWidget::close); + } + + auto gridLayout = new QGridLayout(); + gridLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addLayout(gridLayout); + + // Find. + { + auto label = new QLabel(tr("Find:"), this); + + m_findLineEdit = WidgetsFactory::createLineEdit(this); + m_findLineEdit->setPlaceholderText(tr("Search")); + m_findLineEdit->setClearButtonEnabled(true); + connect(m_findLineEdit, &QLineEdit::textChanged, m_findTextTimer, + QOverload<>::of(&QTimer::start)); + + setFocusProxy(m_findLineEdit); + + const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); + + auto findNextBtn = new QPushButton(tr("Find &Next"), this); + WidgetUtils::addButtonShortcutText(findNextBtn, + editorConfig.getShortcut(EditorConfig::FindNext)); + findNextBtn->setDefault(true); + connect(findNextBtn, &QPushButton::clicked, this, &FindAndReplaceWidget::findNext); + + auto findPrevBtn = new QPushButton(tr("Find &Previous"), this); + WidgetUtils::addButtonShortcutText(findPrevBtn, + editorConfig.getShortcut(EditorConfig::FindPrevious)); + connect(findPrevBtn, &QPushButton::clicked, this, &FindAndReplaceWidget::findPrevious); + + gridLayout->addWidget(label, 0, 0); + gridLayout->addWidget(m_findLineEdit, 0, 1); + gridLayout->addWidget(findNextBtn, 0, 2); + gridLayout->addWidget(findPrevBtn, 0, 3); + } + + // Replace. + { + auto label = new QLabel(tr("Replace with:"), this); + + m_replaceLineEdit = WidgetsFactory::createLineEdit(this); + m_replaceLineEdit->setPlaceholderText(tr("\\1, \\2 for back reference in regular expression")); + m_replaceRelatedWidgets.push_back(m_replaceLineEdit); + + auto replaceBtn = new QPushButton(tr("Replace"), this); + connect(replaceBtn, &QPushButton::clicked, this, &FindAndReplaceWidget::replace); + m_replaceRelatedWidgets.push_back(replaceBtn); + + auto replaceFindBtn = new QPushButton(tr("Replace And Find"), this); + connect(replaceFindBtn, &QPushButton::clicked, this, &FindAndReplaceWidget::replaceAndFind); + m_replaceRelatedWidgets.push_back(replaceFindBtn); + + auto replaceAllBtn = new QPushButton(tr("Replace All"), this); + connect(replaceAllBtn, &QPushButton::clicked, this, &FindAndReplaceWidget::replaceAll); + m_replaceRelatedWidgets.push_back(replaceAllBtn); + + gridLayout->addWidget(label, 1, 0); + gridLayout->addWidget(m_replaceLineEdit, 1, 1); + gridLayout->addWidget(replaceBtn, 1, 2); + gridLayout->addWidget(replaceFindBtn, 1, 3); + gridLayout->addWidget(replaceAllBtn, 1, 4); + } + + // Options. + { + auto optionLayout = new QHBoxLayout(); + optionLayout->setContentsMargins(0, 0, 0, 0); + gridLayout->addLayout(optionLayout, 2, 1, 1, 4); + + m_caseSensitiveCheckBox = WidgetsFactory::createCheckBox(tr("&Case sensitive"), this); + connect(m_caseSensitiveCheckBox, &QCheckBox::stateChanged, this, + &FindAndReplaceWidget::updateFindOptions); + optionLayout->addWidget(m_caseSensitiveCheckBox); + + m_wholeWordOnlyCheckBox = WidgetsFactory::createCheckBox(tr("&Whole word only"), this); + connect(m_wholeWordOnlyCheckBox, &QCheckBox::stateChanged, this, + &FindAndReplaceWidget::updateFindOptions); + optionLayout->addWidget(m_wholeWordOnlyCheckBox); + + m_regularExpressionCheckBox = WidgetsFactory::createCheckBox(tr("Re&gular expression"), this); + connect(m_regularExpressionCheckBox, &QCheckBox::stateChanged, this, + &FindAndReplaceWidget::updateFindOptions); + optionLayout->addWidget(m_regularExpressionCheckBox); + + m_incrementalSearchCheckBox = WidgetsFactory::createCheckBox(tr("&Incremental search"), this); + connect(m_incrementalSearchCheckBox, &QCheckBox::stateChanged, this, + &FindAndReplaceWidget::updateFindOptions); + optionLayout->addWidget(m_incrementalSearchCheckBox); + + optionLayout->addStretch(); + } } -void FindAndReplaceWidget::setReplaceEnabled(bool p_enabled) -{ - for (auto widget : m_replaceRelatedWidgets) { - widget->setEnabled(p_enabled); - } +void FindAndReplaceWidget::close() { + hide(); + emit closed(); } -void FindAndReplaceWidget::keyPressEvent(QKeyEvent *p_event) -{ - switch (p_event->key()) { - case Qt::Key_Escape: - close(); - return; - - case Qt::Key_Return: - { - const int modifiers = p_event->modifiers(); - if (modifiers != Qt::ShiftModifier && modifiers != Qt::NoModifier) { - break; - } - - if (!m_findLineEdit->hasFocus() && !m_replaceLineEdit->hasFocus()) { - break; - } - - if (modifiers == Qt::ShiftModifier) { - findPrevious(); - } else { - findNext(); - } - return; - } - - default: - break; - } - QWidget::keyPressEvent(p_event); +void FindAndReplaceWidget::setReplaceEnabled(bool p_enabled) { + for (auto widget : m_replaceRelatedWidgets) { + widget->setEnabled(p_enabled); + } } -void FindAndReplaceWidget::findNext() -{ - m_findTextTimer->stop(); - auto text = m_findLineEdit->text(); - if (text.isEmpty()) { - return; - } - emit findNextRequested(text, m_options); -} +void FindAndReplaceWidget::keyPressEvent(QKeyEvent *p_event) { + switch (p_event->key()) { + case Qt::Key_Escape: + close(); + return; -void FindAndReplaceWidget::findPrevious() -{ - m_findTextTimer->stop(); - auto text = m_findLineEdit->text(); - if (text.isEmpty()) { - return; + case Qt::Key_Return: { + const int modifiers = p_event->modifiers(); + if (modifiers != Qt::ShiftModifier && modifiers != Qt::NoModifier) { + break; } - emit findNextRequested(text, m_options | FindOption::FindBackward); -} -void FindAndReplaceWidget::updateFindOptions() -{ - if (m_optionCheckBoxMuted) { - return; + if (!m_findLineEdit->hasFocus() && !m_replaceLineEdit->hasFocus()) { + break; } - FindOptions options = FindOption::FindNone; - - if (m_caseSensitiveCheckBox->isChecked()) { - options |= FindOption::CaseSensitive; - } - if (m_wholeWordOnlyCheckBox->isChecked()) { - options |= FindOption::WholeWordOnly; - } - if (m_regularExpressionCheckBox->isChecked()) { - options |= FindOption::RegularExpression; - } - if (m_incrementalSearchCheckBox->isChecked()) { - options |= FindOption::IncrementalSearch; + if (modifiers == Qt::ShiftModifier) { + findPrevious(); + } else { + findNext(); } + return; + } - if (options == m_options) { - return; - } - m_options = options; - ConfigMgr::getInst().getWidgetConfig().setFindAndReplaceOptions(m_options); - m_findTextTimer->start(); + default: + break; + } + QWidget::keyPressEvent(p_event); } -void FindAndReplaceWidget::replace() -{ - m_findTextTimer->stop(); - auto text = m_findLineEdit->text(); - if (text.isEmpty()) { - return; - } - emit replaceRequested(text, m_options, m_replaceLineEdit->text()); +void FindAndReplaceWidget::findNext() { + m_findTextTimer->stop(); + auto text = m_findLineEdit->text(); + if (text.isEmpty()) { + return; + } + emit findNextRequested(text, m_options); } -void FindAndReplaceWidget::replaceAndFind() -{ - m_findTextTimer->stop(); - auto text = m_findLineEdit->text(); - if (text.isEmpty()) { - return; - } - emit replaceRequested(text, m_options, m_replaceLineEdit->text()); - emit findNextRequested(text, m_options); +void FindAndReplaceWidget::findPrevious() { + m_findTextTimer->stop(); + auto text = m_findLineEdit->text(); + if (text.isEmpty()) { + return; + } + emit findNextRequested(text, m_options | FindOption::FindBackward); } -void FindAndReplaceWidget::replaceAll() -{ - m_findTextTimer->stop(); - auto text = m_findLineEdit->text(); - if (text.isEmpty()) { - return; - } - emit replaceAllRequested(text, m_options, m_replaceLineEdit->text()); +void FindAndReplaceWidget::updateFindOptions() { + if (m_optionCheckBoxMuted) { + return; + } + + FindOptions options = FindOption::FindNone; + + if (m_caseSensitiveCheckBox->isChecked()) { + options |= FindOption::CaseSensitive; + } + if (m_wholeWordOnlyCheckBox->isChecked()) { + options |= FindOption::WholeWordOnly; + } + if (m_regularExpressionCheckBox->isChecked()) { + options |= FindOption::RegularExpression; + } + if (m_incrementalSearchCheckBox->isChecked()) { + options |= FindOption::IncrementalSearch; + } + + if (options == m_options) { + return; + } + m_options = options; + ConfigMgr::getInst().getWidgetConfig().setFindAndReplaceOptions(m_options); + m_findTextTimer->start(); } -void FindAndReplaceWidget::setFindOptions(FindOptions p_options) -{ - if (p_options == m_options) { - return; - } +void FindAndReplaceWidget::replace() { + m_findTextTimer->stop(); + auto text = m_findLineEdit->text(); + if (text.isEmpty()) { + return; + } + emit replaceRequested(text, m_options, m_replaceLineEdit->text()); +} - m_optionCheckBoxMuted = true; - m_options = p_options & ~FindOption::FindBackward; - m_caseSensitiveCheckBox->setChecked(m_options & FindOption::CaseSensitive); - m_wholeWordOnlyCheckBox->setChecked(m_options & FindOption::WholeWordOnly); - m_regularExpressionCheckBox->setChecked(m_options & FindOption::RegularExpression); - m_incrementalSearchCheckBox->setChecked(m_options & FindOption::IncrementalSearch); - m_optionCheckBoxMuted = false; +void FindAndReplaceWidget::replaceAndFind() { + m_findTextTimer->stop(); + auto text = m_findLineEdit->text(); + if (text.isEmpty()) { + return; + } + emit replaceRequested(text, m_options, m_replaceLineEdit->text()); + emit findNextRequested(text, m_options); } -void FindAndReplaceWidget::open(const QString &p_text) -{ - show(); +void FindAndReplaceWidget::replaceAll() { + m_findTextTimer->stop(); + auto text = m_findLineEdit->text(); + if (text.isEmpty()) { + return; + } + emit replaceAllRequested(text, m_options, m_replaceLineEdit->text()); +} - if (!p_text.isEmpty()) { - m_findLineEdit->setText(p_text); - } +void FindAndReplaceWidget::setFindOptions(FindOptions p_options) { + if (p_options == m_options) { + return; + } + + m_optionCheckBoxMuted = true; + m_options = p_options & ~FindOption::FindBackward; + m_caseSensitiveCheckBox->setChecked(m_options & FindOption::CaseSensitive); + m_wholeWordOnlyCheckBox->setChecked(m_options & FindOption::WholeWordOnly); + m_regularExpressionCheckBox->setChecked(m_options & FindOption::RegularExpression); + m_incrementalSearchCheckBox->setChecked(m_options & FindOption::IncrementalSearch); + m_optionCheckBoxMuted = false; +} - m_findLineEdit->setFocus(); - m_findLineEdit->selectAll(); +void FindAndReplaceWidget::open(const QString &p_text) { + show(); - emit opened(); -} + if (!p_text.isEmpty()) { + m_findLineEdit->setText(p_text); + } -QString FindAndReplaceWidget::getFindText() const -{ - return m_findLineEdit->text(); -} + m_findLineEdit->setFocus(); + m_findLineEdit->selectAll(); -FindOptions FindAndReplaceWidget::getOptions() const -{ - return m_options; + emit opened(); } -void FindAndReplaceWidget::setOptionsEnabled(FindOptions p_options, bool p_enabled) -{ - if (p_options & FindOption::CaseSensitive) { - m_caseSensitiveCheckBox->setEnabled(p_enabled); - } - if (p_options & FindOption::WholeWordOnly) { - m_wholeWordOnlyCheckBox->setEnabled(p_enabled); - } - if (p_options & FindOption::RegularExpression) { - m_regularExpressionCheckBox->setEnabled(p_enabled); - } - if (p_options & FindOption::IncrementalSearch) { - m_incrementalSearchCheckBox->setEnabled(p_enabled); - } +QString FindAndReplaceWidget::getFindText() const { return m_findLineEdit->text(); } + +FindOptions FindAndReplaceWidget::getOptions() const { return m_options; } + +void FindAndReplaceWidget::setOptionsEnabled(FindOptions p_options, bool p_enabled) { + if (p_options & FindOption::CaseSensitive) { + m_caseSensitiveCheckBox->setEnabled(p_enabled); + } + if (p_options & FindOption::WholeWordOnly) { + m_wholeWordOnlyCheckBox->setEnabled(p_enabled); + } + if (p_options & FindOption::RegularExpression) { + m_regularExpressionCheckBox->setEnabled(p_enabled); + } + if (p_options & FindOption::IncrementalSearch) { + m_incrementalSearchCheckBox->setEnabled(p_enabled); + } } diff --git a/src/widgets/findandreplacewidget.h b/src/widgets/findandreplacewidget.h index 4db41ce3cd..a9fb3d8349 100644 --- a/src/widgets/findandreplacewidget.h +++ b/src/widgets/findandreplacewidget.h @@ -11,80 +11,79 @@ class QLineEdit; class QCheckBox; class QTimer; -namespace vnotex -{ - class FindAndReplaceWidget : public QWidget - { - Q_OBJECT - public: - explicit FindAndReplaceWidget(QWidget *p_parent = nullptr); +namespace vnotex { +class FindAndReplaceWidget : public QWidget { + Q_OBJECT +public: + explicit FindAndReplaceWidget(QWidget *p_parent = nullptr); - void setReplaceEnabled(bool p_enabled); + void setReplaceEnabled(bool p_enabled); - void open(const QString &p_text); + void open(const QString &p_text); - void close(); + void close(); - QString getFindText() const; + QString getFindText() const; - FindOptions getOptions() const; + FindOptions getOptions() const; - void setOptionsEnabled(FindOptions p_options, bool p_enabled); + void setOptionsEnabled(FindOptions p_options, bool p_enabled); - signals: - void findTextChanged(const QString &p_text, FindOptions p_options); +signals: + void findTextChanged(const QString &p_text, FindOptions p_options); - void findNextRequested(const QString &p_text, FindOptions p_options); + void findNextRequested(const QString &p_text, FindOptions p_options); - void replaceRequested(const QString &p_text, FindOptions p_options, const QString &p_replaceText); + void replaceRequested(const QString &p_text, FindOptions p_options, const QString &p_replaceText); - void replaceAllRequested(const QString &p_text, FindOptions p_options, const QString &p_replaceText); + void replaceAllRequested(const QString &p_text, FindOptions p_options, + const QString &p_replaceText); - void closed(); + void closed(); - void opened(); + void opened(); - protected: - void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; +protected: + void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; - private slots: - void findNext(); +private slots: + void findNext(); - void findPrevious(); + void findPrevious(); - void updateFindOptions(); + void updateFindOptions(); - void replace(); + void replace(); - void replaceAndFind(); + void replaceAndFind(); - void replaceAll(); + void replaceAll(); - private: - void setupUI(); +private: + void setupUI(); - void setFindOptions(FindOptions p_options); + void setFindOptions(FindOptions p_options); - QLineEdit *m_findLineEdit = nullptr; + QLineEdit *m_findLineEdit = nullptr; - QLineEdit *m_replaceLineEdit = nullptr; + QLineEdit *m_replaceLineEdit = nullptr; - QVector m_replaceRelatedWidgets; + QVector m_replaceRelatedWidgets; - QCheckBox *m_caseSensitiveCheckBox = nullptr; + QCheckBox *m_caseSensitiveCheckBox = nullptr; - QCheckBox *m_wholeWordOnlyCheckBox = nullptr; + QCheckBox *m_wholeWordOnlyCheckBox = nullptr; - QCheckBox *m_regularExpressionCheckBox = nullptr; + QCheckBox *m_regularExpressionCheckBox = nullptr; - QCheckBox *m_incrementalSearchCheckBox = nullptr; + QCheckBox *m_incrementalSearchCheckBox = nullptr; - FindOptions m_options = FindOption::FindNone; + FindOptions m_options = FindOption::FindNone; - QTimer *m_findTextTimer = nullptr; + QTimer *m_findTextTimer = nullptr; - bool m_optionCheckBoxMuted = false; - }; -} + bool m_optionCheckBoxMuted = false; +}; +} // namespace vnotex #endif // FINDANDREPLACEWIDGET_H diff --git a/src/widgets/floatingwidget.cpp b/src/widgets/floatingwidget.cpp index b7d0069bfd..f5262ae3cc 100644 --- a/src/widgets/floatingwidget.cpp +++ b/src/widgets/floatingwidget.cpp @@ -4,29 +4,21 @@ using namespace vnotex; -FloatingWidget::FloatingWidget(QWidget *p_parent) - : QWidget(p_parent) -{ -} +FloatingWidget::FloatingWidget(QWidget *p_parent) : QWidget(p_parent) {} -void FloatingWidget::showEvent(QShowEvent *p_event) -{ - QWidget::showEvent(p_event); +void FloatingWidget::showEvent(QShowEvent *p_event) { + QWidget::showEvent(p_event); - // May fix potential input method issue. - activateWindow(); + // May fix potential input method issue. + activateWindow(); - setFocus(); + setFocus(); } -void FloatingWidget::finish() -{ - if (m_menu) { - m_menu->hide(); - } +void FloatingWidget::finish() { + if (m_menu) { + m_menu->hide(); + } } -void FloatingWidget::setMenu(QMenu *p_menu) -{ - m_menu = p_menu; -} +void FloatingWidget::setMenu(QMenu *p_menu) { m_menu = p_menu; } diff --git a/src/widgets/floatingwidget.h b/src/widgets/floatingwidget.h index db5c95aca9..4dbd320a34 100644 --- a/src/widgets/floatingwidget.h +++ b/src/widgets/floatingwidget.h @@ -1,33 +1,31 @@ #ifndef FLOATINGWIDGET_H #define FLOATINGWIDGET_H -#include #include +#include class QMenu; -namespace vnotex -{ - // Used for ViewWindow to show as a floating widget (usually via QMenu). - class FloatingWidget : public QWidget - { - Q_OBJECT - public: - void setMenu(QMenu *p_menu); +namespace vnotex { +// Used for ViewWindow to show as a floating widget (usually via QMenu). +class FloatingWidget : public QWidget { + Q_OBJECT +public: + void setMenu(QMenu *p_menu); - virtual QVariant result() const = 0; + virtual QVariant result() const = 0; - protected: - FloatingWidget(QWidget *p_parent = nullptr); +protected: + FloatingWidget(QWidget *p_parent = nullptr); - // Sub-class calls this to indicates completion. - void finish(); + // Sub-class calls this to indicates completion. + void finish(); - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private: - QMenu *m_menu = nullptr; - }; -} +private: + QMenu *m_menu = nullptr; +}; +} // namespace vnotex #endif // FLOATINGWIDGET_H diff --git a/src/widgets/framelessmainwindow/framelessmainwindow.cpp b/src/widgets/framelessmainwindow/framelessmainwindow.cpp index 9ff58a5777..f758eac260 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindow.cpp +++ b/src/widgets/framelessmainwindow/framelessmainwindow.cpp @@ -5,46 +5,35 @@ using namespace vnotex; FramelessMainWindow::FramelessMainWindow(bool p_frameless, QWidget *p_parent) - : QMainWindow(p_parent), - m_frameless(p_frameless), - m_defaultFlags(windowFlags()) -{ - if (m_frameless) { - setWindowFlags(m_defaultFlags | Qt::FramelessWindowHint); - } + : QMainWindow(p_parent), m_frameless(p_frameless), m_defaultFlags(windowFlags()) { + if (m_frameless) { + setWindowFlags(m_defaultFlags | Qt::FramelessWindowHint); + } } +bool FramelessMainWindow::isFrameless() const { return m_frameless; } -bool FramelessMainWindow::isFrameless() const -{ - return m_frameless; -} - -void FramelessMainWindow::setTitleBar(QWidget *p_titleBar) -{ - Q_ASSERT(!m_titleBar && m_frameless); +void FramelessMainWindow::setTitleBar(QWidget *p_titleBar) { + Q_ASSERT(!m_titleBar && m_frameless); - m_titleBar = p_titleBar; + m_titleBar = p_titleBar; } -void FramelessMainWindow::changeEvent(QEvent *p_event) -{ - QMainWindow::changeEvent(p_event); +void FramelessMainWindow::changeEvent(QEvent *p_event) { + QMainWindow::changeEvent(p_event); - if (p_event->type() == QEvent::WindowStateChange) { - m_windowStates = windowState(); - m_resizable = m_windowStates == Qt::WindowNoState; - m_movable = m_windowStates == Qt::WindowNoState; - emit windowStateChanged(m_windowStates); - } + if (p_event->type() == QEvent::WindowStateChange) { + m_windowStates = windowState(); + m_resizable = m_windowStates == Qt::WindowNoState; + m_movable = m_windowStates == Qt::WindowNoState; + emit windowStateChanged(m_windowStates); + } } -bool FramelessMainWindow::isMaximized() const -{ - return (m_windowStates & Qt::WindowMaximized) && !(m_windowStates & Qt::WindowFullScreen); +bool FramelessMainWindow::isMaximized() const { + return (m_windowStates & Qt::WindowMaximized) && !(m_windowStates & Qt::WindowFullScreen); } -void FramelessMainWindow::setWindowFlagsOnUpdate() -{ - // Do nothing by default. +void FramelessMainWindow::setWindowFlagsOnUpdate() { + // Do nothing by default. } diff --git a/src/widgets/framelessmainwindow/framelessmainwindow.h b/src/widgets/framelessmainwindow/framelessmainwindow.h index 00c0dcf9cf..bf9468c593 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindow.h +++ b/src/widgets/framelessmainwindow/framelessmainwindow.h @@ -6,42 +6,40 @@ class QTimer; -namespace vnotex -{ - // Base class. Use FramelessMainWindowImpl instead. - class FramelessMainWindow : public QMainWindow - { - Q_OBJECT - public: - FramelessMainWindow(bool p_frameless, QWidget *p_parent = nullptr); +namespace vnotex { +// Base class. Use FramelessMainWindowImpl instead. +class FramelessMainWindow : public QMainWindow { + Q_OBJECT +public: + FramelessMainWindow(bool p_frameless, QWidget *p_parent = nullptr); - bool isFrameless() const; + bool isFrameless() const; - virtual void setTitleBar(QWidget *p_titleBar); + virtual void setTitleBar(QWidget *p_titleBar); - signals: - void windowStateChanged(Qt::WindowStates p_state); +signals: + void windowStateChanged(Qt::WindowStates p_state); - protected: - void changeEvent(QEvent *p_event) Q_DECL_OVERRIDE; +protected: + void changeEvent(QEvent *p_event) Q_DECL_OVERRIDE; - protected: - bool isMaximized() const; +protected: + bool isMaximized() const; - virtual void setWindowFlagsOnUpdate(); + virtual void setWindowFlagsOnUpdate(); - const bool m_frameless = true; + const bool m_frameless = true; - bool m_movable = true; + bool m_movable = true; - bool m_resizable = true; + bool m_resizable = true; - const Qt::WindowFlags m_defaultFlags; + const Qt::WindowFlags m_defaultFlags; - QWidget *m_titleBar = nullptr; + QWidget *m_titleBar = nullptr; - Qt::WindowStates m_windowStates = Qt::WindowNoState; - }; -} + Qt::WindowStates m_windowStates = Qt::WindowNoState; +}; +} // namespace vnotex #endif // FRAMELESSMAINWINDOW_H diff --git a/src/widgets/framelessmainwindow/framelessmainwindowimpl.h b/src/widgets/framelessmainwindow/framelessmainwindowimpl.h index 210759843a..c92c1c1898 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowimpl.h +++ b/src/widgets/framelessmainwindow/framelessmainwindowimpl.h @@ -1,16 +1,15 @@ #ifndef FRAMELESSMAINWINDOWIMPL_H #define FRAMELESSMAINWINDOWIMPL_H -#include "framelessmainwindowwin.h" #include "framelessmainwindowlinux.h" +#include "framelessmainwindowwin.h" -namespace vnotex -{ +namespace vnotex { #ifdef Q_OS_WIN - typedef FramelessMainWindowWin FramelessMainWindowImpl; +typedef FramelessMainWindowWin FramelessMainWindowImpl; #else - typedef FramelessMainWindowLinux FramelessMainWindowImpl; +typedef FramelessMainWindowLinux FramelessMainWindowImpl; #endif -} +} // namespace vnotex #endif // FRAMELESSMAINWINDOWIMPL_H diff --git a/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp b/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp index 17a06a6f9f..939b9ddcff 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp +++ b/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp @@ -2,97 +2,88 @@ #ifndef Q_OS_WIN -#include -#include #include -#include +#include #include +#include +#include using namespace vnotex; FramelessMainWindowLinux::FramelessMainWindowLinux(bool p_frameless, QWidget *p_parent) - : FramelessMainWindow(p_frameless, p_parent) -{ - if (m_frameless) { - // installEventFilter(this); - } + : FramelessMainWindow(p_frameless, p_parent) { + if (m_frameless) { + // installEventFilter(this); + } } -bool FramelessMainWindowLinux::eventFilter(QObject *p_obj, QEvent *p_event) -{ - if (!m_frameless) { - return FramelessMainWindow::eventFilter(p_obj, p_event); - } - - if (p_obj == m_titleBar) { - const auto type = p_event->type(); - if (type == QEvent::MouseButtonDblClick - || type == QEvent::NonClientAreaMouseButtonDblClick) { - if (!(m_windowStates & Qt::WindowFullScreen)) { - if (m_windowStates & Qt::WindowMaximized) { - showNormal(); - } else { - showMaximized(); - } - } +bool FramelessMainWindowLinux::eventFilter(QObject *p_obj, QEvent *p_event) { + if (!m_frameless) { + return FramelessMainWindow::eventFilter(p_obj, p_event); + } + + if (p_obj == m_titleBar) { + const auto type = p_event->type(); + if (type == QEvent::MouseButtonDblClick || type == QEvent::NonClientAreaMouseButtonDblClick) { + if (!(m_windowStates & Qt::WindowFullScreen)) { + if (m_windowStates & Qt::WindowMaximized) { + showNormal(); + } else { + showMaximized(); } - } else if (p_obj == this) { - doResize(p_event); + } } + } else if (p_obj == this) { + doResize(p_event); + } - return FramelessMainWindow::eventFilter(p_obj, p_event); + return FramelessMainWindow::eventFilter(p_obj, p_event); } -void FramelessMainWindowLinux::setTitleBar(QWidget *p_titleBar) -{ - FramelessMainWindow::setTitleBar(p_titleBar); +void FramelessMainWindowLinux::setTitleBar(QWidget *p_titleBar) { + FramelessMainWindow::setTitleBar(p_titleBar); - m_titleBar->installEventFilter(this); + m_titleBar->installEventFilter(this); } -void FramelessMainWindowLinux::mousePressEvent(QMouseEvent *p_event) -{ - FramelessMainWindow::mousePressEvent(p_event); +void FramelessMainWindowLinux::mousePressEvent(QMouseEvent *p_event) { + FramelessMainWindow::mousePressEvent(p_event); - if (m_frameless) { - recordMousePress(p_event->pos()); - } + if (m_frameless) { + recordMousePress(p_event->pos()); + } } -void FramelessMainWindowLinux::recordMousePress(const QPoint &p_pos) -{ - m_mousePressed = true; - m_mousePressPoint = p_pos; - m_rectOnMousePress = geometry(); - m_mousePressArea = hitArea(m_mousePressPoint); +void FramelessMainWindowLinux::recordMousePress(const QPoint &p_pos) { + m_mousePressed = true; + m_mousePressPoint = p_pos; + m_rectOnMousePress = geometry(); + m_mousePressArea = hitArea(m_mousePressPoint); } -void FramelessMainWindowLinux::mouseReleaseEvent(QMouseEvent *p_event) -{ - FramelessMainWindow::mouseReleaseEvent(p_event); +void FramelessMainWindowLinux::mouseReleaseEvent(QMouseEvent *p_event) { + FramelessMainWindow::mouseReleaseEvent(p_event); - if (m_frameless) { - // setCursor(Qt::ArrowCursor); - m_mousePressed = false; - } + if (m_frameless) { + // setCursor(Qt::ArrowCursor); + m_mousePressed = false; + } } -void FramelessMainWindowLinux::mouseMoveEvent(QMouseEvent *p_event) -{ - FramelessMainWindow::mouseMoveEvent(p_event); +void FramelessMainWindowLinux::mouseMoveEvent(QMouseEvent *p_event) { + FramelessMainWindow::mouseMoveEvent(p_event); - if (m_frameless) { - Q_ASSERT(m_mousePressed); - if (m_movable && m_mousePressArea == Area::Caption) { - const auto delta = p_event->pos() - m_mousePressPoint; - move(pos() + delta); - } + if (m_frameless) { + Q_ASSERT(m_mousePressed); + if (m_movable && m_mousePressArea == Area::Caption) { + const auto delta = p_event->pos() - m_mousePressPoint; + move(pos() + delta); } + } } -void FramelessMainWindowLinux::doResize(QEvent *p_event) -{ - Q_UNUSED(p_event); +void FramelessMainWindowLinux::doResize(QEvent *p_event) { + Q_UNUSED(p_event); #if 0 static bool needResetCursor = false; @@ -181,53 +172,51 @@ void FramelessMainWindowLinux::doResize(QEvent *p_event) #endif } -FramelessMainWindowLinux::Area FramelessMainWindowLinux::hitArea(const QPoint &p_pos) const -{ - const int x = p_pos.x(); - const int y = p_pos.y(); - Area area = Area::None; - if (x < m_resizeAreaWidth) { - // Left. - if (y < m_resizeAreaWidth) { - // Top. - area = Area::TopLeft; - } else if (y > height() - m_resizeAreaWidth) { - // Bottom. - area = Area::BottomLeft; - } else { - area = Area::Left; - } - } else if (x > width() - m_resizeAreaWidth) { - // Right. - if (y < m_resizeAreaWidth) { - // Top. - area = Area::TopRight; - } else if (y > height() - m_resizeAreaWidth) { - // Bottom. - area = Area::BottomRight; - } else { - area = Area::Right; - } - } else if (y < m_resizeAreaWidth) { - // Top. - area = Area::Top; +FramelessMainWindowLinux::Area FramelessMainWindowLinux::hitArea(const QPoint &p_pos) const { + const int x = p_pos.x(); + const int y = p_pos.y(); + Area area = Area::None; + if (x < m_resizeAreaWidth) { + // Left. + if (y < m_resizeAreaWidth) { + // Top. + area = Area::TopLeft; } else if (y > height() - m_resizeAreaWidth) { - // Bottom. - area = Area::Bottom; - } else if (y < m_titleBarHeight) { - area = Area::Caption; + // Bottom. + area = Area::BottomLeft; + } else { + area = Area::Left; } - - return area; + } else if (x > width() - m_resizeAreaWidth) { + // Right. + if (y < m_resizeAreaWidth) { + // Top. + area = Area::TopRight; + } else if (y > height() - m_resizeAreaWidth) { + // Bottom. + area = Area::BottomRight; + } else { + area = Area::Right; + } + } else if (y < m_resizeAreaWidth) { + // Top. + area = Area::Top; + } else if (y > height() - m_resizeAreaWidth) { + // Bottom. + area = Area::Bottom; + } else if (y < m_titleBarHeight) { + area = Area::Caption; + } + + return area; } -void FramelessMainWindowLinux::showEvent(QShowEvent *p_event) -{ - FramelessMainWindow::showEvent(p_event); +void FramelessMainWindowLinux::showEvent(QShowEvent *p_event) { + FramelessMainWindow::showEvent(p_event); - if (m_frameless && m_titleBarHeight == 0 && m_titleBar) { - m_titleBarHeight = m_titleBar->height(); - } + if (m_frameless && m_titleBarHeight == 0 && m_titleBar) { + m_titleBarHeight = m_titleBar->height(); + } } #endif diff --git a/src/widgets/framelessmainwindow/framelessmainwindowlinux.h b/src/widgets/framelessmainwindow/framelessmainwindowlinux.h index 0485b03bdf..f21b1a68b7 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowlinux.h +++ b/src/widgets/framelessmainwindow/framelessmainwindowlinux.h @@ -6,68 +6,64 @@ #include #include -namespace vnotex -{ +namespace vnotex { #ifndef Q_OS_WIN - class FramelessMainWindowLinux : public FramelessMainWindow - { - Q_OBJECT - public: - FramelessMainWindowLinux(bool p_frameless, QWidget *p_parent = nullptr); +class FramelessMainWindowLinux : public FramelessMainWindow { + Q_OBJECT +public: + FramelessMainWindowLinux(bool p_frameless, QWidget *p_parent = nullptr); - void setTitleBar(QWidget *p_titleBar) Q_DECL_OVERRIDE; + void setTitleBar(QWidget *p_titleBar) Q_DECL_OVERRIDE; - protected: - bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE; +protected: + bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; - void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; - private: - enum Area - { - Left = 0, - TopLeft, - Top, - TopRight, - Right, - BottomRight, - Bottom, - BottomLeft, - Caption, - None - }; +private: + enum Area { + Left = 0, + TopLeft, + Top, + TopRight, + Right, + BottomRight, + Bottom, + BottomLeft, + Caption, + None + }; - Area hitArea(const QPoint &p_pos) const; + Area hitArea(const QPoint &p_pos) const; - void doResize(QEvent *p_event); + void doResize(QEvent *p_event); - void recordMousePress(const QPoint &p_pos); + void recordMousePress(const QPoint &p_pos); - const int m_resizeAreaWidth = 6; + const int m_resizeAreaWidth = 6; - int m_titleBarHeight = 0; + int m_titleBarHeight = 0; - Area m_mousePressArea = Area::None; + Area m_mousePressArea = Area::None; - QPoint m_mousePressPoint; + QPoint m_mousePressPoint; - bool m_mousePressed = false; + bool m_mousePressed = false; - QRect m_rectOnMousePress; - }; + QRect m_rectOnMousePress; +}; #else - class FramelessMainWindowLinuxDummy - { - public: - FramelessMainWindowLinuxDummy() = default; - }; +class FramelessMainWindowLinuxDummy { +public: + FramelessMainWindowLinuxDummy() = default; +}; #endif -} +} // namespace vnotex #endif // FRAMELESSMAINWINDOWLINUX_H diff --git a/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp b/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp index d81f8f9772..a227d5b985 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp +++ b/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp @@ -2,232 +2,224 @@ #ifdef Q_OS_WIN -#include #include +#include +#include #include #include -#include -#pragma comment (lib,"dwmapi.lib") -#pragma comment (lib, "user32.lib") +#pragma comment(lib, "dwmapi.lib") +#pragma comment(lib, "user32.lib") using namespace vnotex; FramelessMainWindowWin::FramelessMainWindowWin(bool p_frameless, QWidget *p_parent) - : FramelessMainWindow(p_frameless, p_parent) -{ - if (m_frameless) { - m_resizeAreaWidth *= devicePixelRatio(); - - m_redrawTimer = new QTimer(this); - m_redrawTimer->setSingleShot(true); - m_redrawTimer->setInterval(500); - connect(m_redrawTimer, &QTimer::timeout, - this, &FramelessMainWindowWin::forceRedraw); - - connect(this, &FramelessMainWindow::windowStateChanged, - this, &FramelessMainWindowWin::updateMargins); - - // Enable some window effects on Win, such as snap and maximizing. - // It will activate the title bar again. Need to remove it in WM_NCCALCSIZE msg. - HWND hwnd = reinterpret_cast(winId()); - DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); - ::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); - - // Leave 1 pixel width of border so OS will draw a window shadow. - const MARGINS shadow = {1, 1, 1, 1}; - DwmExtendFrameIntoClientArea(hwnd, &shadow); - } + : FramelessMainWindow(p_frameless, p_parent) { + if (m_frameless) { + m_resizeAreaWidth *= devicePixelRatio(); + + m_redrawTimer = new QTimer(this); + m_redrawTimer->setSingleShot(true); + m_redrawTimer->setInterval(500); + connect(m_redrawTimer, &QTimer::timeout, this, &FramelessMainWindowWin::forceRedraw); + + connect(this, &FramelessMainWindow::windowStateChanged, this, + &FramelessMainWindowWin::updateMargins); + + // Enable some window effects on Win, such as snap and maximizing. + // It will activate the title bar again. Need to remove it in WM_NCCALCSIZE msg. + HWND hwnd = reinterpret_cast(winId()); + DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); + ::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); + + // Leave 1 pixel width of border so OS will draw a window shadow. + const MARGINS shadow = {1, 1, 1, 1}; + DwmExtendFrameIntoClientArea(hwnd, &shadow); + } } -#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) -bool FramelessMainWindowWin::nativeEvent(const QByteArray &p_eventType, void *p_message, qintptr *p_result) +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +bool FramelessMainWindowWin::nativeEvent(const QByteArray &p_eventType, void *p_message, + qintptr *p_result) #else -bool FramelessMainWindowWin::nativeEvent(const QByteArray &p_eventType, void *p_message, long *p_result) +bool FramelessMainWindowWin::nativeEvent(const QByteArray &p_eventType, void *p_message, + long *p_result) #endif { - if (!m_frameless) { - return FramelessMainWindow::nativeEvent(p_eventType, p_message, p_result); - } - - if (p_eventType == QStringLiteral("windows_generic_MSG")) { - MSG *msg = static_cast(p_message); - - switch (msg->message) { - case WM_NCCALCSIZE: - *p_result = 0; - return true; - - case WM_NCHITTEST: - { - if (m_windowStates & Qt::WindowFullScreen) { - *p_result = HTCLIENT; - return true; - } - - RECT windowRect; - ::GetWindowRect(msg->hwnd, &windowRect); - - // x and y could not be compared with width() and height() in hidpi case. - const int x = static_cast(GET_X_LPARAM(msg->lParam) - windowRect.left); - const int y = static_cast(GET_Y_LPARAM(msg->lParam) - windowRect.top); - - *p_result = 0; - if (m_resizable) { - if (x < m_resizeAreaWidth) { - // Left. - if (y < m_resizeAreaWidth) { - // Top. - *p_result = HTTOPLEFT; - } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { - // Bottom. - *p_result = HTBOTTOMLEFT; - } else { - *p_result = HTLEFT; - } - } else if (x > windowRect.right - windowRect.left - m_resizeAreaWidth) { - // Right. - if (y < m_resizeAreaWidth) { - // Top. - *p_result = HTTOPRIGHT; - } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { - // Bottom. - *p_result = HTBOTTOMRIGHT; - } else { - *p_result = HTRIGHT; - } - } else if (y < m_resizeAreaWidth) { - *p_result = HTTOP; - } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { - *p_result = HTBOTTOM; - } - } - - if (0 != *p_result) { - return true; - } - - if (m_titleBar) { - if (m_titleBarHeight == 0) { - m_titleBarHeight = m_titleBar->height() * devicePixelRatio(); - } - - if (y < m_titleBarHeight) { - QWidget *child = m_titleBar->childAt(m_titleBar->mapFromGlobal(QCursor::pos())); - if (!child) { - *p_result = HTCAPTION; - if (::GetAsyncKeyState(VK_LBUTTON) < 0 || ::GetAsyncKeyState(VK_RBUTTON) < 0) { - m_sizeBeforeMove = size(); - } - return true; - } - } - } - - break; + if (!m_frameless) { + return FramelessMainWindow::nativeEvent(p_eventType, p_message, p_result); + } + + if (p_eventType == QStringLiteral("windows_generic_MSG")) { + MSG *msg = static_cast(p_message); + + switch (msg->message) { + case WM_NCCALCSIZE: + *p_result = 0; + return true; + + case WM_NCHITTEST: { + if (m_windowStates & Qt::WindowFullScreen) { + *p_result = HTCLIENT; + return true; + } + + RECT windowRect; + ::GetWindowRect(msg->hwnd, &windowRect); + + // x and y could not be compared with width() and height() in hidpi case. + const int x = static_cast(GET_X_LPARAM(msg->lParam) - windowRect.left); + const int y = static_cast(GET_Y_LPARAM(msg->lParam) - windowRect.top); + + *p_result = 0; + if (m_resizable) { + if (x < m_resizeAreaWidth) { + // Left. + if (y < m_resizeAreaWidth) { + // Top. + *p_result = HTTOPLEFT; + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { + // Bottom. + *p_result = HTBOTTOMLEFT; + } else { + *p_result = HTLEFT; + } + } else if (x > windowRect.right - windowRect.left - m_resizeAreaWidth) { + // Right. + if (y < m_resizeAreaWidth) { + // Top. + *p_result = HTTOPRIGHT; + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { + // Bottom. + *p_result = HTBOTTOMRIGHT; + } else { + *p_result = HTRIGHT; + } + } else if (y < m_resizeAreaWidth) { + *p_result = HTTOP; + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { + *p_result = HTBOTTOM; } + } - case WM_POWERBROADCAST: - { - if (msg->wParam == PBT_APMSUSPEND) { - // Minimize when system is going to sleep to avoid bugs. - showMinimized(); - } - break; + if (0 != *p_result) { + return true; + } + + if (m_titleBar) { + if (m_titleBarHeight == 0) { + m_titleBarHeight = m_titleBar->height() * devicePixelRatio(); } - case WM_GETMINMAXINFO: - { - // When maximized, OS will expand the content area. To avoid missing the real contents, set extra margins. - if (::IsZoomed(msg->hwnd)) { - RECT frame = {0, 0, 0, 0}; - ::AdjustWindowRectEx(&frame, WS_OVERLAPPEDWINDOW, false, 0); - const int dpiScale = devicePixelRatio(); - // Use bottom as top. - QMargins newMargins(qAbs(frame.left) / dpiScale, - qAbs(frame.bottom) / dpiScale, - frame.right / dpiScale, - frame.bottom / dpiScale); - if (newMargins != m_maximizedMargins) { - m_maximizedMargins = newMargins; - updateMargins(); - } + if (y < m_titleBarHeight) { + QWidget *child = m_titleBar->childAt(m_titleBar->mapFromGlobal(QCursor::pos())); + if (!child) { + *p_result = HTCAPTION; + if (::GetAsyncKeyState(VK_LBUTTON) < 0 || ::GetAsyncKeyState(VK_RBUTTON) < 0) { + m_sizeBeforeMove = size(); } - break; + return true; + } } + } - default: - break; - } + break; } - return FramelessMainWindow::nativeEvent(p_eventType, p_message, p_result); -} - -void FramelessMainWindowWin::moveEvent(QMoveEvent *p_event) -{ - FramelessMainWindow::moveEvent(p_event); - - if (m_frameless) { - if (m_windowStates & Qt::WindowMaximized) { - m_redrawTimer->stop(); - } else { - m_redrawTimer->start(); - } + case WM_POWERBROADCAST: { + if (msg->wParam == PBT_APMSUSPEND) { + // Minimize when system is going to sleep to avoid bugs. + showMinimized(); + } + break; } -} -void FramelessMainWindowWin::updateMargins() -{ - if (!m_frameless) { - return; + case WM_GETMINMAXINFO: { + // When maximized, OS will expand the content area. To avoid missing the real contents, set + // extra margins. + if (::IsZoomed(msg->hwnd)) { + RECT frame = {0, 0, 0, 0}; + ::AdjustWindowRectEx(&frame, WS_OVERLAPPEDWINDOW, false, 0); + const int dpiScale = devicePixelRatio(); + // Use bottom as top. + QMargins newMargins(qAbs(frame.left) / dpiScale, qAbs(frame.bottom) / dpiScale, + frame.right / dpiScale, frame.bottom / dpiScale); + if (newMargins != m_maximizedMargins) { + m_maximizedMargins = newMargins; + updateMargins(); + } + } + break; } - int topMargin = 0; - if (isMaximized()) { - setContentsMargins(m_maximizedMargins); - topMargin = m_maximizedMargins.top(); - } else { - setContentsMargins(0, 0, 0, 0); + default: + break; } + } - if (m_titleBar) { - m_titleBarHeight = (m_titleBar->height() + topMargin) * devicePixelRatio(); - } + return FramelessMainWindow::nativeEvent(p_eventType, p_message, p_result); } -void FramelessMainWindowWin::forceRedraw() -{ - Q_ASSERT(m_frameless); +void FramelessMainWindowWin::moveEvent(QMoveEvent *p_event) { + FramelessMainWindow::moveEvent(p_event); + + if (m_frameless) { if (m_windowStates & Qt::WindowMaximized) { - return; + m_redrawTimer->stop(); + } else { + m_redrawTimer->start(); } + } +} - const QSize sz = size(); - RECT frame; - ::GetWindowRect((HWND)winId(), &frame); - const int clientWidth = (frame.right - frame.left) / devicePixelRatio(); - const int clientHeight = (frame.bottom - frame.top) / devicePixelRatio(); - if (clientWidth != sz.width() || clientHeight != sz.height()) { - // resize() may result to "unable to set geometry" warning. - // adjustsize() or resize() to another size before could solve this. - resize(sz.width() + 1, sz.height() + 1); - if (m_sizeBeforeMove.isEmpty()) { - resize(clientWidth, clientHeight); - } else { - resize(m_sizeBeforeMove); - } - } +void FramelessMainWindowWin::updateMargins() { + if (!m_frameless) { + return; + } + + int topMargin = 0; + if (isMaximized()) { + setContentsMargins(m_maximizedMargins); + topMargin = m_maximizedMargins.top(); + } else { + setContentsMargins(0, 0, 0, 0); + } + + if (m_titleBar) { + m_titleBarHeight = (m_titleBar->height() + topMargin) * devicePixelRatio(); + } } -void FramelessMainWindowWin::setWindowFlagsOnUpdate() -{ - if (m_frameless) { - // We need to re-set the window flags again in some cases, such as after StayOnTop. - HWND hwnd = reinterpret_cast(winId()); - DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); - ::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); +void FramelessMainWindowWin::forceRedraw() { + Q_ASSERT(m_frameless); + if (m_windowStates & Qt::WindowMaximized) { + return; + } + + const QSize sz = size(); + RECT frame; + ::GetWindowRect((HWND)winId(), &frame); + const int clientWidth = (frame.right - frame.left) / devicePixelRatio(); + const int clientHeight = (frame.bottom - frame.top) / devicePixelRatio(); + if (clientWidth != sz.width() || clientHeight != sz.height()) { + // resize() may result to "unable to set geometry" warning. + // adjustsize() or resize() to another size before could solve this. + resize(sz.width() + 1, sz.height() + 1); + if (m_sizeBeforeMove.isEmpty()) { + resize(clientWidth, clientHeight); + } else { + resize(m_sizeBeforeMove); } + } +} + +void FramelessMainWindowWin::setWindowFlagsOnUpdate() { + if (m_frameless) { + // We need to re-set the window flags again in some cases, such as after StayOnTop. + HWND hwnd = reinterpret_cast(winId()); + DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); + ::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION); + } } #endif diff --git a/src/widgets/framelessmainwindow/framelessmainwindowwin.h b/src/widgets/framelessmainwindow/framelessmainwindowwin.h index c2ce3e8e1d..8a113251eb 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowwin.h +++ b/src/widgets/framelessmainwindow/framelessmainwindowwin.h @@ -3,49 +3,47 @@ #include "framelessmainwindow.h" -namespace vnotex -{ +namespace vnotex { #ifdef Q_OS_WIN - class FramelessMainWindowWin : public FramelessMainWindow - { - Q_OBJECT - public: - FramelessMainWindowWin(bool p_frameless, QWidget *p_parent = nullptr); - - protected: -#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) - bool nativeEvent(const QByteArray &p_eventType, void *p_message, qintptr *p_result) Q_DECL_OVERRIDE; +class FramelessMainWindowWin : public FramelessMainWindow { + Q_OBJECT +public: + FramelessMainWindowWin(bool p_frameless, QWidget *p_parent = nullptr); + +protected: +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + bool nativeEvent(const QByteArray &p_eventType, void *p_message, + qintptr *p_result) Q_DECL_OVERRIDE; #else - bool nativeEvent(const QByteArray &p_eventType, void *p_message, long *p_result) Q_DECL_OVERRIDE; + bool nativeEvent(const QByteArray &p_eventType, void *p_message, long *p_result) Q_DECL_OVERRIDE; #endif - void moveEvent(QMoveEvent *p_event) Q_DECL_OVERRIDE; + void moveEvent(QMoveEvent *p_event) Q_DECL_OVERRIDE; - void setWindowFlagsOnUpdate() Q_DECL_OVERRIDE; + void setWindowFlagsOnUpdate() Q_DECL_OVERRIDE; - private: - // To fix some unkonwn bugs of the interface. - void forceRedraw(); +private: + // To fix some unkonwn bugs of the interface. + void forceRedraw(); - void updateMargins(); + void updateMargins(); - int m_resizeAreaWidth = 6; + int m_resizeAreaWidth = 6; - QTimer *m_redrawTimer = nullptr; + QTimer *m_redrawTimer = nullptr; - QSize m_sizeBeforeMove; + QSize m_sizeBeforeMove; - QMargins m_maximizedMargins; + QMargins m_maximizedMargins; - int m_titleBarHeight = 0; - }; + int m_titleBarHeight = 0; +}; #else - class FramelessMainWindowWinDummy - { - public: - FramelessMainWindowWinDummy() = default; - }; +class FramelessMainWindowWinDummy { +public: + FramelessMainWindowWinDummy() = default; +}; #endif -} +} // namespace vnotex #endif // FRAMELESSMAINWINDOWWIN_H diff --git a/src/widgets/fullscreentoggleaction.cpp b/src/widgets/fullscreentoggleaction.cpp index b84bcf6b45..47a2368953 100644 --- a/src/widgets/fullscreentoggleaction.cpp +++ b/src/widgets/fullscreentoggleaction.cpp @@ -5,51 +5,41 @@ using namespace vnotex; -FullScreenToggleAction::FullScreenToggleAction(QWidget *p_window, - const QIcon &p_icon, +FullScreenToggleAction::FullScreenToggleAction(QWidget *p_window, const QIcon &p_icon, QObject *p_parent) - : BiAction(p_icon, - tr("F&ull Screen"), - QIcon(), - tr("Exit F&ull Screen"), - p_parent), - m_window(p_window) -{ - setCheckable(true); - - if (m_window) { - m_window->installEventFilter(this); + : BiAction(p_icon, tr("F&ull Screen"), QIcon(), tr("Exit F&ull Screen"), p_parent), + m_window(p_window) { + setCheckable(true); + + if (m_window) { + m_window->installEventFilter(this); + } + + connect(this, &QAction::triggered, this, [this](bool p_checked) { + if ((p_checked && !m_window->isFullScreen()) || (!p_checked && m_window->isFullScreen())) { + setWindowFullScreen(m_window, p_checked); + emit fullScreenToggled(p_checked); } - - connect(this, &QAction::triggered, - this, [this](bool p_checked) { - if ((p_checked && !m_window->isFullScreen()) - || (!p_checked && m_window->isFullScreen())) { - setWindowFullScreen(m_window, p_checked); - emit fullScreenToggled(p_checked); - } - }); + }); } -bool FullScreenToggleAction::eventFilter(QObject *p_object, QEvent *p_event) -{ - if (p_object == m_window) { - if (p_event->type() == QEvent::WindowStateChange) { - if (m_window->isFullScreen() != isChecked()) { - trigger(); - } - } +bool FullScreenToggleAction::eventFilter(QObject *p_object, QEvent *p_event) { + if (p_object == m_window) { + if (p_event->type() == QEvent::WindowStateChange) { + if (m_window->isFullScreen() != isChecked()) { + trigger(); + } } + } - return false; + return false; } -void FullScreenToggleAction::setWindowFullScreen(QWidget *p_window, bool p_set) -{ - Q_ASSERT(p_window); - if (p_set) { - p_window->setWindowState(p_window->windowState() | Qt::WindowFullScreen); - } else { - p_window->setWindowState(p_window->windowState() & ~Qt::WindowFullScreen); - } +void FullScreenToggleAction::setWindowFullScreen(QWidget *p_window, bool p_set) { + Q_ASSERT(p_window); + if (p_set) { + p_window->setWindowState(p_window->windowState() | Qt::WindowFullScreen); + } else { + p_window->setWindowState(p_window->windowState() & ~Qt::WindowFullScreen); + } } diff --git a/src/widgets/fullscreentoggleaction.h b/src/widgets/fullscreentoggleaction.h index b93ee5ebdc..c162c498e3 100644 --- a/src/widgets/fullscreentoggleaction.h +++ b/src/widgets/fullscreentoggleaction.h @@ -3,27 +3,23 @@ #include "biaction.h" -namespace vnotex -{ - class FullScreenToggleAction : public BiAction - { - Q_OBJECT - public: - FullScreenToggleAction(QWidget *p_window, - const QIcon &p_icon, - QObject *p_parent = nullptr); +namespace vnotex { +class FullScreenToggleAction : public BiAction { + Q_OBJECT +public: + FullScreenToggleAction(QWidget *p_window, const QIcon &p_icon, QObject *p_parent = nullptr); - signals: - bool fullScreenToggled(bool p_fullScreen); +signals: + bool fullScreenToggled(bool p_fullScreen); - protected: - bool eventFilter(QObject *p_object, QEvent *p_event) Q_DECL_OVERRIDE; +protected: + bool eventFilter(QObject *p_object, QEvent *p_event) Q_DECL_OVERRIDE; - private: - static void setWindowFullScreen(QWidget *p_window, bool p_set); +private: + static void setWindowFullScreen(QWidget *p_window, bool p_set); - QWidget *m_window = nullptr; - }; -} // ns vnotex + QWidget *m_window = nullptr; +}; +} // namespace vnotex #endif // FULLSCREENTOGGLEACTION_H diff --git a/src/widgets/historypanel.cpp b/src/widgets/historypanel.cpp index 78cc632071..e1a1fd5118 100644 --- a/src/widgets/historypanel.cpp +++ b/src/widgets/historypanel.cpp @@ -1,228 +1,207 @@ #include "historypanel.h" -#include -#include #include +#include +#include -#include -#include -#include -#include -#include +#include #include #include -#include +#include #include #include -#include +#include +#include +#include +#include +#include -#include "titlebar.h" #include "listwidget.h" #include "mainwindow.h" #include "messageboxhelper.h" #include "navigationmodemgr.h" +#include "titlebar.h" using namespace vnotex; -HistoryPanel::HistoryPanel(QWidget *p_parent) - : QFrame(p_parent) -{ - initIcons(); +HistoryPanel::HistoryPanel(QWidget *p_parent) : QFrame(p_parent) { + initIcons(); - setupUI(); + setupUI(); - updateSeparators(); + updateSeparators(); } -void HistoryPanel::initIcons() -{ - const auto &themeMgr = VNoteX::getInst().getThemeMgr(); - m_fileIcon = IconUtils::fetchIcon(themeMgr.getIconFile(QStringLiteral("file_node.svg"))); +void HistoryPanel::initIcons() { + const auto &themeMgr = VNoteX::getInst().getThemeMgr(); + m_fileIcon = IconUtils::fetchIcon(themeMgr.getIconFile(QStringLiteral("file_node.svg"))); } -void HistoryPanel::setupUI() -{ - auto mainLayout = new QVBoxLayout(this); - WidgetUtils::setContentsMargins(mainLayout); +void HistoryPanel::setupUI() { + auto mainLayout = new QVBoxLayout(this); + WidgetUtils::setContentsMargins(mainLayout); - setupTitleBar(QString(), this); - mainLayout->addWidget(m_titleBar); + setupTitleBar(QString(), this); + mainLayout->addWidget(m_titleBar); - m_historyList = new ListWidget(true, this); - m_historyList->setContextMenuPolicy(Qt::CustomContextMenu); - m_historyList->setSelectionMode(QAbstractItemView::ExtendedSelection); - connect(m_historyList, &QListWidget::customContextMenuRequested, - this, &HistoryPanel::handleContextMenuRequested); - connect(m_historyList, &QListWidget::itemActivated, - this, &HistoryPanel::openItem); - mainLayout->addWidget(m_historyList); + m_historyList = new ListWidget(true, this); + m_historyList->setContextMenuPolicy(Qt::CustomContextMenu); + m_historyList->setSelectionMode(QAbstractItemView::ExtendedSelection); + connect(m_historyList, &QListWidget::customContextMenuRequested, this, + &HistoryPanel::handleContextMenuRequested); + connect(m_historyList, &QListWidget::itemActivated, this, &HistoryPanel::openItem); + mainLayout->addWidget(m_historyList); - m_navigationWrapper.reset(new NavigationModeWrapper(m_historyList)); - NavigationModeMgr::getInst().registerNavigationTarget(m_navigationWrapper.data()); + m_navigationWrapper.reset(new NavigationModeWrapper(m_historyList)); + NavigationModeMgr::getInst().registerNavigationTarget(m_navigationWrapper.data()); - setFocusProxy(m_historyList); + setFocusProxy(m_historyList); } -void HistoryPanel::setupTitleBar(const QString &p_title, QWidget *p_parent) -{ - m_titleBar = new TitleBar(p_title, false, TitleBar::Action::None, p_parent); - m_titleBar->setActionButtonsAlwaysShown(true); +void HistoryPanel::setupTitleBar(const QString &p_title, QWidget *p_parent) { + m_titleBar = new TitleBar(p_title, false, TitleBar::Action::None, p_parent); + m_titleBar->setActionButtonsAlwaysShown(true); - { - auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear")); - connect(clearBtn, &QToolButton::triggered, - this, &HistoryPanel::clearHistory); - } + { + auto clearBtn = m_titleBar->addActionButton(QStringLiteral("clear.svg"), tr("Clear")); + connect(clearBtn, &QToolButton::triggered, this, &HistoryPanel::clearHistory); + } } -void HistoryPanel::handleContextMenuRequested(const QPoint &p_pos) -{ - auto item = m_historyList->itemAt(p_pos); - if (!isValidItem(item)) { - return; - } +void HistoryPanel::handleContextMenuRequested(const QPoint &p_pos) { + auto item = m_historyList->itemAt(p_pos); + if (!isValidItem(item)) { + return; + } + + QMenu menu(this); + + const int selectedCount = m_historyList->selectedItems().size(); - QMenu menu(this); - - const int selectedCount = m_historyList->selectedItems().size(); - - menu.addAction(tr("&Open"), - this, - [this]() { - const auto selectedItems = m_historyList->selectedItems(); - for (const auto &selectedItem : selectedItems) { - openItem(selectedItem); - } - }); - - if (selectedCount == 1) { - menu.addAction(tr("&Locate Node"), - &menu, - [this]() { - auto item = m_historyList->currentItem(); - if (!isValidItem(item)) { - return; - } - - auto node = VNoteX::getInst().getNotebookMgr().loadNodeByPath(getPath(item)); - if (node) { - emit VNoteX::getInst().locateNodeRequested(node.data()); - } - }); + menu.addAction(tr("&Open"), this, [this]() { + const auto selectedItems = m_historyList->selectedItems(); + for (const auto &selectedItem : selectedItems) { + openItem(selectedItem); } + }); - menu.exec(m_historyList->mapToGlobal(p_pos)); + if (selectedCount == 1) { + menu.addAction(tr("&Locate Node"), &menu, [this]() { + auto item = m_historyList->currentItem(); + if (!isValidItem(item)) { + return; + } + + auto node = VNoteX::getInst().getNotebookMgr().loadNodeByPath(getPath(item)); + if (node) { + emit VNoteX::getInst().locateNodeRequested(node.data()); + } + }); + } + + menu.exec(m_historyList->mapToGlobal(p_pos)); } -void HistoryPanel::openItem(const QListWidgetItem *p_item) -{ - if (!isValidItem(p_item)) { - return; - } - const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); - auto paras = QSharedPointer::create(); - paras->m_mode = coreConfig.getDefaultOpenMode(); +void HistoryPanel::openItem(const QListWidgetItem *p_item) { + if (!isValidItem(p_item)) { + return; + } + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + auto paras = QSharedPointer::create(); + paras->m_mode = coreConfig.getDefaultOpenMode(); - emit VNoteX::getInst().openFileRequested(getPath(p_item), paras); + emit VNoteX::getInst().openFileRequested(getPath(p_item), paras); } -void HistoryPanel::clearHistory() -{ - int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, - tr("Clear all the history?"), - QString(), - QString(), - VNoteX::getInst().getMainWindow()); - if (ret != QMessageBox::Ok) { - return; - } +void HistoryPanel::clearHistory() { + int ret = + MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, tr("Clear all the history?"), + QString(), QString(), VNoteX::getInst().getMainWindow()); + if (ret != QMessageBox::Ok) { + return; + } - HistoryMgr::getInst().clear(); + HistoryMgr::getInst().clear(); } -bool HistoryPanel::isValidItem(const QListWidgetItem *p_item) const -{ - return p_item && !ListWidget::isSeparatorItem(p_item); +bool HistoryPanel::isValidItem(const QListWidgetItem *p_item) const { + return p_item && !ListWidget::isSeparatorItem(p_item); } -void HistoryPanel::updateHistoryList() -{ - m_historyList->clear(); - - const auto &history = HistoryMgr::getInst().getHistory(); - int itemIdx = history.size() - 1; - for (int sepIdx = 0; sepIdx < m_separators.size() && itemIdx >= 0; ++sepIdx) { - const auto &separator = m_separators[sepIdx]; - if (separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc) { - // Insert this separator. - auto sepItem = ListWidget::createSeparatorItem(separator.m_text); - m_historyList->addItem(sepItem); - - addItem(*history[itemIdx]); - --itemIdx; - - // Insert all qualified items. - for (; - itemIdx >= 0 && separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc; - --itemIdx) { - addItem(*history[itemIdx]); - } - } +void HistoryPanel::updateHistoryList() { + m_historyList->clear(); + + const auto &history = HistoryMgr::getInst().getHistory(); + int itemIdx = history.size() - 1; + for (int sepIdx = 0; sepIdx < m_separators.size() && itemIdx >= 0; ++sepIdx) { + const auto &separator = m_separators[sepIdx]; + if (separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc) { + // Insert this separator. + auto sepItem = ListWidget::createSeparatorItem(separator.m_text); + m_historyList->addItem(sepItem); + + addItem(*history[itemIdx]); + --itemIdx; + + // Insert all qualified items. + for (; itemIdx >= 0 && separator.m_dateUtc <= history[itemIdx]->m_item.m_lastAccessedTimeUtc; + --itemIdx) { + addItem(*history[itemIdx]); + } } + } - if (itemIdx >= 0) { - // Older. - auto sepItem = ListWidget::createSeparatorItem(tr("Older")); - m_historyList->addItem(sepItem); + if (itemIdx >= 0) { + // Older. + auto sepItem = ListWidget::createSeparatorItem(tr("Older")); + m_historyList->addItem(sepItem); - for (; itemIdx >= 0; --itemIdx) { - addItem(*history[itemIdx]); - } + for (; itemIdx >= 0; --itemIdx) { + addItem(*history[itemIdx]); } + } } -void HistoryPanel::initialize() -{ - connect(&HistoryMgr::getInst(), &HistoryMgr::historyUpdated, - this, &HistoryPanel::updateHistoryList); +void HistoryPanel::initialize() { + connect(&HistoryMgr::getInst(), &HistoryMgr::historyUpdated, this, + &HistoryPanel::updateHistoryList); - updateHistoryList(); + updateHistoryList(); } -void HistoryPanel::updateSeparators() -{ - m_separators.resize(3); +void HistoryPanel::updateSeparators() { + m_separators.resize(3); - // Mid-night of today. - auto curDateTime = QDateTime::currentDateTime(); - curDateTime.setTime(QTime()); + // Mid-night of today. + auto curDateTime = QDateTime::currentDateTime(); + curDateTime.setTime(QTime()); - m_separators[0].m_text = tr("Today"); - m_separators[0].m_dateUtc = curDateTime.toUTC(); - m_separators[1].m_text = tr("Yesterday"); - m_separators[1].m_dateUtc = curDateTime.addDays(-1).toUTC(); - m_separators[2].m_text = tr("Last 7 Days"); - m_separators[2].m_dateUtc = curDateTime.addDays(-7).toUTC(); + m_separators[0].m_text = tr("Today"); + m_separators[0].m_dateUtc = curDateTime.toUTC(); + m_separators[1].m_text = tr("Yesterday"); + m_separators[1].m_dateUtc = curDateTime.addDays(-1).toUTC(); + m_separators[2].m_text = tr("Last 7 Days"); + m_separators[2].m_dateUtc = curDateTime.addDays(-7).toUTC(); } -void HistoryPanel::addItem(const HistoryItemFull &p_hisItem) -{ - auto item = new QListWidgetItem(m_historyList); - - item->setText(PathUtils::fileNameCheap(p_hisItem.m_item.m_path)); - item->setData(Qt::UserRole, p_hisItem.m_item.m_path); - item->setIcon(m_fileIcon); - if (p_hisItem.m_notebookName.isEmpty()) { - item->setToolTip(tr("%1\n%2").arg(p_hisItem.m_item.m_path, - Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime()))); - } else { - item->setToolTip(tr("[%1] %2\n%3").arg(p_hisItem.m_notebookName, - p_hisItem.m_item.m_path, - Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime()))); - } +void HistoryPanel::addItem(const HistoryItemFull &p_hisItem) { + auto item = new QListWidgetItem(m_historyList); + + item->setText(PathUtils::fileNameCheap(p_hisItem.m_item.m_path)); + item->setData(Qt::UserRole, p_hisItem.m_item.m_path); + item->setIcon(m_fileIcon); + if (p_hisItem.m_notebookName.isEmpty()) { + item->setToolTip(tr("%1\n%2").arg( + p_hisItem.m_item.m_path, + Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime()))); + } else { + item->setToolTip( + tr("[%1] %2\n%3") + .arg(p_hisItem.m_notebookName, p_hisItem.m_item.m_path, + Utils::dateTimeString(p_hisItem.m_item.m_lastAccessedTimeUtc.toLocalTime()))); + } } -QString HistoryPanel::getPath(const QListWidgetItem *p_item) const -{ - return p_item->data(Qt::UserRole).toString(); +QString HistoryPanel::getPath(const QListWidgetItem *p_item) const { + return p_item->data(Qt::UserRole).toString(); } diff --git a/src/widgets/historypanel.h b/src/widgets/historypanel.h index f7246d811a..faa2e10d5c 100644 --- a/src/widgets/historypanel.h +++ b/src/widgets/historypanel.h @@ -1,8 +1,8 @@ #ifndef HISTORYPANEL_H #define HISTORYPANEL_H -#include #include +#include #include #include @@ -11,60 +11,57 @@ class QListWidget; class QListWidgetItem; -namespace vnotex -{ - class TitleBar; - struct HistoryItemFull; +namespace vnotex { +class TitleBar; +struct HistoryItemFull; - class HistoryPanel : public QFrame - { - Q_OBJECT - public: - explicit HistoryPanel(QWidget *p_parent = nullptr); +class HistoryPanel : public QFrame { + Q_OBJECT +public: + explicit HistoryPanel(QWidget *p_parent = nullptr); - void initialize(); + void initialize(); - private slots: - void handleContextMenuRequested(const QPoint &p_pos); +private slots: + void handleContextMenuRequested(const QPoint &p_pos); - void openItem(const QListWidgetItem *p_item); + void openItem(const QListWidgetItem *p_item); - void clearHistory(); + void clearHistory(); - private: - struct SeparatorData - { - QString m_text; +private: + struct SeparatorData { + QString m_text; - QDateTime m_dateUtc; - }; + QDateTime m_dateUtc; + }; - void initIcons(); + void initIcons(); - void setupUI(); + void setupUI(); - void setupTitleBar(const QString &p_title, QWidget *p_parent = nullptr); + void setupTitleBar(const QString &p_title, QWidget *p_parent = nullptr); - void updateHistoryList(); + void updateHistoryList(); - void updateSeparators(); + void updateSeparators(); - void addItem(const HistoryItemFull &p_hisItem); + void addItem(const HistoryItemFull &p_hisItem); - QString getPath(const QListWidgetItem *p_item) const; + QString getPath(const QListWidgetItem *p_item) const; - bool isValidItem(const QListWidgetItem *p_item) const; + bool isValidItem(const QListWidgetItem *p_item) const; - TitleBar *m_titleBar = nullptr; + TitleBar *m_titleBar = nullptr; - QListWidget *m_historyList = nullptr; + QListWidget *m_historyList = nullptr; - QScopedPointer> m_navigationWrapper; + QScopedPointer> m_navigationWrapper; - QVector m_separators; + QVector m_separators; - QIcon m_fileIcon; - }; -} + QIcon m_fileIcon; +}; +} // namespace vnotex #endif // HISTORYPANEL_H diff --git a/src/widgets/itemproxystyle.cpp b/src/widgets/itemproxystyle.cpp index 664e961f62..ecd737292f 100644 --- a/src/widgets/itemproxystyle.cpp +++ b/src/widgets/itemproxystyle.cpp @@ -3,255 +3,247 @@ #include #include #include -#include #include +#include #include "styleditemdelegate.h" using namespace vnotex; -ItemProxyStyle::ItemProxyStyle(QStyle *p_style) - : QProxyStyle(p_style) -{ -} +ItemProxyStyle::ItemProxyStyle(QStyle *p_style) : QProxyStyle(p_style) {} -void ItemProxyStyle::drawControl(QStyle::ControlElement p_element, - const QStyleOption *p_option, - QPainter *p_painter, - const QWidget *p_widget) const -{ - if (p_element == QStyle::CE_ItemViewItem) { - if (drawItemViewItem(p_option, p_painter, p_widget)) { - return; - } +void ItemProxyStyle::drawControl(QStyle::ControlElement p_element, const QStyleOption *p_option, + QPainter *p_painter, const QWidget *p_widget) const { + if (p_element == QStyle::CE_ItemViewItem) { + if (drawItemViewItem(p_option, p_painter, p_widget)) { + return; } + } - QProxyStyle::drawControl(p_element, p_option, p_painter, p_widget); + QProxyStyle::drawControl(p_element, p_option, p_painter, p_widget); } -bool ItemProxyStyle::drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, const QWidget *p_widget) const -{ - const QStyleOptionViewItem *vopt = qstyleoption_cast(p_option); - if (!vopt) { - return false; +bool ItemProxyStyle::drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, + const QWidget *p_widget) const { + const QStyleOptionViewItem *vopt = qstyleoption_cast(p_option); + if (!vopt) { + return false; + } + + const auto value = vopt->index.data(HighlightsRole); + if (!value.canConvert>()) { + return false; + } + + auto segments = value.value>(); + if (segments.isEmpty()) { + return false; + } + + // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. + + p_painter->save(); + p_painter->setClipRect(vopt->rect); + QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, p_widget); + QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, p_widget); + QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, p_widget); + + // Draw the background. + proxy()->drawPrimitive(PE_PanelItemViewItem, vopt, p_painter, p_widget); + + // Draw the check mark. + if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { + QStyleOptionViewItem option(*vopt); + option.rect = checkRect; + option.state = option.state & ~QStyle::State_HasFocus; + switch (vopt->checkState) { + case Qt::Unchecked: + option.state |= QStyle::State_Off; + break; + case Qt::PartiallyChecked: + option.state |= QStyle::State_NoChange; + break; + case Qt::Checked: + option.state |= QStyle::State_On; + break; } - - const auto value = vopt->index.data(HighlightsRole); - if (!value.canConvert>()) { - return false; + proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p_painter, p_widget); + } + + // Draw the icon. + QIcon::Mode mode = QIcon::Normal; + if (!(vopt->state & QStyle::State_Enabled)) { + mode = QIcon::Disabled; + } else if (vopt->state & QStyle::State_Selected) { + mode = QIcon::Selected; + } + QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; + vopt->icon.paint(p_painter, iconRect, vopt->decorationAlignment, mode, state); + + // Draw the text. + if (!vopt->text.isEmpty()) { + QPalette::ColorGroup cg = + vopt->state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) { + cg = QPalette::Inactive; } - - auto segments = value.value>(); - if (segments.isEmpty()) { - return false; + if (vopt->state & QStyle::State_Selected) { + p_painter->setPen(vopt->palette.color(cg, QPalette::HighlightedText)); + } else { + p_painter->setPen(vopt->palette.color(cg, QPalette::Text)); } - - // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. - - p_painter->save(); - p_painter->setClipRect(vopt->rect); - QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, p_widget); - QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, p_widget); - QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, p_widget); - - // Draw the background. - proxy()->drawPrimitive(PE_PanelItemViewItem, vopt, p_painter, p_widget); - - // Draw the check mark. - if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { - QStyleOptionViewItem option(*vopt); - option.rect = checkRect; - option.state = option.state & ~QStyle::State_HasFocus; - switch (vopt->checkState) { - case Qt::Unchecked: - option.state |= QStyle::State_Off; - break; - case Qt::PartiallyChecked: - option.state |= QStyle::State_NoChange; - break; - case Qt::Checked: - option.state |= QStyle::State_On; - break; - } - proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p_painter, p_widget); - } - - // Draw the icon. - QIcon::Mode mode = QIcon::Normal; - if (!(vopt->state & QStyle::State_Enabled)) { - mode = QIcon::Disabled; - } else if (vopt->state & QStyle::State_Selected) { - mode = QIcon::Selected; + if (vopt->state & QStyle::State_Editing) { + p_painter->setPen(vopt->palette.color(cg, QPalette::Text)); + p_painter->drawRect(textRect.adjusted(0, 0, -1, -1)); } - QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; - vopt->icon.paint(p_painter, iconRect, vopt->decorationAlignment, mode, state); - // Draw the text. - if (!vopt->text.isEmpty()) { - QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; - if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) { - cg = QPalette::Inactive; - } - if (vopt->state & QStyle::State_Selected) { - p_painter->setPen(vopt->palette.color(cg, QPalette::HighlightedText)); - } else { - p_painter->setPen(vopt->palette.color(cg, QPalette::Text)); - } - if (vopt->state & QStyle::State_Editing) { - p_painter->setPen(vopt->palette.color(cg, QPalette::Text)); - p_painter->drawRect(textRect.adjusted(0, 0, -1, -1)); - } - - viewItemDrawText(p_painter, vopt, textRect); - } - - // Draw the focus rect. - if (vopt->state & QStyle::State_HasFocus) { - QStyleOptionFocusRect o; - o.QStyleOption::operator=(*vopt); - o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, p_widget); - o.state |= QStyle::State_KeyboardFocusChange; - o.state |= QStyle::State_Item; - QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; - o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window); - proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p_painter, p_widget); - } - - p_painter->restore(); - - return true; + viewItemDrawText(p_painter, vopt, textRect); + } + + // Draw the focus rect. + if (vopt->state & QStyle::State_HasFocus) { + QStyleOptionFocusRect o; + o.QStyleOption::operator=(*vopt); + o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, p_widget); + o.state |= QStyle::State_KeyboardFocusChange; + o.state |= QStyle::State_Item; + QPalette::ColorGroup cg = + (vopt->state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; + o.backgroundColor = vopt->palette.color( + cg, (vopt->state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window); + proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p_painter, p_widget); + } + + p_painter->restore(); + + return true; } -static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth, int maxHeight = -1, int *lastVisibleLine = nullptr) -{ - if (lastVisibleLine) - *lastVisibleLine = -1; - qreal height = 0; - qreal widthUsed = 0; - textLayout.beginLayout(); - int i = 0; - while (true) { - QTextLine line = textLayout.createLine(); - if (!line.isValid()) - break; - line.setLineWidth(lineWidth); - line.setPosition(QPointF(0, height)); - height += line.height(); - widthUsed = qMax(widthUsed, line.naturalTextWidth()); - // we assume that the height of the next line is the same as the current one - if (maxHeight > 0 && lastVisibleLine && height + line.height() > maxHeight) { - const QTextLine nextLine = textLayout.createLine(); - *lastVisibleLine = nextLine.isValid() ? i : -1; - break; - } - ++i; +static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth, int maxHeight = -1, + int *lastVisibleLine = nullptr) { + if (lastVisibleLine) + *lastVisibleLine = -1; + qreal height = 0; + qreal widthUsed = 0; + textLayout.beginLayout(); + int i = 0; + while (true) { + QTextLine line = textLayout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(lineWidth); + line.setPosition(QPointF(0, height)); + height += line.height(); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + // we assume that the height of the next line is the same as the current one + if (maxHeight > 0 && lastVisibleLine && height + line.height() > maxHeight) { + const QTextLine nextLine = textLayout.createLine(); + *lastVisibleLine = nextLine.isValid() ? i : -1; + break; } - textLayout.endLayout(); - return QSizeF(widthUsed, height); + ++i; + } + textLayout.endLayout(); + return QSizeF(widthUsed, height); } -void ItemProxyStyle::viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, const QRect &p_rect) const -{ - // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. - - const QWidget *widget = p_option->widget; - const int textMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1; - // Remove width padding. - QRect textRect = p_rect.adjusted(textMargin, 0, -textMargin, 0); - const bool wrapText = p_option->features & QStyleOptionViewItem::WrapText; - QTextOption textOption; - textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap); - textOption.setTextDirection(p_option->direction); - textOption.setAlignment(QStyle::visualAlignment(p_option->direction, p_option->displayAlignment)); - QPointF paintPosition; - const QString newText = calculateElidedText(p_option->text, - textOption, - p_option->font, - textRect, - p_option->displayAlignment, - p_option->textElideMode, - 0, - true, - &paintPosition); - QTextLayout textLayout(newText, p_option->font); - textLayout.setTextOption(textOption); - viewItemTextLayout(textLayout, textRect.width()); - textLayout.draw(p_painter, paintPosition); +void ItemProxyStyle::viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, + const QRect &p_rect) const { + // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. + + const QWidget *widget = p_option->widget; + const int textMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1; + // Remove width padding. + QRect textRect = p_rect.adjusted(textMargin, 0, -textMargin, 0); + const bool wrapText = p_option->features & QStyleOptionViewItem::WrapText; + QTextOption textOption; + textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap); + textOption.setTextDirection(p_option->direction); + textOption.setAlignment(QStyle::visualAlignment(p_option->direction, p_option->displayAlignment)); + QPointF paintPosition; + const QString newText = calculateElidedText(p_option->text, textOption, p_option->font, textRect, + p_option->displayAlignment, p_option->textElideMode, + 0, true, &paintPosition); + QTextLayout textLayout(newText, p_option->font); + textLayout.setTextOption(textOption); + viewItemTextLayout(textLayout, textRect.width()); + textLayout.draw(p_painter, paintPosition); } QString ItemProxyStyle::calculateElidedText(const QString &text, const QTextOption &textOption, - const QFont &font, const QRect &textRect, const Qt::Alignment valign, + const QFont &font, const QRect &textRect, + const Qt::Alignment valign, Qt::TextElideMode textElideMode, int flags, - bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const -{ - // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. - - QTextLayout textLayout(text, font); - textLayout.setTextOption(textOption); - // In AlignVCenter mode when more than one line is displayed and the height only allows - // some of the lines it makes no sense to display those. From a users perspective it makes - // more sense to see the start of the text instead something inbetween. - const bool vAlignmentOptimization = paintStartPosition && valign.testFlag(Qt::AlignVCenter); - int lastVisibleLine = -1; - viewItemTextLayout(textLayout, textRect.width(), vAlignmentOptimization ? textRect.height() : -1, &lastVisibleLine); - const QRectF boundingRect = textLayout.boundingRect(); - // don't care about LTR/RTL here, only need the height - const QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, valign, - boundingRect.size().toSize(), textRect); - if (paintStartPosition) - *paintStartPosition = QPointF(textRect.x(), layoutRect.top()); - QString ret; - qreal height = 0; - const int lineCount = textLayout.lineCount(); - for (int i = 0; i < lineCount; ++i) { - const QTextLine line = textLayout.lineAt(i); - height += line.height(); - // above visible rect - if (height + layoutRect.top() <= textRect.top()) { - if (paintStartPosition) - paintStartPosition->ry() += line.height(); - continue; - } - const int start = line.textStart(); - const int length = line.textLength(); - const bool drawElided = line.naturalTextWidth() > textRect.width(); - bool elideLastVisibleLine = lastVisibleLine == i; - if (!drawElided && i + 1 < lineCount && lastVisibleLineShouldBeElided) { - const QTextLine nextLine = textLayout.lineAt(i + 1); - const int nextHeight = height + nextLine.height() / 2; - // elide when less than the next half line is visible - if (nextHeight + layoutRect.top() > textRect.height() + textRect.top()) - elideLastVisibleLine = true; - } - QString text = textLayout.text().mid(start, length); - if (drawElided || elideLastVisibleLine) { - Q_ASSERT(false); - if (elideLastVisibleLine) { - if (text.endsWith(QChar::LineSeparator)) - text.chop(1); - text += QChar(0x2026); - } - /* TODO: QStackTextEngine is a private class. - const QStackTextEngine engine(text, font); - ret += engine.elidedText(textElideMode, textRect.width(), flags); - */ - Q_UNUSED(flags); - Q_UNUSED(textElideMode); - ret += text; - // no newline for the last line (last visible or real) - // sometimes drawElided is true but no eliding is done so the text ends - // with QChar::LineSeparator - don't add another one. This happened with - // arabic text in the testcase for QTBUG-72805 - if (i < lineCount - 1 && - !ret.endsWith(QChar::LineSeparator)) - ret += QChar::LineSeparator; - } else { - ret += text; - } - // below visible text, can stop - if ((height + layoutRect.top() >= textRect.bottom()) || - (lastVisibleLine >= 0 && lastVisibleLine == i)) - break; + bool lastVisibleLineShouldBeElided, + QPointF *paintStartPosition) const { + // Copied from qtbase/src/widgets/styles/qcommonstyle.cpp. + + QTextLayout textLayout(text, font); + textLayout.setTextOption(textOption); + // In AlignVCenter mode when more than one line is displayed and the height only allows + // some of the lines it makes no sense to display those. From a users perspective it makes + // more sense to see the start of the text instead something inbetween. + const bool vAlignmentOptimization = paintStartPosition && valign.testFlag(Qt::AlignVCenter); + int lastVisibleLine = -1; + viewItemTextLayout(textLayout, textRect.width(), vAlignmentOptimization ? textRect.height() : -1, + &lastVisibleLine); + const QRectF boundingRect = textLayout.boundingRect(); + // don't care about LTR/RTL here, only need the height + const QRect layoutRect = + QStyle::alignedRect(Qt::LayoutDirectionAuto, valign, boundingRect.size().toSize(), textRect); + if (paintStartPosition) + *paintStartPosition = QPointF(textRect.x(), layoutRect.top()); + QString ret; + qreal height = 0; + const int lineCount = textLayout.lineCount(); + for (int i = 0; i < lineCount; ++i) { + const QTextLine line = textLayout.lineAt(i); + height += line.height(); + // above visible rect + if (height + layoutRect.top() <= textRect.top()) { + if (paintStartPosition) + paintStartPosition->ry() += line.height(); + continue; + } + const int start = line.textStart(); + const int length = line.textLength(); + const bool drawElided = line.naturalTextWidth() > textRect.width(); + bool elideLastVisibleLine = lastVisibleLine == i; + if (!drawElided && i + 1 < lineCount && lastVisibleLineShouldBeElided) { + const QTextLine nextLine = textLayout.lineAt(i + 1); + const int nextHeight = height + nextLine.height() / 2; + // elide when less than the next half line is visible + if (nextHeight + layoutRect.top() > textRect.height() + textRect.top()) + elideLastVisibleLine = true; + } + QString text = textLayout.text().mid(start, length); + if (drawElided || elideLastVisibleLine) { + Q_ASSERT(false); + if (elideLastVisibleLine) { + if (text.endsWith(QChar::LineSeparator)) + text.chop(1); + text += QChar(0x2026); + } + /* TODO: QStackTextEngine is a private class. + const QStackTextEngine engine(text, font); + ret += engine.elidedText(textElideMode, textRect.width(), flags); + */ + Q_UNUSED(flags); + Q_UNUSED(textElideMode); + ret += text; + // no newline for the last line (last visible or real) + // sometimes drawElided is true but no eliding is done so the text ends + // with QChar::LineSeparator - don't add another one. This happened with + // arabic text in the testcase for QTBUG-72805 + if (i < lineCount - 1 && !ret.endsWith(QChar::LineSeparator)) + ret += QChar::LineSeparator; + } else { + ret += text; } - return ret; + // below visible text, can stop + if ((height + layoutRect.top() >= textRect.bottom()) || + (lastVisibleLine >= 0 && lastVisibleLine == i)) + break; + } + return ret; } diff --git a/src/widgets/itemproxystyle.h b/src/widgets/itemproxystyle.h index 49b1881c97..61f59701ac 100644 --- a/src/widgets/itemproxystyle.h +++ b/src/widgets/itemproxystyle.h @@ -6,30 +6,29 @@ class QStyleOptionViewItem; class QTextOption; -namespace vnotex -{ - // Draw item with text segments highlighted. - class ItemProxyStyle : public QProxyStyle - { - Q_OBJECT - public: - explicit ItemProxyStyle(QStyle *p_style = nullptr); - - void drawControl(QStyle::ControlElement p_element, - const QStyleOption *p_option, - QPainter *p_painter, - const QWidget *p_widget = nullptr) const Q_DECL_OVERRIDE; - - private: - bool drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, const QWidget *p_widget) const; - - void viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, const QRect &p_rect) const; - - QString calculateElidedText(const QString &text, const QTextOption &textOption, - const QFont &font, const QRect &textRect, const Qt::Alignment valign, - Qt::TextElideMode textElideMode, int flags, - bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const; - }; -} +namespace vnotex { +// Draw item with text segments highlighted. +class ItemProxyStyle : public QProxyStyle { + Q_OBJECT +public: + explicit ItemProxyStyle(QStyle *p_style = nullptr); + + void drawControl(QStyle::ControlElement p_element, const QStyleOption *p_option, + QPainter *p_painter, const QWidget *p_widget = nullptr) const Q_DECL_OVERRIDE; + +private: + bool drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, + const QWidget *p_widget) const; + + void viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, + const QRect &p_rect) const; + + QString calculateElidedText(const QString &text, const QTextOption &textOption, const QFont &font, + const QRect &textRect, const Qt::Alignment valign, + Qt::TextElideMode textElideMode, int flags, + bool lastVisibleLineShouldBeElided, + QPointF *paintStartPosition) const; +}; +} // namespace vnotex #endif // ITEMPROXYSTYLE_H diff --git a/src/widgets/labelwithbuttonswidget.cpp b/src/widgets/labelwithbuttonswidget.cpp index 918763d0aa..21f116b6de 100644 --- a/src/widgets/labelwithbuttonswidget.cpp +++ b/src/widgets/labelwithbuttonswidget.cpp @@ -1,82 +1,73 @@ #include "labelwithbuttonswidget.h" -#include +#include +#include #include -#include +#include #include -#include #include +#include #include -#include #include #include using namespace vnotex; -LabelWithButtonsWidget::LabelWithButtonsWidget(const QString &p_label, Buttons p_buttons, QWidget *p_parent) - : QWidget(p_parent) -{ - setupUI(p_buttons); +LabelWithButtonsWidget::LabelWithButtonsWidget(const QString &p_label, Buttons p_buttons, + QWidget *p_parent) + : QWidget(p_parent) { + setupUI(p_buttons); - setLabel(p_label); + setLabel(p_label); } -void LabelWithButtonsWidget::setupUI(Buttons p_buttons) -{ - auto mainLayout = new QHBoxLayout(this); +void LabelWithButtonsWidget::setupUI(Buttons p_buttons) { + auto mainLayout = new QHBoxLayout(this); - m_label = new QLabel(this); - mainLayout->addWidget(m_label); + m_label = new QLabel(this); + mainLayout->addWidget(m_label); - if (p_buttons & Button::Delete) { - auto btn = createButton(Button::Delete, this); - mainLayout->addWidget(btn); - } + if (p_buttons & Button::Delete) { + auto btn = createButton(Button::Delete, this); + mainLayout->addWidget(btn); + } } -void LabelWithButtonsWidget::setLabel(const QString &p_label) -{ - m_label->setText(p_label); -} +void LabelWithButtonsWidget::setLabel(const QString &p_label) { m_label->setText(p_label); } -void LabelWithButtonsWidget::paintEvent(QPaintEvent *p_event) -{ - Q_UNUSED(p_event); +void LabelWithButtonsWidget::paintEvent(QPaintEvent *p_event) { + Q_UNUSED(p_event); - QStyleOption opt; - opt.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); + QStyleOption opt; + opt.initFrom(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } -QToolButton *LabelWithButtonsWidget::createButton(Button p_button, QWidget *p_parent) -{ - auto btn = new QToolButton(p_parent); - QAction *act = nullptr; - switch (p_button) { - case Button::Delete: - act = new QAction(generateIcon(QStringLiteral("delete.svg")), tr("Delete"), p_parent); - break; +QToolButton *LabelWithButtonsWidget::createButton(Button p_button, QWidget *p_parent) { + auto btn = new QToolButton(p_parent); + QAction *act = nullptr; + switch (p_button) { + case Button::Delete: + act = new QAction(generateIcon(QStringLiteral("delete.svg")), tr("Delete"), p_parent); + break; - default: - Q_ASSERT(false); - break; - } + default: + Q_ASSERT(false); + break; + } - if (act) { - act->setData(static_cast(p_button)); - btn->setDefaultAction(act); - connect(btn, &QToolButton::triggered, - this, [this](QAction *p_act) { - emit triggered(static_cast