novelWriter 2.5rc1__py3-none-any.whl → 2.5.1__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.
Files changed (40) hide show
  1. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/METADATA +1 -1
  2. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/RECORD +40 -38
  3. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +3 -3
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  9. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  10. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  11. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  12. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  13. novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
  14. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  15. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  16. novelwriter/assets/i18n/project_pl_PL.json +116 -0
  17. novelwriter/assets/manual.pdf +0 -0
  18. novelwriter/assets/sample.zip +0 -0
  19. novelwriter/assets/text/credits_en.htm +52 -44
  20. novelwriter/common.py +10 -0
  21. novelwriter/core/project.py +15 -4
  22. novelwriter/core/status.py +4 -1
  23. novelwriter/core/storage.py +6 -1
  24. novelwriter/core/tokenizer.py +5 -5
  25. novelwriter/core/toqdoc.py +13 -13
  26. novelwriter/dialogs/preferences.py +14 -27
  27. novelwriter/dialogs/projectsettings.py +6 -10
  28. novelwriter/extensions/configlayout.py +18 -3
  29. novelwriter/extensions/statusled.py +12 -2
  30. novelwriter/gui/doceditor.py +3 -3
  31. novelwriter/gui/docviewer.py +3 -1
  32. novelwriter/gui/docviewerpanel.py +7 -0
  33. novelwriter/gui/outline.py +1 -0
  34. novelwriter/gui/projtree.py +66 -49
  35. novelwriter/guimain.py +50 -42
  36. novelwriter/shared.py +9 -0
  37. novelwriter/tools/welcome.py +9 -0
  38. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/LICENSE.md +0 -0
  39. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/entry_points.txt +0 -0
  40. {novelWriter-2.5rc1.dist-info → novelWriter-2.5.1.dist-info}/top_level.txt +0 -0
novelwriter/guimain.py CHANGED
@@ -189,9 +189,6 @@ class GuiMain(QMainWindow):
189
189
  self.splitView.setVisible(False)
190
190
  self.docEditor.closeSearch()
191
191
 
192
- # Initialise the Project Tree
193
- self.rebuildTrees()
194
-
195
192
  # Assemble Main Window Elements
196
193
  self.mainBox = QHBoxLayout()
197
194
  self.mainBox.addWidget(self.sideBar)
@@ -222,6 +219,8 @@ class GuiMain(QMainWindow):
222
219
  SHARED.projectStatusChanged.connect(self.mainStatus.updateProjectStatus)
223
220
  SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
224
221
  SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
222
+ SHARED.statusLabelsChanged.connect(self.docViewerPanel.updateStatusLabels)
223
+ SHARED.statusLabelsChanged.connect(self.projView.refreshUserLabels)
225
224
 
226
225
  self.mainMenu.requestDocAction.connect(self._passDocumentAction)
227
226
  self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
@@ -461,7 +460,6 @@ class GuiMain(QMainWindow):
461
460
 
462
461
  # Update GUI
463
462
  self._updateWindowTitle(SHARED.project.data.name)
464
- self.rebuildTrees()
465
463
  self.docEditor.toggleSpellCheck(SHARED.project.data.spellCheck)
466
464
  self.mainStatus.setRefTime(SHARED.project.projOpened)
467
465
  self.projView.openProjectTasks()
@@ -526,8 +524,14 @@ class GuiMain(QMainWindow):
526
524
  self.novelView.setActiveHandle(None)
527
525
  return
528
526
 
529
- def openDocument(self, tHandle: str | None, tLine: int | None = None,
530
- changeFocus: bool = True, doScroll: bool = False) -> bool:
527
+ def openDocument(
528
+ self,
529
+ tHandle: str | None,
530
+ tLine: int | None = None,
531
+ sTitle: str | None = None,
532
+ changeFocus: bool = True,
533
+ doScroll: bool = False
534
+ ) -> bool:
531
535
  """Open a specific document, optionally at a given line."""
532
536
  if not SHARED.hasProject:
533
537
  logger.error("No project open")
@@ -537,9 +541,12 @@ class GuiMain(QMainWindow):
537
541
  logger.debug("Requested item '%s' is not a document", tHandle)
538
542
  return False
539
543
 
544
+ if sTitle and tLine is None:
545
+ if hItem := SHARED.project.index.getItemHeading(tHandle, sTitle):
546
+ tLine = hItem.line
547
+
540
548
  self._changeView(nwView.EDITOR)
541
- cHandle = self.docEditor.docHandle
542
- if cHandle == tHandle:
549
+ if tHandle == self.docEditor.docHandle:
543
550
  self.docEditor.setCursorLine(tLine)
544
551
  if changeFocus:
545
552
  self.docEditor.setFocus()
@@ -711,7 +718,6 @@ class GuiMain(QMainWindow):
711
718
  if SHARED.hasProject:
712
719
  tHandle = None
713
720
  sTitle = None
714
- tLine = None
715
721
  if self.projView.treeHasFocus():
716
722
  tHandle = self.projView.getSelectedHandle()
717
723
  elif self.novelView.treeHasFocus():
@@ -722,17 +728,9 @@ class GuiMain(QMainWindow):
722
728
  logger.warning("No item selected")
723
729
  return
724
730
 
725
- if tHandle and sTitle:
726
- if hItem := SHARED.project.index.getItemHeading(tHandle, sTitle):
727
- tLine = hItem.line
728
731
  if tHandle:
729
- self.openDocument(tHandle, tLine=tLine, changeFocus=False, doScroll=False)
730
-
731
- return
732
+ self.openDocument(tHandle, sTitle=sTitle, changeFocus=False, doScroll=False)
732
733
 
733
- def rebuildTrees(self) -> None:
734
- """Rebuild the project tree."""
735
- self.projView.populateTree()
736
734
  return
737
735
 
738
736
  def rebuildIndex(self, beQuiet: bool = False) -> None:
@@ -1006,32 +1004,48 @@ class GuiMain(QMainWindow):
1006
1004
  def _switchFocus(self, paneNo: nwFocus) -> None:
1007
1005
  """Switch focus between main GUI views."""
1008
1006
  if paneNo == nwFocus.TREE:
1009
- if self.projStack.currentWidget() is self.projView:
1010
- if self.projView.treeHasFocus():
1011
- self._changeView(nwView.NOVEL)
1012
- self.novelView.setTreeFocus()
1013
- else:
1014
- self.projView.setTreeFocus()
1015
- elif self.projStack.currentWidget() is self.novelView:
1016
- if self.novelView.treeHasFocus():
1017
- self._changeView(nwView.PROJECT)
1018
- self.projView.setTreeFocus()
1019
- else:
1020
- self.novelView.setTreeFocus()
1007
+ # Decision Matrix
1008
+ # vM | vP | fP | vN | fN | Focus
1009
+ # ----|----|----|----|----|---------
1010
+ # T | T | T | F | F | Novel
1011
+ # T | T | F | F | F | Project
1012
+ # T | F | F | T | T | Project
1013
+ # T | F | F | T | F | Novel
1014
+ # T | F | F | F | F | Project
1015
+ # F | T | T | F | F | Project
1016
+ # F | T | F | F | F | Project
1017
+ # F | F | F | T | T | Novel
1018
+ # F | F | F | T | F | Novel
1019
+ # F | F | F | F | F | Project
1020
+
1021
+ vM = self.mainStack.currentWidget() is self.splitMain
1022
+ vP = self.projStack.currentWidget() is self.projView
1023
+ vN = self.projStack.currentWidget() is self.novelView
1024
+ fP = self.projView.treeHasFocus()
1025
+ fN = self.novelView.treeHasFocus()
1026
+
1027
+ self._changeView(nwView.EDITOR)
1028
+ if (vM and (vP and fP or vN and not fN)) or (not vM and vN):
1029
+ self._changeView(nwView.NOVEL)
1030
+ self.novelView.setTreeFocus()
1021
1031
  else:
1022
1032
  self._changeView(nwView.PROJECT)
1023
1033
  self.projView.setTreeFocus()
1034
+
1024
1035
  elif paneNo == nwFocus.DOCUMENT:
1025
1036
  self._changeView(nwView.EDITOR)
1026
- if self.docEditor.anyFocus():
1037
+ hasViewer = self.splitView.isVisible()
1038
+ if hasViewer and self.docEditor.anyFocus():
1027
1039
  self.docViewer.setFocus()
1028
- elif self.docViewer.anyFocus():
1040
+ elif hasViewer and self.docViewer.anyFocus():
1029
1041
  self.docEditor.setFocus()
1030
1042
  else:
1031
1043
  self.docEditor.setFocus()
1044
+
1032
1045
  elif paneNo == nwFocus.OUTLINE:
1033
1046
  self._changeView(nwView.OUTLINE)
1034
1047
  self.outlineView.setTreeFocus()
1048
+
1035
1049
  return
1036
1050
 
1037
1051
  @pyqtSlot(bool, bool, bool, bool)
@@ -1077,15 +1091,13 @@ class GuiMain(QMainWindow):
1077
1091
 
1078
1092
  return
1079
1093
 
1080
- @pyqtSlot(bool)
1081
- def _processProjectSettingsChanges(self, rebuildTrees: bool) -> None:
1094
+ @pyqtSlot()
1095
+ def _processProjectSettingsChanges(self) -> None:
1082
1096
  """Refresh data dependent on project settings."""
1083
1097
  logger.debug("Applying new project settings")
1084
1098
  SHARED.updateSpellCheckLanguage()
1085
1099
  self.itemDetails.refreshDetails()
1086
1100
  self._updateWindowTitle(SHARED.project.data.name)
1087
- if rebuildTrees:
1088
- self.rebuildTrees()
1089
1101
  return
1090
1102
 
1091
1103
  @pyqtSlot()
@@ -1102,7 +1114,7 @@ class GuiMain(QMainWindow):
1102
1114
  tHandle, sTitle = self._getTagSource(tag)
1103
1115
  if tHandle is not None:
1104
1116
  if mode == nwDocMode.EDIT:
1105
- self.openDocument(tHandle)
1117
+ self.openDocument(tHandle, sTitle=sTitle)
1106
1118
  elif mode == nwDocMode.VIEW:
1107
1119
  self.viewDocument(tHandle=tHandle, sTitle=sTitle)
1108
1120
  return
@@ -1121,11 +1133,7 @@ class GuiMain(QMainWindow):
1121
1133
  """Handle an open document request."""
1122
1134
  if tHandle is not None:
1123
1135
  if mode == nwDocMode.EDIT:
1124
- tLine = None
1125
- hItem = SHARED.project.index.getItemHeading(tHandle, sTitle)
1126
- if hItem is not None:
1127
- tLine = hItem.line
1128
- self.openDocument(tHandle, tLine=tLine, changeFocus=setFocus)
1136
+ self.openDocument(tHandle, sTitle=sTitle, changeFocus=setFocus)
1129
1137
  elif mode == nwDocMode.VIEW:
1130
1138
  self.viewDocument(tHandle=tHandle, sTitle=sTitle)
1131
1139
  return
novelwriter/shared.py CHANGED
@@ -64,6 +64,7 @@ class SharedData(QObject):
64
64
  indexCleared = pyqtSignal()
65
65
  indexAvailable = pyqtSignal()
66
66
  mainClockTick = pyqtSignal()
67
+ statusLabelsChanged = pyqtSignal(str)
67
68
 
68
69
  def __init__(self) -> None:
69
70
  super().__init__()
@@ -309,6 +310,14 @@ class SharedData(QObject):
309
310
  self.indexAvailable.emit()
310
311
  return
311
312
 
313
+ def projectSingalProxy(self, data: dict) -> None:
314
+ """Emit signals on project data change."""
315
+ event = data.get("event")
316
+ logger.debug("Received '%s' event from project data", event)
317
+ if event == "statusLabels":
318
+ self.statusLabelsChanged.emit(data.get("kind", ""))
319
+ return
320
+
312
321
  ##
313
322
  # Alert Boxes
314
323
  ##
@@ -208,6 +208,7 @@ class GuiWelcome(NDialog):
208
208
  """Show the create new project page."""
209
209
  self.mainStack.setCurrentWidget(self.tabNew)
210
210
  self._setButtonVisibility()
211
+ self.tabNew.enterForm()
211
212
  return
212
213
 
213
214
  @pyqtSlot()
@@ -503,6 +504,8 @@ class _NewProjectPage(QWidget):
503
504
  self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
504
505
  self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
505
506
 
507
+ self.enterForm = self.projectForm.enterForm
508
+
506
509
  # Assemble
507
510
  # ========
508
511
 
@@ -696,6 +699,12 @@ class _NewProjectForm(QWidget):
696
699
 
697
700
  return
698
701
 
702
+ def enterForm(self) -> None:
703
+ """Focus the project name field when entering the form."""
704
+ self.projName.setFocus()
705
+ self.projName.selectAll()
706
+ return
707
+
699
708
  def getProjectData(self) -> dict:
700
709
  """Collect form data and return it as a dictionary."""
701
710
  roots = []