From 9add2aaa87492c80187f7e232dcd5c97e125125a Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 17 May 2022 17:51:40 +0200 Subject: [PATCH 01/18] Update the sample project to reflect new functionality --- sample/content/636b6aa9b697b.nwd | 10 +++---- sample/content/6a2d6d5f4f401.nwd | 6 ++--- sample/content/8a5deb88c0e97.nwd | 4 +-- sample/content/96b68994dfa3d.nwd | 8 +++--- sample/content/974e400180a99.nwd | 2 +- sample/content/ba8a28a246524.nwd | 4 +-- sample/content/bc0cbd2a407f3.nwd | 6 ++--- sample/nwProject.nwx | 46 +++++++++++++++----------------- 8 files changed, 41 insertions(+), 45 deletions(-) diff --git a/sample/content/636b6aa9b697b.nwd b/sample/content/636b6aa9b697b.nwd index 2927b7d0..20a66690 100644 --- a/sample/content/636b6aa9b697b.nwd +++ b/sample/content/636b6aa9b697b.nwd @@ -7,13 +7,13 @@ @char: John @location: Earth -A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. +A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference. Each paragraph in the scene is separated by a blank line. The text supports minimal formatting, like **bold**, _italic_ and **_bold italic_**. You can also ~~strike through~~ text. There is **some support for _nested_ emphasis**, but there are some known limitations. If the syntax highlighter doesn’t show it correctly, the export tool will not either. -In addition, the editor supports automatic formatting of “quotes”, both double and ‘single’. Depending on the syntax highlighter, these can be in different colours. “You can of course use **bold** and _italic_ text inside of quotes too.” +In addition, the editor supports automatic formatting of “quotes”, both double and ‘single’. Depending on the syntax highlighter settings and colour theme, these can be in different colours. “You can of course use **bold** and _italic_ text inside of quotes too.” -If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, let’s auto-replace this A with , and this C with . While is just . Press Ctrl+R to see what this looks like in the view pane. +If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, let’s auto-replace this A with , and this C with . While is just . Press Ctrl+R to see what this looks like in the view pane. The list of auto-replaced text is sett in Project Settings. The editor also supports non breaking spaces, and the spell checker accepts long dashes—like this—as valid word separators. Regular dashes are also supported – and can be automatically inserted when typing two hyphens. @@ -25,7 +25,7 @@ If you need to split a scene file up into further pieces, you can do so with the Both scene and section titles can be left out of the final exported document. The formatting of titles can be selected from the Build Novel Project dialog. You can also have them replaced with scene separators like “* * *”. -#### Text Alignment +#### Text Alignment and Indentation The text by default will have the left or justified alignment in the main text files in your project. You can also specify alignment for a specific paragraph by “pushing” it away from an edge with a set of ‘>>’ or ‘<<’ symbols, like so: @@ -35,8 +35,6 @@ This text is left-aligned. << >> This text is centred. << -#### Text Indent - You can indent a paragraph from both the left and right margin with ‘>’ and ‘<’ symbols. > This paragraph is indented from both the left margin and the right margin. This is useful for when you want to quote a large chunk of text for instance. < diff --git a/sample/content/6a2d6d5f4f401.nwd b/sample/content/6a2d6d5f4f401.nwd index 60d8d2a0..2a536e9f 100644 --- a/sample/content/6a2d6d5f4f401.nwd +++ b/sample/content/6a2d6d5f4f401.nwd @@ -1,11 +1,11 @@ %%~name: Chapter One -%%~path: e7ded148d6e4a/6a2d6d5f4f401 +%%~path: 7031beac91f75/6a2d6d5f4f401 %%~kind: NOVEL/DOCUMENT ## So it Begins @pov: Jane @location: Earth -% Synopsis: We can add a chapter file, but keep the scene files separate. In the chapter file we can set the meta data that applies to the whole chapter if we wish to. +% Synopsis: We can add a chapter document, but keep the scene files separate. In the chapter document we can set the meta data that applies to the whole chapter if we wish to. You can add the scenes as child documents directly under the chapter. -A chapter can also contain leading text before the first scene. +A chapter can contain leading text before the first scene, like this piece of text. diff --git a/sample/content/8a5deb88c0e97.nwd b/sample/content/8a5deb88c0e97.nwd index c5b61a9f..31a99aeb 100644 --- a/sample/content/8a5deb88c0e97.nwd +++ b/sample/content/8a5deb88c0e97.nwd @@ -1,6 +1,6 @@ %%~name: Old File %%~path: ae9bf3c3ea159/8a5deb88c0e97 -%%~kind: NOVEL/DOCUMENT +%%~kind: ARCHIVE/DOCUMENT ### Discarded Scene -If you have files you no longer want in your main project, you can move them to the “Archive” folder. This is equivalent to turning off the “Include when building project” switch, just that you also put the file away, although the switch can be ignored when building the project, this folder cannot. +If you have files you no longer want in your main project, you can move them to the “Archive” folder. This is equivalent to turning off the “Include when building project” switch, just that you also put the file away. diff --git a/sample/content/96b68994dfa3d.nwd b/sample/content/96b68994dfa3d.nwd index 849cd41d..05ae7770 100644 --- a/sample/content/96b68994dfa3d.nwd +++ b/sample/content/96b68994dfa3d.nwd @@ -1,11 +1,11 @@ %%~name: A Note on Structure -%%~path: e7ded148d6e4a/96b68994dfa3d +%%~path: 7031beac91f75/96b68994dfa3d %%~kind: NOVEL/NOTE # A Note on Structure This file is just a note. You can save notes anywhere you like in the project tree. Notes can be filtered out when you export the project. -In root folders that isn’t the Novel root folder, you can _only_ add notes. In the Novel root folder, you can choose between a number of layouts. Some of them are just to let yourself know what each file is for. +In root folders that aren’t the Novel or Archive root folders, you can _only_ add notes. In the Novel and Archive folder you can also add Project Documents, which are the documents that make up your actual story. ## Headers in Notes @@ -15,8 +15,10 @@ Unlike in novel files, headers in notes have no particular meaning other than vi The folders in the tree view have no structural meaning other than they’re a way for you to organise your files into groups in whatever way suits you. They are not intended to represent chapters, but you can of course use them for that. If you do, know that you still need to define chapter headers in your structure so novelWriter knows where you want them. +If you do have separate chapter documents, you can always add scene documents as child document of the chapter instead of using folders. + ## Linking Files and Notes -You can link files and notes together by assigning tags to them, and then reference them from other files. The file class of a file determines which reference keywords apply to each file. For instance a file in the Characters root folder can be referenced using either the @char keyword or the @pov keyword. +You can link project documents and notes together by assigning tags to the notes with the @tag keyword, and then reference them from other files using one of the many reference keywords. The file class of a file determines which reference keywords apply to each file. For instance a file in the Characters root folder can be referenced using either the @char keyword or the @pov keyword. If you want to see the content of the file the reference points to, you can click Ctrl+Enter with the cursor on top of the reference, and the view pane will show you the file. In the view pane, all references are clickable, so you can navigate further. At the bottom of the view pane, a list of files referencing the one your viewing will appear. This panel updates when you navigate, unless you make it sticky by clicking the sticky checkbox. \ No newline at end of file diff --git a/sample/content/974e400180a99.nwd b/sample/content/974e400180a99.nwd index ff9b71d5..99919687 100644 --- a/sample/content/974e400180a99.nwd +++ b/sample/content/974e400180a99.nwd @@ -6,4 +6,4 @@ This is a plain page with some text on it. -If you want the text to start on a fresh page, add the [NEW PAGE] code above the text. You can also add empty paragraphs with the [VSPACE] code. +If you want the text to start on a fresh page, add the [NEW PAGE] code above the text. You can also add empty paragraphs with the [VSPACE] code. The above code adds two empty paragraphs before the text starts. diff --git a/sample/content/ba8a28a246524.nwd b/sample/content/ba8a28a246524.nwd index cd684e19..c2acfb26 100644 --- a/sample/content/ba8a28a246524.nwd +++ b/sample/content/ba8a28a246524.nwd @@ -1,9 +1,9 @@ %%~name: Interlude -%%~path: e7ded148d6e4a/ba8a28a246524 +%%~path: 7031beac91f75/ba8a28a246524 %%~kind: NOVEL/DOCUMENT ##! Interlude -% Notice that this is a file with the flag ‘N.Un’. The ‘N’ means it’s a novel file, and the ‘Un’ means it’s an unnumbered chapter. Unnumbered chapters can be treated separately from numbered chapters during export. Perfect for when you want to add an interlude, or for a prologue or epilogue. +% Notice that this document has a title with a ‘!’ in it in addition to the two hash symbols. This means it is an unnumbered chapter. Unnumbered chapters can be treated separately from numbered chapters during export. Perfect for when you want to add an interlude, or for a prologue or epilogue. I am the very model of a modern Major-General I've information vegetable, animal, and mineral diff --git a/sample/content/bc0cbd2a407f3.nwd b/sample/content/bc0cbd2a407f3.nwd index 4ebbca1d..fd920d0d 100644 --- a/sample/content/bc0cbd2a407f3.nwd +++ b/sample/content/bc0cbd2a407f3.nwd @@ -7,9 +7,9 @@ @focus: Jane @location: Earth -Adding more scenes to a chapter is as easy as adding more scene files, with a level three heading, or just adding another level three heading in the same file if that works for the way you want to structure your files. +Adding more scenes to a chapter is as easy as adding more scene files with a level three heading. You can of course also just add another level three heading in the same file if that works for the way you want to structure your files. -In fact, if you wish, you can add all the scenes in the chapter file too. All novelWriter cares about is the level of the headings. +In fact, if you wish, you can add all the scenes in the chapter file too. All novelWriter cares about is the level of the headings and the order in which they appear. ### More Scenes @@ -17,4 +17,4 @@ In fact, if you wish, you can add all the scenes in the chapter file too. All no @focus: John @location: Earth -This is a second scene in the same file as the previous scene. You can always split the files up later. +This is a second scene in the same file as the previous scene. You can always split the files up later using the split tool. diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index 406fa423..21bd7776 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,13 +1,13 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 1327 - 207 - 66285 + 1328 + 220 + 67092 False @@ -17,9 +17,9 @@ True 636b6aa9b697b 636b6aa9b697b - 1206 - 830 - 376 + 1303 + 894 + 409 B E @@ -36,7 +36,7 @@ New Notes Started - 1st Draft + 1st Draft 2nd Draft 3rd Draft Finished @@ -48,7 +48,7 @@ Main - + Novel @@ -58,38 +58,34 @@ Title Page - + Page - + Part One - - - A Folder - - - + + Chapter One - + Making a Scene - + Another Scene - - + + Interlude - - + + A Note on Structure - + Chapter Two @@ -138,7 +134,7 @@ Scenes - + Old File From a71fa02b0c5857f6ddd0994558547fb22e6c6507 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 17 May 2022 18:40:10 +0200 Subject: [PATCH 02/18] Sort i18n credits on about and credits doc --- CREDITS.md | 8 +++++--- novelwriter/dialogs/about.py | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 74089153..469e4c40 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -11,12 +11,14 @@ ## Translations +The default language is English (UK) with English (US) as an option. + +* Dutch: Martijn van der Kleijn (@mvdkleijn) * French: Jan Lüdke (@jyhelle) +* Latin American Spanish: Tommy Marplatt (@tmarplatt) * Norwegian: Veronica Berglyd Olsen (@vkbo) * Portuguese: Bruno Meneguello (@bkmeneguello) * Simplified Chinese: Qianzhi Long (@longqzh) -* Latin American Spanish: Tommy Marplatt (@tmarplatt) -* Dutch: Martijn van der Kleijn (@mvdkleijn) ## Libraries @@ -32,7 +34,7 @@ The following libraries are dependencies of novelWriter: Some of the assets bundled with novelWriter were adapted from the following sources: -* [Typicons](https://github.com/stephenhutchings/typicons.font) icons by Stephen Hutchings (CC BY-SA 4.0) +* Typicons icons by [Stephen Hutchings](https://github.com/stephenhutchings/typicons.font) (CC BY-SA 4.0) * Tomorrow syntax themes by Chris Kempson (MIT License) * Owl syntax themes by Sarah Drasner (MIT License) * Solarized themes by Ethan Schoonover, added by @nullbasis (MIT License) diff --git a/novelwriter/dialogs/about.py b/novelwriter/dialogs/about.py index 574fba34..f832343a 100644 --- a/novelwriter/dialogs/about.py +++ b/novelwriter/dialogs/about.py @@ -182,12 +182,12 @@ class GuiAbout(QDialog): self.tr("Translations"), self._wrapTable([ ("English", "Veronica Berglyd Olsen"), + ("Español Latinoamericano", "Tommy Marplatt"), ("Français", "Jan Lüdke (jyhelle)"), + ("Nederlands", "Martijn van der Kleijn"), ("Norsk Bokmål", "Veronica Berglyd Olsen"), ("Português", "Bruno Meneguello"), ("简体中文", "Qianzhi Long"), - ("Español Latinoamericano", "Tommy Marplatt"), - ("Nederlands", "Martijn van der Kleijn"), ]) ) From 9eaf240674f40d44269b30670014b534b8e83416 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 17 May 2022 18:41:01 +0200 Subject: [PATCH 03/18] Release 1.7-beta1 --- CHANGELOG.md | 89 +++++++++++++++++++++++ novelwriter/__init__.py | 6 +- novelwriter/assets/text/release_notes.htm | 54 ++------------ sample/nwProject.nwx | 6 +- 4 files changed, 102 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00509e4e..b1b08033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,94 @@ # novelWriter Changelog +## Version 1.7 Beta 1 [2022-05-17] + +### Release Notes + +This is a beta release of the next release version, and is intended for testing purposes. Please be +careful when using this version on live writing projects, and make sure you take frequent backups. + +Please check the changelog for an overview of changes. The full release notes will be added to the +final release. + +### Detailed Changelog + +**Features** + +* A simple tool to add Lorem Ipsum placeholder text has been added to the Insert menu. PR #1028. +* Status and Importance flags can now be reorganised in Project Settings. Issue #1035. PR #1040. +* It is now possible to create multiple Root Folders of the same kind. This makes it possible to + add multiple Novel root folders in a project, for instance. Issue #967. PR #1031. +* All documents can now be dragged and dropped anywhere in the project tree. The document layout + may be converted in the process. PR #1031. +* Documents in the project tree can now have other documents as child documents. Issue #1002. + PR #1047. +* Folders in the project tree that are not empty, can now be moved to trash. PR #1048. +* Empty folders are deleted on request, and not moved to trash. Issue #1052. PR #1055. + +**User Interface** + +* The tabs under the project tree and to the right of the main window have been replaced with a + toolbar on the left hand side. The toolbar has a set of buttons to change view between Project, + Novel and Outline. The three buttons that were available under the project tree have been moved + to the bottom of the new toolbar. Issue #1056. PR #1057. +* When a document changes from a project document to a note, and back again, the Status flag + setting is preserved. Previously, the Importance setting would overwrite it during the + conversion. PR #1030. +* Item labels, Status labels, and other labels on the GUI are now run through a "simplify" function + before being accepted. This functions strips out all whitespaces and consecutive whitespaces and + replace them with single plain whitespaces. This is a safer format to store in XML, and also + makes sure there aren't invisible characters floating around in the labels. PR #1038. +* Due to the changes to how drag and drop works, there are no longer any restrictions on folders + and documents. Only root folders remain restricted in terms of moving. Root folders can only be + reordered with the Move Up and Move Down commands. PR #1047. +* The label for the highlighting of redundant spaces in the Preferences dialog has been updated to + better reflect what it does. Issue #1043. PR #1046. +* The New Project Wizard will now try to check if the path selected for the new project can + actually be used before letting the user proceed to the next page. Issue #1058. PR #1062. + +**Internationalisation** + +* Dutch translations have been added by Martijn van der Kleijn (@mvdkleijn). PR #1027. + +**Functionality** + +* Documents that are missing in the project index when a project is opened are automatically + re-indexed. This also handles cases where the cached index is missing. PR #1039. + +**Installation and Packaging** + +* Python 3.6 is no longer supported. PR #1004. +* Ubuntu 18.04 packages will no longer be released, due to dropping Python 3.6. Issue #1005. + PR #1014. + +**Project File Format** + +* The item nodes in the content section of the main project XML file have been compacted. It now + consists of a main item node and meta and a name node. All settings have been made attributes of + one of these three nodes, except the item label which is the text value of the name node. The + file format version has been bumped to 1.4. Issue #995. PR #993. +* Both Importance and Status flag values are now saved to the project file. This means if a + document changes layout, the value is no longer lost. PR #1030. + +**Code Improvements** + +* The linting settings have been updated to select between mutually exclusive options in + pycodestyle. PR #1014. +* The Tokenizer class has been converted to an abstract base class. PR #1026. +* The class handling Status and Importance flags has been completely rewritten. The flags are now + handled using a unique random key as reference rather than relying on the text of the label + itself. This makes it a lot easier to rename them as there is no need to update project items. + PR #1034. +* Many of the decisions regarding where items are allowed to belong has been delegated to the + NWItem class that holds the item. Some is also handled by the NWTree class that holds the project + tree. A new maintenance function in the NWTree class will also ensure that the meta data of an + item is correct and up to date. This is especially important after an item has been moved, but is + also checked when items are initially loaded. PRs #1031 and #1054. +* Item handles are now generated using the standard library random number generator. The new + handles have the same format as the old algorithm, so they are compatible. PR #1044. + +---- + ## Version 1.6.2 [2022-03-20] ### Release Notes diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 164a05e7..0ae10566 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -60,9 +60,9 @@ __license__ = "GPLv3" __author__ = "Veronica Berglyd Olsen" __maintainer__ = "Veronica Berglyd Olsen" __email__ = "code@vkbo.net" -__version__ = "1.7-alpha0" -__hexversion__ = "0x010700a0" -__date__ = "2022-02-20" +__version__ = "1.7-beta1" +__hexversion__ = "0x010700b1" +__date__ = "2022-05-17" __status__ = "Stable" __domain__ = "novelwriter.io" __url__ = "https://novelwriter.io" diff --git a/novelwriter/assets/text/release_notes.htm b/novelwriter/assets/text/release_notes.htm index 0850e30c..aeb5fbc7 100644 --- a/novelwriter/assets/text/release_notes.htm +++ b/novelwriter/assets/text/release_notes.htm @@ -2,56 +2,16 @@ -

Release Notes for 1.6

-

Released on 20 February 2022

+

Release Notes for 1.7 Beta 1

+

Released on 17 May 2022

-

This release does not introduce any major new features, but is instead a collection of minor -improvements and tweaks based on user requests. There are also a number of changes under the hood -to improve the structure and performance of novelWriter.

-

Some key improvements to the user interface are:

-

✓ The max text width setting in Preferences now also applies to the document viewer, and -the setting itself on the Preference dialog has been simplified a bit.

-

✓ When text is selected in the document editor, the number of words selected is displayed -in the editor's footer area.

-

✓ The search tool in the document editor now shows the number of results in the -document.

-

✓ The Enter and Ctrl+O keyboard shortcuts should now work the same way in all tree -views.

-

✓ It is now possible to set a blank section title format on the Build Novel Project tool -and get empty paragraphs in the output. Previously, a blank format would just remove the section -break entirely. This change allows the user to define hard and soft scene breaks using level three -and four headings. The scene and section titles can be hidden completely with two new switches -added to the user interface.

-

Other feature changes include:

-

✓ The project index is now automatically rebuilt in the event it is empty or incomplete -when the project is opened.

-

✓ The user can now add their own syntax and GUI theme files in the app folder in their -user area on the host operating system. Where the custom files must be added is described in the -documentation.

-

✓ A Windows installer is yet again provided for novelWriter. If you have novelWriter -installed using another method, make sure you uninstall it properly first as the two methods are -not compatible.

-

✓ Release versions for Ubuntu 21.04 have been dropped, and added for the upcoming Ubuntu -22.04.

-

✓ Most translations have been updated. A Dutch translation is in the works.

+

This is a beta release of the next release version, and is intended for testing purposes. Please +be careful when using this version on live writing projects, and make sure you take frequent +backups.

+

Please check the changelog for an overview of changes. The full release notes will be added to +the final release.

See also the Releases page.

-

Patch Notes

- -

Patch 1.6.1 – 16 March 2022

- -

This is a bugfix and patch release that fixes two recursion/loop issues. One would potentially -cause a crash if the window was resized rapidly, and one would cause a hang with certain search -parameters in the editor's search box. The Latin American Spanish translation has also been -updated.

- -

Patch 1.6.2 – 20 March 2022

- -

This is a bugfix release that fixes a couple of minor issues. Projects containing one or more -empty documents would trigger a rebuild of the index each time the project was opened. This has now -been fixed. Another fix resolves an error message being written to the console logging output when -a new document was created. Both errors were harmless.

- diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index 21bd7776..e53d6569 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,13 +1,13 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 1328 + 1329 220 - 67092 + 67104 False From 301d81f9877506ff7fa6deba6f307f851c8257ed Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 17 May 2022 20:22:16 +0200 Subject: [PATCH 04/18] Update various translation files --- i18n/nw_base.ts | 1213 +++++++++---------- i18n/nw_en_US.ts | 1221 ++++++++++---------- i18n/nw_nb_NO.ts | 1221 ++++++++++---------- novelwriter/assets/i18n/project_nl_NL.json | 200 ++-- 4 files changed, 1941 insertions(+), 1914 deletions(-) diff --git a/i18n/nw_base.ts b/i18n/nw_base.ts index 4eaa8252..8d7e2940 100644 --- a/i18n/nw_base.ts +++ b/i18n/nw_base.ts @@ -77,259 +77,259 @@ Constant - - - + + + None - + Novel - - + + Plot - - + + Characters - - + + Locations - - + + Timeline - - + + Objects - - + + Entities - - + + Custom - + Archive - + Trash - - + + Novel Document - - + + Project Note - + Root Folder - + Folder - + Novel Title Page - + Novel Chapter - + Novel Scene - + Tag - + Point of View - - + + Focus - + Title - + Level - + Document - + Line - + Chars - + Words - + Pars - + POV - + Synopsis - + Straight single quotation mark - + Straight double quotation mark - + Left single quotation mark - + Right single quotation mark - + Single low-9 quotation mark - + Single high-reversed-9 quotation mark - + Left double quotation mark - + Right double quotation mark - + Double low-9 quotation mark - + Double high-reversed-9 quotation mark - + Double low-reversed-9 quotation mark - + Single left-pointing angle quotation mark - + Single right-pointing angle quotation mark - + Double left-pointing angle quotation mark - + Double right-pointing angle quotation mark - + Left corner bracket - + Right corner bracket - + Left white corner bracket - + Right white corner bracket @@ -353,9 +353,9 @@ - - - + + + Licence @@ -411,31 +411,31 @@ - + Theme: {0} - - - - - Author - - + Author + + + + + + Credit - + Icons: {0} - + Syntax: {0} @@ -718,62 +718,62 @@ - + Open Document - + Flat Open Document - + Plain HTML - + novelWriter Markdown - + Standard Markdown - + GitHub Markdown - + JSON + novelWriter HTML - + JSON + novelWriter Markdown - + PDF - + Save Document As - + {0} file successfully written to: - + Failed to write {0} file. {1} @@ -781,17 +781,17 @@ GuiBuildNovelDocView - + This area will show the content of the document to be exported or printed. Press the "Build Preview" button to generate content. - + Unknown - + Build Time: @@ -799,32 +799,32 @@ GuiDocEditFooter - + Status - + Line: {0} ({1}) - + Words: {0} ({1}) - + Document size is {0} bytes - + Words: {0} selected - + Character count: {0} @@ -832,22 +832,22 @@ GuiDocEditHeader - + Edit document meta - + Search document - + Toggle Focus Mode - + Close the document @@ -855,58 +855,58 @@ GuiDocEditSearch - - + + Search - + Replace - + Case Sensitive - + Whole Words Only - + RegEx Mode - + Loop Search - + Search Next File - + Preserve Case - + Close Search - + Find in current document - + Find and replace in current document @@ -914,117 +914,117 @@ GuiDocEditor - + The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB. - + Opened Document: {0} - + The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB. - + File Changed on Disk - + This document has been changed outside of novelWriter while it was open. Overwrite the file on disk? - + Could not save document. - + Saved Document: {0} - + Spell checking requires the package PyEnchant. It does not appear to be installed. - + Spell check complete - + File Location - + The currently open file is saved in: - + The document has grown too big and you cannot add more text to it. The maximum size of a single novelWriter document is {0} MB. - + Follow Tag - + Cut - + Copy - + Paste - + Select All - + Select Word - + Select Paragraph - + Spelling Suggestion(s) - + No Suggestions - + Add Word to Dictionary - + Please select some text before calling replace quotes. @@ -1067,12 +1067,12 @@ - + Could not save document. - + Element selected in the project tree must be a folder. @@ -1080,83 +1080,78 @@ GuiDocSplit - - + + Split Document - + Document Headers - + Select the maximum level to split into files. - + Split on Header Level 1 (Title) - + Split up to Header Level 2 (Chapter) - + Split up to Header Level 3 (Scene) - + Split up to Header Level 4 (Section) - + No source document selected. Nothing to do. - + Could not parse source document. - + Failed to open document file. - + No headers found. Nothing to do. - - Cannot add new folder for the document split. Maximum folder depth has been reached. Please move the file to another level in the project tree. - - - - + The document will be split into {0} file(s) in a new folder. The original document will remain intact. - + Continue with the splitting process? - + Could not save document. - + Element selected in the project tree must be a file. @@ -1164,42 +1159,42 @@ GuiDocViewFooter - + Show/hide the references panel - + Activate to freeze the content of the references panel when changing document - + Show comments - + Show synopsis comments - + References - + Sticky - + Comments - + Synopsis @@ -1207,22 +1202,22 @@ GuiDocViewHeader - + Go backward - + Go forward - + Reload the document - + Close the document @@ -1283,17 +1278,17 @@ - + Characters - + Words - + Paragraphs @@ -1306,237 +1301,230 @@ - + Include when building project - + Label - + Status - + Layout + + GuiLipsum + + + Insert Placeholder Text + + + + + Insert Lorem Ipsum Text + + + + + Number of paragraphs + + + + + Randomise order + + + + + Insert + + + GuiMain - - Project - - - - - Novel - - - - - Project Details - - - - - Writing Statistics - - - - - Project Settings - - - - - Editor - - - - - Outline - - - - + You are running an untested development version of novelWriter. Please be careful when working on a live project and make sure you take regular backups. - + novelWriter is ready ... - + Cannot create a new project when another project is open. - + A project already exists in that location. Please choose another folder. - + New project created ... - + Close Project - + Close the current project? - - + + Changes are saved automatically. - + Backup Project - + Backup the current project? - + The project was locked by the computer '{0}' ({1} {2}), last active on {3}. - + Project Locked - + The project is already open by another instance of novelWriter, and is therefore locked. Override lock and continue anyway? - + Note: If the program or the computer previously crashed, the lock can safely be overridden. However, overriding it is not recommended if the project is open in another instance of novelWriter. Doing so may corrupt the project. - + The project index is outdated or broken. Rebuilding index. - + Text files ({0}) - + Markdown files ({0}) - + novelWriter files ({0}) - + All files ({0}) - + Import File - + Could not read file. The file must be an existing text file. - + Please open a document to import the text file into. - + Import Document - + Importing the file will overwrite the current content of the document. Do you want to proceed? - - + + Indexing: '{0}' - + Unknown item - + Indexing completed in {0} ms - + The project index has been successfully rebuilt. - + Information - + Warning - + Error - + This is a bug! - + Internal Error - + Exit - + Do you want to exit novelWriter? @@ -1544,677 +1532,682 @@ GuiMainMenu - + &Project - + New Project - + Open Project - + Save Project - + Close Project - + Project Settings - + Project Details - + Create Root Folder - + Novel Root - + Plot Root - + Character Root - + Location Root - + Timeline Root - + Object Root - + Entity Root - + Custom Root - + Archive Root - + Create Folder - + Edit Item - + Delete Item - + Move Item Up - + Move Item Down - + Undo Last Move - + Empty Trash - + Exit - + &Document - + New Document - + Open Document - + Save Document - + Close Document - + View Document - + Close Document View - + Show File Details - + Import Text from File - + Merge Folder to Document - + Split Document to Folder - + &Edit - + Undo - + Redo - + Cut - + Copy - + Paste - + Select All - + Select Paragraph - + &View - + Go to Project Tree - + Go to Document Editor - + Go to Document Viewer - + Go to Outline - + Navigate Backward - + Navigate Forward - + Focus Mode - + Full Screen Mode - + &Insert - + Dashes - + Short Dash - + Long Dash - + Horizontal Bar - + Figure Dash - + Quote Marks - + Left Single Quote - + Right Single Quote - + Left Double Quote - + Right Double Quote - + Alternative Apostrophe - + General Punctuation - + Ellipsis - + Prime - + Double Prime - + White Spaces - + Non-Breaking Space - + Thin Space - + Thin Non-Breaking Space - + Other Symbols - + List Bullet - + Hyphen Bullet - + Flower Mark - + Per Mille - + Degree Symbol - + Minus Sign - + Times Sign - + Division Sign - + Tags and References - + Page Break and Space - + Page Break - + Vertical Space (Single) - + Vertical Space (Multi) - + + Placeholder Text + + + + &Format - + Emphasis - + Strong Emphasis - + Strikethrough - + Wrap Double Quotes - + Wrap Single Quotes - + Header 1 (Partition) - + Header 2 (Chapter) - + Header 3 (Scene) - + Header 4 (Section) - + Novel Title - + Unnumbered Chapter - + Align Left - + Align Centre - + Align Right - + Indent Left - + Indent Right - + Toggle Comment - + Remove Block Format - + Convert Single Quotes - + Convert Double Quotes - + Remove In-Paragraph Breaks - + &Search - + Find - + Replace - + Find Next - + Find Previous - + Replace Next - + &Tools - + Check Spelling - + Re-Run Spell Check - + Project Word List - + Rebuild Index - + Rebuild Outline - + Auto-Update Outline - + Backup Project - + Build Novel Project - + Writing Statistics - + Preferences - + &Help - + About novelWriter - + About Qt5 - + User Manual (Online) - + User Manual (PDF) - + Report an Issue (GitHub) - + Ask a Question (GitHub) - + The novelWriter Website - + Check for New Release @@ -2294,65 +2287,65 @@ GuiOutlineDetails - - - - + + + + Title - + Chapter - + Scene - + Section - + Document - + Status - + Characters - + Words - + Paragraphs - + Synopsis - + Title Details - + Reference Tags @@ -3046,7 +3039,7 @@ - Highlight multiple spaces + Highlight multiple or trailing spaces @@ -3187,58 +3180,58 @@ GuiProjectEditMain - + Project Settings - + Working title - + Should be set only once. - + Novel title - + Change whenever you want! - + Author(s) - + One name per line. - + Default - + Spell check language - - + + Overrides main preferences. - + No backup on close @@ -3246,27 +3239,27 @@ GuiProjectEditReplace - + Text Replace List for Preview and Export - + Keyword - + Replace With - + Select item to edit - + Save @@ -3274,67 +3267,67 @@ GuiProjectEditStatus - + Novel File Status Levels - + Note File Importance Levels - + Label - + Usage - + Select item to edit - + Colour - + Save - + Select Colour - + New Item - + Cannot delete a status item that is in use. - + Not in use - + Used once - + Used by {0} items @@ -3406,27 +3399,27 @@ GuiProjectSettings - + Project Settings - + Settings - + Status - + Importance - + Auto-Replace @@ -3464,100 +3457,78 @@ - - Please select a valid location in the tree to add the document. - - - - - Please select a valid location in the tree to add the folder. - - - - - + Did not find anywhere to add the file or folder! - + Cannot add new files or folders to the Trash folder. - - New File + + New Document - - Cannot add new folder to this item. Maximum folder depth has been reached. + + New Note - + New Folder - + There is currently no Trash folder in this project. - + The Trash folder is already empty. - + Empty Trash - + Permanently delete {0} file(s) from Trash? - - - Delete File - - - - - Permanently delete file '{0}'? - - - - - Could not delete document file. - - - - - Move file '{0}' to Trash? - - - - - Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - - - - + Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - - - The item cannot be moved to that location. + + + Delete - + + Permanently delete '{0}'? + + + + + Move '{0}' to Trash? + + + + + Could not delete document file. + + + + There is nowhere to add item with name '{0}'. @@ -3565,52 +3536,52 @@ GuiProjectTreeMenu - + Edit Project Item - + Open Document - + View Document - + Toggle Included Flag - + New File - + New Folder - + Delete Item - + Empty Trash - + Move Item Up - + Move Item Down @@ -3649,6 +3620,39 @@ + + GuiViewsBar + + + Project + + + + + Novel + + + + + Outline + + + + + Details + + + + + Stats + + + + + Settings + + + GuiWordList @@ -3816,7 +3820,7 @@ - + Failed to read session log file. @@ -3824,314 +3828,309 @@ NWProject - - Duplicate root item detected. - - - - - + + New - + Note - + Draft - + Finished - + Minor - + Major - + Main - + New Project - + By - - + + Novel - + Plot - + Characters - + World - - + + Title Page - - - + + + New Chapter - - + + New Scene - + Chapter {0} - - + + Scene {0} - + File not found: {0} - - + + Failed to parse project xml. - + Attempting to open backup project file instead. - - + + Unknown - + Project file does not appear to be a novelWriterXML file. - + Unknown or unsupported novelWriter project file format. The project cannot be opened by this version of novelWriter. The file was saved with novelWriter version {0}. - + File Version - + The file format of your project is about to be updated. If you proceed, older versions of novelWriter will no longer be able to open this project. Continue? - + Version Conflict - + This project was saved by a newer version of novelWriter, version {0}. This is version {1}. If you continue to open the project, some attributes and settings may not be preserved, but the overall project should be fine. Continue opening the project? - + Opened Project: {0} - + Project path not set, cannot save project. - - + + Failed to save project. - + Saved Project: {0} - + Backing up project ... - + Cannot backup project because no valid backup path is set. Please set a valid backup location in Preferences. - + Cannot backup project because no project name is set. Please set a Working Title in Project Settings. - + Could not create backup folder. - + Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Preferences. - + Backup from {0} - + Backup archive file written to: {0} - + Could not write backup archive. - + Project backed up to '{0}' - - + + Failed to create a new example project. - + Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation. - + Could not create new project folder. - + New project folder is not empty. Each project requires a dedicated project folder. - + You must set a valid backup path in Preferences to use the automatic project backup feature. - + You must set a valid project name in Project Settings to use the automatic project backup feature. - + and - + Could not create folder. - + Found {0} orphaned file(s) in project folder. - + Recovered - + [{0}] {1} - + Recovered File {0} - + One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists. - + Not a folder: {0} - + Could not move: {0} - - + + Could not delete: {0} - + Could not make folder: {0} - + Could not move item {0} to {1}. @@ -4139,47 +4138,47 @@ ProjWizardCustomPage - + Custom Project Options - + Select which additional root folders to make, and how to populate the Novel folder. If you don't want to add chapters or scenes, set the values to 0. You can add scenes without chapters. - + Additional Root Folders - - - - - - + + + + + + {0} folder - + Populate Novel Folder - + Add chapters - + Scenes (per chapter) - + Add chapter folders @@ -4187,27 +4186,27 @@ ProjWizardFinalPage - + Finished - + All done. - + Press '{0}' to create the new project. - + Done - + Finish @@ -4215,7 +4214,7 @@ ProjWizardFolderPage - + Select Project Folder @@ -4231,10 +4230,20 @@ - + Project Path + + + Error: A project folder cannot be created using this path. + + + + + Error: The selected path already exists. + + ProjWizardIntroPage @@ -4287,27 +4296,27 @@ ProjWizardPopulatePage - + Populate Project - + Choose how to pre-fill the project. Either with a minimal set of starter items, an example project explaining and showing many of the features, or show further custom options on the next page. - + Fill the project with a minimal set of items - + Fill the project with example files - + Show detailed options for filling the project @@ -4503,17 +4512,17 @@ Tokenizer - + Synopsis - + Document '{0}' is too big ({1} MB). Skipping. - + ERROR diff --git a/i18n/nw_en_US.ts b/i18n/nw_en_US.ts index 3fb60626..75aee812 100644 --- a/i18n/nw_en_US.ts +++ b/i18n/nw_en_US.ts @@ -77,259 +77,259 @@ Constant - - - + + + None None - + Novel Novel - - + + Plot Plot - - + + Characters Characters - - + + Locations Locations - - + + Timeline Timeline - - + + Objects Objects - - + + Entities Entities - - + + Custom Custom - + Archive Archive - + Trash Trash - - + + Novel Document Novel Document - - + + Project Note Project Note - + Root Folder Root Folder - + Folder Folder - + Novel Title Page Novel Title Page - + Novel Chapter Novel Chapter - + Novel Scene Novel Scene - + Tag Tag - + Point of View Point of View - - + + Focus Focus - + Title Title - + Level Level - + Document Document - + Line Line - + Chars Chars - + Words Words - + Pars Pars - + POV POV - + Synopsis Synopsis - + Straight single quotation mark Straight single quotation mark - + Straight double quotation mark Straight double quotation mark - + Left single quotation mark Left single quotation mark - + Right single quotation mark Right single quotation mark - + Single low-9 quotation mark Single low-9 quotation mark - + Single high-reversed-9 quotation mark Single high-reversed-9 quotation mark - + Left double quotation mark Left double quotation mark - + Right double quotation mark Right double quotation mark - + Double low-9 quotation mark Double low-9 quotation mark - + Double high-reversed-9 quotation mark Double high-reversed-9 quotation mark - + Double low-reversed-9 quotation mark Double low-reversed-9 quotation mark - + Single left-pointing angle quotation mark Single left-pointing angle quotation mark - + Single right-pointing angle quotation mark Single right-pointing angle quotation mark - + Double left-pointing angle quotation mark Double left-pointing angle quotation mark - + Double right-pointing angle quotation mark Double right-pointing angle quotation mark - + Left corner bracket Left corner bracket - + Right corner bracket Right corner bracket - + Left white corner bracket Left white corner bracket - + Right white corner bracket Right white corner bracket @@ -353,9 +353,9 @@ Release - - - + + + Licence License @@ -411,31 +411,31 @@ Translations - + Theme: {0} Theme: {0} - - - - - Author - Author - + Author + Author + + + + + Credit Credit - + Icons: {0} Icons: {0} - + Syntax: {0} Syntax: {0} @@ -718,62 +718,62 @@ There were problems when building the project: - + Open Document Open Document - + Flat Open Document Flat Open Document - + Plain HTML Plain HTML - + novelWriter Markdown novelWriter Markdown - + Standard Markdown Standard Markdown - + GitHub Markdown GitHub Markdown - + JSON + novelWriter HTML JSON + novelWriter HTML - + JSON + novelWriter Markdown JSON + novelWriter Markdown - + PDF PDF - + Save Document As Save Document As - + {0} file successfully written to: {0} file successfully written to: - + Failed to write {0} file. {1} Failed to write {0} file. {1} @@ -781,17 +781,17 @@ GuiBuildNovelDocView - + This area will show the content of the document to be exported or printed. Press the "Build Preview" button to generate content. This area will show the content of the document to be exported or printed. Press the "Build Preview" button to generate content. - + Unknown Unknown - + Build Time: Build Time: @@ -799,32 +799,32 @@ GuiDocEditFooter - + Status Status - + Line: {0} ({1}) Line: {0} ({1}) - + Words: {0} ({1}) Words: {0} ({1}) - + Document size is {0} bytes Document size is {0} bytes - + Words: {0} selected Words: {0} selected - + Character count: {0} Character count: {0} @@ -832,22 +832,22 @@ GuiDocEditHeader - + Edit document meta Edit document meta - + Search document Search document - + Toggle Focus Mode Toggle Focus Mode - + Close the document Close the document @@ -855,58 +855,58 @@ GuiDocEditSearch - - + + Search Search - + Replace Replace - + Case Sensitive Case Sensitive - + Whole Words Only Whole Words Only - + RegEx Mode RegEx Mode - + Loop Search Loop Search - + Search Next File Search Next File - + Preserve Case Preserve Case - + Close Search Close Search - + Find in current document Find in current document - + Find and replace in current document Find and replace in current document @@ -914,117 +914,117 @@ GuiDocEditor - + The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB. The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB. - + Opened Document: {0} Opened Document: {0} - + The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB. The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB. - + File Changed on Disk File Changed on Disk - + This document has been changed outside of novelWriter while it was open. Overwrite the file on disk? This document has been changed outside of novelWriter while it was open. Overwrite the file on disk? - + Could not save document. Could not save document. - + Saved Document: {0} Saved Document: {0} - + Spell checking requires the package PyEnchant. It does not appear to be installed. Spell checking requires the package PyEnchant. It does not appear to be installed. - + Spell check complete Spell check complete - + File Location File Location - + The currently open file is saved in: The currently open file is saved in: - + The document has grown too big and you cannot add more text to it. The maximum size of a single novelWriter document is {0} MB. The document has grown too big and you cannot add more text to it. The maximum size of a single novelWriter document is {0} MB. - + Follow Tag Follow Tag - + Cut Cut - + Copy Copy - + Paste Paste - + Select All Select All - + Select Word Select Word - + Select Paragraph Select Paragraph - + Spelling Suggestion(s) Spelling Suggestion(s) - + No Suggestions No Suggestions - + Add Word to Dictionary Add Word to Dictionary - + Please select some text before calling replace quotes. Please select some text before calling replace quotes. @@ -1067,12 +1067,12 @@ Internal error. - + Could not save document. Could not save document. - + Element selected in the project tree must be a folder. Element selected in the project tree must be a folder. @@ -1080,83 +1080,78 @@ GuiDocSplit - - + + Split Document Split Document - + Document Headers Document Headers - + Select the maximum level to split into files. Select the maximum level to split into files. - + Split on Header Level 1 (Title) Split on Header Level 1 (Title) - + Split up to Header Level 2 (Chapter) Split up to Header Level 2 (Chapter) - + Split up to Header Level 3 (Scene) Split up to Header Level 3 (Scene) - + Split up to Header Level 4 (Section) Split up to Header Level 4 (Section) - + No source document selected. Nothing to do. No source document selected. Nothing to do. - + Could not parse source document. Could not parse source document. - + Failed to open document file. Failed to open document file. - + No headers found. Nothing to do. No headers found. Nothing to do. - - Cannot add new folder for the document split. Maximum folder depth has been reached. Please move the file to another level in the project tree. - Cannot add new folder for the document split. Maximum folder depth has been reached. Please move the file to another level in the project tree. - - - + The document will be split into {0} file(s) in a new folder. The original document will remain intact. The document will be split into {0} file(s) in a new folder. The original document will remain intact. - + Continue with the splitting process? Continue with the splitting process? - + Could not save document. Could not save document. - + Element selected in the project tree must be a file. Element selected in the project tree must be a file. @@ -1164,42 +1159,42 @@ GuiDocViewFooter - + Show/hide the references panel Show/hide the references panel - + Activate to freeze the content of the references panel when changing document Activate to freeze the content of the references panel when changing document - + Show comments Show comments - + Show synopsis comments Show synopsis comments - + References References - + Sticky Sticky - + Comments Comments - + Synopsis Synopsis @@ -1207,22 +1202,22 @@ GuiDocViewHeader - + Go backward Go backward - + Go forward Go forward - + Reload the document Reload the document - + Close the document Close the document @@ -1283,17 +1278,17 @@ Usage - + Characters Characters - + Words Words - + Paragraphs Paragraphs @@ -1306,237 +1301,230 @@ Item Settings - + Include when building project Include when building project - + Label Label - + Status Status - + Layout Layout + + GuiLipsum + + + Insert Placeholder Text + Insert Placeholder Text + + + + Insert Lorem Ipsum Text + Insert Lorem Ipsum Text + + + + Number of paragraphs + Number of paragraphs + + + + Randomise order + Randomize order + + + + Insert + Insert + + GuiMain - - Project - Project - - - - Novel - Novel - - - - Project Details - Project Details - - - - Writing Statistics - Writing Statistics - - - - Project Settings - Project Settings - - - - Editor - Editor - - - - Outline - Outline - - - + You are running an untested development version of novelWriter. Please be careful when working on a live project and make sure you take regular backups. You are running an untested development version of novelWriter. Please be careful when working on a live project and make sure you take regular backups. - + novelWriter is ready ... novelWriter is ready ... - + Cannot create a new project when another project is open. Cannot create a new project when another project is open. - + A project already exists in that location. Please choose another folder. A project already exists in that location. Please choose another folder. - + New project created ... New project created ... - + Close Project Close Project - + Close the current project? Close the current project? - - + + Changes are saved automatically. Changes are saved automatically. - + Backup Project Backup Project - + Backup the current project? Backup the current project? - + The project was locked by the computer '{0}' ({1} {2}), last active on {3}. The project was locked by the computer '{0}' ({1} {2}), last active on {3}. - + Project Locked Project Locked - + The project is already open by another instance of novelWriter, and is therefore locked. Override lock and continue anyway? The project is already open by another instance of novelWriter, and is therefore locked. Override lock and continue anyway? - + Note: If the program or the computer previously crashed, the lock can safely be overridden. However, overriding it is not recommended if the project is open in another instance of novelWriter. Doing so may corrupt the project. Note: If the program or the computer previously crashed, the lock can safely be overridden. However, overriding it is not recommended if the project is open in another instance of novelWriter. Doing so may corrupt the project. - + The project index is outdated or broken. Rebuilding index. The project index is outdated or broken. Rebuilding index. - + Text files ({0}) Text files ({0}) - + Markdown files ({0}) Markdown files ({0}) - + novelWriter files ({0}) novelWriter files ({0}) - + All files ({0}) All files ({0}) - + Import File Import File - + Could not read file. The file must be an existing text file. Could not read file. The file must be an existing text file. - + Please open a document to import the text file into. Please open a document to import the text file into. - + Import Document Import Document - + Importing the file will overwrite the current content of the document. Do you want to proceed? Importing the file will overwrite the current content of the document. Do you want to proceed? - - + + Indexing: '{0}' Indexing: '{0}' - + Unknown item Unknown item - + Indexing completed in {0} ms Indexing completed in {0} ms - + The project index has been successfully rebuilt. The project index has been successfully rebuilt. - + Information Information - + Warning Warning - + Error Error - + This is a bug! This is a bug! - + Internal Error Internal Error - + Exit Exit - + Do you want to exit novelWriter? Do you want to exit novelWriter? @@ -1544,677 +1532,682 @@ GuiMainMenu - + &Project &Project - + New Project New Project - + Open Project Open Project - + Save Project Save Project - + Close Project Close Project - + Project Settings Project Settings - + Project Details Project Details - + Create Root Folder Create Root Folder - + Novel Root Novel Root - + Plot Root Plot Root - + Character Root Character Root - + Location Root Location Root - + Timeline Root Timeline Root - + Object Root Object Root - + Entity Root Entity Root - + Custom Root Custom Root - + Archive Root Archive Root - + Create Folder Create Folder - + Edit Item Edit Item - + Delete Item Delete Item - + Move Item Up Move Item Up - + Move Item Down Move Item Down - + Undo Last Move Undo Last Move - + Empty Trash Empty Trash - + Exit Exit - + &Document &Document - + New Document New Document - + Open Document Open Document - + Save Document Save Document - + Close Document Close Document - + View Document View Document - + Close Document View Close Document View - + Show File Details Show File Details - + Import Text from File Import Text from File - + Merge Folder to Document Merge Folder to Document - + Split Document to Folder Split Document to Folder - + &Edit &Edit - + Undo Undo - + Redo Redo - + Cut Cut - + Copy Copy - + Paste Paste - + Select All Select All - + Select Paragraph Select Paragraph - + &View &View - + Go to Project Tree Go to Project Tree - + Go to Document Editor Go to Document Editor - + Go to Document Viewer Go to Document Viewer - + Go to Outline Go to Outline - + Navigate Backward Navigate Backward - + Navigate Forward Navigate Forward - + Focus Mode Focus Mode - + Full Screen Mode Full Screen Mode - + &Insert &Insert - + Dashes Dashes - + Short Dash Short Dash - + Long Dash Long Dash - + Horizontal Bar Horizontal Bar - + Figure Dash Figure Dash - + Quote Marks Quote Marks - + Left Single Quote Left Single Quote - + Right Single Quote Right Single Quote - + Left Double Quote Left Double Quote - + Right Double Quote Right Double Quote - + Alternative Apostrophe Alternative Apostrophe - + General Punctuation General Punctuation - + Ellipsis Ellipsis - + Prime Prime - + Double Prime Double Prime - + White Spaces White Spaces - + Non-Breaking Space Non-Breaking Space - + Thin Space Thin Space - + Thin Non-Breaking Space Thin Non-Breaking Space - + Other Symbols Other Symbols - + List Bullet List Bullet - + Hyphen Bullet Hyphen Bullet - + Flower Mark Flower Mark - + Per Mille Per Mille - + Degree Symbol Degree Symbol - + Minus Sign Minus Sign - + Times Sign Times Sign - + Division Sign Division Sign - + Tags and References Tags and References - + Page Break and Space Page Break and Space - + Page Break Page Break - + Vertical Space (Single) Vertical Space (Single) - + Vertical Space (Multi) Vertical Space (Multi) - + + Placeholder Text + Placeholder Text + + + &Format &Format - + Emphasis Emphasis - + Strong Emphasis Strong Emphasis - + Strikethrough Strikethrough - + Wrap Double Quotes Wrap Double Quotes - + Wrap Single Quotes Wrap Single Quotes - + Header 1 (Partition) Header 1 (Partition) - + Header 2 (Chapter) Header 2 (Chapter) - + Header 3 (Scene) Header 3 (Scene) - + Header 4 (Section) Header 4 (Section) - + Novel Title Novel Title - + Unnumbered Chapter Unnumbered Chapter - + Align Left Align Left - + Align Centre Align Center - + Align Right Align Right - + Indent Left Indent Left - + Indent Right Indent Right - + Toggle Comment Toggle Comment - + Remove Block Format Remove Block Format - + Convert Single Quotes Convert Single Quotes - + Convert Double Quotes Convert Double Quotes - + Remove In-Paragraph Breaks Remove In-Paragraph Breaks - + &Search &Search - + Find Find - + Replace Replace - + Find Next Find Next - + Find Previous Find Previous - + Replace Next Replace Next - + &Tools &Tools - + Check Spelling Check Spelling - + Re-Run Spell Check Re-Run Spell Check - + Project Word List Project Word List - + Rebuild Index Rebuild Index - + Rebuild Outline Rebuild Outline - + Auto-Update Outline Auto-Update Outline - + Backup Project Backup Project - + Build Novel Project Build Novel Project - + Writing Statistics Writing Statistics - + Preferences Preferences - + &Help &Help - + About novelWriter About novelWriter - + About Qt5 About Qt5 - + User Manual (Online) User Manual (Online) - + User Manual (PDF) User Manual (PDF) - + Report an Issue (GitHub) Report an Issue (GitHub) - + Ask a Question (GitHub) Ask a Question (GitHub) - + The novelWriter Website The novelWriter Website - + Check for New Release Check for New Release @@ -2294,65 +2287,65 @@ GuiOutlineDetails - - - - + + + + Title Title - + Chapter Chapter - + Scene Scene - + Section Section - + Document Document - + Status Status - + Characters Characters - + Words Words - + Paragraphs Paragraphs - + Synopsis Synopsis - + Title Details Title Details - + Reference Tags Reference Tags @@ -3046,8 +3039,8 @@ - Highlight multiple spaces - Highlight multiple spaces + Highlight multiple or trailing spaces + Highlight multiple or trailing spaces @@ -3187,58 +3180,58 @@ GuiProjectEditMain - + Project Settings Project Settings - + Working title Working title - + Should be set only once. Should be set only once. - + Novel title Novel title - + Change whenever you want! Change whenever you want! - + Author(s) Author(s) - + One name per line. One name per line. - + Default Default - + Spell check language Spell check language - - + + Overrides main preferences. Overrides main preferences. - + No backup on close No backup on close @@ -3246,27 +3239,27 @@ GuiProjectEditReplace - + Text Replace List for Preview and Export Text Replace List for Preview and Export - + Keyword Keyword - + Replace With Replace With - + Select item to edit Select item to edit - + Save Save @@ -3274,67 +3267,67 @@ GuiProjectEditStatus - + Novel File Status Levels Novel File Status Levels - + Note File Importance Levels Note File Importance Levels - + Label Label - + Usage Usage - + Select item to edit Select item to edit - + Colour Color - + Save Save - + Select Colour Select Color - + New Item New Item - + Cannot delete a status item that is in use. Cannot delete a status item that is in use. - + Not in use Not in use - + Used once Used once - + Used by {0} items Used by {0} items @@ -3406,27 +3399,27 @@ GuiProjectSettings - + Project Settings Project Settings - + Settings Settings - + Status Status - + Importance Importance - + Auto-Replace Auto-Replace @@ -3464,100 +3457,78 @@ Item status - - Please select a valid location in the tree to add the document. - Please select a valid location in the tree to add the document. - - - - Please select a valid location in the tree to add the folder. - Please select a valid location in the tree to add the folder. - - - - + Did not find anywhere to add the file or folder! Did not find anywhere to add the file or folder! - + Cannot add new files or folders to the Trash folder. Cannot add new files or folders to the Trash folder. - - New File - New File + + New Document + New Document - - Cannot add new folder to this item. Maximum folder depth has been reached. - Cannot add new folder to this item. Maximum folder depth has been reached. + + New Note + New Note - + New Folder New Folder - + There is currently no Trash folder in this project. There is currently no Trash folder in this project. - + The Trash folder is already empty. The Trash folder is already empty. - + Empty Trash Empty Trash - + Permanently delete {0} file(s) from Trash? Permanently delete {0} file(s) from Trash? - - - Delete File - Delete File - - - - Permanently delete file '{0}'? - Permanently delete file '{0}'? - - - - Could not delete document file. - Could not delete document file. - - - - Move file '{0}' to Trash? - Move file '{0}' to Trash? - - - - Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - - - + Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first. Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - - - The item cannot be moved to that location. - The item cannot be moved to that location. + + + Delete + Delete - + + Permanently delete '{0}'? + Permanently delete '{0}'? + + + + Move '{0}' to Trash? + Move '{0}' to Trash? + + + + Could not delete document file. + Could not delete document file. + + + There is nowhere to add item with name '{0}'. There is nowhere to add item with name '{0}'. @@ -3565,52 +3536,52 @@ GuiProjectTreeMenu - + Edit Project Item Edit Project Item - + Open Document Open Document - + View Document View Document - + Toggle Included Flag Toggle Included Flag - + New File New File - + New Folder New Folder - + Delete Item Delete Item - + Empty Trash Empty Trash - + Move Item Up Move Item Up - + Move Item Down Move Item Down @@ -3649,6 +3620,39 @@ Download: {0} + + GuiViewsBar + + + Project + Project + + + + Novel + Novel + + + + Outline + Outline + + + + Details + Details + + + + Stats + Stats + + + + Settings + Settings + + GuiWordList @@ -3816,7 +3820,7 @@ Failed to write {0} file. - + Failed to read session log file. Failed to read session log file. @@ -3824,314 +3828,309 @@ NWProject - - Duplicate root item detected. - Duplicate root item detected. - - - - + + New New - + Note Note - + Draft Draft - + Finished Finished - + Minor Minor - + Major Major - + Main Main - + New Project New Project - + By By - - + + Novel Novel - + Plot Plot - + Characters Characters - + World World - - + + Title Page Title Page - - - + + + New Chapter New Chapter - - + + New Scene New Scene - + Chapter {0} Chapter {0} - - + + Scene {0} Scene {0} - + File not found: {0} File not found: {0} - - + + Failed to parse project xml. Failed to parse project xml. - + Attempting to open backup project file instead. Attempting to open backup project file instead. - - + + Unknown Unknown - + Project file does not appear to be a novelWriterXML file. Project file does not appear to be a novelWriterXML file. - + Unknown or unsupported novelWriter project file format. The project cannot be opened by this version of novelWriter. The file was saved with novelWriter version {0}. Unknown or unsupported novelWriter project file format. The project cannot be opened by this version of novelWriter. The file was saved with novelWriter version {0}. - + File Version File Version - + The file format of your project is about to be updated. If you proceed, older versions of novelWriter will no longer be able to open this project. Continue? The file format of your project is about to be updated. If you proceed, older versions of novelWriter will no longer be able to open this project. Continue? - + Version Conflict Version Conflict - + This project was saved by a newer version of novelWriter, version {0}. This is version {1}. If you continue to open the project, some attributes and settings may not be preserved, but the overall project should be fine. Continue opening the project? This project was saved by a newer version of novelWriter, version {0}. This is version {1}. If you continue to open the project, some attributes and settings may not be preserved, but the overall project should be fine. Continue opening the project? - + Opened Project: {0} Opened Project: {0} - + Project path not set, cannot save project. Project path not set, cannot save project. - - + + Failed to save project. Failed to save project. - + Saved Project: {0} Saved Project: {0} - + Backing up project ... Backing up project ... - + Cannot backup project because no valid backup path is set. Please set a valid backup location in Preferences. Cannot backup project because no valid backup path is set. Please set a valid backup location in Preferences. - + Cannot backup project because no project name is set. Please set a Working Title in Project Settings. Cannot backup project because no project name is set. Please set a Working Title in Project Settings. - + Could not create backup folder. Could not create backup folder. - + Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Preferences. Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Preferences. - + Backup from {0} Backup from {0} - + Backup archive file written to: {0} Backup archive file written to: {0} - + Could not write backup archive. Could not write backup archive. - + Project backed up to '{0}' Project backed up to '{0}' - - + + Failed to create a new example project. Failed to create a new example project. - + Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation. Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation. - + Could not create new project folder. Could not create new project folder. - + New project folder is not empty. Each project requires a dedicated project folder. New project folder is not empty. Each project requires a dedicated project folder. - + You must set a valid backup path in Preferences to use the automatic project backup feature. You must set a valid backup path in Preferences to use the automatic project backup feature. - + You must set a valid project name in Project Settings to use the automatic project backup feature. You must set a valid project name in Project Settings to use the automatic project backup feature. - + and and - + Could not create folder. Could not create folder. - + Found {0} orphaned file(s) in project folder. Found {0} orphaned file(s) in project folder. - + Recovered Recovered - + [{0}] {1} [{0}] {1} - + Recovered File {0} Recovered File {0} - + One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists. One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists. - + Not a folder: {0} Not a folder: {0} - + Could not move: {0} Could not move: {0} - - + + Could not delete: {0} Could not delete: {0} - + Could not make folder: {0} Could not make folder: {0} - + Could not move item {0} to {1}. Could not move item {0} to {1}. @@ -4139,47 +4138,47 @@ ProjWizardCustomPage - + Custom Project Options Custom Project Options - + Select which additional root folders to make, and how to populate the Novel folder. If you don't want to add chapters or scenes, set the values to 0. You can add scenes without chapters. Select which additional root folders to make, and how to populate the Novel folder. If you don't want to add chapters or scenes, set the values to 0. You can add scenes without chapters. - + Additional Root Folders Additional Root Folders - - - - - - + + + + + + {0} folder {0} folder - + Populate Novel Folder Populate Novel Folder - + Add chapters Add chapters - + Scenes (per chapter) Scenes (per chapter) - + Add chapter folders Add chapter folders @@ -4187,27 +4186,27 @@ ProjWizardFinalPage - + Finished Finished - + All done. All done. - + Press '{0}' to create the new project. Press '{0}' to create the new project. - + Done Done - + Finish Finish @@ -4215,7 +4214,7 @@ ProjWizardFolderPage - + Select Project Folder Select Project Folder @@ -4231,10 +4230,20 @@ Required - + Project Path Project Path + + + Error: A project folder cannot be created using this path. + Error: A project folder cannot be created using this path. + + + + Error: The selected path already exists. + Error: The selected path already exists. + ProjWizardIntroPage @@ -4287,27 +4296,27 @@ ProjWizardPopulatePage - + Populate Project Populate Project - + Choose how to pre-fill the project. Either with a minimal set of starter items, an example project explaining and showing many of the features, or show further custom options on the next page. Choose how to pre-fill the project. Either with a minimal set of starter items, an example project explaining and showing many of the features, or show further custom options on the next page. - + Fill the project with a minimal set of items Fill the project with a minimal set of items - + Fill the project with example files Fill the project with example files - + Show detailed options for filling the project Show detailed options for filling the project @@ -4503,17 +4512,17 @@ Tokenizer - + Synopsis Synopsis - + Document '{0}' is too big ({1} MB). Skipping. Document '{0}' is too big ({1} MB). Skipping. - + ERROR ERROR diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index a4a6c915..17cb5ddb 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -77,259 +77,259 @@ Constant - - - + + + None Ingen - + Novel Roman - - + + Plot Plott - - + + Characters Karakterer - - + + Locations Lokasjoner - - + + Timeline Tidslinje - - + + Objects Objekter - - + + Entities Enheter - - + + Custom Annet - + Archive Arkiv - + Trash Søppel - - + + Novel Document Romandokument - - + + Project Note Prosjektnotat - + Root Folder Hovedmappe - + Folder Mappe - + Novel Title Page Tittelside - + Novel Chapter Kapittel - + Novel Scene Scene - + Tag Knagg - + Point of View Perspektiv - - + + Focus Fokus - + Title Tittel - + Level Nivå - + Document Dokument - + Line Linje - + Chars Tegn - + Words Ord - + Pars Avsnitt - + POV Persp. - + Synopsis Sammendrag - + Straight single quotation mark Rett, enkelt sitattegn - + Straight double quotation mark Rett, dobbelt sitattegn - + Left single quotation mark Venstre, enkelt sitattegn - + Right single quotation mark Høyre, enkelt sitattegn - + Single low-9 quotation mark Enkelt, lavt-9 sitattegn - + Single high-reversed-9 quotation mark Enkelt, høyt, reversert-9 sitattegn - + Left double quotation mark Venstre, dobbelt sitattegn - + Right double quotation mark Høyre, dobbelt sitattegn - + Double low-9 quotation mark Dobbelt, lavt-9 sitattegn - + Double high-reversed-9 quotation mark Dobbelt, høyt, reversert-9 sitattegn - + Double low-reversed-9 quotation mark Dobbelt, lavt, reversert-9 sitattegn - + Single left-pointing angle quotation mark Enkelt, venstre, angulært sitattegn - + Single right-pointing angle quotation mark Enkelt, høyre, angulært sitattegn - + Double left-pointing angle quotation mark Dobbelt, venstre, angulært sitattegn - + Double right-pointing angle quotation mark Dobbelt, høyre, angulært sitattegn - + Left corner bracket Venstre hjørnevinkel - + Right corner bracket Høyre hjørnevinkel - + Left white corner bracket Venstre, hvit hjørnevinkel - + Right white corner bracket Høyre, hvit hjørnevinkel @@ -353,9 +353,9 @@ Utgivelse - - - + + + Licence Lisens @@ -411,31 +411,31 @@ Oversettelser - + Theme: {0} Tema: {0} - - - - - Author - Ansvarlig - + Author + Ansvarlig + + + + + Credit Kreditert - + Icons: {0} Ikoner: {0} - + Syntax: {0} Syntaks: {0} @@ -718,62 +718,62 @@ Det har oppstått problemer under bygging av prosjektet: - + Open Document Open Document - + Flat Open Document Flat Open Document - + Plain HTML Enkel HTML - + novelWriter Markdown novelWriter Markdown - + Standard Markdown Standard Markdown - + GitHub Markdown GitHub Markdown - + JSON + novelWriter HTML JSON + novelWriter HTML - + JSON + novelWriter Markdown JSON + novelWriter Markdown - + PDF PDF - + Save Document As Lagre dokumentet som - + {0} file successfully written to: Lagring av {0} var vellykket, og filen ble skrevet til: - + Failed to write {0} file. {1} Misslykkes i å skrive {0} til. {1} @@ -781,17 +781,17 @@ GuiBuildNovelDocView - + This area will show the content of the document to be exported or printed. Press the "Build Preview" button to generate content. Dette området vil vise innholdet av dokumentet som skal eksporteres. Trykk på knappen merket med "Lag forhåndsvisning" for å oppdatere innholdet. - + Unknown Ukjent - + Build Time: Bygget: @@ -799,32 +799,32 @@ GuiDocEditFooter - + Status Status - + Line: {0} ({1}) Linje: {0} ({1}) - + Words: {0} ({1}) Ord: {0} ({1}) - + Document size is {0} bytes Dokumentet er {0} byte - + Words: {0} selected Ord: {0} valgt - + Character count: {0} Antall tegn: {0} @@ -832,22 +832,22 @@ GuiDocEditHeader - + Edit document meta Rediger dokumentinstillinger - + Search document Søk i dokumentet - + Toggle Focus Mode Slå av/på "Fokus-modus" - + Close the document Lukk dokumentet @@ -855,58 +855,58 @@ GuiDocEditSearch - - + + Search Søk - + Replace Erstatt - + Case Sensitive Skill store/små bokstaver - + Whole Words Only Kun hele ord - + RegEx Mode RegEx-modus - + Loop Search Søk rundt - + Search Next File Søk i neste file - + Preserve Case Behold store/små bokstaver - + Close Search Lukk søk - + Find in current document Søk i det åpne dokumentet - + Find and replace in current document Søk og erstatt i det åpne dokumentet @@ -914,117 +914,117 @@ GuiDocEditor - + The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB. Dokumentet du prøver å åpne er for stort. Dokumenter er på {0} MB. Den maksimale størrelsen tillat er {1} MB. - + Opened Document: {0} Åpnet dokument: {0} - + The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB. Teksten du forsøker å legge til er for stor. Teksten er {0} MB. Den maksimale tillatte størrelsen er {1} MB. - + File Changed on Disk Filen er endret på disk - + This document has been changed outside of novelWriter while it was open. Overwrite the file on disk? Dette dokumentet er endret utenfor novelWriter mens det var åpent. Overskrive filen på disken? - + Could not save document. Kunne ikke lagre dokumentet. - + Saved Document: {0} Lagret dokument: {0} - + Spell checking requires the package PyEnchant. It does not appear to be installed. Stavekontroll krever at pakken PyEnchant er installert. Det ser det ikke ut til at den er. - + Spell check complete Stavekontrollen er ferdig - + File Location Filens plassering - + The currently open file is saved in: Det åpne dokumentet er lagret på følgende sted: - + The document has grown too big and you cannot add more text to it. The maximum size of a single novelWriter document is {0} MB. Dokumentet har blitt for stort og du kan ikke legge til mer tekst. Den maksimale tillatte størrelsen for et novelWriter-dokument er {0} MB. - + Follow Tag Følg knagg - + Cut Klipp - + Copy Kopier - + Paste Lim inn - + Select All Velg hele teksten - + Select Word Velg hele ordet - + Select Paragraph Velg hele avsnittet - + Spelling Suggestion(s) Forslag fra stavekontrollen - + No Suggestions Ingen forslag - + Add Word to Dictionary Legg til ord i ordbok - + Please select some text before calling replace quotes. Venligst velg en del av teksten før du velger å erstatte sitattegn. @@ -1067,12 +1067,12 @@ Intern feil - + Could not save document. Kunne ikke lagre dokumentet. - + Element selected in the project tree must be a folder. Elementet som er valgt i prosjekttreet må være en mappe. @@ -1080,83 +1080,78 @@ GuiDocSplit - - + + Split Document Del opp dokument - + Document Headers Dokumentets overskrifter - + Select the maximum level to split into files. Velg hvilket nivå av overskrifter å dele opp til. - + Split on Header Level 1 (Title) Del på overskrifter på nivå 1 (titler) - + Split up to Header Level 2 (Chapter) Del på overskrifter opp til nivå 2 (kapitler) - + Split up to Header Level 3 (Scene) Del på overskrifter opp til nivå 3 (scener) - + Split up to Header Level 4 (Section) Del på overskrifter opp til nivå 4 (seksjoner) - + No source document selected. Nothing to do. Ingen kilde-dokument er valgt. Det er ingenting å gjøre. - + Could not parse source document. Klarte ikke å lese kilde-dokumentet. - + Failed to open document file. Kunne ikke åpne dokumentets fil. - + No headers found. Nothing to do. Ingen overskrifter ble funnet i dokumentet. Det er ikke noe å gjøre. - - Cannot add new folder for the document split. Maximum folder depth has been reached. Please move the file to another level in the project tree. - Kan ikke legge til ny mappe for å dele opp dokumentet. Dokumentet har allerede maksimal dybde i prosjekttreet. Flytt dokumentet til et annet nivå først. - - - + The document will be split into {0} file(s) in a new folder. The original document will remain intact. Dokumentet vil nå bli delt opp i {0} nye filer i en ny mappe. Det originale dokumentet vil ikke bli endret eller fjernet. - + Continue with the splitting process? Fortsette med oppdelingen? - + Could not save document. Kunne ikke lagre dokumentet. - + Element selected in the project tree must be a file. Elementet som er valgt i prosjekttreet må være et dokument. @@ -1164,42 +1159,42 @@ GuiDocViewFooter - + Show/hide the references panel Skjul eller vis referanse-panelet - + Activate to freeze the content of the references panel when changing document Aktiver for å fryse innholdet i referanse-panelet ved bytte av vist dokument - + Show comments Vis kommentarer - + Show synopsis comments Vis sammendrag - + References Referanser - + Sticky Hold igjen - + Comments Kommentarer - + Synopsis Sammendrag @@ -1207,22 +1202,22 @@ GuiDocViewHeader - + Go backward Gå bakover - + Go forward Gå fremover - + Reload the document Last dokumentet på nytt - + Close the document Lukk dokumentet @@ -1283,17 +1278,17 @@ Formål - + Characters Tegn - + Words Ord - + Paragraphs Avsnitt @@ -1306,237 +1301,230 @@ Enhetsinstillinger - + Include when building project Ta med ved eksport - + Label Navn - + Status Status - + Layout Format + + GuiLipsum + + + Insert Placeholder Text + Sett inn midlertidig tekst + + + + Insert Lorem Ipsum Text + Sett inn Lorem Ipsum-tekst + + + + Number of paragraphs + Antall avsnitt + + + + Randomise order + Tilfeldig rekkefølge + + + + Insert + Sett inn + + GuiMain - - Project - Prosjekt - - - - Novel - Roman - - - - Project Details - Prosjektdetaljer - - - - Writing Statistics - Statistikk - - - - Project Settings - Prosjektinnstillinger - - - - Editor - Editor - - - - Outline - Disposisjon - - - + You are running an untested development version of novelWriter. Please be careful when working on a live project and make sure you take regular backups. Du kjører nå en utestet versjon av novelWriter. Vær forsiktig om du jobber med et av dine faktiske prosjekter. Husk å ta backup! - + novelWriter is ready ... novelWriter er klar ... - + Cannot create a new project when another project is open. Kan ikke lage et nytt prosjekt mens et annet prosjekt er åpent. - + A project already exists in that location. Please choose another folder. Et prosjekt finnes allerede i den mappen. Vennligst velg et annet sted å lagre prosjektet. - + New project created ... Et nytt prosjekt har blitt opprettet ... - + Close Project Lukk prosjektet - + Close the current project? Ønsker du å lukke dette prosjektet? - - + + Changes are saved automatically. Endringer lagres automatisk. - + Backup Project Sikkerhetskopiering - + Backup the current project? Ønsker du å ta sikkerhetskopi av dette prosjektet? - + The project was locked by the computer '{0}' ({1} {2}), last active on {3}. Prosjektet er låst av datamaskinen {0} ({1} {2}), siste registrerte aktivitet var {3}. - + Project Locked Prosjektlås - + The project is already open by another instance of novelWriter, and is therefore locked. Override lock and continue anyway? Prosjektet er allerede åpent av en annen instans av novelWriter, og er derfor låst. Vil du overstyre denne låsen og fortsette likevel? - + Note: If the program or the computer previously crashed, the lock can safely be overridden. However, overriding it is not recommended if the project is open in another instance of novelWriter. Doing so may corrupt the project. Merk: Hvis programmet eller datamaskinen tidligere krasjet, kan fil-låsen trygt overstyres. Det anbefales imidlertid ikke å overstyre den hvis prosjektet er åpent i en annen instans av novelWriter. Å gjøre det kan skape konflikter i prosjektets filer. - + The project index is outdated or broken. Rebuilding index. Prosjektets indeks er utdatert eller skadet. Bygger indeksen på nytt. - + Text files ({0}) Tekstfiler ({0}) - + Markdown files ({0}) Markdown-filer ({0}) - + novelWriter files ({0}) novelWriter-filer ({0}) - + All files ({0}) Alle filer ({0}) - + Import File Importer fil - + Could not read file. The file must be an existing text file. Kunne ikke lese filen. Filen må eksistere fra før av. - + Please open a document to import the text file into. Vennligst åpne et dokument hvor teksten i filen kan importeres. - + Import Document Importer dokument - + Importing the file will overwrite the current content of the document. Do you want to proceed? Å importere filen vil overskrive all eksisterende tekst i dokumentet. Ønsker du å fortsette? - - + + Indexing: '{0}' Indekserer: '{0}' - + Unknown item Ukjent enhet - + Indexing completed in {0} ms Indekseringen tok {0} ms - + The project index has been successfully rebuilt. Prosjektets indeks har blitt bygget på nytt. - + Information Informasjon - + Warning Advarsel - + Error Feil - + This is a bug! Dette er en systemfeil! - + Internal Error Intern feil - + Exit Avslutt - + Do you want to exit novelWriter? Ønsker du å avslutte novelWriter? @@ -1544,677 +1532,682 @@ GuiMainMenu - + &Project &Prosjekt - + New Project Nytt prosjekt - + Open Project Åpne prosjekt - + Save Project Lagre prosjektet - + Close Project Lukk prosjektet - + Project Settings Prosjektinnstillinger - + Project Details Prosjektdetaljer - + Create Root Folder Lag ny hovedmappe - + Novel Root Mappe for "Roman" - + Plot Root Mappe for "Plott" - + Character Root Mappe for "Karakterer" - + Location Root Mappe for "Lokasjoner" - + Timeline Root Mappe for "Tidslinjer" - + Object Root Mappe for "Objekter" - + Entity Root Mappe for "Enheter" - + Custom Root Mappe for "Annet" - + Archive Root Mappe for Arkiv - + Create Folder Lag ny mappe - + Edit Item Endre enhet - + Delete Item Slett enhet - + Move Item Up Flytt enhet opp - + Move Item Down Flytt enhet ned - + Undo Last Move Angre siste flytting - + Empty Trash Tøm søppel - + Exit Avslutt - + &Document &Dokument - + New Document Nytt dokument - + Open Document Åpne dokument - + Save Document Lagre dokumentet - + Close Document Lukk dokumentet - + View Document Vis dokument - + Close Document View Lukk dokumentvisning - + Show File Details Vis filinformasjon - + Import Text from File Importer tekst fra fil - + Merge Folder to Document Slå sammen mappe - + Split Document to Folder Del opp dokument - + &Edit &Rediger - + Undo Angre - + Redo Gjenopprett - + Cut Klipp - + Copy Kopier - + Paste Lim inn - + Select All Velg hele teksten - + Select Paragraph Velg hele avsnittet - + &View &Vis - + Go to Project Tree Gå til prosjekt-tre - + Go to Document Editor Gå til dokument-editor - + Go to Document Viewer Gå til visningsvindu - + Go to Outline Gå til disposisjon - + Navigate Backward Navigere bakover - + Navigate Forward Navigere fremover - + Focus Mode Focus-modus - + Full Screen Mode Fullskjerm-modus - + &Insert Sett &inn - + Dashes Bindestreker - + Short Dash Kort bindestrek - + Long Dash Lang bindestrek - + Horizontal Bar Horisontal strek - + Figure Dash Tallstrek - + Quote Marks Sitattegn - + Left Single Quote Venstre, enkelt sitattegn - + Right Single Quote Høyre, enkelt sitattegn - + Left Double Quote Venstre, dobbelt sitattegn - + Right Double Quote Høyre, dobbelt sitattegn - + Alternative Apostrophe Alternativ apostrof - + General Punctuation Generell tegnsetting - + Ellipsis Ellipsis - + Prime Primtegn - + Double Prime Dobbelt primtegn - + White Spaces Mellomrom - + Non-Breaking Space Hardt mellomrom - + Thin Space Kort mellomrom - + Thin Non-Breaking Space Hardt, kort mellomrom - + Other Symbols Andre symboler - + List Bullet Kulepunkt - + Hyphen Bullet Bindestrekpunkt - + Flower Mark Blomsterpunkt - + Per Mille Promille - + Degree Symbol Gradertegn - + Minus Sign Minustegn - + Times Sign Gangetegn - + Division Sign Deletegn - + Tags and References Knagger og referanser - + Page Break and Space Sideskift og avstand - + Page Break Sideskift - + Vertical Space (Single) Vertikal avstand (enkel) - + Vertical Space (Multi) Vertikal avstand (flere) - + + Placeholder Text + Midlertidig tekst + + + &Format &Formattering - + Emphasis Kursiv - + Strong Emphasis Uthev - + Strikethrough Gjennomstrek - + Wrap Double Quotes Sett i doble sitattegn - + Wrap Single Quotes Sett i enkle sitattegn - + Header 1 (Partition) Overskrift 1 (inndeling) - + Header 2 (Chapter) Overskrift 2 (kapittel) - + Header 3 (Scene) Overskrift 3 (scene) - + Header 4 (Section) Overskrift 4 (seksjon) - + Novel Title Boktittel - + Unnumbered Chapter Unumrert kapittel - + Align Left Venstrejuster - + Align Centre Sentrer - + Align Right Høyrejuster - + Indent Left Innrykk fra venstre - + Indent Right Innrykk fra høyre - + Toggle Comment Veksle kommentar - + Remove Block Format Fjern formattering - + Convert Single Quotes Konverter enkle sitattegn - + Convert Double Quotes Konverter doble sitattegn - + Remove In-Paragraph Breaks Fjern linjeskift i avsnittet - + &Search &Søk - + Find Søk - + Replace Erstatt - + Find Next Finn neste - + Find Previous Finn forrige - + Replace Next Erstatt neste - + &Tools &Verktøy - + Check Spelling Stavekontroll - + Re-Run Spell Check Kjør stavekontroll - + Project Word List Prosjektets ordliste - + Rebuild Index Bygg indeks - + Rebuild Outline Bygg disposisjon - + Auto-Update Outline Auto-oppdater disposisjon - + Backup Project Lag sikkerhetskopi av prosjektets mappe - + Build Novel Project Bygg prosjektet - + Writing Statistics Statistikk - + Preferences Innstillinger - + &Help &Hjelp - + About novelWriter Om novelWriter - + About Qt5 Om Qt5 - + User Manual (Online) Brukermanual (på nett) - + User Manual (PDF) Brukermanual (PDF) - + Report an Issue (GitHub) Rapporter en feil (GitHub) - + Ask a Question (GitHub) Still et spørsmål (GitHub) - + The novelWriter Website novelWriters nettside - + Check for New Release Sjekk etter oppdateringer @@ -2294,65 +2287,65 @@ GuiOutlineDetails - - - - + + + + Title Tittel - + Chapter Kapittel - + Scene Scene - + Section Seksjon - + Document Dokument - + Status Status - + Characters Tegn - + Words Ord - + Paragraphs Avsnitt - + Synopsis Sammendrag - + Title Details Oversikt - + Reference Tags Referanser @@ -3046,8 +3039,8 @@ - Highlight multiple spaces - Fremheve repeterte mellomrom + Highlight multiple or trailing spaces + Fremhev flere eller etterfølgende mellomrom @@ -3187,58 +3180,58 @@ GuiProjectEditMain - + Project Settings Prosjektinnstillinger - + Working title Arbeidstittel - + Should be set only once. Bør bare settes én gang. - + Novel title Bokens tittel - + Change whenever you want! Kan endres når som helst! - + Author(s) Forfatter(e) - + One name per line. Ett navn per linje. - + Default Ingen valg - + Spell check language Språk for stavekontroll - - + + Overrides main preferences. Overstyrer valg i innstillinger. - + No backup on close Slå av sikkerhetskopi @@ -3246,27 +3239,27 @@ GuiProjectEditReplace - + Text Replace List for Preview and Export Erstatningsliste for forhåndsvisning og eksport - + Keyword Kodeord - + Replace With Erstatt med - + Select item to edit Velg enhet å redigere - + Save Lagre @@ -3274,67 +3267,67 @@ GuiProjectEditStatus - + Novel File Status Levels Statusnivåer i roman-filer - + Note File Importance Levels Viktighetsnivåer i notatfiler - + Label Navn - + Usage Bruk - + Select item to edit Velg enhet å redigere - + Colour Farge - + Save Lagre - + Select Colour Velg farge - + New Item Legg til - + Cannot delete a status item that is in use. Kan ikke slette status som er i bruk. - + Not in use Ikke i bruk - + Used once Brukt ett sted - + Used by {0} items Brukt {0} steder @@ -3406,27 +3399,27 @@ GuiProjectSettings - + Project Settings Prosjektinnstillinger - + Settings Innstillinger - + Status Status - + Importance Viktighet - + Auto-Replace Autoerstatt @@ -3464,100 +3457,78 @@ Filen eller dokumentets status - - Please select a valid location in the tree to add the document. - Du må velge et gyldig sted i prosjekttreet for å legge til dokumentet. - - - - Please select a valid location in the tree to add the folder. - Du må velge et gyldig sted i prosjekttreet for å legge til mappen. - - - - + Did not find anywhere to add the file or folder! Fant ikke noe sted å legge til filen eller mappen! - + Cannot add new files or folders to the Trash folder. Kan ikke legge til nye filer eller mapper til søppel-mappen. - - New File - Ny fil + + New Document + Nytt dokument - - Cannot add new folder to this item. Maximum folder depth has been reached. - Kan ikke legge til ny mappe på dette stedet da maksimum mappe-dypde er nådd. + + New Note + Nytt notat - + New Folder Ny mappe - + There is currently no Trash folder in this project. Det er for øyeblikket ingen søppel-mappe i dette prosjektet. - + The Trash folder is already empty. Søppel-mappen er allerede tom. - + Empty Trash Tøm søppel - + Permanently delete {0} file(s) from Trash? Vil du slette {0} filer i søppel-mappen for godt? - - - Delete File - Slett fil - - - - Permanently delete file '{0}'? - Slette filen {0} for godt'? - - - - Could not delete document file. - Kunne ikke slette dokumentets fil. - - - - Move file '{0}' to Trash? - Vil du flytte filen {0} til søpla? - - - - Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first. - Kan ikke slette mappen da den ikke er tom. Rekursiv sletting er ikke støttet. Du må slette innholdet først. - - - + Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first. Kan ikke slette hovedmappen da den ikke er tom. Rekursiv sletting er ikke støttet. Du må slette innholdet først. - - - The item cannot be moved to that location. - Denne enheten kan ikke flyttes til denne lokasjonen. + + + Delete + Slett - + + Permanently delete '{0}'? + Slette filen "{0}" for godt? + + + + Move '{0}' to Trash? + Vil du flytte filen "{0}" til søpla? + + + + Could not delete document file. + Kunne ikke slette dokumentets fil. + + + There is nowhere to add item with name '{0}'. Fant ikke noe sted å legge til enheten med navn {0}'. @@ -3565,52 +3536,52 @@ GuiProjectTreeMenu - + Edit Project Item Endre enhet - + Open Document Åpne dokument - + View Document Vis dokument - + Toggle Included Flag Slå av/på inkludering - + New File Ny fil - + New Folder Ny mappe - + Delete Item Slett enhet - + Empty Trash Tøm søppel - + Move Item Up Flytt enhet opp - + Move Item Down Flytt enhet ned @@ -3649,6 +3620,39 @@ Last ned: {0} + + GuiViewsBar + + + Project + Prosjekt + + + + Novel + Roman + + + + Outline + Oversikt + + + + Details + Detaljer + + + + Stats + Statistikk + + + + Settings + Oppsett + + GuiWordList @@ -3816,7 +3820,7 @@ Kunne ikke skrive {0}-filen. - + Failed to read session log file. Kunne ikke lese loggfil med skrive-statistikk. @@ -3824,314 +3828,309 @@ NWProject - - Duplicate root item detected. - Duplikat hovedmappe. - - - - + + New Ny - + Note Notat - + Draft Utkast - + Finished Ferdig - + Minor Mindre - + Major Større - + Main Hoved - + New Project Nytt prosjekt - + By Av - - + + Novel Roman - + Plot Plott - + Characters Karakterer - + World Verden - - + + Title Page Tittelside - - - + + + New Chapter Nytt kapittel - - + + New Scene Ny scene - + Chapter {0} Kapittel {0} - - + + Scene {0} Scene {0} - + File not found: {0} Fant ikke filen: {0} - - + + Failed to parse project xml. Kunne ikke lese prosjektets xml-data. - + Attempting to open backup project file instead. Forsøker å åpne prosjektets sekundære prosjektfil istedet. - - + + Unknown Ukjent - + Project file does not appear to be a novelWriterXML file. Prosjektfilen later ikke til å være en novelWriterXML-fil. - + Unknown or unsupported novelWriter project file format. The project cannot be opened by this version of novelWriter. The file was saved with novelWriter version {0}. Prosjektfilen har et ukjent eller ikke støttet format, og kan ikke åpnes med denne versjonen av novelWriter. Prosjektet ble lagret av novelWriter versjon {0}. - + File Version Filversjon - + The file format of your project is about to be updated. If you proceed, older versions of novelWriter will no longer be able to open this project. Continue? Filformatet til prosjektet ditt er i ferd med å bli oppdatert. Hvis du fortsetter, vil ikke eldre versjoner av novelWriter lenger kunne åpne dette prosjektet. Fortsette? - + Version Conflict Versjonskonflikt - + This project was saved by a newer version of novelWriter, version {0}. This is version {1}. If you continue to open the project, some attributes and settings may not be preserved, but the overall project should be fine. Continue opening the project? Dette prosjektet ble lagret av en nyere versjon av novelWriter, versjon {0}. Dette er versjon {1}. Hvis du ønsker å fortsette med å åpne prosjektet, kan noen av innstillingene bli borte, men selve prosjektet vil være i orden. Vil du fortsatt åpne prosjektet? - + Opened Project: {0} Åpnet prosjekt: {0} - + Project path not set, cannot save project. Prosjektet mangler filbane, og kan ikke lagres. - - + + Failed to save project. Kunne ikke lagre prosjektet. - + Saved Project: {0} Lagret prosjekt: {0} - + Backing up project ... Lager sikkerhetskopi ... - + Cannot backup project because no valid backup path is set. Please set a valid backup location in Preferences. Kan ikke ta sikkerhetskopi av prosjektet da ingen filbane er satt. Du må først sette en gyldig filbane i Innstillinger. - + Cannot backup project because no project name is set. Please set a Working Title in Project Settings. Kan ikke ta sikkerhetskopi av prosjektet da ingen arbeidstittel er satt. Du må først sette en arbeidstittel i Prosjektinnstillinger. - + Could not create backup folder. Kunne ikke lage mappe til sikkerhetskopi. - + Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Preferences. Kan ikke ta sikkerhetskopi av prosjektet da filbanen er inne i prosjektmappen. Du må sette en ny filbane i Innstillinger. - + Backup from {0} Sikkerhetskopi fra {0} - + Backup archive file written to: {0} Sikkerhetskopi skrevet til: {0} - + Could not write backup archive. Kunne ikke lage sikkerhetskopi. - + Project backed up to '{0}' Sikkerhetskopi skrevet til '{0}' - - + + Failed to create a new example project. Kunne ikke lage nytt eksempel-prosjekt. - + Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation. Kunne ikke lage nytt eksempel-prosjekt. Kunne ikke finne de nødvendige filene. De ser ut til å mangle i denne installasjonen. - + Could not create new project folder. Kunne ikke lage ny prosjekt-mappe. - + New project folder is not empty. Each project requires a dedicated project folder. Ny prosjektmappe er ikke tom. Hvert prosjekt trenger sin egen mappe. - + You must set a valid backup path in Preferences to use the automatic project backup feature. Du må sette en gyldig filbane i innstillingene for å kunne bruke automatisk sikkerhetskopi. - + You must set a valid project name in Project Settings to use the automatic project backup feature. Du må sette en gyldig arbeidstittel i prosjektinnstillingene for å kunne bruke automatisk sikkerhetskopi. - + and og - + Could not create folder. Kunne ikke opprette mappe. - + Found {0} orphaned file(s) in project folder. Fant {0} tapte filer i prosjektmappen. - + Recovered Gjennopprettet - + [{0}] {1} [{0}] {1} - + Recovered File {0} Gjennopprettet fil {0} - + One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists. Én eller flere gjennopprettede filer kunne ikke bli lagt til i posjektet. Pass på at "Roman"-mappen i det minste eksisterer. - + Not a folder: {0} Ikke en mappe: {0} - + Could not move: {0} Kunne ikke flytte: {0} - - + + Could not delete: {0} Kunne ikke slette: {0} - + Could not make folder: {0} Kunne ikke lage mappe: {0} - + Could not move item {0} to {1}. Kunne ikke flytte {0} til {1}. @@ -4139,47 +4138,47 @@ ProjWizardCustomPage - + Custom Project Options Flere alternativer - + Select which additional root folders to make, and how to populate the Novel folder. If you don't want to add chapters or scenes, set the values to 0. You can add scenes without chapters. Velg hvilke mapper du ønsker i prosjektet, og hvordan du ønsker å fylle hovedmappen for boken. Hvis du ikke ønsker å legge til kapitler og scener, sett verdiene til 0. Du kan også legge til scener uten å legge til kapitler. - + Additional Root Folders Hovedmapper - - - - - - + + + + + + {0} folder {0} - + Populate Novel Folder Fyll roman-mappen - + Add chapters Legg til kapitler - + Scenes (per chapter) Scener (per kapittel) - + Add chapter folders Lag kapittel-mapper @@ -4187,27 +4186,27 @@ ProjWizardFinalPage - + Finished Ferdig - + All done. Alt er klart. - + Press '{0}' to create the new project. Trykk '{0}' for å opprette det nye prosjektet. - + Done Ferdig - + Finish Fullfør @@ -4215,7 +4214,7 @@ ProjWizardFolderPage - + Select Project Folder Velg prosjektmappe @@ -4231,10 +4230,20 @@ Påkrevd - + Project Path Filbane + + + Error: A project folder cannot be created using this path. + Feil: En prosjektmappe kan ikke opprettes ved hjelp av denne banen. + + + + Error: The selected path already exists. + Feil: Den valgte banen finnes allerede. + ProjWizardIntroPage @@ -4287,27 +4296,27 @@ ProjWizardPopulatePage - + Populate Project Fyll prosjektet - + Choose how to pre-fill the project. Either with a minimal set of starter items, an example project explaining and showing many of the features, or show further custom options on the next page. Velg hvordan du vil forhåndsfylle prosjektet. Du kan velge mellom et minimalt sett med mapper og filer, et eksempel-prosjekt som forklarer og viser hvordan du bruker programmet, eller se flere valg på neste side. - + Fill the project with a minimal set of items Fyll prosjektet med et minimalt innhold - + Fill the project with example files Fyll prosjektet med eksempelfiler - + Show detailed options for filling the project Vis detaljerte valg for å fylle prosjektet @@ -4503,17 +4512,17 @@ Tokenizer - + Synopsis Sammendrag - + Document '{0}' is too big ({1} MB). Skipping. Dokumentet '{0}' er for stort ({1} MB). Hopper over. - + ERROR FEIL diff --git a/novelwriter/assets/i18n/project_nl_NL.json b/novelwriter/assets/i18n/project_nl_NL.json index 644da56a..65f4eaca 100644 --- a/novelwriter/assets/i18n/project_nl_NL.json +++ b/novelwriter/assets/i18n/project_nl_NL.json @@ -2,104 +2,104 @@ "Synopsis": "Synopsis", "Comment": "Opmerking", "Notes": "Notities", - "0": "Nul", - "1": "Één", - "2": "Twee", - "3": "Drie", - "4": "Vier", - "5": "Vijf", - "6": "Zes", - "7": "Zeven", - "8": "Acht", - "9": "Negen", - "10": "Tien", - "11": "Elf", - "12": "Twaalf", - "13": "Dertien", - "14": "Veertien", - "15": "Vijftien", - "16": "Zestien", - "17": "Zeventien", - "18": "Achttien", - "19": "Negentien", - "20": "Twintig", - "21": "Eenentwintig", - "22": "Tweeentwintig", - "23": "Drieentwintig", - "24": "Vierentwintig", - "25": "Vijfentwintig", - "26": "Zesentwintig", - "27": "Zevenentwintig", - "28": "Achtentwintig", - "29": "Negenentwintig", - "30": "Dertig", - "31": "Eenendertig", - "32": "Tweeendertig", - "33": "Drieendertig", - "34": "Vierendertig", - "35": "Vijfendertig", - "36": "Zesendertig", - "37": "Zevenendertig", - "38": "Achtendertig", - "39": "Negenendertig", - "40": "Veertig", - "41": "Eenenveertig", - "42": "Tweeënveertig", - "43": "Drieenveertig", - "44": "Vierenveertig", - "45": "Vijfenveertig", - "46": "Zesenveertig", - "47": "Zevenenveertig", - "48": "Achtenveertig", - "49": "Negenenveertig", - "50": "Vijftig", - "51": "Eenenvijftig", - "52": "Tweeenvijftig", - "53": "Drieenvijftig", - "54": "Vierenvijftig", - "55": "Vijfenvijftig", - "56": "Zesenvijftig", - "57": "Zevenenvijftig", - "58": "Achtenvijftig", - "59": "Negenenvijftig", - "60": "Zestig", - "61": "Eenenzestig", - "62": "Tweeenzestig", - "63": "Drieenzestig", - "64": "Vierenzestig", - "65": "Vijfenzestig", - "66": "Zesenzestig", - "67": "Zevenenzestig", - "68": "Achtenzestig", - "69": "Negenenzestig", - "70": "Zeventig", - "71": "Eenenzeventig", - "72": "Tweeenzeventig", - "73": "Drieenzeventig", - "74": "Vierenzeventig", - "75": "Vijfenzeventig", - "76": "Zesenzeventig", - "77": "Zevenenzeventig", - "78": "Achtenzeventig", - "79": "Negenenzeventig", - "80": "Tachtig", - "81": "Eenentachtig", - "82": "Tweeentachtig", - "83": "Drieentachtig", - "84": "Vierentachtig", - "85": "Vijfentachtig", - "86": "Zesentachtig", - "87": "Zevenentachtig", - "88": "Achtentachtig", - "89": "Negenentachtig", - "90": "Negentig", - "91": "Eenennegentig", - "92": "Tweeennegentig", - "93": "Drieennegentig", - "94": "Vierennegentig", - "95": "Vijfennegentig", - "96": "Zesennegentig", - "97": "Zevenennegentig", - "98": "Achtennegentig", - "99": "Negenennegentig" + "0": "nul", + "1": "één", + "2": "twee", + "3": "drie", + "4": "vier", + "5": "vijf", + "6": "zes", + "7": "zeven", + "8": "acht", + "9": "negen", + "10": "tien", + "11": "elf", + "12": "twaalf", + "13": "dertien", + "14": "veertien", + "15": "vijftien", + "16": "zestien", + "17": "zeventien", + "18": "achttien", + "19": "negentien", + "20": "twintig", + "21": "eenentwintig", + "22": "tweeëntwintig", + "23": "drieëntwintig", + "24": "vierentwintig", + "25": "vijfentwintig", + "26": "zesentwintig", + "27": "zevenentwintig", + "28": "achtentwintig", + "29": "negenentwintig", + "30": "dertig", + "31": "eenendertig", + "32": "tweeëndertig", + "33": "drieëndertig", + "34": "vierendertig", + "35": "vijfendertig", + "36": "zesendertig", + "37": "zevenendertig", + "38": "achtendertig", + "39": "negenendertig", + "40": "veertig", + "41": "eenenveertig", + "42": "tweeënveertig", + "43": "drieënveertig", + "44": "vierenveertig", + "45": "vijfenveertig", + "46": "zesenveertig", + "47": "zevenenveertig", + "48": "achtenveertig", + "49": "negenenveertig", + "50": "vijftig", + "51": "eenenvijftig", + "52": "tweeënvijftig", + "53": "drieënvijftig", + "54": "vierenvijftig", + "55": "vijfenvijftig", + "56": "zesenvijftig", + "57": "zevenenvijftig", + "58": "achtenvijftig", + "59": "negenenvijftig", + "60": "zestig", + "61": "eenenzestig", + "62": "tweeënzestig", + "63": "drieënzestig", + "64": "vierenzestig", + "65": "vijfenzestig", + "66": "zesenzestig", + "67": "zevenenzestig", + "68": "achtenzestig", + "69": "negenenzestig", + "70": "zeventig", + "71": "eenenzeventig", + "72": "tweeënzeventig", + "73": "drieënzeventig", + "74": "vierenzeventig", + "75": "vijfenzeventig", + "76": "zesenzeventig", + "77": "zevenenzeventig", + "78": "achtenzeventig", + "79": "negenenzeventig", + "80": "tachtig", + "81": "eenentachtig", + "82": "tweeëntachtig", + "83": "drieëntachtig", + "84": "vierentachtig", + "85": "vijfentachtig", + "86": "zesentachtig", + "87": "zevenentachtig", + "88": "achtentachtig", + "89": "negenentachtig", + "90": "negentig", + "91": "eenennegentig", + "92": "tweeënnegentig", + "93": "drieënnegentig", + "94": "vierennegentig", + "95": "vijfennegentig", + "96": "zesennegentig", + "97": "zevenennegentig", + "98": "achtennegentig", + "99": "negenennegentig" } From ae2b5d4403566b180a6dc17260a6b0f749c278de Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 17 May 2022 20:22:39 +0200 Subject: [PATCH 05/18] Fix typo and set max width on views bar --- novelwriter/gui/viewsbar.py | 2 ++ novelwriter/tools/lipsum.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/novelwriter/gui/viewsbar.py b/novelwriter/gui/viewsbar.py index 92244781..c4dfc476 100644 --- a/novelwriter/gui/viewsbar.py +++ b/novelwriter/gui/viewsbar.py @@ -49,6 +49,7 @@ class GuiViewsBar(QToolBar): # Style iPx = self.mainConf.pxInt(22) + mPx = self.mainConf.pxInt(58) lblFont = self.theTheme.guiFont lblFont.setPointSizeF(0.65*self.theTheme.fontPointSize) @@ -57,6 +58,7 @@ class GuiViewsBar(QToolBar): self.setMovable(False) self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.setIconSize(QSize(iPx, iPx)) + self.setMaximumWidth(mPx) self.setContentsMargins(0, 0, 0, 0) stretch = QWidget(self) diff --git a/novelwriter/tools/lipsum.py b/novelwriter/tools/lipsum.py index a6ac572d..4ce21643 100644 --- a/novelwriter/tools/lipsum.py +++ b/novelwriter/tools/lipsum.py @@ -72,7 +72,7 @@ class GuiLipsum(QDialog): # Form self.headLabel = QLabel("{0}".format(self.tr("Insert Lorem Ipsum Text"))) - self.paraLabel = QLabel(self.tr("Number of pragraphs")) + self.paraLabel = QLabel(self.tr("Number of paragraphs")) self.paraCount = QSpinBox() self.paraCount.setMinimum(1) self.paraCount.setMaximum(100) From a166d9a4ddfd5aa6e28d10d2b01f47a062d7ec61 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Thu, 19 May 2022 20:04:10 +0200 Subject: [PATCH 06/18] Add a Translation Guidelines section in i18n --- i18n/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/i18n/README.md b/i18n/README.md index 27486cf9..b2dd8cc9 100644 --- a/i18n/README.md +++ b/i18n/README.md @@ -2,6 +2,7 @@ The maintenance of translations has been moved to the Crowdin service. The translation strings can be edited there at the [novelWriter project page](https://crowdin.com/project/novelwriter). +However, please read the Translation Guidelines section below. You can still use the manual approach listed below, and then upload the file through the website's interface. The translation strings for that language will then be updated and queued for approval. @@ -11,6 +12,22 @@ To verify a language file translated through the Crowdin tool, download and extr [Generate an Updated Translation File](#generate-an-updated-translation-file) below. +# Translation Guidelines + +When contributing translations, keep the following things in mind. + +* For descriptive labels and dialog boxes, make sure you do _not_ change the meaning of the text + when you translate it from English. The user must receive the same instructions or information + regardless of language. This is improtant, otherwise the documentation will be inconsistent with + the user interface and it will become a lot more difficult to handle user issues and questions. +* If you think a label or description is misleading or incomplete, please file an issue report. The + correct way to handle such changes is to change the text in the code first, which will then be + forwarded to _all_ translators such that the GUI is consistent across all languages. +* For very short labels, like button labels. it may be fine to replace the word with a similar + word, but only as long as the user understands what it is supposed to do. Some buttons and tabs + have limited space. If necessary, it is OK to use abbreviations. + + # Direct Approach Using Qt Linguist Here you will find instructions for translating novelWriter to a new language directly using Qt From 5574d8d6c0826fc19822d0a73f97439a2241fede Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 15:11:33 +0200 Subject: [PATCH 07/18] Update and clarify the options on the Wizard --- novelwriter/tools/projwizard.py | 113 ++++++++++---------------------- 1 file changed, 34 insertions(+), 79 deletions(-) diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index e4cc6862..a5f96d64 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -31,12 +31,10 @@ from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QWizard, QWizardPage, QLabel, QVBoxLayout, QLineEdit, QPlainTextEdit, QPushButton, QFileDialog, QHBoxLayout, QRadioButton, QFormLayout, - QGroupBox, QGridLayout, QSpinBox + QGridLayout, QSpinBox ) -from novelwriter.enum import nwItemClass from novelwriter.common import makeFileNameSafe -from novelwriter.constants import trConst, nwLabels from novelwriter.gui.custom import QSwitch logger = logging.getLogger(__name__) @@ -98,10 +96,10 @@ class ProjWizardIntroPage(QWizardPage): self.setTitle(self.tr("Create New Project")) self.theText = QLabel(self.tr( - "Provide at least a working title. The working title should not " - "be change beyond this point as it is used by the application for " - "generating file names for for instance backups. The other fields " - "are optional and can be changed at any time in Project Settings." + "Provide at least a project name. The project name should not " + "be change beyond this point as it is used for generating file " + "names for for instance backups. The other fields are optional " + "and can be changed at any time in Project Settings." )) self.theText.setWordWrap(True) @@ -134,7 +132,7 @@ class ProjWizardIntroPage(QWizardPage): self.projAuthors.setPlaceholderText(self.tr("Optional. One name per line.")) self.mainForm = QFormLayout() - self.mainForm.addRow(self.tr("Working Title"), self.projName) + self.mainForm.addRow(self.tr("Project Name"), self.projName) self.mainForm.addRow(self.tr("Novel Title"), self.projTitle) self.mainForm.addRow(self.tr("Author(s)"), self.projAuthors) self.mainForm.setVerticalSpacing(fS) @@ -324,68 +322,26 @@ class ProjWizardCustomPage(QWizardPage): self.setTitle(self.tr("Custom Project Options")) self.theText = QLabel(self.tr( - "Select which additional root folders to make, and how to populate " - "the Novel folder. If you don't want to add chapters or scenes, set " - "the values to 0. You can add scenes without chapters." + "Select which additional elements to populate the project with. " + "You can skip making chapters and add only scenes by setting the " + "number of chapters to 0." )) self.theText.setWordWrap(True) vS = self.mainConf.pxInt(12) # Root Folders - self.rootGroup = QGroupBox(self.tr("Additional Root Folders")) - self.rootForm = QGridLayout() - self.rootGroup.setLayout(self.rootForm) - - self.lblPlot = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.PLOT])) - ) - self.lblChar = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.CHARACTER])) - ) - self.lblWorld = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.WORLD])) - ) - self.lblTime = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.TIMELINE])) - ) - self.lblObject = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.OBJECT])) - ) - self.lblEntity = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.ENTITY])) - ) - - self.addPlot = QSwitch() - self.addChar = QSwitch() - self.addWorld = QSwitch() - self.addTime = QSwitch() - self.addObject = QSwitch() - self.addEntity = QSwitch() + self.addPlot = QSwitch() + self.addChar = QSwitch() + self.addWorld = QSwitch() + self.addNotes = QSwitch() self.addPlot.setChecked(True) self.addChar.setChecked(True) - self.addWorld.setChecked(True) - - self.rootForm.addWidget(self.lblPlot, 0, 0) - self.rootForm.addWidget(self.lblChar, 1, 0) - self.rootForm.addWidget(self.lblWorld, 2, 0) - self.rootForm.addWidget(self.lblTime, 3, 0) - self.rootForm.addWidget(self.lblObject, 4, 0) - self.rootForm.addWidget(self.lblEntity, 5, 0) - self.rootForm.addWidget(self.addPlot, 0, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addChar, 1, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addWorld, 2, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addTime, 3, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addObject, 4, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addEntity, 5, 1, 1, 1, Qt.AlignRight) - self.rootForm.setRowStretch(6, 1) - - # Novel Options - self.novelGroup = QGroupBox(self.tr("Populate Novel Folder")) - self.novelForm = QGridLayout() - self.novelGroup.setLayout(self.novelForm) + self.addWorld.setChecked(False) + self.addNotes.setChecked(False) + # Generate Content self.numChapters = QSpinBox() self.numChapters.setRange(0, 100) self.numChapters.setValue(5) @@ -394,37 +350,36 @@ class ProjWizardCustomPage(QWizardPage): self.numScenes.setRange(0, 200) self.numScenes.setValue(5) - self.chFolders = QSwitch() - self.chFolders.setChecked(True) - - self.novelForm.addWidget(QLabel(self.tr("Add chapters")), 0, 0) - self.novelForm.addWidget(QLabel(self.tr("Scenes (per chapter)")), 1, 0) - self.novelForm.addWidget(QLabel(self.tr("Add chapter folders")), 2, 0) - self.novelForm.addWidget(self.numChapters, 0, 1, 1, 1, Qt.AlignRight) - self.novelForm.addWidget(self.numScenes, 1, 1, 1, 1, Qt.AlignRight) - self.novelForm.addWidget(self.chFolders, 2, 1, 1, 1, Qt.AlignRight) - self.novelForm.setRowStretch(3, 1) + # Grid Form + self.addBox = QGridLayout() + self.addBox.addWidget(QLabel(self.tr("Add a folder for plot notes")), 0, 0) + self.addBox.addWidget(QLabel(self.tr("Add a folder for character notes")), 1, 0) + self.addBox.addWidget(QLabel(self.tr("Add a folder for location notes")), 2, 0) + self.addBox.addWidget(QLabel(self.tr("Add example notes to the above")), 3, 0) + self.addBox.addWidget(QLabel(self.tr("Add chapters to the novel folder")), 4, 0) + self.addBox.addWidget(QLabel(self.tr("Add scenes to each chapter")), 5, 0) + self.addBox.addWidget(self.addPlot, 0, 1, 1, 1, Qt.AlignRight) + self.addBox.addWidget(self.addChar, 1, 1, 1, 1, Qt.AlignRight) + self.addBox.addWidget(self.addWorld, 2, 1, 1, 1, Qt.AlignRight) + self.addBox.addWidget(self.addNotes, 3, 1, 1, 1, Qt.AlignRight) + self.addBox.addWidget(self.numChapters, 4, 1, 1, 1, Qt.AlignRight) + self.addBox.addWidget(self.numScenes, 5, 1, 1, 1, Qt.AlignRight) + self.addBox.setRowStretch(6, 1) + self.addBox.setColumnStretch(2, 1) # Wizard Fields self.registerField("addPlot", self.addPlot) self.registerField("addChar", self.addChar) self.registerField("addWorld", self.addWorld) - self.registerField("addTime", self.addTime) - self.registerField("addObject", self.addObject) - self.registerField("addEntity", self.addEntity) + self.registerField("addNotes", self.addNotes) self.registerField("numChapters", self.numChapters) self.registerField("numScenes", self.numScenes) - self.registerField("chFolders", self.chFolders) # Assemble - self.innerBox = QHBoxLayout() - self.innerBox.addWidget(self.rootGroup) - self.innerBox.addWidget(self.novelGroup) - self.outerBox = QVBoxLayout() self.outerBox.setSpacing(vS) self.outerBox.addWidget(self.theText) - self.outerBox.addLayout(self.innerBox) + self.outerBox.addLayout(self.addBox) self.outerBox.addStretch(1) self.setLayout(self.outerBox) From 7a8c97225bb0769fff0bc72e3530e6f58a7067b1 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 15:47:21 +0200 Subject: [PATCH 08/18] Add a summary page to the wizard --- novelwriter/tools/projwizard.py | 68 +++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index a5f96d64..0fceb899 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -328,7 +328,9 @@ class ProjWizardCustomPage(QWizardPage): )) self.theText.setWordWrap(True) - vS = self.mainConf.pxInt(12) + cM = self.mainConf.pxInt(12) + mH = self.mainConf.pxInt(26) + fS = self.mainConf.pxInt(4) # Root Folders self.addPlot = QSwitch() @@ -364,8 +366,12 @@ class ProjWizardCustomPage(QWizardPage): self.addBox.addWidget(self.addNotes, 3, 1, 1, 1, Qt.AlignRight) self.addBox.addWidget(self.numChapters, 4, 1, 1, 1, Qt.AlignRight) self.addBox.addWidget(self.numScenes, 5, 1, 1, 1, Qt.AlignRight) - self.addBox.setRowStretch(6, 1) + self.addBox.setVerticalSpacing(fS) + self.addBox.setHorizontalSpacing(cM) + self.addBox.setContentsMargins(cM, 0, cM, 0) self.addBox.setColumnStretch(2, 1) + for i in range(6): + self.addBox.setRowMinimumHeight(i, mH) # Wizard Fields self.registerField("addPlot", self.addPlot) @@ -377,7 +383,7 @@ class ProjWizardCustomPage(QWizardPage): # Assemble self.outerBox = QVBoxLayout() - self.outerBox.setSpacing(vS) + self.outerBox.setSpacing(cM) self.outerBox.addWidget(self.theText) self.outerBox.addLayout(self.addBox) self.outerBox.addStretch(1) @@ -397,14 +403,7 @@ class ProjWizardFinalPage(QWizardPage): self.theWizard = theWizard self.setTitle(self.tr("Finished")) - self.theText = QLabel( - "

%s

%s

" % ( - self.tr("All done."), - self.tr("Press '{0}' to create the new project.").format( - self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish") - ) - ) - ) + self.theText = QLabel("") self.theText.setWordWrap(True) # Assemble @@ -416,4 +415,51 @@ class ProjWizardFinalPage(QWizardPage): return + def initializePage(self): + """Update the summary information on the final page. + """ + QWizardPage.initializePage(self) + + sumList = [] + sumList.append(self.tr("Project Name: {0}").format(self.field("projName"))) + sumList.append(self.tr("Project Path: {0}").format(self.field("projPath"))) + + if self.field("popMinimal"): + sumList.append(self.tr("Fill the project with a minimal set of items")) + elif self.field("popSample"): + sumList.append(self.tr("Fill the project with example files")) + elif self.field("popCustom"): + if self.field("addPlot"): + sumList.append(self.tr("Add a folder for plot notes")) + if self.field("addChar"): + sumList.append(self.tr("Add a folder for character notes")) + if self.field("addWorld"): + sumList.append(self.tr("Add a folder for location notes")) + if self.field("addNotes"): + sumList.append(self.tr("Add example notes to the above")) + if self.field("numChapters") > 0: + sumList.append(self.tr("Add {0} chapters to the novel folder").format( + self.field("numChapters") + )) + if self.field("numScenes") > 0: + sumList.append(self.tr("Add {0} scenes to each chapter").format( + self.field("numScenes") + )) + else: + if self.field("numScenes") > 0: + sumList.append(self.tr("Add {0} scenes").format( + self.field("numScenes") + )) + + self.theText.setText( + "

%s

 • %s

%s

" % ( + self.tr("Summary"), + "
 • ".join(sumList), + self.tr("Press '{0}' to create the new project.").format( + self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish") + ) + ) + ) + return + # END Class ProjWizardFinalPage From 46dce17dfe51bef274b1231fed1e27c66f094e64 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 16:29:41 +0200 Subject: [PATCH 09/18] Update new project generation to match wizard --- novelwriter/core/project.py | 35 +++++++++++++++++++++-------------- novelwriter/guimain.py | 10 ++-------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 26efb323..fa0bddc9 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -295,11 +295,23 @@ class NWProject(): # and a number of chapters and scenes selected in the # wizard's custom page. + noteTitles = { + nwItemClass.PLOT: self.tr("Main Plot"), + nwItemClass.CHARACTER: self.tr("Protagonist"), + nwItemClass.WORLD: self.tr("Main Location"), + } + # Create root folders nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) + addNotes = projData.get("addNotes", False) for newRoot in projData.get("addRoots", []): if newRoot in nwItemClass: - self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot) + rHandle = self.newRoot(nwLabels.CLASS_NAME[newRoot], newRoot) + if addNotes: + aHandle = self.newFile(noteTitles[newRoot], rHandle) + ntTag = simplified(noteTitles[newRoot]).replace(" ", "") + aDoc = NWDoc(self, aHandle) + aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") # Create a title page tHandle = self.newFile(self.tr("Title Page"), nHandle) @@ -310,38 +322,33 @@ class NWProject(): # Create chapters and scenes numChapters = projData.get("numChapters", 0) numScenes = projData.get("numScenes", 0) - chFolders = projData.get("chFolders", False) + + chSynop = self.tr("Summary of the chapter.") + scSynop = self.tr("Summary of the scene.") # Create chapters if numChapters > 0: for ch in range(numChapters): chTitle = self.tr("Chapter {0}").format(f"{ch+1:d}") - pHandle = nHandle - if chFolders: - pHandle = self.newFolder(chTitle, nHandle) - - cHandle = self.newFile(chTitle, pHandle) - + cHandle = self.newFile(chTitle, nHandle) aDoc = NWDoc(self, cHandle) - aDoc.writeDocument("## %s\n\n" % chTitle) + aDoc.writeDocument(f"## {chTitle}\n\n% Synopsis: {chSynop}\n\n") # Create chapter scenes if numScenes > 0: for sc in range(numScenes): scTitle = self.tr("Scene {0}").format(f"{ch+1:d}.{sc+1:d}") - sHandle = self.newFile(scTitle, pHandle) - + sHandle = self.newFile(scTitle, cHandle) aDoc = NWDoc(self, sHandle) - aDoc.writeDocument("### %s\n\n" % scTitle) + aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") # Create scenes (no chapters) elif numScenes > 0: for sc in range(numScenes): scTitle = self.tr("Scene {0}").format(f"{sc+1:d}") sHandle = self.newFile(scTitle, nHandle) - aDoc = NWDoc(self, sHandle) - aDoc.writeDocument("### %s\n\n" % scTitle) + aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") # Finalise if popCustom or popMinimal: diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index ad06cc59..724989f9 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -1440,9 +1440,9 @@ class GuiMain(QMainWindow): "popMinimal": newProj.field("popMinimal"), "popCustom": newProj.field("popCustom"), "addRoots": [], + "addNotes": False, "numChapters": 0, "numScenes": 0, - "chFolders": False, } if newProj.field("popCustom"): addRoots = [] @@ -1452,16 +1452,10 @@ class GuiMain(QMainWindow): addRoots.append(nwItemClass.CHARACTER) if newProj.field("addWorld"): addRoots.append(nwItemClass.WORLD) - if newProj.field("addTime"): - addRoots.append(nwItemClass.TIMELINE) - if newProj.field("addObject"): - addRoots.append(nwItemClass.OBJECT) - if newProj.field("addEntity"): - addRoots.append(nwItemClass.ENTITY) projData["addRoots"] = addRoots + projData["addNotes"] = newProj.field("addNotes") projData["numChapters"] = newProj.field("numChapters") projData["numScenes"] = newProj.field("numScenes") - projData["chFolders"] = newProj.field("chFolders") return projData From ad42a714277c578747072d246e5dbab04a76204c Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 16:57:09 +0200 Subject: [PATCH 10/18] Fix tests --- novelwriter/core/project.py | 37 ++++---- .../coreProject_NewCustomA_nwProject.nwx | 92 ++++++++----------- .../coreProject_NewCustomB_nwProject.nwx | 64 ++++++------- tests/test_core/test_core_project.py | 14 +-- tests/test_tools/test_tools_projwizard.py | 14 +-- 5 files changed, 96 insertions(+), 125 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index fa0bddc9..d193b4eb 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -295,27 +295,9 @@ class NWProject(): # and a number of chapters and scenes selected in the # wizard's custom page. - noteTitles = { - nwItemClass.PLOT: self.tr("Main Plot"), - nwItemClass.CHARACTER: self.tr("Protagonist"), - nwItemClass.WORLD: self.tr("Main Location"), - } - - # Create root folders + # Create novel folders nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) - addNotes = projData.get("addNotes", False) - for newRoot in projData.get("addRoots", []): - if newRoot in nwItemClass: - rHandle = self.newRoot(nwLabels.CLASS_NAME[newRoot], newRoot) - if addNotes: - aHandle = self.newFile(noteTitles[newRoot], rHandle) - ntTag = simplified(noteTitles[newRoot]).replace(" ", "") - aDoc = NWDoc(self, aHandle) - aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") - - # Create a title page tHandle = self.newFile(self.tr("Title Page"), nHandle) - aDoc = NWDoc(self, tHandle) aDoc.writeDocument(titlePage) @@ -350,6 +332,23 @@ class NWProject(): aDoc = NWDoc(self, sHandle) aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") + # Create notes folders + noteTitles = { + nwItemClass.PLOT: self.tr("Main Plot"), + nwItemClass.CHARACTER: self.tr("Protagonist"), + nwItemClass.WORLD: self.tr("Main Location"), + } + + addNotes = projData.get("addNotes", False) + for newRoot in projData.get("addRoots", []): + if newRoot in nwItemClass: + rHandle = self.newRoot(nwLabels.CLASS_NAME[newRoot], newRoot) + if addNotes: + aHandle = self.newFile(noteTitles[newRoot], rHandle) + ntTag = simplified(noteTitles[newRoot]).replace(" ", "") + aDoc = NWDoc(self, aHandle) + aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") + # Finalise if popCustom or popMinimal: self.projOpened = time() diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx index 14abf9e2..4e201ccd 100644 --- a/tests/reference/coreProject_NewCustomA_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -29,7 +29,7 @@
- New + New Note Draft Finished @@ -41,98 +41,86 @@ Main
- + Novel - - - Plot - - - - Characters - - - - Locations - - - - Timeline - - - - Objects - - - - Entities - - + Title Page - - - Chapter 1 - - + Chapter 1 - + Scene 1.1 - + Scene 1.2 - + Scene 1.3 - - - Chapter 2 - - + Chapter 2 - + Scene 2.1 - + Scene 2.2 - + Scene 2.3 - - - Chapter 3 - - + Chapter 3 - + Scene 3.1 - + Scene 3.2 - + Scene 3.3 + + + Plot + + + + Main Plot + + + + Characters + + + + Protagonist + + + + Locations + + + + Main Location +
diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx index bca6ea80..6b45cbbc 100644 --- a/tests/reference/coreProject_NewCustomB_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -46,57 +46,57 @@ Novel - - - Plot - - - - Characters - - - - Locations - - - - Timeline - - - - Objects - - - - Entities - - + Title Page - + Scene 1 - + Scene 2 - + Scene 3 - + Scene 4 - + Scene 5 - + Scene 6 + + + Plot + + + + Main Plot + + + + Characters + + + + Protagonist + + + + Locations + + + + Main Location + diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 55c18e65..5162e0b9 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -103,13 +103,10 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, mockGUI, mockRnd): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ], + "addNotes": True, "numChapters": 3, "numScenes": 3, - "chFolders": True, } theProject = NWProject(mockGUI) @@ -144,13 +141,10 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, mockGUI, mockRnd): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ], + "addNotes": True, "numChapters": 0, "numScenes": 6, - "chFolders": True, } theProject = NWProject(mockGUI) @@ -1178,10 +1172,6 @@ def testCoreProject_LegacyData(monkeypatch, mockGUI, fncDir): theProject = NWProject(mockGUI) theProject.setProjectPath(fncDir) - # assert theProject.newProject({"projPath": fncDir}) - # assert theProject.saveProject() - # assert theProject.closeProject() - # Check behaviour of deprecated files function on OSError tstFile = os.path.join(fncDir, "ToC.json") writeFile(tstFile, "stuff") diff --git a/tests/test_tools/test_tools_projwizard.py b/tests/test_tools/test_tools_projwizard.py index ef4c31cd..8839964e 100644 --- a/tests/test_tools/test_tools_projwizard.py +++ b/tests/test_tools/test_tools_projwizard.py @@ -205,14 +205,11 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType): customPage.addPlot.setChecked(True) customPage.addChar.setChecked(True) customPage.addWorld.setChecked(True) - customPage.addTime.setChecked(True) - customPage.addObject.setChecked(True) - customPage.addEntity.setChecked(True) + customPage.addNotes.setChecked(True) if prjType == "custom2": customPage.numChapters.setValue(0) customPage.numScenes.setValue(10) - customPage.chFolders.setChecked(False) qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) @@ -240,23 +237,20 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ] if prjType == "custom1": assert projData["numChapters"] == 5 assert projData["numScenes"] == 5 - assert projData["chFolders"] + assert projData["addNotes"] is True else: assert projData["numChapters"] == 0 assert projData["numScenes"] == 10 - assert not projData["chFolders"] + assert projData["addNotes"] is True else: assert projData["addRoots"] == [] assert projData["numChapters"] == 0 assert projData["numScenes"] == 0 - assert not projData["chFolders"] + assert projData["addNotes"] is False # Cleanup nwWiz.reject() From b4ea5bc8d05d93e59cac083b077aa36b4f09b091 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 17:33:36 +0200 Subject: [PATCH 11/18] Update minimal project content --- novelwriter/core/project.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index d193b4eb..9cabb53e 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -277,17 +277,16 @@ class NWProject(): xHandle[3] = self.newRoot(self.tr("Characters"), nwItemClass.CHARACTER) xHandle[4] = self.newRoot(self.tr("World"), nwItemClass.WORLD) xHandle[5] = self.newFile(self.tr("Title Page"), xHandle[1]) - xHandle[6] = self.newFolder(self.tr("New Chapter"), xHandle[1]) - xHandle[7] = self.newFile(self.tr("New Chapter"), xHandle[6]) - xHandle[8] = self.newFile(self.tr("New Scene"), xHandle[6]) + xHandle[6] = self.newFile(self.tr("New Chapter"), xHandle[1]) + xHandle[7] = self.newFile(self.tr("New Scene"), xHandle[6]) aDoc = NWDoc(self, xHandle[5]) aDoc.writeDocument(titlePage) - aDoc = NWDoc(self, xHandle[7]) + aDoc = NWDoc(self, xHandle[6]) aDoc.writeDocument("## %s\n\n" % self.tr("New Chapter")) - aDoc = NWDoc(self, xHandle[8]) + aDoc = NWDoc(self, xHandle[7]) aDoc.writeDocument("### %s\n\n" % self.tr("New Scene")) elif popCustom: From 06d39ea35269b60a7b31cadcc27fc7d1b79af657 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 17:33:58 +0200 Subject: [PATCH 12/18] Make tests not depend on minimal project settings --- .../coreProject_NewFile_nwProject.nwx | 5 +- .../coreProject_NewMinimal_nwProject.nwx | 14 ++--- .../coreProject_NewRoot_nwProject.nwx | 5 +- .../guiEditor_Main_Final_nwProject.nwx | 13 ++--- .../guiEditor_Main_Initial_nwProject.nwx | 13 ++--- .../guiProjSettings_Dialog_nwProject.nwx | 10 ++-- tests/test_core/test_core_project.py | 10 ++-- tests/test_dialogs/test_dlg_docmerge.py | 4 +- tests/test_dialogs/test_dlg_docsplit.py | 4 +- tests/test_dialogs/test_dlg_itemeditor.py | 10 ++-- tests/test_dialogs/test_dlg_projsettings.py | 7 +-- tests/test_gui/test_gui_guimain.py | 14 +++-- tests/test_gui/test_gui_mainmenu.py | 4 +- tests/test_gui/test_gui_projtree.py | 8 +-- tests/test_gui/test_gui_statusbar.py | 8 +-- tests/test_tools/test_tools_lipsum.py | 4 +- tests/test_tools/test_tools_writingstats.py | 4 +- tests/tools.py | 54 +++++++++++++++++++ 18 files changed, 124 insertions(+), 67 deletions(-) diff --git a/tests/reference/coreProject_NewFile_nwProject.nwx b/tests/reference/coreProject_NewFile_nwProject.nwx index d253ebcc..19a2f4bf 100644 --- a/tests/reference/coreProject_NewFile_nwProject.nwx +++ b/tests/reference/coreProject_NewFile_nwProject.nwx @@ -1,8 +1,9 @@ - + New Project - + New Novel + Jane Doe 2 1 0 diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx index a6711a84..68e08580 100644 --- a/tests/reference/coreProject_NewMinimal_nwProject.nwx +++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -27,7 +27,7 @@
- New + New Note Draft Finished @@ -39,7 +39,7 @@ Main - + Novel @@ -60,15 +60,11 @@ Title Page - - - New Chapter - - + New Chapter - + New Scene diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx index 2ab62301..02930a4e 100644 --- a/tests/reference/coreProject_NewRoot_nwProject.nwx +++ b/tests/reference/coreProject_NewRoot_nwProject.nwx @@ -1,8 +1,9 @@ - + New Project - + New Novel + Jane Doe 2 1 0 diff --git a/tests/reference/guiEditor_Main_Final_nwProject.nwx b/tests/reference/guiEditor_Main_Final_nwProject.nwx index c4ba847c..a47d454d 100644 --- a/tests/reference/guiEditor_Main_Final_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Final_nwProject.nwx @@ -1,9 +1,10 @@ - + New Project - - 5 + New Novel + Jane Doe + 4 2 3 @@ -15,8 +16,8 @@ True 000000000000f None - 126 - 99 + 129 + 102 27 @@ -45,7 +46,7 @@ Novel - + Title Page diff --git a/tests/reference/guiEditor_Main_Initial_nwProject.nwx b/tests/reference/guiEditor_Main_Initial_nwProject.nwx index 1a5fd5be..03313570 100644 --- a/tests/reference/guiEditor_Main_Initial_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Initial_nwProject.nwx @@ -1,9 +1,10 @@ - + New Project - - 3 + New Novel + Jane Doe + 2 1 0 @@ -15,8 +16,8 @@ True None None - 6 - 6 + 9 + 9 0 @@ -45,7 +46,7 @@ Novel - + Title Page diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx index 326c63e5..f12c1dc2 100644 --- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx +++ b/tests/reference/guiProjSettings_Dialog_nwProject.nwx @@ -1,11 +1,11 @@ - + Project Name Project Title Jane Doe John Doh - 2 + 1 1 0 @@ -17,8 +17,8 @@ True None None - 6 - 6 + 9 + 9 0 B @@ -51,7 +51,7 @@ Novel - + Title Page diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 5162e0b9..df0638fd 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -26,7 +26,7 @@ from shutil import copyfile from zipfile import ZipFile from lxml import etree -from tools import cmpFiles, writeFile, readFile +from tools import cmpFiles, writeFile, readFile, buildTestProject from mock import causeOSError from novelwriter.core.project import NWProject @@ -252,8 +252,8 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd): compFile = os.path.join(refDir, "coreProject_NewRoot_nwProject.nwx") theProject = NWProject(mockGUI) + buildTestProject(theProject, fncDir) - assert theProject.newProject({"projPath": fncDir}) is True assert theProject.setProjectPath(fncDir) is True assert theProject.saveProject() is True assert theProject.closeProject() is True @@ -288,8 +288,8 @@ def testCoreProject_NewFile(fncDir, outDir, refDir, mockGUI, mockRnd): compFile = os.path.join(refDir, "coreProject_NewFile_nwProject.nwx") theProject = NWProject(mockGUI) + buildTestProject(theProject, fncDir) - assert theProject.newProject({"projPath": fncDir}) is True assert theProject.setProjectPath(fncDir) is True assert theProject.saveProject() is True assert theProject.closeProject() is True @@ -671,7 +671,7 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd): """Test the status and importance flag handling. """ theProject = NWProject(mockGUI) - assert theProject.newProject({"projPath": fncDir}) is True + buildTestProject(theProject, fncDir) statusKeys = ["s000008", "s000009", "s00000a", "s00000b"] importKeys = ["i00000c", "i00000d", "i00000e", "i00000f"] @@ -792,7 +792,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd): """Test other project class methods and functions. """ theProject = NWProject(mockGUI) - assert theProject.newProject({"projPath": fncDir}) is True + buildTestProject(theProject, fncDir) # Setting project path assert theProject.setProjectPath(None) diff --git a/tests/test_dialogs/test_dlg_docmerge.py b/tests/test_dialogs/test_dlg_docmerge.py index f635be4a..a82c77bd 100644 --- a/tests/test_dialogs/test_dlg_docmerge.py +++ b/tests/test_dialogs/test_dlg_docmerge.py @@ -23,7 +23,7 @@ import os import pytest from mock import causeOSError -from tools import getGuiItem, readFile, writeFile +from tools import getGuiItem, readFile, writeFile, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox, QDialog @@ -41,7 +41,7 @@ def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" diff --git a/tests/test_dialogs/test_dlg_docsplit.py b/tests/test_dialogs/test_dlg_docsplit.py index 19988c0b..90e3375d 100644 --- a/tests/test_dialogs/test_dlg_docsplit.py +++ b/tests/test_dialogs/test_dlg_docsplit.py @@ -23,7 +23,7 @@ import os import pytest from mock import causeOSError -from tools import getGuiItem, readFile, writeFile +from tools import getGuiItem, readFile, writeFile, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox, QDialog @@ -42,7 +42,7 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" diff --git a/tests/test_dialogs/test_dlg_itemeditor.py b/tests/test_dialogs/test_dlg_itemeditor.py index ebd71d6c..c221138e 100644 --- a/tests/test_dialogs/test_dlg_itemeditor.py +++ b/tests/test_dialogs/test_dlg_itemeditor.py @@ -21,7 +21,7 @@ along with this program. If not, see . import pytest -from tools import getGuiItem +from tools import getGuiItem, buildTestProject from PyQt5.QtWidgets import QAction, QDialog, QMessageBox @@ -48,7 +48,7 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): assert nwGUI.editItem() is False # Create and Open Project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) tHandle = "000000000000f" # No Selection @@ -99,7 +99,7 @@ def testDlgItemEditor_Novel(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) tHandle = "000000000000f" assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New" @@ -156,7 +156,7 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New" assert nwGUI.theProject.statusItems.name(statusKeys[1]) == "Note" assert nwGUI.theProject.importItems.name(importKeys[0]) == "New" @@ -209,7 +209,7 @@ def testDlgItemEditor_Folder(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) # Edit a Folder itemEdit = GuiItemEditor(nwGUI, "000000000000d") diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projsettings.py index 54827cfd..f193194a 100644 --- a/tests/test_dialogs/test_dlg_projsettings.py +++ b/tests/test_dialogs/test_dlg_projsettings.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles, getGuiItem +from tools import cmpFiles, getGuiItem, buildTestProject from PyQt5.QtGui import QColor from PyQt5.QtCore import Qt @@ -57,7 +57,7 @@ def testDlgProjSettings_Dialog( assert getGuiItem("GuiProjectSettings") is None # Create new project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) nwGUI.mainConf.backupPath = fncDir nwGUI.theProject.setSpellLang("en") @@ -81,7 +81,7 @@ def testDlgProjSettings_Dialog( # ============ assert projEdit.tabMain.editName.text() == "New Project" - assert projEdit.tabMain.editTitle.text() == "" + assert projEdit.tabMain.editTitle.text() == "New Novel" assert projEdit.tabMain.editAuthors.toPlainText() == "Jane Smith\nJohn Smith" assert projEdit.tabMain.spellLang.currentData() == "en" assert projEdit.tabMain.doBackup.isChecked() is False @@ -90,6 +90,7 @@ def testDlgProjSettings_Dialog( projEdit.tabMain.editName.setText("") for c in "Project Name": qtbot.keyClick(projEdit.tabMain.editName, c, delay=typeDelay) + projEdit.tabMain.editTitle.setText("") for c in "Project Title": qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=typeDelay) diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index ddb4f09b..04d43d7f 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles +from tools import cmpFiles, buildTestProject from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMessageBox, QDialog @@ -76,9 +76,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) is True - assert nwGUI.saveProject() is True - # assert False + buildTestProject(nwGUI, fncProj) sHandle = "000000000000f" assert nwGUI.openSelectedItem() is False @@ -139,7 +137,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True) # Create new, save, close project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.saveProject() assert nwGUI.closeProject() @@ -178,9 +176,9 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta") assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projName == "New Project" - assert nwGUI.theProject.bookTitle == "" - assert len(nwGUI.theProject.bookAuthors) == 0 - assert not nwGUI.theProject.spellCheck + assert nwGUI.theProject.bookTitle == "New Novel" + assert len(nwGUI.theProject.bookAuthors) == 1 + assert nwGUI.theProject.spellCheck is False # Check that tree items have been created assert nwGUI.treeView._getTreeItem("0000000000008") is not None diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py index 815c8566..801abd68 100644 --- a/tests/test_gui/test_gui_mainmenu.py +++ b/tests/test_gui/test_gui_mainmenu.py @@ -26,7 +26,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QTextCursor, QTextBlock from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox -from tools import writeFile +from tools import writeFile, buildTestProject from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.enum import nwDocAction, nwDocInsert @@ -465,7 +465,7 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.treeView._getTreeItem("000000000000f") is not None assert nwGUI.openDocument("000000000000f") is True diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py index af851138..5d3354f9 100644 --- a/tests/test_gui/test_gui_projtree.py +++ b/tests/test_gui/test_gui_projtree.py @@ -22,6 +22,8 @@ along with this program. If not, see . import pytest import os +from tools import buildTestProject + from PyQt5.QtWidgets import QAction, QMessageBox from novelwriter.guimain import GuiMain @@ -47,7 +49,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd) # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # No itemType set nwTree.clearSelection() @@ -155,7 +157,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd): # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # Move Documents # ============== @@ -283,7 +285,7 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # Try emptying the trash already now, when there is no trash folder assert nwTree.emptyTrash() is False diff --git a/tests/test_gui/test_gui_statusbar.py b/tests/test_gui/test_gui_statusbar.py index 8993a2e8..51e9c70b 100644 --- a/tests/test_gui/test_gui_statusbar.py +++ b/tests/test_gui/test_gui_statusbar.py @@ -22,6 +22,8 @@ along with this program. If not, see . import time import pytest +from tools import buildTestProject + from PyQt5.QtWidgets import QMessageBox from novelwriter.core import NWDoc @@ -34,7 +36,7 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) cHandle = nwGUI.theProject.newFile("A Note", "000000000000a") newDoc = NWDoc(nwGUI.theProject, cHandle) newDoc.writeDocument("# A Note\n\n") @@ -89,10 +91,10 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): # Project Stats nwGUI.statusBar.mainConf.incNotesWCount = False nwGUI._updateStatusWordCount() - assert nwGUI.statusBar.statsText.text() == "Words: 6 (+6)" + assert nwGUI.statusBar.statsText.text() == "Words: 9 (+9)" nwGUI.statusBar.mainConf.incNotesWCount = True nwGUI._updateStatusWordCount() - assert nwGUI.statusBar.statsText.text() == "Words: 8 (+8)" + assert nwGUI.statusBar.statsText.text() == "Words: 11 (+11)" # qtbot.stopForInteraction() diff --git a/tests/test_tools/test_tools_lipsum.py b/tests/test_tools/test_tools_lipsum.py index 7d6c08f9..629deb56 100644 --- a/tests/test_tools/test_tools_lipsum.py +++ b/tests/test_tools/test_tools_lipsum.py @@ -21,7 +21,7 @@ along with this program. If not, see . import pytest -from tools import getGuiItem +from tools import getGuiItem, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox @@ -40,7 +40,7 @@ def testToolLipsum_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): assert getGuiItem("GuiLipsum") is None # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) assert nwGUI.openDocument("000000000000f") is True assert len(nwGUI.docEditor.getText()) == 15 diff --git a/tests/test_tools/test_tools_writingstats.py b/tests/test_tools/test_tools_writingstats.py index cffef9e6..b7358b20 100644 --- a/tests/test_tools/test_tools_writingstats.py +++ b/tests/test_tools/test_tools_writingstats.py @@ -23,8 +23,8 @@ import pytest import json import os -from tools import getGuiItem, writeFile from mock import causeOSError +from tools import getGuiItem, writeFile, buildTestProject from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox @@ -48,7 +48,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) # Create a project to work on - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) qtbot.wait(100) assert nwGUI.saveProject() sessFile = os.path.join(fncProj, "meta", nwFiles.SESS_STATS) diff --git a/tests/tools.py b/tests/tools.py index bd417aae..a8e2c774 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -20,6 +20,7 @@ along with this program. If not, see . """ import os +import time import shutil from PyQt5.QtWidgets import qApp @@ -119,3 +120,56 @@ def cleanProject(projPath): os.unlink(tocFile) return + + +def buildTestProject(theObject, projPath): + """Build a standard test project in projPath using theProject + object as the parent. + """ + from novelwriter.enum import nwItemClass + from novelwriter.core import NWProject, NWDoc + + if isinstance(theObject, NWProject): + theGUI = None + theProject = theObject + else: + theGUI = theObject + theProject = theObject.theProject + + theProject.clearProject() + theProject.setProjectPath(projPath, newProject=True) + theProject.setProjectName("New Project") + theProject.setBookTitle("New Novel") + theProject.setBookAuthors("Jane Doe") + + # Creating a minimal project with a few root folders and a + # single chapter folder with a single file. + xHandle = {} + xHandle[1] = theProject.newRoot(theProject.tr("Novel"), nwItemClass.NOVEL) + xHandle[2] = theProject.newRoot(theProject.tr("Plot"), nwItemClass.PLOT) + xHandle[3] = theProject.newRoot(theProject.tr("Characters"), nwItemClass.CHARACTER) + xHandle[4] = theProject.newRoot(theProject.tr("World"), nwItemClass.WORLD) + xHandle[5] = theProject.newFile(theProject.tr("Title Page"), xHandle[1]) + xHandle[6] = theProject.newFolder(theProject.tr("New Chapter"), xHandle[1]) + xHandle[7] = theProject.newFile(theProject.tr("New Chapter"), xHandle[6]) + xHandle[8] = theProject.newFile(theProject.tr("New Scene"), xHandle[6]) + + aDoc = NWDoc(theProject, xHandle[5]) + aDoc.writeDocument("#! New Novel\n\n>> By Jane DOe <<\n") + + aDoc = NWDoc(theProject, xHandle[7]) + aDoc.writeDocument("## %s\n\n" % theProject.tr("New Chapter")) + + aDoc = NWDoc(theProject, xHandle[8]) + aDoc.writeDocument("### %s\n\n" % theProject.tr("New Scene")) + + theProject.projOpened = time.time() + theProject.setProjectChanged(True) + theProject.saveProject(autoSave=True) + + if theGUI is not None: + theGUI.hasProject = True + theGUI.rebuildTrees() + theGUI.rebuildIndex(beQuiet=True) + + return From cea22b6147ab5456d0ebd67475a62fe38785ec2b Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 17:58:47 +0200 Subject: [PATCH 13/18] Clean up new project creation function --- novelwriter/core/project.py | 51 ++++++++++--------- .../coreProject_NewCustomA_nwProject.nwx | 16 ++++-- .../coreProject_NewCustomB_nwProject.nwx | 16 ++++-- .../coreProject_NewMinimal_nwProject.nwx | 40 ++++++++------- 4 files changed, 73 insertions(+), 50 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 9cabb53e..0557ce6e 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -264,42 +264,41 @@ class NWProject(): self.setBookTitle(projTitle) self.setBookAuthors(projAuthors) + hNovelRoot = self.newRoot( + trConst(nwLabels.CLASS_NAME[nwItemClass.NOVEL]), nwItemClass.NOVEL + ) + titlePage = "#! %s\n\n" % (self.bookTitle if self.bookTitle else self.projName) if self.bookAuthors: titlePage = "%s>> %s %s <<\n" % (titlePage, self.tr("By"), self.getAuthors()) + hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot) + aDoc = NWDoc(self, hTitlePage) + aDoc.writeDocument(titlePage) + if popMinimal: # Creating a minimal project with a few root folders and a - # single chapter folder with a single file. - xHandle = {} - xHandle[1] = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) - xHandle[2] = self.newRoot(self.tr("Plot"), nwItemClass.PLOT) - xHandle[3] = self.newRoot(self.tr("Characters"), nwItemClass.CHARACTER) - xHandle[4] = self.newRoot(self.tr("World"), nwItemClass.WORLD) - xHandle[5] = self.newFile(self.tr("Title Page"), xHandle[1]) - xHandle[6] = self.newFile(self.tr("New Chapter"), xHandle[1]) - xHandle[7] = self.newFile(self.tr("New Scene"), xHandle[6]) - - aDoc = NWDoc(self, xHandle[5]) - aDoc.writeDocument(titlePage) - - aDoc = NWDoc(self, xHandle[6]) + # single chapter with a single scene. + hChapter = self.newFile(self.tr("New Chapter"), hNovelRoot) + aDoc = NWDoc(self, hChapter) aDoc.writeDocument("## %s\n\n" % self.tr("New Chapter")) - aDoc = NWDoc(self, xHandle[7]) + hScene = self.newFile(self.tr("New Scene"), hChapter) + aDoc = NWDoc(self, hScene) aDoc.writeDocument("### %s\n\n" % self.tr("New Scene")) + minClasses = [ + nwItemClass.PLOT, nwItemClass.CHARACTER, + nwItemClass.WORLD, nwItemClass.ARCHIVE + ] + for minClass in minClasses: + self.newRoot(trConst(nwLabels.CLASS_NAME[minClass]), minClass) + elif popCustom: # Create a project structure based on selected root folders # and a number of chapters and scenes selected in the # wizard's custom page. - # Create novel folders - nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) - tHandle = self.newFile(self.tr("Title Page"), nHandle) - aDoc = NWDoc(self, tHandle) - aDoc.writeDocument(titlePage) - # Create chapters and scenes numChapters = projData.get("numChapters", 0) numScenes = projData.get("numScenes", 0) @@ -311,7 +310,7 @@ class NWProject(): if numChapters > 0: for ch in range(numChapters): chTitle = self.tr("Chapter {0}").format(f"{ch+1:d}") - cHandle = self.newFile(chTitle, nHandle) + cHandle = self.newFile(chTitle, hNovelRoot) aDoc = NWDoc(self, cHandle) aDoc.writeDocument(f"## {chTitle}\n\n% Synopsis: {chSynop}\n\n") @@ -327,7 +326,7 @@ class NWProject(): elif numScenes > 0: for sc in range(numScenes): scTitle = self.tr("Scene {0}").format(f"{sc+1:d}") - sHandle = self.newFile(scTitle, nHandle) + sHandle = self.newFile(scTitle, hNovelRoot) aDoc = NWDoc(self, sHandle) aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") @@ -341,13 +340,17 @@ class NWProject(): addNotes = projData.get("addNotes", False) for newRoot in projData.get("addRoots", []): if newRoot in nwItemClass: - rHandle = self.newRoot(nwLabels.CLASS_NAME[newRoot], newRoot) + rHandle = self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot) if addNotes: aHandle = self.newFile(noteTitles[newRoot], rHandle) ntTag = simplified(noteTitles[newRoot]).replace(" ", "") aDoc = NWDoc(self, aHandle) aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") + # Also add the archive and trash folders + self.newRoot(trConst(nwLabels.CLASS_NAME[nwItemClass.ARCHIVE]), nwItemClass.ARCHIVE) + self.trashFolder() + # Finalise if popCustom or popMinimal: self.projOpened = time() diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx index 4e201ccd..be4845bf 100644 --- a/tests/reference/coreProject_NewCustomA_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -29,19 +29,19 @@
- New + New Note Draft Finished - New + New Minor Major Main - + Novel @@ -122,5 +122,13 @@ Main Location + + + Archive + + + + Trash +
diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx index 6b45cbbc..12f911cd 100644 --- a/tests/reference/coreProject_NewCustomB_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -29,19 +29,19 @@
- New + New Note Draft Finished - New + New Minor Major Main - + Novel @@ -98,5 +98,13 @@ Main Location + + + Archive + + + + Trash +
diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx index 68e08580..422bb6b2 100644 --- a/tests/reference/coreProject_NewMinimal_nwProject.nwx +++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -27,7 +27,7 @@
- New + New Note Draft Finished @@ -39,34 +39,38 @@ Main - + Novel - - - Plot - - - - Characters - - - - World - - + Title Page - + New Chapter - + New Scene + + + Plot + + + + Characters + + + + Locations + + + + Archive +
From 63a3e56cdb2da35c95c5942bd731032ef5a350d8 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 18:15:38 +0200 Subject: [PATCH 14/18] Fix ignored lines in XML comparison --- tests/test_core/test_core_project.py | 18 +++++++++--------- tests/test_gui/test_gui_guimain.py | 6 +++--- tests/tools.py | 2 ++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index df0638fd..4f71b787 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -26,7 +26,7 @@ from shutil import copyfile from zipfile import ZipFile from lxml import etree -from tools import cmpFiles, writeFile, readFile, buildTestProject +from tools import cmpFiles, writeFile, readFile, buildTestProject, XML_IGNORE from mock import causeOSError from novelwriter.core.project import NWProject @@ -67,7 +67,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.saveProject() is True assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # Open a second time @@ -77,7 +77,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.saveProject() is True assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewMinimal @@ -115,7 +115,7 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewCustomA @@ -153,7 +153,7 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewCustomB @@ -273,7 +273,7 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # END Test testCoreProject_NewRoot @@ -302,7 +302,7 @@ def testCoreProject_NewFile(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # END Test testCoreProject_NewFile @@ -483,7 +483,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir): assert theProject.saveProject() is True assert theProject.saveCount == saveCount + 1 assert theProject.autoCount == autoCount - assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # Check that a second save creates a .bak file assert os.path.isfile(backFile) is True @@ -494,7 +494,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir): assert theProject.saveProject(autoSave=True) is True assert theProject.saveCount == saveCount assert theProject.autoCount == autoCount + 1 - assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # Close test project assert theProject.closeProject() diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index 04d43d7f..a52e486e 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles, buildTestProject +from tools import cmpFiles, buildTestProject, XML_IGNORE from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMessageBox, QDialog @@ -158,7 +158,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock testFile = os.path.join(outDir, "guiEditor_Main_Initial_nwProject.nwx") compFile = os.path.join(refDir, "guiEditor_Main_Initial_nwProject.nwx") copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) qtbot.wait(stepDelay) # qtbot.stopForInteraction() @@ -436,7 +436,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock testFile = os.path.join(outDir, "guiEditor_Main_Final_nwProject.nwx") compFile = os.path.join(refDir, "guiEditor_Main_Final_nwProject.nwx") copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) projFile = os.path.join(fncProj, "content", "000000000000f.nwd") testFile = os.path.join(outDir, "guiEditor_Main_Final_000000000000f.nwd") diff --git a/tests/tools.py b/tests/tools.py index a8e2c774..bfdb5140 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -25,6 +25,8 @@ import shutil from PyQt5.QtWidgets import qApp +XML_IGNORE = (" Date: Sat, 21 May 2022 21:55:19 +0200 Subject: [PATCH 15/18] Update test coverage --- tests/test_gui/test_gui_guimain.py | 91 +++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index a52e486e..e0d7e2ec 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles, buildTestProject, XML_IGNORE +from tools import cmpFiles, buildTestProject, XML_IGNORE, writeFile from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMessageBox, QDialog @@ -32,6 +32,7 @@ from novelwriter.gui import ( GuiDocEditor, GuiProjectTree, GuiNovelTree, GuiOutline ) from novelwriter.enum import nwItemType, nwWidget +from novelwriter.tools import GuiProjectWizard from novelwriter.dialogs.itemeditor import GuiItemEditor keyDelay = 2 @@ -70,6 +71,45 @@ def testGuiMain_ProjectBlocker(monkeypatch, nwGUI): # END Test testGuiMain_NoProject +@pytest.mark.gui +def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj): + """Test creating a new project. + """ + monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) + monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) + + # No data + with monkeypatch.context() as mp: + mp.setattr(GuiProjectWizard, "exec_", lambda *a: None) + assert nwGUI.newProject(projData=None) is False + + # Close project + with monkeypatch.context() as mp: + nwGUI.hasProject = True + mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No) + assert nwGUI.newProject(projData={"projPath": fncProj}) is False + + # No project path + assert nwGUI.newProject(projData={}) is False + + # Project file already exists + projFile = os.path.join(fncProj, nwGUI.theProject.projFile) + writeFile(projFile, "Stuff") + assert nwGUI.newProject(projData={"projPath": fncProj}) is False + os.unlink(projFile) + + # An unreachable path should also fail + projPath = os.path.join(fncProj, "stuff", "stuff", "stuff") + assert nwGUI.newProject(projData={"projPath": projPath}) is False + + # This one should work just fine + assert nwGUI.newProject(projData={"projPath": fncProj}) is True + assert os.path.isfile(os.path.join(fncProj, nwGUI.theProject.projFile)) + assert os.path.isdir(os.path.join(fncProj, "content")) + +# END Test testGuiMain_NewProject + + @pytest.mark.gui def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """Test handling of project tree items based on GUI focus states. @@ -465,3 +505,52 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock # qtbot.stopForInteraction() # END Test testGuiMain_Editing + + +@pytest.mark.gui +def testGuiMain_FocusFullMode(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): + """Test toggling focus mode in main window. + """ + monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) + + buildTestProject(nwGUI, fncProj) + assert nwGUI.isFocusMode is False + + # Focus Mode + # ========== + + # No document open, so not allowing focus mode + assert nwGUI.toggleFocusMode() is False + + # Open a file in editor and viewer + assert nwGUI.openDocument("000000000000f") + assert nwGUI.viewDocument("000000000000f") + + # Enable focus mode + assert nwGUI.toggleFocusMode() is True + assert nwGUI.treePane.isVisible() is False + assert nwGUI.statusBar.isVisible() is False + assert nwGUI.mainMenu.isVisible() is False + assert nwGUI.viewsBar.isVisible() is False + assert nwGUI.splitView.isVisible() is False + + # Disable focus mode + assert nwGUI.toggleFocusMode() is True + assert nwGUI.treePane.isVisible() is True + assert nwGUI.statusBar.isVisible() is True + assert nwGUI.mainMenu.isVisible() is True + assert nwGUI.viewsBar.isVisible() is True + assert nwGUI.splitView.isVisible() is True + + # Full Screen Mode + # ================ + + assert nwGUI.mainConf.isFullScreen is False + nwGUI.toggleFullScreenMode() + assert nwGUI.mainConf.isFullScreen is True + nwGUI.toggleFullScreenMode() + assert nwGUI.mainConf.isFullScreen is False + + # qtbot.stopForInteraction() + +# END Test testGuiMain_FocusFullMode From 78b97ce8fb9213c80be379984c1930f3b3c42aff Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 22:10:25 +0200 Subject: [PATCH 16/18] Remove name as a required parameter for new root folders since no part of the GUI uses it --- novelwriter/core/project.py | 42 +++++++++---------- novelwriter/gui/projtree.py | 5 +-- .../coreProject_NewRoot_nwProject.nwx | 12 +++--- tests/test_core/test_core_index.py | 2 +- tests/test_core/test_core_project.py | 16 +++---- tests/tools.py | 16 +++---- 6 files changed, 44 insertions(+), 49 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 0557ce6e..3341e578 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -120,32 +120,34 @@ class NWProject(): # Item Methods ## - def newRoot(self, rootName, rootClass): - """Add a new root item. + def newRoot(self, itemClass, label=None): + """Add a new root item. If label is None, use the class label. """ + if label is None: + label = trConst(nwLabels.CLASS_NAME[itemClass]) newItem = NWItem(self) - newItem.setName(rootName) + newItem.setName(label) newItem.setType(nwItemType.ROOT) - newItem.setClass(rootClass) + newItem.setClass(itemClass) self.projTree.append(None, None, newItem) self.projTree.updateItemData(newItem.itemHandle) return newItem.itemHandle - def newFolder(self, folderName, pHandle): - """Add a new folder with a given name and parent item. + def newFolder(self, label, pHandle): + """Add a new folder with a given label and parent item. """ newItem = NWItem(self) - newItem.setName(folderName) + newItem.setName(label) newItem.setType(nwItemType.FOLDER) self.projTree.append(None, pHandle, newItem) self.projTree.updateItemData(newItem.itemHandle) return newItem.itemHandle - def newFile(self, fileName, pHandle): - """Add a new file with a given name and parent item. + def newFile(self, label, pHandle): + """Add a new file with a given label and parent item. """ newItem = NWItem(self) - newItem.setName(fileName) + newItem.setName(label) newItem.setType(nwItemType.FILE) self.projTree.append(None, pHandle, newItem) self.projTree.updateItemData(newItem.itemHandle) @@ -264,15 +266,13 @@ class NWProject(): self.setBookTitle(projTitle) self.setBookAuthors(projAuthors) - hNovelRoot = self.newRoot( - trConst(nwLabels.CLASS_NAME[nwItemClass.NOVEL]), nwItemClass.NOVEL - ) + hNovelRoot = self.newRoot(nwItemClass.NOVEL) + hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot) titlePage = "#! %s\n\n" % (self.bookTitle if self.bookTitle else self.projName) if self.bookAuthors: titlePage = "%s>> %s %s <<\n" % (titlePage, self.tr("By"), self.getAuthors()) - hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot) aDoc = NWDoc(self, hTitlePage) aDoc.writeDocument(titlePage) @@ -287,12 +287,10 @@ class NWProject(): aDoc = NWDoc(self, hScene) aDoc.writeDocument("### %s\n\n" % self.tr("New Scene")) - minClasses = [ - nwItemClass.PLOT, nwItemClass.CHARACTER, - nwItemClass.WORLD, nwItemClass.ARCHIVE - ] - for minClass in minClasses: - self.newRoot(trConst(nwLabels.CLASS_NAME[minClass]), minClass) + self.newRoot(nwItemClass.PLOT) + self.newRoot(nwItemClass.CHARACTER) + self.newRoot(nwItemClass.WORLD) + self.newRoot(nwItemClass.ARCHIVE) elif popCustom: # Create a project structure based on selected root folders @@ -340,7 +338,7 @@ class NWProject(): addNotes = projData.get("addNotes", False) for newRoot in projData.get("addRoots", []): if newRoot in nwItemClass: - rHandle = self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot) + rHandle = self.newRoot(newRoot) if addNotes: aHandle = self.newFile(noteTitles[newRoot], rHandle) ntTag = simplified(noteTitles[newRoot]).replace(" ", "") @@ -348,7 +346,7 @@ class NWProject(): aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") # Also add the archive and trash folders - self.newRoot(trConst(nwLabels.CLASS_NAME[nwItemClass.ARCHIVE]), nwItemClass.ARCHIVE) + self.newRoot(nwItemClass.ARCHIVE) self.trashFolder() # Finalise diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 0339ec5f..5d40aeae 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -37,7 +37,6 @@ from PyQt5.QtWidgets import ( from novelwriter.core import NWDoc from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert -from novelwriter.constants import trConst, nwLabels logger = logging.getLogger(__name__) @@ -176,9 +175,7 @@ class GuiProjectTree(QTreeWidget): if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass): - tHandle = self.theProject.newRoot( - trConst(nwLabels.CLASS_NAME[itemClass]), itemClass - ) + tHandle = self.theProject.newRoot(itemClass) elif itemType in (nwItemType.FILE, nwItemType.FOLDER): diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx index 02930a4e..cd25c1cf 100644 --- a/tests/reference/coreProject_NewRoot_nwProject.nwx +++ b/tests/reference/coreProject_NewRoot_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project New Novel @@ -83,11 +83,11 @@
- Character + Characters - World + Locations @@ -95,15 +95,15 @@ - Object + Objects - Custom1 + Custom - Custom2 + Custom
diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index c3e6ef47..93ec35c6 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -280,7 +280,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI): assert theIndex.scanText(xHandle, "Hello World!") is False # Create the archive root - aHandle = theProject.newRoot("Archive", nwItemClass.ARCHIVE) + aHandle = theProject.newRoot(nwItemClass.ARCHIVE) assert theProject.projTree[aHandle] is not None xItem.setParent(aHandle) theProject.projTree.updateItemData(xItem.itemHandle) diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 4f71b787..e6e5092d 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -259,14 +259,14 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True assert theProject.openProject(projFile) is True - assert isinstance(theProject.newRoot("Novel", nwItemClass.NOVEL), str) - assert isinstance(theProject.newRoot("Plot", nwItemClass.PLOT), str) - assert isinstance(theProject.newRoot("Character", nwItemClass.CHARACTER), str) - assert isinstance(theProject.newRoot("World", nwItemClass.WORLD), str) - assert isinstance(theProject.newRoot("Timeline", nwItemClass.TIMELINE), str) - assert isinstance(theProject.newRoot("Object", nwItemClass.OBJECT), str) - assert isinstance(theProject.newRoot("Custom1", nwItemClass.CUSTOM), str) - assert isinstance(theProject.newRoot("Custom2", nwItemClass.CUSTOM), str) + assert isinstance(theProject.newRoot(nwItemClass.NOVEL), str) + assert isinstance(theProject.newRoot(nwItemClass.PLOT), str) + assert isinstance(theProject.newRoot(nwItemClass.CHARACTER), str) + assert isinstance(theProject.newRoot(nwItemClass.WORLD), str) + assert isinstance(theProject.newRoot(nwItemClass.TIMELINE), str) + assert isinstance(theProject.newRoot(nwItemClass.OBJECT), str) + assert isinstance(theProject.newRoot(nwItemClass.CUSTOM), str) + assert isinstance(theProject.newRoot(nwItemClass.CUSTOM), str) assert theProject.projChanged is True assert theProject.saveProject() is True diff --git a/tests/tools.py b/tests/tools.py index bfdb5140..fcdd3817 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -147,14 +147,14 @@ def buildTestProject(theObject, projPath): # Creating a minimal project with a few root folders and a # single chapter folder with a single file. xHandle = {} - xHandle[1] = theProject.newRoot(theProject.tr("Novel"), nwItemClass.NOVEL) - xHandle[2] = theProject.newRoot(theProject.tr("Plot"), nwItemClass.PLOT) - xHandle[3] = theProject.newRoot(theProject.tr("Characters"), nwItemClass.CHARACTER) - xHandle[4] = theProject.newRoot(theProject.tr("World"), nwItemClass.WORLD) - xHandle[5] = theProject.newFile(theProject.tr("Title Page"), xHandle[1]) - xHandle[6] = theProject.newFolder(theProject.tr("New Chapter"), xHandle[1]) - xHandle[7] = theProject.newFile(theProject.tr("New Chapter"), xHandle[6]) - xHandle[8] = theProject.newFile(theProject.tr("New Scene"), xHandle[6]) + xHandle[1] = theProject.newRoot(nwItemClass.NOVEL, "Novel") + xHandle[2] = theProject.newRoot(nwItemClass.PLOT, "Plot") + xHandle[3] = theProject.newRoot(nwItemClass.CHARACTER, "Characters") + xHandle[4] = theProject.newRoot(nwItemClass.WORLD, "World") + xHandle[5] = theProject.newFile("Title Page", xHandle[1]) + xHandle[6] = theProject.newFolder("New Chapter", xHandle[1]) + xHandle[7] = theProject.newFile("New Chapter", xHandle[6]) + xHandle[8] = theProject.newFile("New Scene", xHandle[6]) aDoc = NWDoc(theProject, xHandle[5]) aDoc.writeDocument("#! New Novel\n\n>> By Jane DOe <<\n") From e14348a05bb6a69d6a1f873921f7d86b6df45605 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 21 May 2022 22:18:16 +0200 Subject: [PATCH 17/18] Fix a few text labels on the wizard --- novelwriter/tools/projwizard.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index 0fceb899..765445b9 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -97,7 +97,7 @@ class ProjWizardIntroPage(QWizardPage): self.setTitle(self.tr("Create New Project")) self.theText = QLabel(self.tr( "Provide at least a project name. The project name should not " - "be change beyond this point as it is used for generating file " + "be changed beyond this point as it is used for generating file " "names for for instance backups. The other fields are optional " "and can be changed at any time in Project Settings." )) @@ -402,7 +402,7 @@ class ProjWizardFinalPage(QWizardPage): self.mainConf = novelwriter.CONFIG self.theWizard = theWizard - self.setTitle(self.tr("Finished")) + self.setTitle(self.tr("Summary")) self.theText = QLabel("") self.theText.setWordWrap(True) @@ -452,8 +452,8 @@ class ProjWizardFinalPage(QWizardPage): )) self.theText.setText( - "

%s

 • %s

%s

" % ( - self.tr("Summary"), + "

%s

 • %s

%s

" % ( + self.tr("You have selected the following:"), "
 • ".join(sumList), self.tr("Press '{0}' to create the new project.").format( self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish") From a541c906901ca1c638895063090a040090d1a98f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 22 May 2022 15:58:09 +0200 Subject: [PATCH 18/18] Add icon name to xdg mime type just in case (#1068) --- setup/data/x-novelwriter-project.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/data/x-novelwriter-project.xml b/setup/data/x-novelwriter-project.xml index 789c08fd..db045446 100644 --- a/setup/data/x-novelwriter-project.xml +++ b/setup/data/x-novelwriter-project.xml @@ -4,5 +4,6 @@ novelWriter Project +