novelWriter 2.7.4__py3-none-any.whl → 2.8b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- novelwriter/__init__.py +8 -7
 - novelwriter/assets/icons/font_awesome.icons +22 -4
 - novelwriter/assets/icons/material_filled_normal.icons +20 -2
 - novelwriter/assets/icons/material_filled_thin.icons +20 -2
 - novelwriter/assets/icons/material_rounded_normal.icons +20 -2
 - novelwriter/assets/icons/material_rounded_thin.icons +20 -2
 - novelwriter/assets/icons/material_sharp_normal.icons +20 -2
 - novelwriter/assets/icons/material_sharp_thin.icons +20 -2
 - novelwriter/assets/icons/remix_filled.icons +20 -2
 - novelwriter/assets/icons/remix_outline.icons +20 -2
 - novelwriter/assets/images/welcome.webp +0 -0
 - novelwriter/assets/manual.pdf +0 -0
 - novelwriter/assets/manual_fr.pdf +0 -0
 - novelwriter/assets/sample.zip +0 -0
 - novelwriter/assets/text/credits_en.htm +61 -11
 - novelwriter/assets/themes/aura.conf +97 -0
 - novelwriter/assets/themes/aura_bright.conf +95 -0
 - novelwriter/assets/themes/aura_soft.conf +97 -0
 - novelwriter/assets/themes/b2t_garden_dark.conf +97 -0
 - novelwriter/assets/themes/b2t_garden_light.conf +97 -0
 - novelwriter/assets/themes/b2t_suburb_dark.conf +97 -0
 - novelwriter/assets/themes/b2t_suburb_light.conf +97 -0
 - novelwriter/assets/themes/b4t_classic_o_dark.conf +97 -0
 - novelwriter/assets/themes/b4t_classic_o_light.conf +97 -0
 - novelwriter/assets/themes/b4t_modern_c_dark.conf +97 -0
 - novelwriter/assets/themes/b4t_modern_c_light.conf +97 -0
 - novelwriter/assets/themes/blue_streak_dark.conf +97 -0
 - novelwriter/assets/themes/blue_streak_light.conf +97 -0
 - novelwriter/assets/themes/castle_day.conf +95 -0
 - novelwriter/assets/themes/castle_night.conf +95 -0
 - novelwriter/assets/themes/catppuccin_latte.conf +97 -0
 - novelwriter/assets/themes/catppuccin_mocha.conf +97 -0
 - novelwriter/assets/themes/chalky_soil.conf +95 -0
 - novelwriter/assets/themes/chernozem.conf +95 -0
 - novelwriter/assets/themes/cyberpunk_night.conf +88 -40
 - novelwriter/assets/themes/default_dark.conf +89 -41
 - novelwriter/assets/themes/default_light.conf +89 -41
 - novelwriter/assets/themes/dracula.conf +91 -42
 - novelwriter/assets/themes/espresso.conf +97 -0
 - novelwriter/assets/themes/everforest_dark.conf +97 -0
 - novelwriter/assets/themes/everforest_light.conf +97 -0
 - novelwriter/assets/themes/floral_daydream.conf +95 -0
 - novelwriter/assets/themes/floral_midnight.conf +95 -0
 - novelwriter/assets/themes/full_moon.conf +95 -0
 - novelwriter/assets/themes/grey_dark.conf +97 -0
 - novelwriter/assets/themes/grey_light.conf +97 -0
 - novelwriter/assets/themes/horizon_dark.conf +97 -0
 - novelwriter/assets/themes/horizon_light.conf +97 -0
 - novelwriter/assets/themes/jewel_case_dark.conf +95 -0
 - novelwriter/assets/themes/jewel_case_light.conf +95 -0
 - novelwriter/assets/themes/lcars.conf +97 -0
 - novelwriter/assets/themes/light_owl.conf +117 -0
 - novelwriter/assets/themes/new_moon.conf +97 -0
 - novelwriter/assets/themes/night_owl.conf +117 -0
 - novelwriter/assets/themes/noctis.conf +129 -0
 - novelwriter/assets/themes/noctis_lux.conf +129 -0
 - novelwriter/assets/themes/nord.conf +97 -0
 - novelwriter/assets/themes/nordlicht.conf +95 -0
 - novelwriter/assets/themes/otium_dark.conf +95 -0
 - novelwriter/assets/themes/otium_light.conf +95 -0
 - novelwriter/assets/themes/paragon.conf +96 -0
 - novelwriter/assets/themes/primer_light.conf +97 -0
 - novelwriter/assets/themes/primer_night.conf +97 -0
 - novelwriter/assets/themes/rose_pine.conf +97 -0
 - novelwriter/assets/themes/rose_pine_dawn.conf +97 -0
 - novelwriter/assets/themes/ruby_day.conf +95 -0
 - novelwriter/assets/themes/ruby_night.conf +95 -0
 - novelwriter/assets/themes/selenium_dark.conf +95 -0
 - novelwriter/assets/themes/selenium_light.conf +95 -0
 - novelwriter/assets/themes/sepia_dark.conf +95 -0
 - novelwriter/assets/themes/sepia_light.conf +95 -0
 - novelwriter/assets/themes/snazzy.conf +102 -40
 - novelwriter/assets/themes/solarized_dark.conf +108 -40
 - novelwriter/assets/themes/solarized_light.conf +108 -40
 - novelwriter/assets/themes/sultana_light.conf +95 -0
 - novelwriter/assets/themes/sultana_night.conf +95 -0
 - novelwriter/assets/themes/tango_dark.conf +111 -0
 - novelwriter/assets/themes/tango_light.conf +111 -0
 - novelwriter/assets/themes/tomorrow.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_blue.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_bright.conf +117 -0
 - novelwriter/assets/themes/tomorrow_night_eighties.conf +117 -0
 - novelwriter/assets/themes/vivid_black_green.conf +97 -0
 - novelwriter/assets/themes/vivid_black_red.conf +97 -0
 - novelwriter/assets/themes/vivid_white_green.conf +97 -0
 - novelwriter/assets/themes/vivid_white_red.conf +97 -0
 - novelwriter/assets/themes/warpgate.conf +96 -0
 - novelwriter/assets/themes/waterlily_dark.conf +95 -0
 - novelwriter/assets/themes/waterlily_light.conf +95 -0
 - novelwriter/common.py +47 -17
 - novelwriter/config.py +57 -62
 - novelwriter/constants.py +32 -6
 - novelwriter/core/buildsettings.py +3 -23
 - novelwriter/core/coretools.py +21 -25
 - novelwriter/core/docbuild.py +4 -9
 - novelwriter/core/document.py +2 -6
 - novelwriter/core/index.py +33 -53
 - novelwriter/core/indexdata.py +17 -22
 - novelwriter/core/item.py +11 -35
 - novelwriter/core/itemmodel.py +5 -21
 - novelwriter/core/novelmodel.py +3 -7
 - novelwriter/core/options.py +3 -4
 - novelwriter/core/project.py +31 -21
 - novelwriter/core/projectdata.py +2 -21
 - novelwriter/core/projectxml.py +13 -21
 - novelwriter/core/sessions.py +2 -4
 - novelwriter/core/spellcheck.py +12 -13
 - novelwriter/core/status.py +27 -20
 - novelwriter/core/storage.py +5 -10
 - novelwriter/core/tree.py +6 -15
 - novelwriter/dialogs/about.py +9 -10
 - novelwriter/dialogs/docmerge.py +17 -14
 - novelwriter/dialogs/docsplit.py +18 -14
 - novelwriter/dialogs/editlabel.py +15 -9
 - novelwriter/dialogs/preferences.py +69 -68
 - novelwriter/dialogs/projectsettings.py +88 -67
 - novelwriter/dialogs/quotes.py +15 -10
 - novelwriter/dialogs/wordlist.py +18 -21
 - novelwriter/enum.py +75 -30
 - novelwriter/error.py +6 -11
 - novelwriter/extensions/configlayout.py +8 -34
 - novelwriter/extensions/eventfilters.py +3 -3
 - novelwriter/extensions/modified.py +87 -32
 - novelwriter/extensions/novelselector.py +13 -12
 - novelwriter/extensions/pagedsidebar.py +10 -18
 - novelwriter/extensions/progressbars.py +5 -11
 - novelwriter/extensions/statusled.py +3 -6
 - novelwriter/extensions/switch.py +8 -11
 - novelwriter/extensions/switchbox.py +2 -11
 - novelwriter/extensions/versioninfo.py +6 -7
 - novelwriter/formats/shared.py +10 -2
 - novelwriter/formats/todocx.py +15 -37
 - novelwriter/formats/tohtml.py +52 -61
 - novelwriter/formats/tokenizer.py +33 -64
 - novelwriter/formats/tomarkdown.py +4 -11
 - novelwriter/formats/toodt.py +12 -71
 - novelwriter/formats/toqdoc.py +11 -21
 - novelwriter/formats/toraw.py +2 -6
 - novelwriter/gui/doceditor.py +207 -245
 - novelwriter/gui/dochighlight.py +142 -101
 - novelwriter/gui/docviewer.py +53 -84
 - novelwriter/gui/docviewerpanel.py +18 -41
 - novelwriter/gui/editordocument.py +12 -17
 - novelwriter/gui/itemdetails.py +5 -14
 - novelwriter/gui/mainmenu.py +24 -32
 - novelwriter/gui/noveltree.py +13 -51
 - novelwriter/gui/outline.py +20 -61
 - novelwriter/gui/projtree.py +40 -96
 - novelwriter/gui/search.py +9 -24
 - novelwriter/gui/sidebar.py +54 -22
 - novelwriter/gui/statusbar.py +7 -22
 - novelwriter/gui/theme.py +482 -368
 - novelwriter/guimain.py +87 -101
 - novelwriter/shared.py +79 -48
 - novelwriter/splash.py +9 -5
 - novelwriter/text/comments.py +1 -1
 - novelwriter/text/counting.py +9 -5
 - novelwriter/text/patterns.py +20 -15
 - novelwriter/tools/dictionaries.py +18 -16
 - novelwriter/tools/lipsum.py +15 -17
 - novelwriter/tools/manusbuild.py +25 -45
 - novelwriter/tools/manuscript.py +94 -95
 - novelwriter/tools/manussettings.py +149 -104
 - novelwriter/tools/noveldetails.py +10 -24
 - novelwriter/tools/welcome.py +24 -72
 - novelwriter/tools/writingstats.py +17 -26
 - novelwriter/types.py +25 -13
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/METADATA +7 -7
 - novelwriter-2.8b1.dist-info/RECORD +212 -0
 - novelwriter/assets/images/welcome-dark.jpg +0 -0
 - novelwriter/assets/images/welcome-light.jpg +0 -0
 - novelwriter/assets/syntax/cyberpunk_night.conf +0 -28
 - novelwriter/assets/syntax/default_dark.conf +0 -42
 - novelwriter/assets/syntax/default_light.conf +0 -42
 - novelwriter/assets/syntax/dracula.conf +0 -44
 - novelwriter/assets/syntax/grey_dark.conf +0 -29
 - novelwriter/assets/syntax/grey_light.conf +0 -29
 - novelwriter/assets/syntax/light_owl.conf +0 -49
 - novelwriter/assets/syntax/night_owl.conf +0 -49
 - novelwriter/assets/syntax/snazzy.conf +0 -42
 - novelwriter/assets/syntax/solarized_dark.conf +0 -29
 - novelwriter/assets/syntax/solarized_light.conf +0 -29
 - novelwriter/assets/syntax/tango.conf +0 -39
 - novelwriter/assets/syntax/tomorrow.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_blue.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_bright.conf +0 -49
 - novelwriter/assets/syntax/tomorrow_night_eighties.conf +0 -49
 - novelwriter/assets/themes/default.conf +0 -3
 - novelwriter-2.7.4.dist-info/RECORD +0 -163
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/WHEEL +0 -0
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/entry_points.txt +0 -0
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/licenses/LICENSE.md +0 -0
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/licenses/setup/LICENSE-Apache-2.0.txt +0 -0
 - {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/top_level.txt +0 -0
 
| 
         @@ -20,7 +20,7 @@ General Public License for more details. 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            You should have received a copy of the GNU General Public License
         
     | 
| 
       22 
22 
     | 
    
         
             
            along with this program. If not, see <https://www.gnu.org/licenses/>.
         
     | 
| 
       23 
     | 
    
         
            -
            """
         
     | 
| 
      
 23 
     | 
    
         
            +
            """  # noqa
         
     | 
| 
       24 
24 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
            import logging
         
     | 
| 
         @@ -38,12 +38,13 @@ from PyQt6.QtWidgets import ( 
     | 
|
| 
       38 
38 
     | 
    
         
             
            from novelwriter import SHARED
         
     | 
| 
       39 
39 
     | 
    
         
             
            from novelwriter.common import formatTime, numberToRoman
         
     | 
| 
       40 
40 
     | 
    
         
             
            from novelwriter.constants import nwUnicode
         
     | 
| 
      
 41 
     | 
    
         
            +
            from novelwriter.enum import nwStandardButton
         
     | 
| 
       41 
42 
     | 
    
         
             
            from novelwriter.extensions.configlayout import NColorLabel, NFixedPage, NScrollablePage
         
     | 
| 
       42 
43 
     | 
    
         
             
            from novelwriter.extensions.modified import NNonBlockingDialog
         
     | 
| 
       43 
44 
     | 
    
         
             
            from novelwriter.extensions.novelselector import NovelSelector
         
     | 
| 
       44 
45 
     | 
    
         
             
            from novelwriter.extensions.pagedsidebar import NPagedSideBar
         
     | 
| 
       45 
46 
     | 
    
         
             
            from novelwriter.extensions.switch import NSwitch
         
     | 
| 
       46 
     | 
    
         
            -
            from novelwriter.types import QtAlignRight, QtDecoration,  
     | 
| 
      
 47 
     | 
    
         
            +
            from novelwriter.types import QtAlignRight, QtDecoration, QtRoleDestruct
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       49 
50 
     | 
    
         
             
                from PyQt6.QtGui import QCloseEvent
         
     | 
| 
         @@ -52,6 +53,7 @@ logger = logging.getLogger(__name__) 
     | 
|
| 
       52 
53 
     | 
    
         | 
| 
       53 
54 
     | 
    
         | 
| 
       54 
55 
     | 
    
         
             
            class GuiNovelDetails(NNonBlockingDialog):
         
     | 
| 
      
 56 
     | 
    
         
            +
                """GUI: Novel Details Tool."""
         
     | 
| 
       55 
57 
     | 
    
         | 
| 
       56 
58 
     | 
    
         
             
                PAGE_OVERVIEW = 1
         
     | 
| 
       57 
59 
     | 
    
         
             
                PAGE_CONTENTS = 2
         
     | 
| 
         @@ -101,8 +103,11 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       101 
103 
     | 
    
         
             
                    self.mainStack.addWidget(self.contentsPage)
         
     | 
| 
       102 
104 
     | 
    
         | 
| 
       103 
105 
     | 
    
         
             
                    # Buttons
         
     | 
| 
       104 
     | 
    
         
            -
                    self. 
     | 
| 
       105 
     | 
    
         
            -
                    self. 
     | 
| 
      
 106 
     | 
    
         
            +
                    self.btnClose = SHARED.theme.getStandardButton(nwStandardButton.CLOSE, self)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    self.btnClose.clicked.connect(self.reject)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    self.btnBox = QDialogButtonBox(self)
         
     | 
| 
      
 110 
     | 
    
         
            +
                    self.btnBox.addButton(self.btnClose, QtRoleDestruct)
         
     | 
| 
       106 
111 
     | 
    
         | 
| 
       107 
112 
     | 
    
         
             
                    # Assemble
         
     | 
| 
       108 
113 
     | 
    
         
             
                    self.topBox = QHBoxLayout()
         
     | 
| 
         @@ -118,7 +123,7 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       118 
123 
     | 
    
         
             
                    self.outerBox = QVBoxLayout()
         
     | 
| 
       119 
124 
     | 
    
         
             
                    self.outerBox.addLayout(self.topBox)
         
     | 
| 
       120 
125 
     | 
    
         
             
                    self.outerBox.addLayout(self.mainBox)
         
     | 
| 
       121 
     | 
    
         
            -
                    self.outerBox.addWidget(self. 
     | 
| 
      
 126 
     | 
    
         
            +
                    self.outerBox.addWidget(self.btnBox)
         
     | 
| 
       122 
127 
     | 
    
         
             
                    self.outerBox.setSpacing(8)
         
     | 
| 
       123 
128 
     | 
    
         | 
| 
       124 
129 
     | 
    
         
             
                    self.setLayout(self.outerBox)
         
     | 
| 
         @@ -130,11 +135,8 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       130 
135 
     | 
    
         | 
| 
       131 
136 
     | 
    
         
             
                    logger.debug("Ready: GuiNovelDetails")
         
     | 
| 
       132 
137 
     | 
    
         | 
| 
       133 
     | 
    
         
            -
                    return
         
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
138 
     | 
    
         
             
                def __del__(self) -> None:  # pragma: no cover
         
     | 
| 
       136 
139 
     | 
    
         
             
                    logger.debug("Delete: GuiNovelDetails")
         
     | 
| 
       137 
     | 
    
         
            -
                    return
         
     | 
| 
       138 
140 
     | 
    
         | 
| 
       139 
141 
     | 
    
         
             
                ##
         
     | 
| 
       140 
142 
     | 
    
         
             
                #  Methods
         
     | 
| 
         @@ -146,7 +148,6 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       146 
148 
     | 
    
         
             
                        self.overviewPage.updateProjectData()
         
     | 
| 
       147 
149 
     | 
    
         
             
                        self.overviewPage.novelValueChanged(handle)
         
     | 
| 
       148 
150 
     | 
    
         
             
                        self.contentsPage.novelValueChanged(handle)
         
     | 
| 
       149 
     | 
    
         
            -
                    return
         
     | 
| 
       150 
151 
     | 
    
         | 
| 
       151 
152 
     | 
    
         
             
                ##
         
     | 
| 
       152 
153 
     | 
    
         
             
                #  Events
         
     | 
| 
         @@ -157,7 +158,6 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       157 
158 
     | 
    
         
             
                    self._saveSettings()
         
     | 
| 
       158 
159 
     | 
    
         
             
                    event.accept()
         
     | 
| 
       159 
160 
     | 
    
         
             
                    self.softDelete()
         
     | 
| 
       160 
     | 
    
         
            -
                    return
         
     | 
| 
       161 
161 
     | 
    
         | 
| 
       162 
162 
     | 
    
         
             
                ##
         
     | 
| 
       163 
163 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
         @@ -170,7 +170,6 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       170 
170 
     | 
    
         
             
                        self.mainStack.setCurrentWidget(self.overviewPage)
         
     | 
| 
       171 
171 
     | 
    
         
             
                    elif pageId == self.PAGE_CONTENTS:
         
     | 
| 
       172 
172 
     | 
    
         
             
                        self.mainStack.setCurrentWidget(self.contentsPage)
         
     | 
| 
       173 
     | 
    
         
            -
                    return
         
     | 
| 
       174 
173 
     | 
    
         | 
| 
       175 
174 
     | 
    
         
             
                ##
         
     | 
| 
       176 
175 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
         @@ -185,7 +184,6 @@ class GuiNovelDetails(NNonBlockingDialog): 
     | 
|
| 
       185 
184 
     | 
    
         
             
                    options.setValue("GuiNovelDetails", "winHeight", self.height())
         
     | 
| 
       186 
185 
     | 
    
         
             
                    options.setValue("GuiNovelDetails", "novelRoot", novelRoot)
         
     | 
| 
       187 
186 
     | 
    
         
             
                    self.contentsPage.saveSettings()
         
     | 
| 
       188 
     | 
    
         
            -
                    return
         
     | 
| 
       189 
187 
     | 
    
         | 
| 
       190 
188 
     | 
    
         | 
| 
       191 
189 
     | 
    
         
             
            class _OverviewPage(NScrollablePage):
         
     | 
| 
         @@ -248,8 +246,6 @@ class _OverviewPage(NScrollablePage): 
     | 
|
| 
       248 
246 
     | 
    
         | 
| 
       249 
247 
     | 
    
         
             
                    self.setCentralLayout(self.outerBox)
         
     | 
| 
       250 
248 
     | 
    
         | 
| 
       251 
     | 
    
         
            -
                    return
         
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
249 
     | 
    
         
             
                ##
         
     | 
| 
       254 
250 
     | 
    
         
             
                #  Methods
         
     | 
| 
       255 
251 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -266,7 +262,6 @@ class _OverviewPage(NScrollablePage): 
     | 
|
| 
       266 
262 
     | 
    
         
             
                    self.projWords.setText(f"{wcNovel + wcNotes:n}")
         
     | 
| 
       267 
263 
     | 
    
         
             
                    self.projNovels.setText(f"{wcNovel:n}")
         
     | 
| 
       268 
264 
     | 
    
         
             
                    self.projNotes.setText(f"{wcNotes:n}")
         
     | 
| 
       269 
     | 
    
         
            -
                    return
         
     | 
| 
       270 
265 
     | 
    
         | 
| 
       271 
266 
     | 
    
         
             
                ##
         
     | 
| 
       272 
267 
     | 
    
         
             
                #  Public Slots
         
     | 
| 
         @@ -286,8 +281,6 @@ class _OverviewPage(NScrollablePage): 
     | 
|
| 
       286 
281 
     | 
    
         
             
                    self.novelChapters.setText(f"{hCounts[2]:n}")
         
     | 
| 
       287 
282 
     | 
    
         
             
                    self.novelScenes.setText(f"{hCounts[3]:n}")
         
     | 
| 
       288 
283 
     | 
    
         | 
| 
       289 
     | 
    
         
            -
                    return
         
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
284 
     | 
    
         | 
| 
       292 
285 
     | 
    
         
             
            class _ContentsPage(NFixedPage):
         
     | 
| 
       293 
286 
     | 
    
         | 
| 
         @@ -400,8 +393,6 @@ class _ContentsPage(NFixedPage): 
     | 
|
| 
       400 
393 
     | 
    
         | 
| 
       401 
394 
     | 
    
         
             
                    self.setCentralLayout(self.outerBox)
         
     | 
| 
       402 
395 
     | 
    
         | 
| 
       403 
     | 
    
         
            -
                    return
         
     | 
| 
       404 
     | 
    
         
            -
             
     | 
| 
       405 
396 
     | 
    
         
             
                def saveSettings(self) -> None:
         
     | 
| 
       406 
397 
     | 
    
         
             
                    """Save the user GUI settings."""
         
     | 
| 
       407 
398 
     | 
    
         
             
                    options = SHARED.project.options
         
     | 
| 
         @@ -413,7 +404,6 @@ class _ContentsPage(NFixedPage): 
     | 
|
| 
       413 
404 
     | 
    
         
             
                    options.setValue("GuiNovelDetails", "wordsPerPage", self.wpValue.value())
         
     | 
| 
       414 
405 
     | 
    
         
             
                    options.setValue("GuiNovelDetails", "countFrom",    self.poValue.value())
         
     | 
| 
       415 
406 
     | 
    
         
             
                    options.setValue("GuiNovelDetails", "clearDouble",  self.dblValue.isChecked())
         
     | 
| 
       416 
     | 
    
         
            -
                    return
         
     | 
| 
       417 
407 
     | 
    
         | 
| 
       418 
408 
     | 
    
         
             
                ##
         
     | 
| 
       419 
409 
     | 
    
         
             
                #  Public Slots
         
     | 
| 
         @@ -426,7 +416,6 @@ class _ContentsPage(NFixedPage): 
     | 
|
| 
       426 
416 
     | 
    
         
             
                        self._prepareData(tHandle)
         
     | 
| 
       427 
417 
     | 
    
         
             
                        self._populateTree()
         
     | 
| 
       428 
418 
     | 
    
         
             
                        self._currentRoot = tHandle
         
     | 
| 
       429 
     | 
    
         
            -
                    return
         
     | 
| 
       430 
419 
     | 
    
         | 
| 
       431 
420 
     | 
    
         
             
                ##
         
     | 
| 
       432 
421 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
         @@ -496,8 +485,6 @@ class _ContentsPage(NFixedPage): 
     | 
|
| 
       496 
485 
     | 
    
         | 
| 
       497 
486 
     | 
    
         
             
                        self.tocTree.addTopLevelItem(newItem)
         
     | 
| 
       498 
487 
     | 
    
         | 
| 
       499 
     | 
    
         
            -
                    return
         
     | 
| 
       500 
     | 
    
         
            -
             
     | 
| 
       501 
488 
     | 
    
         
             
                ##
         
     | 
| 
       502 
489 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
       503 
490 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -507,4 +494,3 @@ class _ContentsPage(NFixedPage): 
     | 
|
| 
       507 
494 
     | 
    
         
             
                    logger.debug("Populating ToC from handle '%s'", rootHandle)
         
     | 
| 
       508 
495 
     | 
    
         
             
                    self._data = SHARED.project.index.getTableOfContents(rootHandle, 2)
         
     | 
| 
       509 
496 
     | 
    
         
             
                    self._data.append(("", 0, self.tr("END"), 0))
         
     | 
| 
       510 
     | 
    
         
            -
                    return
         
     | 
    
        novelwriter/tools/welcome.py
    CHANGED
    
    | 
         @@ -20,7 +20,7 @@ General Public License for more details. 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            You should have received a copy of the GNU General Public License
         
     | 
| 
       22 
22 
     | 
    
         
             
            along with this program. If not, see <https://www.gnu.org/licenses/>.
         
     | 
| 
       23 
     | 
    
         
            -
            """
         
     | 
| 
      
 23 
     | 
    
         
            +
            """  # noqa
         
     | 
| 
       24 
24 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
            import logging
         
     | 
| 
         @@ -32,18 +32,18 @@ from PyQt6.QtCore import ( 
     | 
|
| 
       32 
32 
     | 
    
         
             
                QAbstractListModel, QModelIndex, QObject, QPoint, QSize, Qt, pyqtSignal,
         
     | 
| 
       33 
33 
     | 
    
         
             
                pyqtSlot
         
     | 
| 
       34 
34 
     | 
    
         
             
            )
         
     | 
| 
       35 
     | 
    
         
            -
            from PyQt6.QtGui import QAction, QCloseEvent,  
     | 
| 
      
 35 
     | 
    
         
            +
            from PyQt6.QtGui import QAction, QCloseEvent, QFont, QPainter, QPaintEvent, QPen, QShortcut
         
     | 
| 
       36 
36 
     | 
    
         
             
            from PyQt6.QtWidgets import (
         
     | 
| 
       37 
37 
     | 
    
         
             
                QApplication, QFileDialog, QFormLayout, QHBoxLayout, QLabel, QLineEdit,
         
     | 
| 
       38 
     | 
    
         
            -
                QListView, QMenu,  
     | 
| 
       39 
     | 
    
         
            -
                 
     | 
| 
      
 38 
     | 
    
         
            +
                QListView, QMenu, QScrollArea, QStackedWidget, QStyledItemDelegate,
         
     | 
| 
      
 39 
     | 
    
         
            +
                QStyleOptionViewItem, QVBoxLayout, QWidget
         
     | 
| 
       40 
40 
     | 
    
         
             
            )
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
            from novelwriter import CONFIG, SHARED
         
     | 
| 
       43 
43 
     | 
    
         
             
            from novelwriter.common import formatInt, makeFileNameSafe, qtAddAction, qtLambda
         
     | 
| 
       44 
44 
     | 
    
         
             
            from novelwriter.constants import nwFiles
         
     | 
| 
       45 
45 
     | 
    
         
             
            from novelwriter.core.coretools import ProjectBuilder
         
     | 
| 
       46 
     | 
    
         
            -
            from novelwriter.enum import nwItemClass
         
     | 
| 
      
 46 
     | 
    
         
            +
            from novelwriter.enum import nwItemClass, nwStandardButton
         
     | 
| 
       47 
47 
     | 
    
         
             
            from novelwriter.extensions.configlayout import NWrappedWidgetBox
         
     | 
| 
       48 
48 
     | 
    
         
             
            from novelwriter.extensions.modified import NDialog, NIconToolButton, NSpinBox
         
     | 
| 
       49 
49 
     | 
    
         
             
            from novelwriter.extensions.switch import NSwitch
         
     | 
| 
         @@ -56,6 +56,11 @@ PANEL_ALPHA = 178 
     | 
|
| 
       56 
56 
     | 
    
         | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
            class GuiWelcome(NDialog):
         
     | 
| 
      
 59 
     | 
    
         
            +
                """GUI: Welcome Dialog.
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                This is the main dialog shown when novelWriter launches or when the
         
     | 
| 
      
 62 
     | 
    
         
            +
                user wants to create or open another project.
         
     | 
| 
      
 63 
     | 
    
         
            +
                """
         
     | 
| 
       59 
64 
     | 
    
         | 
| 
       60 
65 
     | 
    
         
             
                openProjectRequest = pyqtSignal(Path)
         
     | 
| 
       61 
66 
     | 
    
         | 
| 
         @@ -70,14 +75,11 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       70 
75 
     | 
    
         
             
                    self.setMinimumHeight(450)
         
     | 
| 
       71 
76 
     | 
    
         
             
                    self.resize(*CONFIG.welcomeWinSize)
         
     | 
| 
       72 
77 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                    btnIconSize = SHARED.theme.buttonIconSize
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
78 
     | 
    
         
             
                    # Elements
         
     | 
| 
       76 
79 
     | 
    
         
             
                    # ========
         
     | 
| 
       77 
80 
     | 
    
         | 
| 
       78 
81 
     | 
    
         
             
                    self.bgImage = SHARED.theme.getDecoration("welcome")
         
     | 
| 
       79 
82 
     | 
    
         
             
                    self.nwImage = SHARED.theme.getDecoration("nw-text", h=36)
         
     | 
| 
       80 
     | 
    
         
            -
                    self.bgColor = QColor(54, 54, 54) if SHARED.theme.isDarkTheme else QColor(255, 255, 255)
         
     | 
| 
       81 
83 
     | 
    
         | 
| 
       82 
84 
     | 
    
         
             
                    self.nwLogo = QLabel(self)
         
     | 
| 
       83 
85 
     | 
    
         
             
                    self.nwLogo.setPixmap(SHARED.theme.getPixmap("novelwriter", (128, 128)))
         
     | 
| 
         @@ -100,34 +102,22 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       100 
102 
     | 
    
         
             
                    # Buttons
         
     | 
| 
       101 
103 
     | 
    
         
             
                    # =======
         
     | 
| 
       102 
104 
     | 
    
         | 
| 
       103 
     | 
    
         
            -
                    self.btnList =  
     | 
| 
       104 
     | 
    
         
            -
                    self.btnList.setIcon(SHARED.theme.getIcon("list", "blue"))
         
     | 
| 
       105 
     | 
    
         
            -
                    self.btnList.setIconSize(btnIconSize)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    self.btnList = SHARED.theme.getStandardButton(nwStandardButton.LIST, self)
         
     | 
| 
       106 
106 
     | 
    
         
             
                    self.btnList.clicked.connect(self._showOpenProjectPage)
         
     | 
| 
       107 
107 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                    self.btnNew =  
     | 
| 
       109 
     | 
    
         
            -
                    self.btnNew.setIcon(SHARED.theme.getIcon("add", "green"))
         
     | 
| 
       110 
     | 
    
         
            -
                    self.btnNew.setIconSize(btnIconSize)
         
     | 
| 
      
 108 
     | 
    
         
            +
                    self.btnNew = SHARED.theme.getStandardButton(nwStandardButton.NEW, self)
         
     | 
| 
       111 
109 
     | 
    
         
             
                    self.btnNew.clicked.connect(self._showNewProjectPage)
         
     | 
| 
       112 
110 
     | 
    
         | 
| 
       113 
     | 
    
         
            -
                    self.btnBrowse =  
     | 
| 
       114 
     | 
    
         
            -
                    self.btnBrowse.setIcon(SHARED.theme.getIcon("browse", "yellow"))
         
     | 
| 
       115 
     | 
    
         
            -
                    self.btnBrowse.setIconSize(btnIconSize)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    self.btnBrowse = SHARED.theme.getStandardButton(nwStandardButton.BROWSE, self)
         
     | 
| 
       116 
112 
     | 
    
         
             
                    self.btnBrowse.clicked.connect(self._browseForProject)
         
     | 
| 
       117 
113 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                    self.btnCancel =  
     | 
| 
       119 
     | 
    
         
            -
                    self.btnCancel.setIcon(SHARED.theme.getIcon("cancel", "red"))
         
     | 
| 
       120 
     | 
    
         
            -
                    self.btnCancel.setIconSize(btnIconSize)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    self.btnCancel = SHARED.theme.getStandardButton(nwStandardButton.CANCEL, self)
         
     | 
| 
       121 
115 
     | 
    
         
             
                    self.btnCancel.clicked.connect(qtLambda(self.close))
         
     | 
| 
       122 
116 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
                    self.btnCreate =  
     | 
| 
       124 
     | 
    
         
            -
                    self.btnCreate.setIcon(SHARED.theme.getIcon("star", "yellow"))
         
     | 
| 
       125 
     | 
    
         
            -
                    self.btnCreate.setIconSize(btnIconSize)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    self.btnCreate = SHARED.theme.getStandardButton(nwStandardButton.CREATE, self)
         
     | 
| 
       126 
118 
     | 
    
         
             
                    self.btnCreate.clicked.connect(self.tabNew.createNewProject)
         
     | 
| 
       127 
119 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
                    self.btnOpen =  
     | 
| 
       129 
     | 
    
         
            -
                    self.btnOpen.setIcon(SHARED.theme.getIcon("open", "blue"))
         
     | 
| 
       130 
     | 
    
         
            -
                    self.btnOpen.setIconSize(btnIconSize)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    self.btnOpen = SHARED.theme.getStandardButton(nwStandardButton.OPEN, self)
         
     | 
| 
       131 
121 
     | 
    
         
             
                    self.btnOpen.clicked.connect(self._openSelectedItem)
         
     | 
| 
       132 
122 
     | 
    
         | 
| 
       133 
123 
     | 
    
         
             
                    self.btnBox = QHBoxLayout()
         
     | 
| 
         @@ -162,11 +152,8 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       162 
152 
     | 
    
         | 
| 
       163 
153 
     | 
    
         
             
                    logger.debug("Ready: GuiWelcome")
         
     | 
| 
       164 
154 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
                    return
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
155 
     | 
    
         
             
                def __del__(self) -> None:  # pragma: no cover
         
     | 
| 
       168 
156 
     | 
    
         
             
                    logger.debug("Delete: GuiWelcome")
         
     | 
| 
       169 
     | 
    
         
            -
                    return
         
     | 
| 
       170 
157 
     | 
    
         | 
| 
       171 
158 
     | 
    
         
             
                ##
         
     | 
| 
       172 
159 
     | 
    
         
             
                #  Events
         
     | 
| 
         @@ -178,17 +165,15 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       178 
165 
     | 
    
         
             
                    hPix = min(hWin, 600)
         
     | 
| 
       179 
166 
     | 
    
         
             
                    tMode = Qt.TransformationMode.SmoothTransformation
         
     | 
| 
       180 
167 
     | 
    
         
             
                    painter = QPainter(self)
         
     | 
| 
       181 
     | 
    
         
            -
                    painter.fillRect(self.rect(), self.bgColor)
         
     | 
| 
       182 
168 
     | 
    
         
             
                    painter.drawPixmap(0, hWin - hPix, self.bgImage.scaledToHeight(hPix, tMode))
         
     | 
| 
      
 169 
     | 
    
         
            +
                    painter.end()
         
     | 
| 
       183 
170 
     | 
    
         
             
                    super().paintEvent(event)
         
     | 
| 
       184 
     | 
    
         
            -
                    return
         
     | 
| 
       185 
171 
     | 
    
         | 
| 
       186 
172 
     | 
    
         
             
                def closeEvent(self, event: QCloseEvent) -> None:
         
     | 
| 
       187 
173 
     | 
    
         
             
                    """Capture the user closing the window and save settings."""
         
     | 
| 
       188 
174 
     | 
    
         
             
                    self._saveSettings()
         
     | 
| 
       189 
175 
     | 
    
         
             
                    event.accept()
         
     | 
| 
       190 
176 
     | 
    
         
             
                    self.softDelete()
         
     | 
| 
       191 
     | 
    
         
            -
                    return
         
     | 
| 
       192 
177 
     | 
    
         | 
| 
       193 
178 
     | 
    
         
             
                ##
         
     | 
| 
       194 
179 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
         @@ -200,28 +185,24 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       200 
185 
     | 
    
         
             
                    self.mainStack.setCurrentWidget(self.tabNew)
         
     | 
| 
       201 
186 
     | 
    
         
             
                    self._setButtonVisibility()
         
     | 
| 
       202 
187 
     | 
    
         
             
                    self.tabNew.enterForm()
         
     | 
| 
       203 
     | 
    
         
            -
                    return
         
     | 
| 
       204 
188 
     | 
    
         | 
| 
       205 
189 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       206 
190 
     | 
    
         
             
                def _showOpenProjectPage(self) -> None:
         
     | 
| 
       207 
191 
     | 
    
         
             
                    """Show the open exiting project page."""
         
     | 
| 
       208 
192 
     | 
    
         
             
                    self.mainStack.setCurrentWidget(self.tabOpen)
         
     | 
| 
       209 
193 
     | 
    
         
             
                    self._setButtonVisibility()
         
     | 
| 
       210 
     | 
    
         
            -
                    return
         
     | 
| 
       211 
194 
     | 
    
         | 
| 
       212 
195 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       213 
196 
     | 
    
         
             
                def _browseForProject(self) -> None:
         
     | 
| 
       214 
197 
     | 
    
         
             
                    """Browse for a project to open."""
         
     | 
| 
       215 
198 
     | 
    
         
             
                    if path := SHARED.getProjectPath(self, path=CONFIG.homePath(), allowZip=False):
         
     | 
| 
       216 
199 
     | 
    
         
             
                        self._openProjectPath(path)
         
     | 
| 
       217 
     | 
    
         
            -
                    return
         
     | 
| 
       218 
200 
     | 
    
         | 
| 
       219 
201 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       220 
202 
     | 
    
         
             
                def _openSelectedItem(self) -> None:
         
     | 
| 
       221 
203 
     | 
    
         
             
                    """Open the currently selected project item."""
         
     | 
| 
       222 
204 
     | 
    
         
             
                    if self.mainStack.currentWidget() == self.tabOpen:
         
     | 
| 
       223 
205 
     | 
    
         
             
                        self.tabOpen.openSelectedItem()
         
     | 
| 
       224 
     | 
    
         
            -
                    return
         
     | 
| 
       225 
206 
     | 
    
         | 
| 
       226 
207 
     | 
    
         
             
                @pyqtSlot(Path)
         
     | 
| 
       227 
208 
     | 
    
         
             
                def _openProjectPath(self, path: Path) -> None:
         
     | 
| 
         @@ -232,7 +213,6 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       232 
213 
     | 
    
         
             
                        self.hide()
         
     | 
| 
       233 
214 
     | 
    
         
             
                        self.openProjectRequest.emit(path)
         
     | 
| 
       234 
215 
     | 
    
         
             
                    self.close()
         
     | 
| 
       235 
     | 
    
         
            -
                    return
         
     | 
| 
       236 
216 
     | 
    
         | 
| 
       237 
217 
     | 
    
         
             
                ##
         
     | 
| 
       238 
218 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
         @@ -242,7 +222,6 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       242 
222 
     | 
    
         
             
                    """Save the user GUI settings."""
         
     | 
| 
       243 
223 
     | 
    
         
             
                    logger.debug("Saving State: GuiWelcome")
         
     | 
| 
       244 
224 
     | 
    
         
             
                    CONFIG.setWelcomeWinSize(self.width(), self.height())
         
     | 
| 
       245 
     | 
    
         
            -
                    return
         
     | 
| 
       246 
225 
     | 
    
         | 
| 
       247 
226 
     | 
    
         
             
                def _setButtonVisibility(self) -> None:
         
     | 
| 
       248 
227 
     | 
    
         
             
                    """Change the visibility of the dialog buttons."""
         
     | 
| 
         @@ -256,7 +235,6 @@ class GuiWelcome(NDialog): 
     | 
|
| 
       256 
235 
     | 
    
         
             
                        self.btnOpen.setFocus()
         
     | 
| 
       257 
236 
     | 
    
         
             
                    else:
         
     | 
| 
       258 
237 
     | 
    
         
             
                        self.btnCreate.setFocus()
         
     | 
| 
       259 
     | 
    
         
            -
                    return
         
     | 
| 
       260 
238 
     | 
    
         | 
| 
       261 
239 
     | 
    
         | 
| 
       262 
240 
     | 
    
         
             
            class _OpenProjectPage(QWidget):
         
     | 
| 
         @@ -280,7 +258,7 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       280 
258 
     | 
    
         | 
| 
       281 
259 
     | 
    
         
             
                    # Info / Tool
         
     | 
| 
       282 
260 
     | 
    
         
             
                    self.aMissing = QAction(self)
         
     | 
| 
       283 
     | 
    
         
            -
                    self.aMissing.setIcon(SHARED.theme.getIcon("alert_warn", " 
     | 
| 
      
 261 
     | 
    
         
            +
                    self.aMissing.setIcon(SHARED.theme.getIcon("alert_warn", "warning"))
         
     | 
| 
       284 
262 
     | 
    
         
             
                    self.aMissing.setToolTip(self.tr("The project path is not reachable."))
         
     | 
| 
       285 
263 
     | 
    
         | 
| 
       286 
264 
     | 
    
         
             
                    self.selectedPath = QLineEdit(self)
         
     | 
| 
         @@ -309,8 +287,6 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       309 
287 
     | 
    
         
             
                        f"QLineEdit {{border: none; background: {baseCol}; padding: 4px;}} "
         
     | 
| 
       310 
288 
     | 
    
         
             
                    )
         
     | 
| 
       311 
289 
     | 
    
         | 
| 
       312 
     | 
    
         
            -
                    return
         
     | 
| 
       313 
     | 
    
         
            -
             
     | 
| 
       314 
290 
     | 
    
         
             
                ##
         
     | 
| 
       315 
291 
     | 
    
         
             
                #  Public Slots
         
     | 
| 
       316 
292 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -320,7 +296,6 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       320 
296 
     | 
    
         
             
                    """Open the currently selected project item."""
         
     | 
| 
       321 
297 
     | 
    
         
             
                    if (selection := self.listWidget.selectedIndexes()) and (index := selection[0]).isValid():
         
     | 
| 
       322 
298 
     | 
    
         
             
                        self.openProjectRequest.emit(Path(str(index.data()[1])))
         
     | 
| 
       323 
     | 
    
         
            -
                    return
         
     | 
| 
       324 
299 
     | 
    
         | 
| 
       325 
300 
     | 
    
         
             
                ##
         
     | 
| 
       326 
301 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
         @@ -336,14 +311,12 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       336 
311 
     | 
    
         
             
                    self.selectedPath.setToolTip(text)
         
     | 
| 
       337 
312 
     | 
    
         
             
                    self.selectedPath.setCursorPosition(0)
         
     | 
| 
       338 
313 
     | 
    
         
             
                    self.aMissing.setVisible(not (Path(value) / nwFiles.PROJ_FILE).is_file())
         
     | 
| 
       339 
     | 
    
         
            -
                    return
         
     | 
| 
       340 
314 
     | 
    
         | 
| 
       341 
315 
     | 
    
         
             
                @pyqtSlot(QModelIndex)
         
     | 
| 
       342 
316 
     | 
    
         
             
                def _projectDoubleClicked(self, index: QModelIndex) -> None:
         
     | 
| 
       343 
317 
     | 
    
         
             
                    """Process double click on project item."""
         
     | 
| 
       344 
318 
     | 
    
         
             
                    if index.isValid():
         
     | 
| 
       345 
319 
     | 
    
         
             
                        self.openProjectRequest.emit(Path(str(index.data()[1])))
         
     | 
| 
       346 
     | 
    
         
            -
                    return
         
     | 
| 
       347 
320 
     | 
    
         | 
| 
       348 
321 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       349 
322 
     | 
    
         
             
                def _deleteSelectedItem(self) -> None:
         
     | 
| 
         @@ -356,7 +329,6 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       356 
329 
     | 
    
         
             
                        if SHARED.question(text):
         
     | 
| 
       357 
330 
     | 
    
         
             
                            self.listModel.removeEntry(index)
         
     | 
| 
       358 
331 
     | 
    
         
             
                        self._selectFirstItem()
         
     | 
| 
       359 
     | 
    
         
            -
                    return
         
     | 
| 
       360 
332 
     | 
    
         | 
| 
       361 
333 
     | 
    
         
             
                @pyqtSlot("QPoint")
         
     | 
| 
       362 
334 
     | 
    
         
             
                def _openContextMenu(self, pos: QPoint) -> None:
         
     | 
| 
         @@ -369,7 +341,6 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       369 
341 
     | 
    
         
             
                    action.triggered.connect(self._deleteSelectedItem)
         
     | 
| 
       370 
342 
     | 
    
         
             
                    ctxMenu.exec(self.mapToGlobal(pos))
         
     | 
| 
       371 
343 
     | 
    
         
             
                    ctxMenu.setParent(None)
         
     | 
| 
       372 
     | 
    
         
            -
                    return
         
     | 
| 
       373 
344 
     | 
    
         | 
| 
       374 
345 
     | 
    
         
             
                ##
         
     | 
| 
       375 
346 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
         @@ -380,7 +351,6 @@ class _OpenProjectPage(QWidget): 
     | 
|
| 
       380 
351 
     | 
    
         
             
                    index = self.listModel.index(0)
         
     | 
| 
       381 
352 
     | 
    
         
             
                    self.listWidget.setCurrentIndex(index)
         
     | 
| 
       382 
353 
     | 
    
         
             
                    self._projectClicked(index)
         
     | 
| 
       383 
     | 
    
         
            -
                    return
         
     | 
| 
       384 
354 
     | 
    
         | 
| 
       385 
355 
     | 
    
         | 
| 
       386 
356 
     | 
    
         
             
            class _ProjectListItem(QStyledItemDelegate):
         
     | 
| 
         @@ -408,8 +378,6 @@ class _ProjectListItem(QStyledItemDelegate): 
     | 
|
| 
       408 
378 
     | 
    
         | 
| 
       409 
379 
     | 
    
         
             
                    self._icon = SHARED.theme.getPixmap("proj_nwx", (iPx, iPx))
         
     | 
| 
       410 
380 
     | 
    
         | 
| 
       411 
     | 
    
         
            -
                    return
         
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
381 
     | 
    
         
             
                def paint(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex) -> None:
         
     | 
| 
       414 
382 
     | 
    
         
             
                    """Paint a project entry on the canvas."""
         
     | 
| 
       415 
383 
     | 
    
         
             
                    rect = opt.rect
         
     | 
| 
         @@ -420,7 +388,7 @@ class _ProjectListItem(QStyledItemDelegate): 
     | 
|
| 
       420 
388 
     | 
    
         
             
                    painter.save()
         
     | 
| 
       421 
389 
     | 
    
         
             
                    if opt.state & QtSelected == QtSelected:
         
     | 
| 
       422 
390 
     | 
    
         
             
                        painter.setOpacity(0.25)
         
     | 
| 
       423 
     | 
    
         
            -
                        painter.fillRect(rect, QApplication.palette(). 
     | 
| 
      
 391 
     | 
    
         
            +
                        painter.fillRect(rect, QApplication.palette().text())
         
     | 
| 
       424 
392 
     | 
    
         
             
                        painter.setOpacity(1.0)
         
     | 
| 
       425 
393 
     | 
    
         | 
| 
       426 
394 
     | 
    
         
             
                    painter.drawPixmap(2, rect.top() + 6, self._icon)
         
     | 
| 
         @@ -431,8 +399,6 @@ class _ProjectListItem(QStyledItemDelegate): 
     | 
|
| 
       431 
399 
     | 
    
         
             
                    painter.drawText(rect.adjusted(x, y, 0, 0), tFlag, details)
         
     | 
| 
       432 
400 
     | 
    
         
             
                    painter.restore()
         
     | 
| 
       433 
401 
     | 
    
         | 
| 
       434 
     | 
    
         
            -
                    return
         
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
402 
     | 
    
         
             
                def sizeHint(self, opt: QStyleOptionViewItem, index: QModelIndex) -> QSize:
         
     | 
| 
       437 
403 
     | 
    
         
             
                    """Set the size hint to fixed height."""
         
     | 
| 
       438 
404 
     | 
    
         
             
                    return QSize(opt.rect.width(), self._hPx)
         
     | 
| 
         @@ -450,7 +416,6 @@ class _ProjectListModel(QAbstractListModel): 
     | 
|
| 
       450 
416 
     | 
    
         
             
                        when = CONFIG.localDate(datetime.fromtimestamp(time))
         
     | 
| 
       451 
417 
     | 
    
         
             
                        data.append((title, path, f"{opened}: {when}, {words}: {formatInt(count)}"))
         
     | 
| 
       452 
418 
     | 
    
         
             
                    self._data = data
         
     | 
| 
       453 
     | 
    
         
            -
                    return
         
     | 
| 
       454 
419 
     | 
    
         | 
| 
       455 
420 
     | 
    
         
             
                def rowCount(self, parent: QModelIndex | None = None) -> int:
         
     | 
| 
       456 
421 
     | 
    
         
             
                    """Return the size of the model."""
         
     | 
| 
         @@ -517,8 +482,6 @@ class _NewProjectPage(QWidget): 
     | 
|
| 
       517 
482 
     | 
    
         
             
                        f"_NewProjectForm {{border: none; background: {baseCol};}} "
         
     | 
| 
       518 
483 
     | 
    
         
             
                    )
         
     | 
| 
       519 
484 
     | 
    
         | 
| 
       520 
     | 
    
         
            -
                    return
         
     | 
| 
       521 
     | 
    
         
            -
             
     | 
| 
       522 
485 
     | 
    
         
             
                ##
         
     | 
| 
       523 
486 
     | 
    
         
             
                #  Public Slots
         
     | 
| 
       524 
487 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -571,7 +534,7 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       571 
534 
     | 
    
         
             
                    self.projPath = QLineEdit(self)
         
     | 
| 
       572 
535 
     | 
    
         
             
                    self.projPath.setReadOnly(True)
         
     | 
| 
       573 
536 
     | 
    
         | 
| 
       574 
     | 
    
         
            -
                    self.browsePath = NIconToolButton(self, iSz, "browse")
         
     | 
| 
      
 537 
     | 
    
         
            +
                    self.browsePath = NIconToolButton(self, iSz, "browse", "systemio")
         
     | 
| 
       575 
538 
     | 
    
         
             
                    self.browsePath.clicked.connect(self._doBrowse)
         
     | 
| 
       576 
539 
     | 
    
         | 
| 
       577 
540 
     | 
    
         
             
                    self.pathBox = QHBoxLayout()
         
     | 
| 
         @@ -582,20 +545,20 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       582 
545 
     | 
    
         
             
                    self.projFill = QLineEdit(self)
         
     | 
| 
       583 
546 
     | 
    
         
             
                    self.projFill.setReadOnly(True)
         
     | 
| 
       584 
547 
     | 
    
         | 
| 
       585 
     | 
    
         
            -
                    self.browseFill = NIconToolButton(self, iSz, "document_add", " 
     | 
| 
      
 548 
     | 
    
         
            +
                    self.browseFill = NIconToolButton(self, iSz, "document_add", "add")
         
     | 
| 
       586 
549 
     | 
    
         | 
| 
       587 
550 
     | 
    
         
             
                    self.fillMenu = QMenu(self.browseFill)
         
     | 
| 
       588 
551 
     | 
    
         | 
| 
       589 
552 
     | 
    
         
             
                    self.fillBlank = qtAddAction(self.fillMenu, self.tr("Create a fresh project"))
         
     | 
| 
       590 
     | 
    
         
            -
                    self.fillBlank.setIcon(SHARED.theme.getIcon("document"))
         
     | 
| 
      
 553 
     | 
    
         
            +
                    self.fillBlank.setIcon(SHARED.theme.getIcon("document", "file"))
         
     | 
| 
       591 
554 
     | 
    
         
             
                    self.fillBlank.triggered.connect(self._setFillBlank)
         
     | 
| 
       592 
555 
     | 
    
         | 
| 
       593 
556 
     | 
    
         
             
                    self.fillSample = qtAddAction(self.fillMenu, self.tr("Create an example project"))
         
     | 
| 
       594 
     | 
    
         
            -
                    self.fillSample.setIcon(SHARED.theme.getIcon("document_add", " 
     | 
| 
      
 557 
     | 
    
         
            +
                    self.fillSample.setIcon(SHARED.theme.getIcon("document_add", "add"))
         
     | 
| 
       595 
558 
     | 
    
         
             
                    self.fillSample.triggered.connect(self._setFillSample)
         
     | 
| 
       596 
559 
     | 
    
         | 
| 
       597 
560 
     | 
    
         
             
                    self.fillCopy = qtAddAction(self.fillMenu, self.tr("Copy an existing project"))
         
     | 
| 
       598 
     | 
    
         
            -
                    self.fillCopy.setIcon(SHARED.theme.getIcon("project_copy", " 
     | 
| 
      
 561 
     | 
    
         
            +
                    self.fillCopy.setIcon(SHARED.theme.getIcon("project_copy", "action"))
         
     | 
| 
       599 
562 
     | 
    
         
             
                    self.fillCopy.triggered.connect(self._setFillCopy)
         
     | 
| 
       600 
563 
     | 
    
         | 
| 
       601 
564 
     | 
    
         
             
                    self.browseFill.setMenu(self.fillMenu)
         
     | 
| 
         @@ -690,13 +653,10 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       690 
653 
     | 
    
         
             
                    self._updateProjPath()
         
     | 
| 
       691 
654 
     | 
    
         
             
                    self._updateFillInfo()
         
     | 
| 
       692 
655 
     | 
    
         | 
| 
       693 
     | 
    
         
            -
                    return
         
     | 
| 
       694 
     | 
    
         
            -
             
     | 
| 
       695 
656 
     | 
    
         
             
                def enterForm(self) -> None:
         
     | 
| 
       696 
657 
     | 
    
         
             
                    """Focus the project name field when entering the form."""
         
     | 
| 
       697 
658 
     | 
    
         
             
                    self.projName.setFocus()
         
     | 
| 
       698 
659 
     | 
    
         
             
                    self.projName.selectAll()
         
     | 
| 
       699 
     | 
    
         
            -
                    return
         
     | 
| 
       700 
660 
     | 
    
         | 
| 
       701 
661 
     | 
    
         
             
                def getProjectData(self) -> dict:
         
     | 
| 
       702 
662 
     | 
    
         
             
                    """Collect form data and return it as a dictionary."""
         
     | 
| 
         @@ -734,14 +694,12 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       734 
694 
     | 
    
         
             
                        self._basePath = Path(path)
         
     | 
| 
       735 
695 
     | 
    
         
             
                        self._updateProjPath()
         
     | 
| 
       736 
696 
     | 
    
         
             
                        CONFIG.setLastPath("project", path)
         
     | 
| 
       737 
     | 
    
         
            -
                    return
         
     | 
| 
       738 
697 
     | 
    
         | 
| 
       739 
698 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       740 
699 
     | 
    
         
             
                def _updateProjPath(self) -> None:
         
     | 
| 
       741 
700 
     | 
    
         
             
                    """Update the path box to show the full project path."""
         
     | 
| 
       742 
701 
     | 
    
         
             
                    projName = makeFileNameSafe(self.projName.text().strip())
         
     | 
| 
       743 
702 
     | 
    
         
             
                    self.projPath.setText(str(self._basePath / projName))
         
     | 
| 
       744 
     | 
    
         
            -
                    return
         
     | 
| 
       745 
703 
     | 
    
         | 
| 
       746 
704 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       747 
705 
     | 
    
         
             
                def _syncSwitches(self) -> None:
         
     | 
| 
         @@ -751,21 +709,18 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       751 
709 
     | 
    
         
             
                    addWorld = self.addWorld.isChecked()
         
     | 
| 
       752 
710 
     | 
    
         
             
                    if not (addPlot or addChar or addWorld):
         
     | 
| 
       753 
711 
     | 
    
         
             
                        self.addNotes.setChecked(False)
         
     | 
| 
       754 
     | 
    
         
            -
                    return
         
     | 
| 
       755 
712 
     | 
    
         | 
| 
       756 
713 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       757 
714 
     | 
    
         
             
                def _setFillBlank(self) -> None:
         
     | 
| 
       758 
715 
     | 
    
         
             
                    """Set fill mode to blank project."""
         
     | 
| 
       759 
716 
     | 
    
         
             
                    self._fillMode = self.FILL_BLANK
         
     | 
| 
       760 
717 
     | 
    
         
             
                    self._updateFillInfo()
         
     | 
| 
       761 
     | 
    
         
            -
                    return
         
     | 
| 
       762 
718 
     | 
    
         | 
| 
       763 
719 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       764 
720 
     | 
    
         
             
                def _setFillSample(self) -> None:
         
     | 
| 
       765 
721 
     | 
    
         
             
                    """Set fill mode to sample project."""
         
     | 
| 
       766 
722 
     | 
    
         
             
                    self._fillMode = self.FILL_SAMPLE
         
     | 
| 
       767 
723 
     | 
    
         
             
                    self._updateFillInfo()
         
     | 
| 
       768 
     | 
    
         
            -
                    return
         
     | 
| 
       769 
724 
     | 
    
         | 
| 
       770 
725 
     | 
    
         
             
                @pyqtSlot()
         
     | 
| 
       771 
726 
     | 
    
         
             
                def _setFillCopy(self) -> None:
         
     | 
| 
         @@ -774,7 +729,6 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       774 
729 
     | 
    
         
             
                        self._fillMode = self.FILL_COPY
         
     | 
| 
       775 
730 
     | 
    
         
             
                        self._copyPath = copyPath
         
     | 
| 
       776 
731 
     | 
    
         
             
                        self._updateFillInfo()
         
     | 
| 
       777 
     | 
    
         
            -
                    return
         
     | 
| 
       778 
732 
     | 
    
         | 
| 
       779 
733 
     | 
    
         
             
                ##
         
     | 
| 
       780 
734 
     | 
    
         
             
                #  Internal Functions
         
     | 
| 
         @@ -794,5 +748,3 @@ class _NewProjectForm(QWidget): 
     | 
|
| 
       794 
748 
     | 
    
         
             
                    self.projFill.setToolTip(text)
         
     | 
| 
       795 
749 
     | 
    
         
             
                    self.projFill.setCursorPosition(0)
         
     | 
| 
       796 
750 
     | 
    
         
             
                    self.extraWidget.setVisible(self._fillMode == self.FILL_BLANK)
         
     | 
| 
       797 
     | 
    
         
            -
             
     | 
| 
       798 
     | 
    
         
            -
                    return
         
     | 
| 
         @@ -20,7 +20,7 @@ General Public License for more details. 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            You should have received a copy of the GNU General Public License
         
     | 
| 
       22 
22 
     | 
    
         
             
            along with this program. If not, see <https://www.gnu.org/licenses/>.
         
     | 
| 
       23 
     | 
    
         
            -
            """
         
     | 
| 
      
 23 
     | 
    
         
            +
            """  # noqa
         
     | 
| 
       24 
24 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
            import json
         
     | 
| 
         @@ -39,12 +39,13 @@ from PyQt6.QtWidgets import ( 
     | 
|
| 
       39 
39 
     | 
    
         
             
            from novelwriter import CONFIG, SHARED
         
     | 
| 
       40 
40 
     | 
    
         
             
            from novelwriter.common import checkInt, checkIntTuple, formatTime, minmax, qtLambda
         
     | 
| 
       41 
41 
     | 
    
         
             
            from novelwriter.constants import nwConst
         
     | 
| 
      
 42 
     | 
    
         
            +
            from novelwriter.enum import nwStandardButton
         
     | 
| 
       42 
43 
     | 
    
         
             
            from novelwriter.error import formatException
         
     | 
| 
       43 
     | 
    
         
            -
            from novelwriter.extensions.modified import NToolDialog
         
     | 
| 
      
 44 
     | 
    
         
            +
            from novelwriter.extensions.modified import NPushButton, NToolDialog
         
     | 
| 
       44 
45 
     | 
    
         
             
            from novelwriter.extensions.switch import NSwitch
         
     | 
| 
       45 
46 
     | 
    
         
             
            from novelwriter.types import (
         
     | 
| 
       46 
47 
     | 
    
         
             
                QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration,
         
     | 
| 
       47 
     | 
    
         
            -
                 
     | 
| 
      
 48 
     | 
    
         
            +
                QtRoleAction, QtRoleDestruct
         
     | 
| 
       48 
49 
     | 
    
         
             
            )
         
     | 
| 
       49 
50 
     | 
    
         | 
| 
       50 
51 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
         @@ -54,7 +55,7 @@ logger = logging.getLogger(__name__) 
     | 
|
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
57 
     | 
    
         
             
            class GuiWritingStats(NToolDialog):
         
     | 
| 
       57 
     | 
    
         
            -
                """GUI Tools: Writing Statistics
         
     | 
| 
      
 58 
     | 
    
         
            +
                """GUI Tools: Writing Statistics.
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
60 
     | 
    
         
             
                Displays data from the NWSessionLog object.
         
     | 
| 
       60 
61 
     | 
    
         
             
                """
         
     | 
| 
         @@ -182,6 +183,7 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       182 
183 
     | 
    
         | 
| 
       183 
184 
     | 
    
         
             
                    # Filter Options
         
     | 
| 
       184 
185 
     | 
    
         
             
                    iPx = SHARED.theme.baseIconHeight
         
     | 
| 
      
 186 
     | 
    
         
            +
                    bSz = SHARED.theme.toolButtonIconSize
         
     | 
| 
       185 
187 
     | 
    
         | 
| 
       186 
188 
     | 
    
         
             
                    self.filterForm = QGridLayout(self)
         
     | 
| 
       187 
189 
     | 
    
         
             
                    self.filterForm.setRowStretch(6, 1)
         
     | 
| 
         @@ -276,6 +278,10 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       276 
278 
     | 
    
         
             
                    self.optsBox.addWidget(self.histMax, 0)
         
     | 
| 
       277 
279 
     | 
    
         | 
| 
       278 
280 
     | 
    
         
             
                    # Buttons
         
     | 
| 
      
 281 
     | 
    
         
            +
                    self.btnClose = SHARED.theme.getStandardButton(nwStandardButton.CLOSE, self)
         
     | 
| 
      
 282 
     | 
    
         
            +
                    self.btnClose.clicked.connect(self._doClose)
         
     | 
| 
      
 283 
     | 
    
         
            +
                    self.btnClose.setAutoDefault(False)
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
       279 
285 
     | 
    
         
             
                    self.saveJSON = QAction(self.tr("JSON Data File (.json)"), self)
         
     | 
| 
       280 
286 
     | 
    
         
             
                    self.saveJSON.triggered.connect(qtLambda(self._saveData, self.FMT_JSON))
         
     | 
| 
       281 
287 
     | 
    
         | 
| 
         @@ -286,17 +292,13 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       286 
292 
     | 
    
         
             
                    self.saveMenu.addAction(self.saveJSON)
         
     | 
| 
       287 
293 
     | 
    
         
             
                    self.saveMenu.addAction(self.saveCSV)
         
     | 
| 
       288 
294 
     | 
    
         | 
| 
       289 
     | 
    
         
            -
                    self. 
     | 
| 
       290 
     | 
    
         
            -
                    self. 
     | 
| 
      
 295 
     | 
    
         
            +
                    self.btnSave = NPushButton(self, self.tr("Save As"), bSz, "btn_save", "action")
         
     | 
| 
      
 296 
     | 
    
         
            +
                    self.btnSave.setAutoDefault(False)
         
     | 
| 
      
 297 
     | 
    
         
            +
                    self.btnSave.setMenu(self.saveMenu)
         
     | 
| 
       291 
298 
     | 
    
         | 
| 
       292 
     | 
    
         
            -
                    self. 
     | 
| 
       293 
     | 
    
         
            -
                     
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
       296 
     | 
    
         
            -
                    self.btnSave = self.buttonBox.addButton(self.tr("Save As"), QtRoleAction)
         
     | 
| 
       297 
     | 
    
         
            -
                    if self.btnSave:
         
     | 
| 
       298 
     | 
    
         
            -
                        self.btnSave.setAutoDefault(False)
         
     | 
| 
       299 
     | 
    
         
            -
                        self.btnSave.setMenu(self.saveMenu)
         
     | 
| 
      
 299 
     | 
    
         
            +
                    self.btnBox = QDialogButtonBox(self)
         
     | 
| 
      
 300 
     | 
    
         
            +
                    self.btnBox.addButton(self.btnSave, QtRoleAction)
         
     | 
| 
      
 301 
     | 
    
         
            +
                    self.btnBox.addButton(self.btnClose, QtRoleDestruct)
         
     | 
| 
       300 
302 
     | 
    
         | 
| 
       301 
303 
     | 
    
         
             
                    # Assemble
         
     | 
| 
       302 
304 
     | 
    
         
             
                    self.outerBox = QGridLayout()
         
     | 
| 
         @@ -304,18 +306,15 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       304 
306 
     | 
    
         
             
                    self.outerBox.addLayout(self.optsBox,   1, 0, 1, 2)
         
     | 
| 
       305 
307 
     | 
    
         
             
                    self.outerBox.addWidget(self.infoBox,   2, 0)
         
     | 
| 
       306 
308 
     | 
    
         
             
                    self.outerBox.addWidget(self.filterBox, 2, 1)
         
     | 
| 
       307 
     | 
    
         
            -
                    self.outerBox.addWidget(self. 
     | 
| 
      
 309 
     | 
    
         
            +
                    self.outerBox.addWidget(self.btnBox,    3, 0, 1, 2)
         
     | 
| 
       308 
310 
     | 
    
         
             
                    self.outerBox.setRowStretch(0, 1)
         
     | 
| 
       309 
311 
     | 
    
         | 
| 
       310 
312 
     | 
    
         
             
                    self.setLayout(self.outerBox)
         
     | 
| 
       311 
313 
     | 
    
         | 
| 
       312 
314 
     | 
    
         
             
                    logger.debug("Ready: GuiWritingStats")
         
     | 
| 
       313 
315 
     | 
    
         | 
| 
       314 
     | 
    
         
            -
                    return
         
     | 
| 
       315 
     | 
    
         
            -
             
     | 
| 
       316 
316 
     | 
    
         
             
                def __del__(self) -> None:  # pragma: no cover
         
     | 
| 
       317 
317 
     | 
    
         
             
                    logger.debug("Delete: GuiWritingStats")
         
     | 
| 
       318 
     | 
    
         
            -
                    return
         
     | 
| 
       319 
318 
     | 
    
         | 
| 
       320 
319 
     | 
    
         
             
                def populateGUI(self) -> None:
         
     | 
| 
       321 
320 
     | 
    
         
             
                    """Populate list box with data from the log file."""
         
     | 
| 
         @@ -323,7 +322,6 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       323 
322 
     | 
    
         
             
                    self._loadLogFile()
         
     | 
| 
       324 
323 
     | 
    
         
             
                    self._updateListBox()
         
     | 
| 
       325 
324 
     | 
    
         
             
                    QApplication.restoreOverrideCursor()
         
     | 
| 
       326 
     | 
    
         
            -
                    return
         
     | 
| 
       327 
325 
     | 
    
         | 
| 
       328 
326 
     | 
    
         
             
                ##
         
     | 
| 
       329 
327 
     | 
    
         
             
                #  Events
         
     | 
| 
         @@ -333,7 +331,6 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       333 
331 
     | 
    
         
             
                    """Capture the user closing the window."""
         
     | 
| 
       334 
332 
     | 
    
         
             
                    event.accept()
         
     | 
| 
       335 
333 
     | 
    
         
             
                    self.softDelete()
         
     | 
| 
       336 
     | 
    
         
            -
                    return
         
     | 
| 
       337 
334 
     | 
    
         | 
| 
       338 
335 
     | 
    
         
             
                ##
         
     | 
| 
       339 
336 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
         @@ -377,8 +374,6 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       377 
374 
     | 
    
         | 
| 
       378 
375 
     | 
    
         
             
                    self.close()
         
     | 
| 
       379 
376 
     | 
    
         | 
| 
       380 
     | 
    
         
            -
                    return
         
     | 
| 
       381 
     | 
    
         
            -
             
     | 
| 
       382 
377 
     | 
    
         
             
                def _saveData(self, dataFmt: int) -> bool:
         
     | 
| 
       383 
378 
     | 
    
         
             
                    """Save the content of the list box to a file."""
         
     | 
| 
       384 
379 
     | 
    
         
             
                    fileExt = ""
         
     | 
| 
         @@ -498,8 +493,6 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       498 
493 
     | 
    
         
             
                    self.notesWords.setText(f"{ttNotes:n}")
         
     | 
| 
       499 
494 
     | 
    
         
             
                    self.totalWords.setText(f"{ttWords:n}")
         
     | 
| 
       500 
495 
     | 
    
         | 
| 
       501 
     | 
    
         
            -
                    return
         
     | 
| 
       502 
     | 
    
         
            -
             
     | 
| 
       503 
496 
     | 
    
         
             
                ##
         
     | 
| 
       504 
497 
     | 
    
         
             
                #  Private Slots
         
     | 
| 
       505 
498 
     | 
    
         
             
                ##
         
     | 
| 
         @@ -622,5 +615,3 @@ class GuiWritingStats(NToolDialog): 
     | 
|
| 
       622 
615 
     | 
    
         
             
                        self.timeFilter += sDiff
         
     | 
| 
       623 
616 
     | 
    
         | 
| 
       624 
617 
     | 
    
         
             
                    self.labelFilter.setText(formatTime(round(self.timeFilter)))
         
     | 
| 
       625 
     | 
    
         
            -
             
     | 
| 
       626 
     | 
    
         
            -
                    return
         
     |