diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d8b991a..6687543d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# novelWriter ChangeLog +# novelWriter Change Log ## Version 1.0 Release Candidate 1 [2020-11-16] diff --git a/nw/assets/text/release_notes.htm b/nw/assets/text/release_notes.htm new file mode 100644 index 00000000..d9818aa9 --- /dev/null +++ b/nw/assets/text/release_notes.htm @@ -0,0 +1,35 @@ + + +
+This is the first release candidate for the upcoming release of novelWriter 1.0.
+Since the fifth beta release about four weeks ago, not much has been changed in novelWriter. A +few minor tweaks have been made to the GUI.
+A number of features and tools are now automatically switched off when there is no project or +document open for those features to act upon. Previously, this was a bit inconsistent, although no +serious bugs have been reported or encountered.
+Most of the minor changes in this release should not be noticeable to most users. However, there +are a couple of noticeable changes.
+The "Typewriter Mode" of the editor has been improved. Essentially, this feature is a sort of +smart scroll. It tries to keep the cursor stationary in the vertical direction, and will try to +scroll the document up when the cursor skips to a new line while typing (or down in case of +backspaces). This is similar to the way a typewriter scrolls the paper when hitting the return key. +It improves the writing experience as the current active line will stay at the same eye height +level on the screen.
+Previously, the feature would lock the cursor to a given vertical position defined by the user. +Now, instead, the cursor will remain stationary in the vertical direction at any position the user +sets it to by mouse click or keyboard navigation. The user can define a minimum distance from the +top where this feature is activated. These changes makes it more flexible in terms of where the +focus is in the editor. The feature can be controlled from the main Preferences.
+It is now possible to switch syntax highlighting theme without restarting novelWriter. +Previously, changing the theme would only half-way update the document, header and footer +background and text colours. The new settings would not be fully applied until the application was +shut down and started again, thus making it a bit tedious to look through syntax themes to find the +one you want.
+Switching main GUI theme still requires a restart.
+The full changelog is available +here.
+ + diff --git a/nw/config.py b/nw/config.py index 05345b45..04c1a4db 100644 --- a/nw/config.py +++ b/nw/config.py @@ -91,6 +91,7 @@ class Config: self.guiFont = "" # Defaults to system default font self.guiFontSize = 11 self.guiScale = 1.0 # Set automatically by Theme class + self.lastNotes = "" # The latest release notes that have been shown ## Sizes self.winGeometry = [1200, 650] @@ -380,6 +381,9 @@ class Config: self.guiFontSize = self._parseLine( cnfParse, cnfSec, "guifontsize", self.CNF_INT, self.guiFontSize ) + self.lastNotes = self._parseLine( + cnfParse, cnfSec, "lastnotes", self.CNF_STR, self.lastNotes + ) ## Sizes cnfSec = "Sizes" @@ -584,6 +588,7 @@ class Config: cnfParse.set(cnfSec, "guidark", str(self.guiDark)) cnfParse.set(cnfSec, "guifont", str(self.guiFont)) cnfParse.set(cnfSec, "guifontsize", str(self.guiFontSize)) + cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes)) ## Sizes cnfSec = "Sizes" diff --git a/nw/gui/about.py b/nw/gui/about.py index 7f00cf11..99a4d296 100644 --- a/nw/gui/about.py +++ b/nw/gui/about.py @@ -32,8 +32,9 @@ import os from datetime import datetime from PyQt5.QtCore import Qt +from PyQt5.QtGui import QCursor from PyQt5.QtWidgets import ( - QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, QTabWidget, + qApp, QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, QTabWidget, QTextBrowser, QLabel ) @@ -80,6 +81,10 @@ class GuiAbout(QDialog): self.pageAbout.setOpenExternalLinks(True) self.pageAbout.document().setDocumentMargin(self.mainConf.pxInt(16)) + self.pageNotes = QTextBrowser() + self.pageNotes.setOpenExternalLinks(True) + self.pageNotes.document().setDocumentMargin(self.mainConf.pxInt(16)) + self.pageLicense = QTextBrowser() self.pageLicense.setOpenExternalLinks(True) self.pageLicense.document().setDocumentMargin(self.mainConf.pxInt(16)) @@ -87,6 +92,7 @@ class GuiAbout(QDialog): # Main Tab Area self.tabBox = QTabWidget() self.tabBox.addTab(self.pageAbout, "About") + self.tabBox.addTab(self.pageNotes, "Release") self.tabBox.addTab(self.pageLicense, "License") self.innerBox.addWidget(self.tabBox) @@ -98,14 +104,27 @@ class GuiAbout(QDialog): self.outerBox.addWidget(self.buttonBox) self.setLayout(self.outerBox) - self._setStyleSheet() - self._fillAboutPage() - self._fillLicensePage() - logger.debug("GuiAbout initialisation complete") return + def populateGUI(self): + """Populate tabs with text. + """ + qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) + self._setStyleSheet() + self._fillAboutPage() + self._fillNotesPage() + self._fillLicensePage() + qApp.restoreOverrideCursor() + return + + def showReleaseNotes(self): + """Show the release notes. + """ + self.tabBox.setCurrentWidget(self.pageNotes) + return + ## # Internal Functions ## @@ -192,11 +211,22 @@ class GuiAbout(QDialog): return + def _fillNotesPage(self): + """Load the content for the Release Notes page. + """ + docPath = os.path.join(self.mainConf.assetPath, "text", "release_notes.htm") + if os.path.isfile(docPath): + with open(docPath, mode="r", encoding="utf8") as inFile: + helpText = inFile.read() + self.pageNotes.setHtml(helpText) + else: + self.pageNotes.setHtml("Error loading release notes text ...") + return + def _fillLicensePage(self): """Load the content for the License page. """ - docName = "gplv3_%s.htm" % self.mainConf.guiLang - docPath = os.path.join(self.mainConf.assetPath, "text", docName) + docPath = os.path.join(self.mainConf.assetPath, "text", "gplv3_en.htm") if os.path.isfile(docPath): with open(docPath, mode="r", encoding="utf8") as inFile: helpText = inFile.read() @@ -221,6 +251,7 @@ class GuiAbout(QDialog): hColB = self.theParent.theTheme.colHead[2], ) self.pageAbout.document().setDefaultStyleSheet(styleSheet) + self.pageNotes.document().setDefaultStyleSheet(styleSheet) self.pageLicense.document().setDefaultStyleSheet(styleSheet) return diff --git a/nw/guimain.py b/nw/guimain.py index b4ff651a..801de5af 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -238,6 +238,12 @@ class GuiMain(QMainWindow): if self.mainConf.showGUI: self.showProjectLoadDialog() + # Show the latest release notes, if they haven't been shown before + if self.mainConf.lastNotes != nw.__version__: + if self.mainConf.showGUI: + self.showAboutNWDialog(showNotes=True) + self.mainConf.lastNotes = nw.__version__ + logger.debug("novelWriter is ready ...") self.setStatus("novelWriter is ready ...") @@ -915,11 +921,18 @@ class GuiMain(QMainWindow): return - def showAboutNWDialog(self): + def showAboutNWDialog(self, showNotes=False): """Show the about dialog for novelWriter. """ dlgAbout = GuiAbout(self) - dlgAbout.exec_() + dlgAbout.setModal(True) + dlgAbout.show() + qApp.processEvents() + dlgAbout.populateGUI() + + if showNotes: + dlgAbout.showReleaseNotes() + return def showAboutQtDialog(self): diff --git a/tests/reference/novelwriter.conf b/tests/reference/novelwriter.conf index 99b01f75..5ff6f852 100644 --- a/tests/reference/novelwriter.conf +++ b/tests/reference/novelwriter.conf @@ -6,6 +6,7 @@ icons = typicons_colour_light guidark = False guifont = guifontsize = 11 +lastnotes = 1.0 [Sizes] geometry = 1200, 650 diff --git a/tests/reference/novelwriter_prefs.conf b/tests/reference/novelwriter_prefs.conf index 831bbf08..901a6937 100644 --- a/tests/reference/novelwriter_prefs.conf +++ b/tests/reference/novelwriter_prefs.conf @@ -6,6 +6,7 @@ icons = typicons_colour_light guidark = True guifont = Cantarell guifontsize = 12 +lastnotes = 1.0 [Sizes] geometry = 1100, 650 diff --git a/tests/test_config.py b/tests/test_config.py index f9ce767b..5d72cdfd 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -14,7 +14,7 @@ def testConfigCore(tmpConf, nwTemp, nwRef): assert tmpConf.confPath == nwTemp assert tmpConf.saveConfig() - assert cmpFiles(testConf, refConf, [2]) + assert cmpFiles(testConf, refConf, [2, 9]) assert not tmpConf.confChanged assert tmpConf.loadConfig() @@ -51,7 +51,7 @@ def testConfigSetWinSize(tmpConf, nwTemp, nwRef): assert tmpConf.setWinSize(1200, 650) assert tmpConf.saveConfig() - assert cmpFiles(testConf, refConf, [2]) + assert cmpFiles(testConf, refConf, [2, 9]) assert not tmpConf.confChanged @pytest.mark.core @@ -73,7 +73,7 @@ def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef): assert tmpConf.confChanged assert tmpConf.saveConfig() - assert cmpFiles(testConf, refConf, [2]) + assert cmpFiles(testConf, refConf, [2, 9]) assert not tmpConf.confChanged @pytest.mark.core @@ -109,7 +109,7 @@ def testConfigSetPanePos(tmpConf, nwTemp, nwRef): assert tmpConf.confChanged assert tmpConf.saveConfig() - assert cmpFiles(testConf, refConf, [2]) + assert cmpFiles(testConf, refConf, [2, 9]) assert not tmpConf.confChanged @pytest.mark.core @@ -133,7 +133,7 @@ def testConfigFlags(tmpConf, nwTemp, nwRef): assert tmpConf.confChanged assert tmpConf.saveConfig() - assert cmpFiles(testConf, refConf, [2]) + assert cmpFiles(testConf, refConf, [2, 9]) assert not tmpConf.confChanged @pytest.mark.core diff --git a/tests/test_dialogs.py b/tests/test_dialogs.py index 81c1fc89..4c1f1885 100644 --- a/tests/test_dialogs.py +++ b/tests/test_dialogs.py @@ -374,12 +374,20 @@ def testAboutBox(qtbot, monkeypatch, nwFuncTemp, nwTemp): msgAbout.show() assert msgAbout.pageAbout.document().characterCount() > 100 + assert msgAbout.pageNotes.document().characterCount() > 100 assert msgAbout.pageLicense.document().characterCount() > 100 - msgAbout.mainConf.guiLang = "whatever" + msgAbout.mainConf.assetPath = "whatever" + + msgAbout._fillNotesPage() + assert msgAbout.pageNotes.toPlainText() == "Error loading release notes text ..." + msgAbout._fillLicensePage() assert msgAbout.pageLicense.toPlainText() == "Error loading license text ..." + msgAbout.showReleaseNotes() + assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes + # Qt About monkeypatch.setattr(QMessageBox, "aboutQt", lambda *args, **kwargs: None) nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger) @@ -1201,8 +1209,9 @@ def testPreferences(qtbot, monkeypatch, yesToAll, nwMinimal, nwTemp, nwRef, tmpC copyfile(projConf, testConf) ignoreLines = [ 2, # Timestamp - 11, 12, 13, 14, 15, 16, 17, # Window sizes - 7, 27, # Fonts (depends on system default) + 9, # Release Notes + 12, 13, 14, 15, 16, 17, 18, # Window sizes + 7, 28, # Fonts (depends on system default) ] assert cmpFiles(testConf, refConf, ignoreLines)