Merge pull request #760 from vkbo/doc_class

Non-Reusable Document Class
This commit is contained in:
Veronica Berglyd Olsen
2021-05-02 19:53:20 +02:00
committed by GitHub
47 changed files with 1310 additions and 1151 deletions
+150 -138
View File
@@ -793,22 +793,22 @@
<context>
<name>GuiDocEditFooter</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2475"/>
<location filename="../nw/gui/doceditor.py" line="2489"/>
<source>Status</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2616"/>
<location filename="../nw/gui/doceditor.py" line="2630"/>
<source>Line: {0} ({1})</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2632"/>
<location filename="../nw/gui/doceditor.py" line="2646"/>
<source>Words: {0} ({1})</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2637"/>
<location filename="../nw/gui/doceditor.py" line="2651"/>
<source>Document size is {0} bytes</source>
<translation></translation>
</message>
@@ -816,22 +816,22 @@
<context>
<name>GuiDocEditHeader</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2267"/>
<location filename="../nw/gui/doceditor.py" line="2281"/>
<source>Edit document meta</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2278"/>
<location filename="../nw/gui/doceditor.py" line="2292"/>
<source>Search document</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2289"/>
<location filename="../nw/gui/doceditor.py" line="2303"/>
<source>Toggle Focus Mode</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2300"/>
<location filename="../nw/gui/doceditor.py" line="2314"/>
<source>Close the document</source>
<translation></translation>
</message>
@@ -839,97 +839,97 @@
<context>
<name>GuiDocEditSearch</name>
<message>
<location filename="../nw/gui/doceditor.py" line="1895"/>
<location filename="../nw/gui/doceditor.py" line="1909"/>
<source>Search</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1886"/>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<source>Replace</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1899"/>
<location filename="../nw/gui/doceditor.py" line="1913"/>
<source>Case Sensitive</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<location filename="../nw/gui/doceditor.py" line="1914"/>
<source>Match case</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1907"/>
<location filename="../nw/gui/doceditor.py" line="1921"/>
<source>Whole Words Only</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1908"/>
<location filename="../nw/gui/doceditor.py" line="1922"/>
<source>Match whole words</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1915"/>
<location filename="../nw/gui/doceditor.py" line="1929"/>
<source>RegEx Mode</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1916"/>
<location filename="../nw/gui/doceditor.py" line="1930"/>
<source>Search using regular expressions</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1923"/>
<location filename="../nw/gui/doceditor.py" line="1937"/>
<source>Loop Search</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1924"/>
<location filename="../nw/gui/doceditor.py" line="1938"/>
<source>Loop the search when reaching the end</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1931"/>
<location filename="../nw/gui/doceditor.py" line="1945"/>
<source>Search Next File</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1932"/>
<location filename="../nw/gui/doceditor.py" line="1946"/>
<source>Continue searching in the next file</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1941"/>
<location filename="../nw/gui/doceditor.py" line="1955"/>
<source>Preserve Case</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1942"/>
<location filename="../nw/gui/doceditor.py" line="1956"/>
<source>Preserve case on replace</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1951"/>
<location filename="../nw/gui/doceditor.py" line="1965"/>
<source>Close Search</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1952"/>
<location filename="../nw/gui/doceditor.py" line="1966"/>
<source>Close the search box [{0}]</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1964"/>
<location filename="../nw/gui/doceditor.py" line="1978"/>
<source>Show/hide the replace text box</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1970"/>
<location filename="../nw/gui/doceditor.py" line="1984"/>
<source>Find in current document</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1975"/>
<location filename="../nw/gui/doceditor.py" line="1989"/>
<source>Find and replace in current document</source>
<translation></translation>
</message>
@@ -937,99 +937,104 @@
<context>
<name>GuiDocEditor</name>
<message>
<location filename="../nw/gui/doceditor.py" line="308"/>
<location filename="../nw/gui/doceditor.py" line="313"/>
<source>The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="407"/>
<location filename="../nw/gui/doceditor.py" line="411"/>
<source>The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="680"/>
<location filename="../nw/gui/doceditor.py" line="694"/>
<source>Spell check complete</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>File Location</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>The currently open file is saved in:</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="964"/>
<location filename="../nw/gui/doceditor.py" line="978"/>
<source>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.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1002"/>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<source>Follow Tag</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1008"/>
<location filename="../nw/gui/doceditor.py" line="1022"/>
<source>Cut</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1012"/>
<location filename="../nw/gui/doceditor.py" line="1026"/>
<source>Copy</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<location filename="../nw/gui/doceditor.py" line="1030"/>
<source>Paste</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1025"/>
<location filename="../nw/gui/doceditor.py" line="1039"/>
<source>Select All</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1029"/>
<location filename="../nw/gui/doceditor.py" line="1043"/>
<source>Select Word</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1035"/>
<location filename="../nw/gui/doceditor.py" line="1049"/>
<source>Select Paragraph</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1061"/>
<location filename="../nw/gui/doceditor.py" line="1075"/>
<source>Spelling Suggestion(s)</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1073"/>
<location filename="../nw/gui/doceditor.py" line="1087"/>
<source>No Suggestions</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1079"/>
<location filename="../nw/gui/doceditor.py" line="1093"/>
<source>Add Word to Dictionary</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1507"/>
<location filename="../nw/gui/doceditor.py" line="1521"/>
<source>Please select some text before calling replace quotes.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="382"/>
<location filename="../nw/gui/doceditor.py" line="386"/>
<source>Opened Document: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="467"/>
<location filename="../nw/gui/doceditor.py" line="482"/>
<source>Saved Document: {0}</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="458"/>
<source>Could not save document.</source>
<translation></translation>
</message>
</context>
<context>
@@ -1055,25 +1060,35 @@
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="118"/>
<location filename="../nw/dialogs/docmerge.py" line="123"/>
<source>No source document selected. Nothing to do.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="125"/>
<location filename="../nw/dialogs/docmerge.py" line="130"/>
<source>Could not parse source document.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="168"/>
<location filename="../nw/dialogs/docmerge.py" line="177"/>
<source>Element selected in the project tree must be a folder.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="116"/>
<source>Failed to open document file.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="141"/>
<source>Could not save document.</source>
<translation></translation>
</message>
</context>
<context>
<name>GuiDocSplit</name>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Split Document</source>
<translation></translation>
</message>
@@ -1118,30 +1133,40 @@
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="153"/>
<location filename="../nw/dialogs/docsplit.py" line="160"/>
<source>No headers found. Nothing to do.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="161"/>
<location filename="../nw/dialogs/docsplit.py" line="168"/>
<source>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.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>The document will be split into {0} file(s) in a new folder. The original document will remain intact.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Continue with the splitting process?</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="256"/>
<location filename="../nw/dialogs/docsplit.py" line="267"/>
<source>Element selected in the project tree must be a file.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="135"/>
<source>Failed to open document file.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="230"/>
<source>Could not save document.</source>
<translation></translation>
</message>
</context>
<context>
<name>GuiDocViewFooter</name>
@@ -3965,7 +3990,7 @@
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Delete File</source>
<translation></translation>
</message>
@@ -3975,80 +4000,85 @@
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Move file &apos;{0}&apos; to Trash?</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="572"/>
<location filename="../nw/gui/projtree.py" line="577"/>
<source>Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="588"/>
<location filename="../nw/gui/projtree.py" line="593"/>
<source>Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="875"/>
<location filename="../nw/gui/projtree.py" line="880"/>
<source>The item cannot be moved to that location.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="972"/>
<location filename="../nw/gui/projtree.py" line="977"/>
<source>There is nowhere to add item with name &apos;{0}&apos;.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="532"/>
<source>Could not delete document file.</source>
<translation></translation>
</message>
</context>
<context>
<name>GuiProjectTreeMenu</name>
<message>
<location filename="../nw/gui/projtree.py" line="1094"/>
<location filename="../nw/gui/projtree.py" line="1099"/>
<source>Edit Project Item</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1098"/>
<location filename="../nw/gui/projtree.py" line="1103"/>
<source>Open Document</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1102"/>
<location filename="../nw/gui/projtree.py" line="1107"/>
<source>View Document</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1106"/>
<location filename="../nw/gui/projtree.py" line="1111"/>
<source>Toggle Included Flag</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1110"/>
<location filename="../nw/gui/projtree.py" line="1115"/>
<source>New File</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1114"/>
<location filename="../nw/gui/projtree.py" line="1119"/>
<source>New Folder</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1118"/>
<location filename="../nw/gui/projtree.py" line="1123"/>
<source>Delete Item</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1122"/>
<location filename="../nw/gui/projtree.py" line="1127"/>
<source>Empty Trash</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1126"/>
<location filename="../nw/gui/projtree.py" line="1131"/>
<source>Move Item Up</source>
<translation></translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1130"/>
<location filename="../nw/gui/projtree.py" line="1135"/>
<source>Move Item Down</source>
<translation></translation>
</message>
@@ -4237,24 +4267,6 @@
<translation></translation>
</message>
</context>
<context>
<name>NWDoc</name>
<message>
<location filename="../nw/core/document.py" line="118"/>
<source>Failed to open document file.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/document.py" line="162"/>
<source>Could not save document.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/document.py" line="192"/>
<source>Could not delete document file.</source>
<translation></translation>
</message>
</context>
<context>
<name>NWProject</name>
<message>
@@ -4313,242 +4325,242 @@
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="305"/>
<location filename="../nw/core/project.py" line="299"/>
<source>Novel</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="276"/>
<location filename="../nw/core/project.py" line="273"/>
<source>Plot</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="277"/>
<location filename="../nw/core/project.py" line="274"/>
<source>Characters</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="278"/>
<location filename="../nw/core/project.py" line="275"/>
<source>World</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="311"/>
<location filename="../nw/core/project.py" line="305"/>
<source>Title Page</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="292"/>
<location filename="../nw/core/project.py" line="288"/>
<source>New Chapter</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="296"/>
<location filename="../nw/core/project.py" line="291"/>
<source>New Scene</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="326"/>
<location filename="../nw/core/project.py" line="319"/>
<source>Chapter {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="351"/>
<location filename="../nw/core/project.py" line="342"/>
<source>Scene {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="375"/>
<location filename="../nw/core/project.py" line="365"/>
<source>File not found: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="435"/>
<location filename="../nw/core/project.py" line="425"/>
<source>Failed to parse project xml.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="429"/>
<location filename="../nw/core/project.py" line="419"/>
<source>Attempting to open backup project file instead.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="449"/>
<location filename="../nw/core/project.py" line="439"/>
<source>Unknown</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="458"/>
<location filename="../nw/core/project.py" line="448"/>
<source>Project file does not appear to be a novelWriterXML file.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="478"/>
<location filename="../nw/core/project.py" line="468"/>
<source>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}.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>Version Conflict</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>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?</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="592"/>
<location filename="../nw/core/project.py" line="582"/>
<source>Opened Project: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="613"/>
<location filename="../nw/core/project.py" line="603"/>
<source>Project path not set, cannot save project.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="694"/>
<location filename="../nw/core/project.py" line="684"/>
<source>Failed to save project.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="713"/>
<location filename="../nw/core/project.py" line="703"/>
<source>Saved Project: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="765"/>
<location filename="../nw/core/project.py" line="755"/>
<source>Backing up project ...</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="768"/>
<location filename="../nw/core/project.py" line="758"/>
<source>Cannot backup project because no backup path is set. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="777"/>
<location filename="../nw/core/project.py" line="767"/>
<source>Cannot backup project because no project name is set. Please set a Working Title in Project &gt; Project Settings.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="786"/>
<location filename="../nw/core/project.py" line="776"/>
<source>Cannot backup project because the backup path does not exist. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="801"/>
<location filename="../nw/core/project.py" line="791"/>
<source>Could not create backup folder.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="808"/>
<location filename="../nw/core/project.py" line="798"/>
<source>Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Tools &gt; Preferences.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="817"/>
<location filename="../nw/core/project.py" line="807"/>
<source>Backup from {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="826"/>
<location filename="../nw/core/project.py" line="816"/>
<source>Backup archive file written to: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="835"/>
<location filename="../nw/core/project.py" line="825"/>
<source>Could not write backup archive.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="841"/>
<location filename="../nw/core/project.py" line="831"/>
<source>Project backed up to &apos;{0}&apos;</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="889"/>
<location filename="../nw/core/project.py" line="879"/>
<source>Failed to create a new example project.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="894"/>
<location filename="../nw/core/project.py" line="884"/>
<source>Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="929"/>
<location filename="../nw/core/project.py" line="919"/>
<source>Could not create new project folder.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="936"/>
<location filename="../nw/core/project.py" line="926"/>
<source>New project folder is not empty. Each project requires a dedicated project folder.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="988"/>
<location filename="../nw/core/project.py" line="978"/>
<source>You must set a valid backup path in Preferences to use the automatic project backup feature.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="997"/>
<location filename="../nw/core/project.py" line="987"/>
<source>You must set a valid project name in Project Settings to use the automatic project backup feature.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1141"/>
<location filename="../nw/core/project.py" line="1131"/>
<source>and</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1387"/>
<location filename="../nw/core/project.py" line="1377"/>
<source>Found {0} orphaned file(s) in project folder.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1399"/>
<location filename="../nw/core/project.py" line="1388"/>
<source>Recovered</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1411"/>
<location filename="../nw/core/project.py" line="1402"/>
<source>[{0}] {1}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1416"/>
<location filename="../nw/core/project.py" line="1407"/>
<source>Recovered File {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1443"/>
<location filename="../nw/core/project.py" line="1434"/>
<source>One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists.</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1504"/>
<location filename="../nw/core/project.py" line="1495"/>
<source>Not a folder: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1527"/>
<location filename="../nw/core/project.py" line="1518"/>
<source>Could not move: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1551"/>
<location filename="../nw/core/project.py" line="1542"/>
<source>Could not delete: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1563"/>
<location filename="../nw/core/project.py" line="1554"/>
<source>Could not make folder: {0}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1574"/>
<location filename="../nw/core/project.py" line="1565"/>
<source>Could not move item {0} to {1}.</source>
<translation></translation>
</message>
+149 -137
View File
@@ -793,22 +793,22 @@
<context>
<name>GuiDocEditFooter</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2475"/>
<location filename="../nw/gui/doceditor.py" line="2489"/>
<source>Status</source>
<translation>État</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2616"/>
<location filename="../nw/gui/doceditor.py" line="2630"/>
<source>Line: {0} ({1})</source>
<translation>Ligne: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2632"/>
<location filename="../nw/gui/doceditor.py" line="2646"/>
<source>Words: {0} ({1})</source>
<translation>Mots: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2637"/>
<location filename="../nw/gui/doceditor.py" line="2651"/>
<source>Document size is {0} bytes</source>
<translation>La taille du document est de {0} octets</translation>
</message>
@@ -816,22 +816,22 @@
<context>
<name>GuiDocEditHeader</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2267"/>
<location filename="../nw/gui/doceditor.py" line="2281"/>
<source>Edit document meta</source>
<translation>Modifier les métadonnées du document</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2278"/>
<location filename="../nw/gui/doceditor.py" line="2292"/>
<source>Search document</source>
<translation>Chercher dans le document</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2289"/>
<location filename="../nw/gui/doceditor.py" line="2303"/>
<source>Toggle Focus Mode</source>
<translation>Basculer le mode focus</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2300"/>
<location filename="../nw/gui/doceditor.py" line="2314"/>
<source>Close the document</source>
<translation>Fermer le document</translation>
</message>
@@ -839,97 +839,97 @@
<context>
<name>GuiDocEditSearch</name>
<message>
<location filename="../nw/gui/doceditor.py" line="1895"/>
<location filename="../nw/gui/doceditor.py" line="1909"/>
<source>Search</source>
<translation>Chercher</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1886"/>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<source>Replace</source>
<translation>Remplacer</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1899"/>
<location filename="../nw/gui/doceditor.py" line="1913"/>
<source>Case Sensitive</source>
<translation>Sensible à la casse</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<location filename="../nw/gui/doceditor.py" line="1914"/>
<source>Match case</source>
<translation>Respecter la casse</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1907"/>
<location filename="../nw/gui/doceditor.py" line="1921"/>
<source>Whole Words Only</source>
<translation>Mots entiers uniquement</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1908"/>
<location filename="../nw/gui/doceditor.py" line="1922"/>
<source>Match whole words</source>
<translation>Ne vérifier la correspondance que sur des mots entiers</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1915"/>
<location filename="../nw/gui/doceditor.py" line="1929"/>
<source>RegEx Mode</source>
<translation>Expressions régulières</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1916"/>
<location filename="../nw/gui/doceditor.py" line="1930"/>
<source>Search using regular expressions</source>
<translation>Chercher en utilisant des expressions régulières</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1923"/>
<location filename="../nw/gui/doceditor.py" line="1937"/>
<source>Loop Search</source>
<translation>Recherche en boucle</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1924"/>
<location filename="../nw/gui/doceditor.py" line="1938"/>
<source>Loop the search when reaching the end</source>
<translation>Reprendre la recherche au début du texte lorsque la fin est atteinte</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1931"/>
<location filename="../nw/gui/doceditor.py" line="1945"/>
<source>Search Next File</source>
<translation>Chercher dans le fichier suivant</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1932"/>
<location filename="../nw/gui/doceditor.py" line="1946"/>
<source>Continue searching in the next file</source>
<translation>Continuer la recherche dans le fichier suivant</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1941"/>
<location filename="../nw/gui/doceditor.py" line="1955"/>
<source>Preserve Case</source>
<translation>Conserver la casse</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1942"/>
<location filename="../nw/gui/doceditor.py" line="1956"/>
<source>Preserve case on replace</source>
<translation>Conserver la casse lors d&apos;un remplacement</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1951"/>
<location filename="../nw/gui/doceditor.py" line="1965"/>
<source>Close Search</source>
<translation>Terminer la recherche</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1952"/>
<location filename="../nw/gui/doceditor.py" line="1966"/>
<source>Close the search box [{0}]</source>
<translation>Fermer la boîte de recherche [{0}]</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1964"/>
<location filename="../nw/gui/doceditor.py" line="1978"/>
<source>Show/hide the replace text box</source>
<translation>Montrer/cacher le texte de remplacement</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1970"/>
<location filename="../nw/gui/doceditor.py" line="1984"/>
<source>Find in current document</source>
<translation>Chercher dans le document actuel</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1975"/>
<location filename="../nw/gui/doceditor.py" line="1989"/>
<source>Find and replace in current document</source>
<translation>Chercher et remplacer dans le document actuel</translation>
</message>
@@ -937,100 +937,105 @@
<context>
<name>GuiDocEditor</name>
<message>
<location filename="../nw/gui/doceditor.py" line="308"/>
<location filename="../nw/gui/doceditor.py" line="313"/>
<source>The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>Le document que vous essayez d&apos;ouvrir est trop grand. La taille du document est de {0} MB alors que la taille maximale est de {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="407"/>
<location filename="../nw/gui/doceditor.py" line="411"/>
<source>The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>Le texte que vous voulez ajouter est trop grand. La taille du texte est de {0} MB alors que la taille maximale est de {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="680"/>
<location filename="../nw/gui/doceditor.py" line="694"/>
<source>Spell check complete</source>
<translation>La vérification orthographique est terminée</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>File Location</source>
<translation>Emplacement du fichier</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>The currently open file is saved in:</source>
<translation>Le fichier actuellement ouvert est enregistré dans :</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="964"/>
<location filename="../nw/gui/doceditor.py" line="978"/>
<source>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.</source>
<translation>Le document est devenu trop grand et vous ne pouvez plus lui ajouter de texte. La taille maximale d&apos;un fichier novelWriter est de {0} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1002"/>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<source>Follow Tag</source>
<translation>Suivre cette étiquette</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1008"/>
<location filename="../nw/gui/doceditor.py" line="1022"/>
<source>Cut</source>
<translation>Couper</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1012"/>
<location filename="../nw/gui/doceditor.py" line="1026"/>
<source>Copy</source>
<translation>Copier</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<location filename="../nw/gui/doceditor.py" line="1030"/>
<source>Paste</source>
<translation>Coller</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1025"/>
<location filename="../nw/gui/doceditor.py" line="1039"/>
<source>Select All</source>
<translation>Sélectionner tout</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1029"/>
<location filename="../nw/gui/doceditor.py" line="1043"/>
<source>Select Word</source>
<translation>Sélectionner le mot</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1035"/>
<location filename="../nw/gui/doceditor.py" line="1049"/>
<source>Select Paragraph</source>
<translation>Sélectionner le paragraphe</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1061"/>
<location filename="../nw/gui/doceditor.py" line="1075"/>
<source>Spelling Suggestion(s)</source>
<translation>Orthographe suggérée</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1073"/>
<location filename="../nw/gui/doceditor.py" line="1087"/>
<source>No Suggestions</source>
<translation>Pas de suggestion</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1079"/>
<location filename="../nw/gui/doceditor.py" line="1093"/>
<source>Add Word to Dictionary</source>
<translation>Ajouter ce mot au dictionnaire</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1507"/>
<location filename="../nw/gui/doceditor.py" line="1521"/>
<source>Please select some text before calling replace quotes.</source>
<translation>Veuillez sélectionner du texte avant de demander le remplacement des guillemets.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="382"/>
<location filename="../nw/gui/doceditor.py" line="386"/>
<source>Opened Document: {0}</source>
<translation>Document ouvert : {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="467"/>
<location filename="../nw/gui/doceditor.py" line="482"/>
<source>Saved Document: {0}</source>
<translation>Document enregistré : {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="458"/>
<source>Could not save document.</source>
<translation>Impossible d&apos;enregistrer le document.</translation>
</message>
</context>
<context>
<name>GuiDocMerge</name>
@@ -1055,25 +1060,35 @@
<translation>Pas de document source trouvé. Aucune action.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="118"/>
<location filename="../nw/dialogs/docmerge.py" line="123"/>
<source>No source document selected. Nothing to do.</source>
<translation>Pas de document source sélectionné. Aucune action.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="125"/>
<location filename="../nw/dialogs/docmerge.py" line="130"/>
<source>Could not parse source document.</source>
<translation>Impossible d&apos;interpréter le nom du document source.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="168"/>
<location filename="../nw/dialogs/docmerge.py" line="177"/>
<source>Element selected in the project tree must be a folder.</source>
<translation>L&apos;élement selectionné dans l&apos;arborescence doit être un dossier.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="116"/>
<source>Failed to open document file.</source>
<translation>Impossible d&apos;ouvrir le document.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="141"/>
<source>Could not save document.</source>
<translation>Impossible d&apos;enregistrer le document.</translation>
</message>
</context>
<context>
<name>GuiDocSplit</name>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Split Document</source>
<translation>Découper un document</translation>
</message>
@@ -1118,30 +1133,40 @@
<translation>Impossible d&apos;interpréter le nom du document source.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="153"/>
<location filename="../nw/dialogs/docsplit.py" line="160"/>
<source>No headers found. Nothing to do.</source>
<translation>Pas d&apos;en-tête trouvé. Aucune action.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="161"/>
<location filename="../nw/dialogs/docsplit.py" line="168"/>
<source>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.</source>
<translation>Impossible d&apos;ajouter un nouveau dossier lors du découpage. Le nombre maximum de dossiers a é atteint. Veuillez placer ce fichier à un autre niveau dans l&apos;arborescence.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>The document will be split into {0} file(s) in a new folder. The original document will remain intact.</source>
<translation>Ce document va être découpé en {0} fichier(s) dans un nouveau dossier. Le document d&apos;origine restera intact.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Continue with the splitting process?</source>
<translation>Continuer le découpage ?</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="256"/>
<location filename="../nw/dialogs/docsplit.py" line="267"/>
<source>Element selected in the project tree must be a file.</source>
<translation>L&apos;élément sélectionné dans l&apos;arborescence doit être un fichier.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="135"/>
<source>Failed to open document file.</source>
<translation>Impossible d&apos;ouvrir le document.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="230"/>
<source>Could not save document.</source>
<translation>Impossible d&apos;enregistrer le document.</translation>
</message>
</context>
<context>
<name>GuiDocViewFooter</name>
@@ -3965,7 +3990,7 @@
<translation>Effacer définitivement {0} fichier(s) dans la Corbeille ?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Delete File</source>
<translation>Effacer un fichier</translation>
</message>
@@ -3975,80 +4000,85 @@
<translation>Effacer définitivement le fichier &apos;{0}&apos; ?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Move file &apos;{0}&apos; to Trash?</source>
<translation>Mettre le fichier &apos;{0}&apos; dans la Corbeille ?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="572"/>
<location filename="../nw/gui/projtree.py" line="577"/>
<source>Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Impossible d&apos;effacer le dossier car il n&apos;est pas vide. Les effacements récursifs n&apos;étant pas permis vous devez d&apos;abord effacer le contenu.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="588"/>
<location filename="../nw/gui/projtree.py" line="593"/>
<source>Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Impossible d&apos;effacer le dossier racine car il n&apos;est pas vide. Les effacements récursifs n&apos;étant pas permis vous devez d&apos;abord effacer le contenu.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="875"/>
<location filename="../nw/gui/projtree.py" line="880"/>
<source>The item cannot be moved to that location.</source>
<translation>Impossible de déplacer cet item vers cet emplacement.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="972"/>
<location filename="../nw/gui/projtree.py" line="977"/>
<source>There is nowhere to add item with name &apos;{0}&apos;.</source>
<translation>Il n&apos;y a pas d&apos;emplacement pour ajouter l&apos;item nommé &apos;{0}&apos;.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="532"/>
<source>Could not delete document file.</source>
<translation>Impossible d&apos;effacer le document.</translation>
</message>
</context>
<context>
<name>GuiProjectTreeMenu</name>
<message>
<location filename="../nw/gui/projtree.py" line="1094"/>
<location filename="../nw/gui/projtree.py" line="1099"/>
<source>Edit Project Item</source>
<translation>Éditer les caractéristiques</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1098"/>
<location filename="../nw/gui/projtree.py" line="1103"/>
<source>Open Document</source>
<translation>Ouvrir ce document</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1102"/>
<location filename="../nw/gui/projtree.py" line="1107"/>
<source>View Document</source>
<translation>Afficher ce document</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1106"/>
<location filename="../nw/gui/projtree.py" line="1111"/>
<source>Toggle Included Flag</source>
<translation>Basculer le marqueur d&apos;inclusion</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1110"/>
<location filename="../nw/gui/projtree.py" line="1115"/>
<source>New File</source>
<translation>Nouveau fichier</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1114"/>
<location filename="../nw/gui/projtree.py" line="1119"/>
<source>New Folder</source>
<translation>Nouveau dossier</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1118"/>
<location filename="../nw/gui/projtree.py" line="1123"/>
<source>Delete Item</source>
<translation>Supprimer ce composant</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1122"/>
<location filename="../nw/gui/projtree.py" line="1127"/>
<source>Empty Trash</source>
<translation>Vider la corbeille</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1126"/>
<location filename="../nw/gui/projtree.py" line="1131"/>
<source>Move Item Up</source>
<translation>Faire monter ce composant</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1130"/>
<location filename="../nw/gui/projtree.py" line="1135"/>
<source>Move Item Down</source>
<translation>Faire descendre ce composant</translation>
</message>
@@ -4237,24 +4267,6 @@
<translation>Impossible de lire le fichier log de la session.</translation>
</message>
</context>
<context>
<name>NWDoc</name>
<message>
<location filename="../nw/core/document.py" line="118"/>
<source>Failed to open document file.</source>
<translation>Impossible d&apos;ouvrir le document.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="162"/>
<source>Could not save document.</source>
<translation>Impossible d&apos;enregistrer le document.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="192"/>
<source>Could not delete document file.</source>
<translation>Impossible d&apos;effacer le document.</translation>
</message>
</context>
<context>
<name>NWProject</name>
<message>
@@ -4313,242 +4325,242 @@
<translation>Par</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="305"/>
<location filename="../nw/core/project.py" line="299"/>
<source>Novel</source>
<translation>Roman</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="276"/>
<location filename="../nw/core/project.py" line="273"/>
<source>Plot</source>
<translation>Intrigue</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="277"/>
<location filename="../nw/core/project.py" line="274"/>
<source>Characters</source>
<translation>Personnages</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="278"/>
<location filename="../nw/core/project.py" line="275"/>
<source>World</source>
<translation>Monde</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="311"/>
<location filename="../nw/core/project.py" line="305"/>
<source>Title Page</source>
<translation>Page de titre</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="292"/>
<location filename="../nw/core/project.py" line="288"/>
<source>New Chapter</source>
<translation>Nouveau chapitre</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="296"/>
<location filename="../nw/core/project.py" line="291"/>
<source>New Scene</source>
<translation>Nouvelle scène</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="326"/>
<location filename="../nw/core/project.py" line="319"/>
<source>Chapter {0}</source>
<translation>Chapitre{0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="351"/>
<location filename="../nw/core/project.py" line="342"/>
<source>Scene {0}</source>
<translation>Scène {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="375"/>
<location filename="../nw/core/project.py" line="365"/>
<source>File not found: {0}</source>
<translation>Fichier introuvable : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="435"/>
<location filename="../nw/core/project.py" line="425"/>
<source>Failed to parse project xml.</source>
<translation>Impossible de décoder le xml du projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="429"/>
<location filename="../nw/core/project.py" line="419"/>
<source>Attempting to open backup project file instead.</source>
<translation>Essai d&apos;ouverture depuis le fichier de sauvegarde du projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="449"/>
<location filename="../nw/core/project.py" line="439"/>
<source>Unknown</source>
<translation>Inconnu</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="458"/>
<location filename="../nw/core/project.py" line="448"/>
<source>Project file does not appear to be a novelWriterXML file.</source>
<translation>Ce fichier projet ne semble pas être un fichier novelWriterXML.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="478"/>
<location filename="../nw/core/project.py" line="468"/>
<source>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}.</source>
<translation>Format de projet novelWriter inconnu ou non supporté. Ce projet ne peut pas être ouvert avec cette version de novelWriter, il a é enregistré avec novelWriter version {0}.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>Version Conflict</source>
<translation>Conflit de version</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>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?</source>
<translation>Ce projet a é enregistré par une version plus récente de novelWriter, la version {0}. Ceci est la version {1}. Si vous ouvrez quand même ce projet, certaines propriétés ou certains réglages risquent d&apos;être perdus, toutefois le projet dans son ensemble devrait être intact. Voulez-vous quand même ouvrir ce projet ?</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="592"/>
<location filename="../nw/core/project.py" line="582"/>
<source>Opened Project: {0}</source>
<translation>Projet ouvert : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="613"/>
<location filename="../nw/core/project.py" line="603"/>
<source>Project path not set, cannot save project.</source>
<translation>L&apos;emplacement du projet n&apos;est pas défini, il est impossible de l&apos;enregistrer.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="694"/>
<location filename="../nw/core/project.py" line="684"/>
<source>Failed to save project.</source>
<translation>Impossible d&apos;enregistrer le projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="713"/>
<location filename="../nw/core/project.py" line="703"/>
<source>Saved Project: {0}</source>
<translation>Projet enregistré : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="765"/>
<location filename="../nw/core/project.py" line="755"/>
<source>Backing up project ...</source>
<translation>Sauvegarde du projet en cours ...</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="768"/>
<location filename="../nw/core/project.py" line="758"/>
<source>Cannot backup project because no backup path is set. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Il est impossible de sauvegarder le projet car aucun emplacement de sauvegarde n&apos;a é défini. Veuillez en définir un dans Outils &gt; Préférences.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="777"/>
<location filename="../nw/core/project.py" line="767"/>
<source>Cannot backup project because no project name is set. Please set a Working Title in Project &gt; Project Settings.</source>
<translation>Il est impossible de sauvegarder le projet car il n&apos;a pas reçu de nom. Veuillez définir un titre de travail dans Projet &gt; Caractéristiques du projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="786"/>
<location filename="../nw/core/project.py" line="776"/>
<source>Cannot backup project because the backup path does not exist. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Il est impossible de sauvegarder le projet car l&apos;emplacement de sauvegarde défini n&apos;existe pas. Veuillez définir un emplacement correct dans Outils &gt; Préférences.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="801"/>
<location filename="../nw/core/project.py" line="791"/>
<source>Could not create backup folder.</source>
<translation>Il n&apos;a pas é possible de créer le répertoire de sauvegarde.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="808"/>
<location filename="../nw/core/project.py" line="798"/>
<source>Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Tools &gt; Preferences.</source>
<translation>La sauvegarde du projet est impossible car l&apos;emplacement défini est situé dans le dossier à sauvegarder. Veuillez définir un autre répertoire de sauvegarde dans Outils &gt; Préférences.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="817"/>
<location filename="../nw/core/project.py" line="807"/>
<source>Backup from {0}</source>
<translation>Sauvegarde depuis {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="826"/>
<location filename="../nw/core/project.py" line="816"/>
<source>Backup archive file written to: {0}</source>
<translation>Archivage du fichier de sauvegarde effectué en : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="835"/>
<location filename="../nw/core/project.py" line="825"/>
<source>Could not write backup archive.</source>
<translation>Il n&apos;a pas é possible d&apos;écrire l&apos;archive de sauvegarde.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="841"/>
<location filename="../nw/core/project.py" line="831"/>
<source>Project backed up to &apos;{0}&apos;</source>
<translation>Projet sauvegardé en &apos;{0}&apos;</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="889"/>
<location filename="../nw/core/project.py" line="879"/>
<source>Failed to create a new example project.</source>
<translation>Il n&apos;a pas é possible de créer un nouveau projet exemple.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="894"/>
<location filename="../nw/core/project.py" line="884"/>
<source>Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation.</source>
<translation>Il n&apos;a pas é possible de créer un nouveau projet exemple. Il semble que les fichiers nécessaires soient manquants dans cette installation.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="929"/>
<location filename="../nw/core/project.py" line="919"/>
<source>Could not create new project folder.</source>
<translation>Il n&apos;a pas é possible de créer un nouveau dossier de projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="936"/>
<location filename="../nw/core/project.py" line="926"/>
<source>New project folder is not empty. Each project requires a dedicated project folder.</source>
<translation>Le dossier pour le nouveau projet n&apos;est pas vide. Chaque projet doit résider dans un dossier spécifique.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="988"/>
<location filename="../nw/core/project.py" line="978"/>
<source>You must set a valid backup path in Preferences to use the automatic project backup feature.</source>
<translation>Vous devez spécifier un répertoire de sauvegarde valide dans les préférences du projet avant d&apos;utiliser la fonction de sauvegarde automatique.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="997"/>
<location filename="../nw/core/project.py" line="987"/>
<source>You must set a valid project name in Project Settings to use the automatic project backup feature.</source>
<translation>Vous devez spécifier un titre de travail valide dans les préférences du projet avant d&apos;utiliser la fonction de sauvegarde automatique.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1141"/>
<location filename="../nw/core/project.py" line="1131"/>
<source>and</source>
<translation>et</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1387"/>
<location filename="../nw/core/project.py" line="1377"/>
<source>Found {0} orphaned file(s) in project folder.</source>
<translation>Trouvé {0} fichier(s) orphelin(s) dans le dossier du projet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1399"/>
<location filename="../nw/core/project.py" line="1388"/>
<source>Recovered</source>
<translation>Récupéré</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1411"/>
<location filename="../nw/core/project.py" line="1402"/>
<source>[{0}] {1}</source>
<translation>[{0}] {1}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1416"/>
<location filename="../nw/core/project.py" line="1407"/>
<source>Recovered File {0}</source>
<translation>Fichier récupéré {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1443"/>
<location filename="../nw/core/project.py" line="1434"/>
<source>One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists.</source>
<translation>Un ou plusieurs fichiers orphelins n&apos;ont pas pu être repris dans le projet. Vérifiez qu&apos;il y a au moins un dossier racine Roman.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1504"/>
<location filename="../nw/core/project.py" line="1495"/>
<source>Not a folder: {0}</source>
<translation>Pas un dossier : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1527"/>
<location filename="../nw/core/project.py" line="1518"/>
<source>Could not move: {0}</source>
<translation>Pas pu déplacer : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1551"/>
<location filename="../nw/core/project.py" line="1542"/>
<source>Could not delete: {0}</source>
<translation>Pas pu effacer : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1563"/>
<location filename="../nw/core/project.py" line="1554"/>
<source>Could not make folder: {0}</source>
<translation>Pas pu crér le dossier : {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1574"/>
<location filename="../nw/core/project.py" line="1565"/>
<source>Could not move item {0} to {1}.</source>
<translation>Pas pu déplacer l&apos;item {0} vers {1}.</translation>
</message>
+149 -137
View File
@@ -793,22 +793,22 @@
<context>
<name>GuiDocEditFooter</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2475"/>
<location filename="../nw/gui/doceditor.py" line="2489"/>
<source>Status</source>
<translation>Status</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2616"/>
<location filename="../nw/gui/doceditor.py" line="2630"/>
<source>Line: {0} ({1})</source>
<translation>Linje: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2632"/>
<location filename="../nw/gui/doceditor.py" line="2646"/>
<source>Words: {0} ({1})</source>
<translation>Ord: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2637"/>
<location filename="../nw/gui/doceditor.py" line="2651"/>
<source>Document size is {0} bytes</source>
<translation>Dokumentet er {0} byte</translation>
</message>
@@ -816,22 +816,22 @@
<context>
<name>GuiDocEditHeader</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2267"/>
<location filename="../nw/gui/doceditor.py" line="2281"/>
<source>Edit document meta</source>
<translation>Rediger dokumentinstillinger</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2278"/>
<location filename="../nw/gui/doceditor.py" line="2292"/>
<source>Search document</source>
<translation>Søk i dokumentet</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2289"/>
<location filename="../nw/gui/doceditor.py" line="2303"/>
<source>Toggle Focus Mode</source>
<translation>Slå av/ &quot;Fokus-modus&quot;</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2300"/>
<location filename="../nw/gui/doceditor.py" line="2314"/>
<source>Close the document</source>
<translation>Lukk dokumentet</translation>
</message>
@@ -839,97 +839,97 @@
<context>
<name>GuiDocEditSearch</name>
<message>
<location filename="../nw/gui/doceditor.py" line="1895"/>
<location filename="../nw/gui/doceditor.py" line="1909"/>
<source>Search</source>
<translation>Søk</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1886"/>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<source>Replace</source>
<translation>Erstatt</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1899"/>
<location filename="../nw/gui/doceditor.py" line="1913"/>
<source>Case Sensitive</source>
<translation>Skill store/små bokstaver</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<location filename="../nw/gui/doceditor.py" line="1914"/>
<source>Match case</source>
<translation>Søket skiller mellom store og små bokstaver</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1907"/>
<location filename="../nw/gui/doceditor.py" line="1921"/>
<source>Whole Words Only</source>
<translation>Kun hele ord</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1908"/>
<location filename="../nw/gui/doceditor.py" line="1922"/>
<source>Match whole words</source>
<translation>Søk kun etter hele ord</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1915"/>
<location filename="../nw/gui/doceditor.py" line="1929"/>
<source>RegEx Mode</source>
<translation>RegEx-modus</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1916"/>
<location filename="../nw/gui/doceditor.py" line="1930"/>
<source>Search using regular expressions</source>
<translation>Søk ved hjelp av &quot;regular expressions&quot;</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1923"/>
<location filename="../nw/gui/doceditor.py" line="1937"/>
<source>Loop Search</source>
<translation>Søk rundt</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1924"/>
<location filename="../nw/gui/doceditor.py" line="1938"/>
<source>Loop the search when reaching the end</source>
<translation>Begynn søket nytt når enden er nådd</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1931"/>
<location filename="../nw/gui/doceditor.py" line="1945"/>
<source>Search Next File</source>
<translation>Søk i neste file</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1932"/>
<location filename="../nw/gui/doceditor.py" line="1946"/>
<source>Continue searching in the next file</source>
<translation>Fortsett søket i neste fil</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1941"/>
<location filename="../nw/gui/doceditor.py" line="1955"/>
<source>Preserve Case</source>
<translation>Behold store/små bokstaver</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1942"/>
<location filename="../nw/gui/doceditor.py" line="1956"/>
<source>Preserve case on replace</source>
<translation>Behold store og små bokstaver samme sted ved erstatt</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1951"/>
<location filename="../nw/gui/doceditor.py" line="1965"/>
<source>Close Search</source>
<translation>Lukk søk</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1952"/>
<location filename="../nw/gui/doceditor.py" line="1966"/>
<source>Close the search box [{0}]</source>
<translation>Lukk søkeboksen [{0}]</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1964"/>
<location filename="../nw/gui/doceditor.py" line="1978"/>
<source>Show/hide the replace text box</source>
<translation>Vis/skjul erstatt-boksen</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1970"/>
<location filename="../nw/gui/doceditor.py" line="1984"/>
<source>Find in current document</source>
<translation>Søk i det åpne dokumentet</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1975"/>
<location filename="../nw/gui/doceditor.py" line="1989"/>
<source>Find and replace in current document</source>
<translation>Søk og erstatt i det åpne dokumentet</translation>
</message>
@@ -937,100 +937,105 @@
<context>
<name>GuiDocEditor</name>
<message>
<location filename="../nw/gui/doceditor.py" line="308"/>
<location filename="../nw/gui/doceditor.py" line="313"/>
<source>The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>Dokumentet du prøver å åpne er for stort. Dokumenter er {0} MB. Den maksimale størrelsen tillat er {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="407"/>
<location filename="../nw/gui/doceditor.py" line="411"/>
<source>The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>Teksten du forsøker å legge til er for stor. Teksten er {0} MB. Den maksimale tillatte størrelsen er {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="680"/>
<location filename="../nw/gui/doceditor.py" line="694"/>
<source>Spell check complete</source>
<translation>Stavekontrollen er ferdig</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>File Location</source>
<translation>Filens plassering</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>The currently open file is saved in:</source>
<translation>Det åpne dokumentet er lagret følgende sted:</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="964"/>
<location filename="../nw/gui/doceditor.py" line="978"/>
<source>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.</source>
<translation>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.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1002"/>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<source>Follow Tag</source>
<translation>Følg knagg</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1008"/>
<location filename="../nw/gui/doceditor.py" line="1022"/>
<source>Cut</source>
<translation>Klipp</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1012"/>
<location filename="../nw/gui/doceditor.py" line="1026"/>
<source>Copy</source>
<translation>Kopier</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<location filename="../nw/gui/doceditor.py" line="1030"/>
<source>Paste</source>
<translation>Lim inn</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1025"/>
<location filename="../nw/gui/doceditor.py" line="1039"/>
<source>Select All</source>
<translation>Velg hele teksten</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1029"/>
<location filename="../nw/gui/doceditor.py" line="1043"/>
<source>Select Word</source>
<translation>Velg hele ordet</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1035"/>
<location filename="../nw/gui/doceditor.py" line="1049"/>
<source>Select Paragraph</source>
<translation>Velg hele avsnittet</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1061"/>
<location filename="../nw/gui/doceditor.py" line="1075"/>
<source>Spelling Suggestion(s)</source>
<translation>Forslag fra stavekontrollen</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1073"/>
<location filename="../nw/gui/doceditor.py" line="1087"/>
<source>No Suggestions</source>
<translation>Ingen forslag</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1079"/>
<location filename="../nw/gui/doceditor.py" line="1093"/>
<source>Add Word to Dictionary</source>
<translation>Legg til ord i ordbok</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1507"/>
<location filename="../nw/gui/doceditor.py" line="1521"/>
<source>Please select some text before calling replace quotes.</source>
<translation>Venligst velg en del av teksten før du velger å erstatte sitattegn.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="382"/>
<location filename="../nw/gui/doceditor.py" line="386"/>
<source>Opened Document: {0}</source>
<translation>Åpnet dokument: {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="467"/>
<location filename="../nw/gui/doceditor.py" line="482"/>
<source>Saved Document: {0}</source>
<translation>Lagret dokument: {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="458"/>
<source>Could not save document.</source>
<translation>Kunne ikke lagre dokumentet.</translation>
</message>
</context>
<context>
<name>GuiDocMerge</name>
@@ -1055,25 +1060,35 @@
<translation>Ingen kilde-dokument funnet. Det er ingenting å gjøre.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="118"/>
<location filename="../nw/dialogs/docmerge.py" line="123"/>
<source>No source document selected. Nothing to do.</source>
<translation>Ingen kilde-dokument er valgt. Det er ingenting å gjøre.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="125"/>
<location filename="../nw/dialogs/docmerge.py" line="130"/>
<source>Could not parse source document.</source>
<translation>Klarte ikke å lese kilde-dokumentet.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="168"/>
<location filename="../nw/dialogs/docmerge.py" line="177"/>
<source>Element selected in the project tree must be a folder.</source>
<translation>Elementet som er valgt i prosjekttreet være en mappe.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="116"/>
<source>Failed to open document file.</source>
<translation>Kunne ikke åpne dokumentets fil.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="141"/>
<source>Could not save document.</source>
<translation>Kunne ikke lagre dokumentet.</translation>
</message>
</context>
<context>
<name>GuiDocSplit</name>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Split Document</source>
<translation>Del opp dokument</translation>
</message>
@@ -1118,30 +1133,40 @@
<translation>Klarte ikke å lese kilde-dokumentet.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="153"/>
<location filename="../nw/dialogs/docsplit.py" line="160"/>
<source>No headers found. Nothing to do.</source>
<translation>Ingen overskrifter ble funnet i dokumentet. Det er ikke noe å gjøre.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="161"/>
<location filename="../nw/dialogs/docsplit.py" line="168"/>
<source>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.</source>
<translation>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.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>The document will be split into {0} file(s) in a new folder. The original document will remain intact.</source>
<translation>Dokumentet vil bli delt opp i {0} nye filer i en ny mappe. Det originale dokumentet vil ikke bli endret eller fjernet.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Continue with the splitting process?</source>
<translation>Fortsette med oppdelingen?</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="256"/>
<location filename="../nw/dialogs/docsplit.py" line="267"/>
<source>Element selected in the project tree must be a file.</source>
<translation>Elementet som er valgt i prosjekttreet være et dokument.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="135"/>
<source>Failed to open document file.</source>
<translation>Kunne ikke åpne dokumentets fil.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="230"/>
<source>Could not save document.</source>
<translation>Kunne ikke lagre dokumentet.</translation>
</message>
</context>
<context>
<name>GuiDocViewFooter</name>
@@ -3960,7 +3985,7 @@
<translation>Vil du slette {0} filer i søppel-mappen for godt?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Delete File</source>
<translation>Slett fil</translation>
</message>
@@ -3970,22 +3995,22 @@
<translation>Slette filen &apos;{0}&apos; for godt?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Move file &apos;{0}&apos; to Trash?</source>
<translation>Vil du flytte filen &apos;{0}&apos; til søpla?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="572"/>
<location filename="../nw/gui/projtree.py" line="577"/>
<source>Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Kan ikke slette mappen da den ikke er tom. Rekursiv sletting er ikke støttet. Du slette innholdet først.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="588"/>
<location filename="../nw/gui/projtree.py" line="593"/>
<source>Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Kan ikke slette hovedmappen da den ikke er tom. Rekursiv sletting er ikke støttet. Du slette innholdet først.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="875"/>
<location filename="../nw/gui/projtree.py" line="880"/>
<source>The item cannot be moved to that location.</source>
<translation>Denne enheten kan ikke flyttes til denne lokasjonen.</translation>
</message>
@@ -3995,60 +4020,65 @@
<translation>Kan ikke legge til nye filer eller mapper til søppel-mappen.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="972"/>
<location filename="../nw/gui/projtree.py" line="977"/>
<source>There is nowhere to add item with name &apos;{0}&apos;.</source>
<translation>Fant ikke noe sted å legge til enheten med navn &apos;{0}&apos;.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="532"/>
<source>Could not delete document file.</source>
<translation>Kunne ikke slette dokumentets fil.</translation>
</message>
</context>
<context>
<name>GuiProjectTreeMenu</name>
<message>
<location filename="../nw/gui/projtree.py" line="1094"/>
<location filename="../nw/gui/projtree.py" line="1099"/>
<source>Edit Project Item</source>
<translation>Endre enhet</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1098"/>
<location filename="../nw/gui/projtree.py" line="1103"/>
<source>Open Document</source>
<translation>Åpne dokument</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1102"/>
<location filename="../nw/gui/projtree.py" line="1107"/>
<source>View Document</source>
<translation>Vis dokument</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1106"/>
<location filename="../nw/gui/projtree.py" line="1111"/>
<source>Toggle Included Flag</source>
<translation>Slå av/ inkludering</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1110"/>
<location filename="../nw/gui/projtree.py" line="1115"/>
<source>New File</source>
<translation>Ny fil</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1114"/>
<location filename="../nw/gui/projtree.py" line="1119"/>
<source>New Folder</source>
<translation>Ny mappe</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1118"/>
<location filename="../nw/gui/projtree.py" line="1123"/>
<source>Delete Item</source>
<translation>Slett enhet</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1122"/>
<location filename="../nw/gui/projtree.py" line="1127"/>
<source>Empty Trash</source>
<translation>Tøm søppel</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1126"/>
<location filename="../nw/gui/projtree.py" line="1131"/>
<source>Move Item Up</source>
<translation>Flytt enhet opp</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1130"/>
<location filename="../nw/gui/projtree.py" line="1135"/>
<source>Move Item Down</source>
<translation>Flytt enhet ned</translation>
</message>
@@ -4237,24 +4267,6 @@
<translation>Lagre data som</translation>
</message>
</context>
<context>
<name>NWDoc</name>
<message>
<location filename="../nw/core/document.py" line="118"/>
<source>Failed to open document file.</source>
<translation>Kunne ikke åpne dokumentets fil.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="162"/>
<source>Could not save document.</source>
<translation>Kunne ikke lagre dokumentet.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="192"/>
<source>Could not delete document file.</source>
<translation>Kunne ikke slette dokumentets fil.</translation>
</message>
</context>
<context>
<name>NWProject</name>
<message>
@@ -4308,237 +4320,237 @@
<translation>Av</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="305"/>
<location filename="../nw/core/project.py" line="299"/>
<source>Novel</source>
<translation>Roman</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="276"/>
<location filename="../nw/core/project.py" line="273"/>
<source>Plot</source>
<translation>Plott</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="277"/>
<location filename="../nw/core/project.py" line="274"/>
<source>Characters</source>
<translation>Karakterer</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="278"/>
<location filename="../nw/core/project.py" line="275"/>
<source>World</source>
<translation>Verden</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="311"/>
<location filename="../nw/core/project.py" line="305"/>
<source>Title Page</source>
<translation>Tittelside</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="292"/>
<location filename="../nw/core/project.py" line="288"/>
<source>New Chapter</source>
<translation>Nytt kapittel</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="296"/>
<location filename="../nw/core/project.py" line="291"/>
<source>New Scene</source>
<translation>Ny scene</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="326"/>
<location filename="../nw/core/project.py" line="319"/>
<source>Chapter {0}</source>
<translation>Kapittel {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="351"/>
<location filename="../nw/core/project.py" line="342"/>
<source>Scene {0}</source>
<translation>Scene {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="375"/>
<location filename="../nw/core/project.py" line="365"/>
<source>File not found: {0}</source>
<translation>Fant ikke filen: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="435"/>
<location filename="../nw/core/project.py" line="425"/>
<source>Failed to parse project xml.</source>
<translation>Kunne ikke lese prosjektets xml-data.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="429"/>
<location filename="../nw/core/project.py" line="419"/>
<source>Attempting to open backup project file instead.</source>
<translation>Forsøker å åpne prosjektets sekundære prosjektfil istedet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="449"/>
<location filename="../nw/core/project.py" line="439"/>
<source>Unknown</source>
<translation>Ukjent</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="458"/>
<location filename="../nw/core/project.py" line="448"/>
<source>Project file does not appear to be a novelWriterXML file.</source>
<translation>Prosjektfilen later ikke til å være en novelWriterXML-fil.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="478"/>
<location filename="../nw/core/project.py" line="468"/>
<source>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}.</source>
<translation>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}.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>Version Conflict</source>
<translation>Versjonskonflikt</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="592"/>
<location filename="../nw/core/project.py" line="582"/>
<source>Opened Project: {0}</source>
<translation>Åpnet prosjekt: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="613"/>
<location filename="../nw/core/project.py" line="603"/>
<source>Project path not set, cannot save project.</source>
<translation>Prosjektet mangler filbane, og kan ikke lagres.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="694"/>
<location filename="../nw/core/project.py" line="684"/>
<source>Failed to save project.</source>
<translation>Kunne ikke lagre prosjektet.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="713"/>
<location filename="../nw/core/project.py" line="703"/>
<source>Saved Project: {0}</source>
<translation>Lagret prosjekt: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="765"/>
<location filename="../nw/core/project.py" line="755"/>
<source>Backing up project ...</source>
<translation>Lager sikkerhetskopi ...</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="768"/>
<location filename="../nw/core/project.py" line="758"/>
<source>Cannot backup project because no backup path is set. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Kan ikke ta sikkerhetskopi av prosjektet da ingen filbane er satt. Du først sette en filbane i Verktøy &gt; Innstillinger.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="777"/>
<location filename="../nw/core/project.py" line="767"/>
<source>Cannot backup project because no project name is set. Please set a Working Title in Project &gt; Project Settings.</source>
<translation>Kan ikke ta sikkerhetskopi av prosjektet da ingen arbeidstittel er satt. Du først sette en arbeidstittel i Prosjekt &gt; Prosjektinnstillinger.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="786"/>
<location filename="../nw/core/project.py" line="776"/>
<source>Cannot backup project because the backup path does not exist. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Kan ikke ta sikkerhetskopi av prosjektet da filbane ikke finnes. Du sette en ny filbane i Verktøy &gt; Innstillinger.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="801"/>
<location filename="../nw/core/project.py" line="791"/>
<source>Could not create backup folder.</source>
<translation>Kunne ikke lage mappe til sikkerhetskopi.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="808"/>
<location filename="../nw/core/project.py" line="798"/>
<source>Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Tools &gt; Preferences.</source>
<translation>Kan ikke ta sikkerhetskopi av prosjektet da filbanen er inne i prosjektmappen. Du sette en ny filbane i Verktøy &gt; Innstillinger.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="817"/>
<location filename="../nw/core/project.py" line="807"/>
<source>Backup from {0}</source>
<translation>Sikkerhetskopi fra {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="826"/>
<location filename="../nw/core/project.py" line="816"/>
<source>Backup archive file written to: {0}</source>
<translation>Sikkerhetskopi skrevet til: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="835"/>
<location filename="../nw/core/project.py" line="825"/>
<source>Could not write backup archive.</source>
<translation>Kunne ikke lage sikkerhetskopi.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="841"/>
<location filename="../nw/core/project.py" line="831"/>
<source>Project backed up to &apos;{0}&apos;</source>
<translation>Sikkerhetskopi skrevet til &apos;{0}&apos;</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="889"/>
<location filename="../nw/core/project.py" line="879"/>
<source>Failed to create a new example project.</source>
<translation>Kunne ikke lage nytt eksempel-prosjekt.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="894"/>
<location filename="../nw/core/project.py" line="884"/>
<source>Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation.</source>
<translation>Kunne ikke lage nytt eksempel-prosjekt. Kunne ikke finne de nødvendige filene. De ser ut til å mangle i denne installasjonen.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="929"/>
<location filename="../nw/core/project.py" line="919"/>
<source>Could not create new project folder.</source>
<translation>Kunne ikke lage ny prosjekt-mappe.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="936"/>
<location filename="../nw/core/project.py" line="926"/>
<source>New project folder is not empty. Each project requires a dedicated project folder.</source>
<translation>Ny prosjektmappe er ikke tom. Hvert prosjekt trenger sin egen mappe.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="988"/>
<location filename="../nw/core/project.py" line="978"/>
<source>You must set a valid backup path in Preferences to use the automatic project backup feature.</source>
<translation>Du sette en gyldig filbane i innstillingene for å kunne bruke automatisk sikkerhetskopi.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="997"/>
<location filename="../nw/core/project.py" line="987"/>
<source>You must set a valid project name in Project Settings to use the automatic project backup feature.</source>
<translation>Du sette en gyldig arbeidstittel i prosjektinnstillingene for å kunne bruke automatisk sikkerhetskopi.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1141"/>
<location filename="../nw/core/project.py" line="1131"/>
<source>and</source>
<translation>og</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1387"/>
<location filename="../nw/core/project.py" line="1377"/>
<source>Found {0} orphaned file(s) in project folder.</source>
<translation>Fant {0} tapte filer i prosjektmappen.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1399"/>
<location filename="../nw/core/project.py" line="1388"/>
<source>Recovered</source>
<translation>Gjennopprettet</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1411"/>
<location filename="../nw/core/project.py" line="1402"/>
<source>[{0}] {1}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1416"/>
<location filename="../nw/core/project.py" line="1407"/>
<source>Recovered File {0}</source>
<translation>Gjennopprettet fil {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1443"/>
<location filename="../nw/core/project.py" line="1434"/>
<source>One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists.</source>
<translation>Én eller flere gjennopprettede filer kunne ikke bli lagt til i posjektet. Pass at &quot;Roman&quot;-mappen i det minste eksisterer.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1504"/>
<location filename="../nw/core/project.py" line="1495"/>
<source>Not a folder: {0}</source>
<translation>Ikke en mappe: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1527"/>
<location filename="../nw/core/project.py" line="1518"/>
<source>Could not move: {0}</source>
<translation>Kunne ikke flytte: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1551"/>
<location filename="../nw/core/project.py" line="1542"/>
<source>Could not delete: {0}</source>
<translation>Kunne ikke slette: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1563"/>
<location filename="../nw/core/project.py" line="1554"/>
<source>Could not make folder: {0}</source>
<translation>Kunne ikke lage mappe: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1574"/>
<location filename="../nw/core/project.py" line="1565"/>
<source>Could not move item {0} to {1}.</source>
<translation>Kunne ikke flytte {0} til {1}.</translation>
</message>
@@ -4548,7 +4560,7 @@
<translation>Kapittel</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>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?</source>
<translation>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?</translation>
</message>
+149 -137
View File
@@ -793,22 +793,22 @@
<context>
<name>GuiDocEditFooter</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2616"/>
<location filename="../nw/gui/doceditor.py" line="2630"/>
<source>Line: {0} ({1})</source>
<translation>Linha: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2632"/>
<location filename="../nw/gui/doceditor.py" line="2646"/>
<source>Words: {0} ({1})</source>
<translation>Palavras: {0} ({1})</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2475"/>
<location filename="../nw/gui/doceditor.py" line="2489"/>
<source>Status</source>
<translation>Estado</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2637"/>
<location filename="../nw/gui/doceditor.py" line="2651"/>
<source>Document size is {0} bytes</source>
<translation>O tamanho do documento é {0} bytes</translation>
</message>
@@ -816,22 +816,22 @@
<context>
<name>GuiDocEditHeader</name>
<message>
<location filename="../nw/gui/doceditor.py" line="2267"/>
<location filename="../nw/gui/doceditor.py" line="2281"/>
<source>Edit document meta</source>
<translation>Editar os meta-dados do documento</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2278"/>
<location filename="../nw/gui/doceditor.py" line="2292"/>
<source>Search document</source>
<translation>Procurar no documento</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2289"/>
<location filename="../nw/gui/doceditor.py" line="2303"/>
<source>Toggle Focus Mode</source>
<translation>Alternar o &quot;Modo Foco&quot;</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="2300"/>
<location filename="../nw/gui/doceditor.py" line="2314"/>
<source>Close the document</source>
<translation>Fechar o documento</translation>
</message>
@@ -839,97 +839,97 @@
<context>
<name>GuiDocEditSearch</name>
<message>
<location filename="../nw/gui/doceditor.py" line="1895"/>
<location filename="../nw/gui/doceditor.py" line="1909"/>
<source>Search</source>
<translation>Pesquisa</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1886"/>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<source>Replace</source>
<translation>Substituir</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1899"/>
<location filename="../nw/gui/doceditor.py" line="1913"/>
<source>Case Sensitive</source>
<translation>Diferenciar Maiúsculas e Minúsculas</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1900"/>
<location filename="../nw/gui/doceditor.py" line="1914"/>
<source>Match case</source>
<translation>Diferencia Maiúsculas e Minúsculas</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1907"/>
<location filename="../nw/gui/doceditor.py" line="1921"/>
<source>Whole Words Only</source>
<translation>Apenas Palavras Inteiras</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1908"/>
<location filename="../nw/gui/doceditor.py" line="1922"/>
<source>Match whole words</source>
<translation>Encontra apenas palavras inteiras</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1915"/>
<location filename="../nw/gui/doceditor.py" line="1929"/>
<source>RegEx Mode</source>
<translation>Expressão Regular</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1923"/>
<location filename="../nw/gui/doceditor.py" line="1937"/>
<source>Loop Search</source>
<translation>Pesquisa do Início</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1924"/>
<location filename="../nw/gui/doceditor.py" line="1938"/>
<source>Loop the search when reaching the end</source>
<translation>Pesquisa do início quando chega no final do documento</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1931"/>
<location filename="../nw/gui/doceditor.py" line="1945"/>
<source>Search Next File</source>
<translation>Busca no Próximo Arquivo</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1932"/>
<location filename="../nw/gui/doceditor.py" line="1946"/>
<source>Continue searching in the next file</source>
<translation>Continua a busca no próximo arquivo</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1941"/>
<location filename="../nw/gui/doceditor.py" line="1955"/>
<source>Preserve Case</source>
<translation>Preserva Maiúsculas e Minúsculas</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1942"/>
<location filename="../nw/gui/doceditor.py" line="1956"/>
<source>Preserve case on replace</source>
<translation>Preserva maiúsculas e minúsculas ao substituir</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1951"/>
<location filename="../nw/gui/doceditor.py" line="1965"/>
<source>Close Search</source>
<translation>Fechar a Busca</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1964"/>
<location filename="../nw/gui/doceditor.py" line="1978"/>
<source>Show/hide the replace text box</source>
<translation>Mostrar/Ocultar a caixa substituição</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1970"/>
<location filename="../nw/gui/doceditor.py" line="1984"/>
<source>Find in current document</source>
<translation>Encontrar no documento atual</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1975"/>
<location filename="../nw/gui/doceditor.py" line="1989"/>
<source>Find and replace in current document</source>
<translation>Encontrar e substituir no documento atual</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1952"/>
<location filename="../nw/gui/doceditor.py" line="1966"/>
<source>Close the search box [{0}]</source>
<translation>Fechar a caixa de busca [{0}]</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1916"/>
<location filename="../nw/gui/doceditor.py" line="1930"/>
<source>Search using regular expressions</source>
<translation>Busca usando expressões regulares</translation>
</message>
@@ -937,100 +937,105 @@
<context>
<name>GuiDocEditor</name>
<message>
<location filename="../nw/gui/doceditor.py" line="680"/>
<location filename="../nw/gui/doceditor.py" line="694"/>
<source>Spell check complete</source>
<translation>Verificação ortográfica completa</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1073"/>
<location filename="../nw/gui/doceditor.py" line="1087"/>
<source>No Suggestions</source>
<translation>Sem Sugestões</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="308"/>
<location filename="../nw/gui/doceditor.py" line="313"/>
<source>The document you are trying to open is too big. The document size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>O documento que você está tentando abrir é muito grande. O tamanho do documento é {0} MB. O tamanho máximo permitido é {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="407"/>
<location filename="../nw/gui/doceditor.py" line="411"/>
<source>The text you are trying to add is too big. The text size is {0} MB. The maximum size allowed is {1} MB.</source>
<translation>O texto que você está tentando adicionar é muito grande. O tamanho do texto é {0} MB. O tamanho máximo permitido é {1} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>File Location</source>
<translation>Localização do Arquivo</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1002"/>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<source>Follow Tag</source>
<translation>Seguir Etiqueta</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1008"/>
<location filename="../nw/gui/doceditor.py" line="1022"/>
<source>Cut</source>
<translation>Recortar</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1012"/>
<location filename="../nw/gui/doceditor.py" line="1026"/>
<source>Copy</source>
<translation>Copiar</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1016"/>
<location filename="../nw/gui/doceditor.py" line="1030"/>
<source>Paste</source>
<translation>Colar</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1025"/>
<location filename="../nw/gui/doceditor.py" line="1039"/>
<source>Select All</source>
<translation>Selecionar Tudo</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1029"/>
<location filename="../nw/gui/doceditor.py" line="1043"/>
<source>Select Word</source>
<translation>Selecionar Palavra</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1035"/>
<location filename="../nw/gui/doceditor.py" line="1049"/>
<source>Select Paragraph</source>
<translation>Selecionar Parágrafo</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1061"/>
<location filename="../nw/gui/doceditor.py" line="1075"/>
<source>Spelling Suggestion(s)</source>
<translation>Sugestão de Ortografia</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1079"/>
<location filename="../nw/gui/doceditor.py" line="1093"/>
<source>Add Word to Dictionary</source>
<translation>Adicionar Palavra ao Dicionário</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="1507"/>
<location filename="../nw/gui/doceditor.py" line="1521"/>
<source>Please select some text before calling replace quotes.</source>
<translation>Por favor, selecione algum texto antes de invocar a substituição de aspas.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="774"/>
<location filename="../nw/gui/doceditor.py" line="788"/>
<source>The currently open file is saved in:</source>
<translation>O arquivo aberto atualmente está salvo em:</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="964"/>
<location filename="../nw/gui/doceditor.py" line="978"/>
<source>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.</source>
<translation>O tamanho do documento aumentou muito e você não pode adicionar mais texto nele. O tamanho máximo de um único documento do novelWriter é {0} MB.</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="382"/>
<location filename="../nw/gui/doceditor.py" line="386"/>
<source>Opened Document: {0}</source>
<translation>Documento Aberto: {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="467"/>
<location filename="../nw/gui/doceditor.py" line="482"/>
<source>Saved Document: {0}</source>
<translation>Documento Salvo: {0}</translation>
</message>
<message>
<location filename="../nw/gui/doceditor.py" line="458"/>
<source>Could not save document.</source>
<translation>Não foi possível salvar o documento.</translation>
</message>
</context>
<context>
<name>GuiDocMerge</name>
@@ -1055,20 +1060,30 @@
<translation>Nenhum documento-fonte foi encontrado. Nada para fazer.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="118"/>
<location filename="../nw/dialogs/docmerge.py" line="123"/>
<source>No source document selected. Nothing to do.</source>
<translation>Nenhum documento de origem selecionado. Nada a ser feito.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="125"/>
<location filename="../nw/dialogs/docmerge.py" line="130"/>
<source>Could not parse source document.</source>
<translation>Não foi possível interpretar o documento.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="168"/>
<location filename="../nw/dialogs/docmerge.py" line="177"/>
<source>Element selected in the project tree must be a folder.</source>
<translation>O elemento selecionado na árvore do projeto deve ser um diretório.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="116"/>
<source>Failed to open document file.</source>
<translation>Houve uma falha ao abrir o arquivo do documento.</translation>
</message>
<message>
<location filename="../nw/dialogs/docmerge.py" line="141"/>
<source>Could not save document.</source>
<translation>Não foi possível salvar o documento.</translation>
</message>
</context>
<context>
<name>GuiDocSplit</name>
@@ -1103,7 +1118,7 @@
<translation>Dividir até os cabeçalhos de nível 4 (Seção)</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Split Document</source>
<translation>Divisão de Documento</translation>
</message>
@@ -1118,30 +1133,40 @@
<translation>Não foi possível interpretar o documento.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="153"/>
<location filename="../nw/dialogs/docsplit.py" line="160"/>
<source>No headers found. Nothing to do.</source>
<translation>Nenhum cabeçalho foi encontrado. Nada para fazer.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="161"/>
<location filename="../nw/dialogs/docsplit.py" line="168"/>
<source>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.</source>
<translation>Não é possível adicionar um novo diretório para a divisão do documento. A profundidade máxima dos diretórios foi alcançada. Por favor mova o arquivo para outro nível na árvore do projeto.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>Continue with the splitting process?</source>
<translation>Continuar com o processo de divisão?</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="256"/>
<location filename="../nw/dialogs/docsplit.py" line="267"/>
<source>Element selected in the project tree must be a file.</source>
<translation>O elemento selecionado na árvore do projeto deve ser um arquivo.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="170"/>
<location filename="../nw/dialogs/docsplit.py" line="177"/>
<source>The document will be split into {0} file(s) in a new folder. The original document will remain intact.</source>
<translation>O documento será dividio em {0} arquivo(s) em um novo diretório. O documento original será mantido intacto.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="135"/>
<source>Failed to open document file.</source>
<translation>Houve uma falha ao abrir o arquivo do documento.</translation>
</message>
<message>
<location filename="../nw/dialogs/docsplit.py" line="230"/>
<source>Could not save document.</source>
<translation>Não foi possível salvar o documento.</translation>
</message>
</context>
<context>
<name>GuiDocViewFooter</name>
@@ -3905,12 +3930,12 @@
<translation>Esvaziar a Lixeira</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Delete File</source>
<translation>Remover Arquivo</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="875"/>
<location filename="../nw/gui/projtree.py" line="880"/>
<source>The item cannot be moved to that location.</source>
<translation>O item não pode ser movido para este local.</translation>
</message>
@@ -3975,17 +4000,17 @@
<translation>Permanentemente remover o arquivo &apos;{0}&apos;?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="539"/>
<location filename="../nw/gui/projtree.py" line="544"/>
<source>Move file &apos;{0}&apos; to Trash?</source>
<translation>Mover o arquivo &apos;{0}&apos; para a Lixeira?</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="572"/>
<location filename="../nw/gui/projtree.py" line="577"/>
<source>Cannot delete folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Não foi possível remover o diretório. O diretório não está vazio. Exclusão recursiva não é suportada. Por favor remova todo o conteúdo primeiro.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="588"/>
<location filename="../nw/gui/projtree.py" line="593"/>
<source>Cannot delete root folder. It is not empty. Recursive deletion is not supported. Please delete the content first.</source>
<translation>Não foi possível remover o diretório-raiz. O diretório não está vazio. Exclusão recursiva não é suportada. Por favor remova todo o conteúdo primeiro.</translation>
</message>
@@ -3995,60 +4020,65 @@
<translation>Não foi possível adicionar novos arquivos ou diretórios à Lixeira.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="972"/>
<location filename="../nw/gui/projtree.py" line="977"/>
<source>There is nowhere to add item with name &apos;{0}&apos;.</source>
<translation>Não lugar para adicionar o item com o nome &apos;{0}&apos;.</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="532"/>
<source>Could not delete document file.</source>
<translation>Não foi possível remover o arquivo do documento.</translation>
</message>
</context>
<context>
<name>GuiProjectTreeMenu</name>
<message>
<location filename="../nw/gui/projtree.py" line="1094"/>
<location filename="../nw/gui/projtree.py" line="1099"/>
<source>Edit Project Item</source>
<translation>Editar Item do Projeto</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1098"/>
<location filename="../nw/gui/projtree.py" line="1103"/>
<source>Open Document</source>
<translation>Abrir Documento</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1102"/>
<location filename="../nw/gui/projtree.py" line="1107"/>
<source>View Document</source>
<translation>Ver Documento</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1106"/>
<location filename="../nw/gui/projtree.py" line="1111"/>
<source>Toggle Included Flag</source>
<translation>Alternar Opção de Inclusão</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1110"/>
<location filename="../nw/gui/projtree.py" line="1115"/>
<source>New File</source>
<translation>Novo Arquivo</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1114"/>
<location filename="../nw/gui/projtree.py" line="1119"/>
<source>New Folder</source>
<translation>Novo Diretório</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1118"/>
<location filename="../nw/gui/projtree.py" line="1123"/>
<source>Delete Item</source>
<translation>Remover Item</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1122"/>
<location filename="../nw/gui/projtree.py" line="1127"/>
<source>Empty Trash</source>
<translation>Esvaziar a Lixeira</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1126"/>
<location filename="../nw/gui/projtree.py" line="1131"/>
<source>Move Item Up</source>
<translation>Mover Item Acima</translation>
</message>
<message>
<location filename="../nw/gui/projtree.py" line="1130"/>
<location filename="../nw/gui/projtree.py" line="1135"/>
<source>Move Item Down</source>
<translation>Mover Item Abaixo</translation>
</message>
@@ -4237,24 +4267,6 @@
<translation>Salvar Dados Como</translation>
</message>
</context>
<context>
<name>NWDoc</name>
<message>
<location filename="../nw/core/document.py" line="118"/>
<source>Failed to open document file.</source>
<translation>Houve uma falha ao abrir o arquivo do documento.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="162"/>
<source>Could not save document.</source>
<translation>Não foi possível salvar o documento.</translation>
</message>
<message>
<location filename="../nw/core/document.py" line="192"/>
<source>Could not delete document file.</source>
<translation>Não foi possível remover o arquivo do documento.</translation>
</message>
</context>
<context>
<name>NWProject</name>
<message>
@@ -4303,232 +4315,232 @@
<translation>Novo Projeto</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="305"/>
<location filename="../nw/core/project.py" line="299"/>
<source>Novel</source>
<translation>Livro</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="276"/>
<location filename="../nw/core/project.py" line="273"/>
<source>Plot</source>
<translation>Enredo</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="277"/>
<location filename="../nw/core/project.py" line="274"/>
<source>Characters</source>
<translation>Personagens</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="278"/>
<location filename="../nw/core/project.py" line="275"/>
<source>World</source>
<translation>Mundo</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="311"/>
<location filename="../nw/core/project.py" line="305"/>
<source>Title Page</source>
<translation>Página de Título</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="292"/>
<location filename="../nw/core/project.py" line="288"/>
<source>New Chapter</source>
<translation>Novo Capítulo</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="296"/>
<location filename="../nw/core/project.py" line="291"/>
<source>New Scene</source>
<translation>Nova Cena</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="435"/>
<location filename="../nw/core/project.py" line="425"/>
<source>Failed to parse project xml.</source>
<translation>Houve uma falha ao interpretar o conteúdo XML do projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="429"/>
<location filename="../nw/core/project.py" line="419"/>
<source>Attempting to open backup project file instead.</source>
<translation>Tentando abrir a cópia de segurança do projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="449"/>
<location filename="../nw/core/project.py" line="439"/>
<source>Unknown</source>
<translation>Desconhecido</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="458"/>
<location filename="../nw/core/project.py" line="448"/>
<source>Project file does not appear to be a novelWriterXML file.</source>
<translation>O arquivo do projeto não parece ser um arquivo XML do novelWriter.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>Version Conflict</source>
<translation>Conflito de Versão</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="592"/>
<location filename="../nw/core/project.py" line="582"/>
<source>Opened Project: {0}</source>
<translation>Projeto Aberto: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="613"/>
<location filename="../nw/core/project.py" line="603"/>
<source>Project path not set, cannot save project.</source>
<translation>O caminho do projeto não foi definido, não é possível salvar o projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="694"/>
<location filename="../nw/core/project.py" line="684"/>
<source>Failed to save project.</source>
<translation>Houve uma falha ao salvar o projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="713"/>
<location filename="../nw/core/project.py" line="703"/>
<source>Saved Project: {0}</source>
<translation>Projeto Salvo: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="765"/>
<location filename="../nw/core/project.py" line="755"/>
<source>Backing up project ...</source>
<translation>Realizando uma cópia de segurança do projeto...</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="768"/>
<location filename="../nw/core/project.py" line="758"/>
<source>Cannot backup project because no backup path is set. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Não foi possível realizar uma cópia de segurança do projeto porquê o caminho das cópias de segurança não foi definido. Por favor, defina um caminho válido para as cópias de segurança em Ferramentas &gt; Preferências.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="777"/>
<location filename="../nw/core/project.py" line="767"/>
<source>Cannot backup project because no project name is set. Please set a Working Title in Project &gt; Project Settings.</source>
<translation>Não foi possível realizar a cópia de segurança do projeto porque o nome do projeto não está definido. Por favor defina o Nome do Projeto em Projeto &gt; Configurações do Projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="786"/>
<location filename="../nw/core/project.py" line="776"/>
<source>Cannot backup project because the backup path does not exist. Please set a valid backup location in Tools &gt; Preferences.</source>
<translation>Não foi possível realizar a cópia de segurança do projeto porque o caminho das cópias de segurança não exite. Por favor, defina um cainho válido para as cópias de segurança em Ferramentas &gt; Preferências.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="801"/>
<location filename="../nw/core/project.py" line="791"/>
<source>Could not create backup folder.</source>
<translation>Não foi possível ler o diretório de cópias de segurança.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="808"/>
<location filename="../nw/core/project.py" line="798"/>
<source>Cannot backup project because the backup path is within the project folder to be backed up. Please choose a different backup path in Tools &gt; Preferences.</source>
<translation>Não foi possível realizar a cópia de segurança do projeto porque o caminho das cópias de segurança está em um caminho dentro do diretório do projeto. Por favor, escolha um caminho diferente para as cópias de segurança em Ferramentas&gt; Preferências.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="835"/>
<location filename="../nw/core/project.py" line="825"/>
<source>Could not write backup archive.</source>
<translation>Não foi possível escrever o arquivo da cópia de segurança.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="889"/>
<location filename="../nw/core/project.py" line="879"/>
<source>Failed to create a new example project.</source>
<translation>Houve uma falha ao criar um novo projeto de exemplo.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="894"/>
<location filename="../nw/core/project.py" line="884"/>
<source>Failed to create a new example project. Could not find the necessary files. They seem to be missing from this installation.</source>
<translation>Houve uma falha ao criar um novo projeto de exemplo. Não foi possível encontrar os arquivos necessários. Eles parecem estar faltando nesta instalação.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="929"/>
<location filename="../nw/core/project.py" line="919"/>
<source>Could not create new project folder.</source>
<translation>Não foi possível criar o diretório do novo projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="936"/>
<location filename="../nw/core/project.py" line="926"/>
<source>New project folder is not empty. Each project requires a dedicated project folder.</source>
<translation>O diretório do novo projeto não está vazio. Cada projeto requer um diretório dedicado.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="988"/>
<location filename="../nw/core/project.py" line="978"/>
<source>You must set a valid backup path in Preferences to use the automatic project backup feature.</source>
<translation>Deve ser definido um caminho válido para as cópias de segurança nas preferências para usar a funcionalidade de cópias de segurança automáticas.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="997"/>
<location filename="../nw/core/project.py" line="987"/>
<source>You must set a valid project name in Project Settings to use the automatic project backup feature.</source>
<translation>Deve ser definido um nome de projeto válido nas preferências do projeto para usar a funcionalidade de cópias de segurança automáticas.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1399"/>
<location filename="../nw/core/project.py" line="1388"/>
<source>Recovered</source>
<translation>Recuperado</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1443"/>
<location filename="../nw/core/project.py" line="1434"/>
<source>One or more orphaned files could not be added back into the project. Make sure at least a Novel root folder exists.</source>
<translation>Um ou mais arquivos-órfãos não puderam ser readicionados ao projeto. Verifique que pelo menos um diretório-raiz de Livro exista.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1527"/>
<location filename="../nw/core/project.py" line="1518"/>
<source>Could not move: {0}</source>
<translation>Não foi possível mover: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1551"/>
<location filename="../nw/core/project.py" line="1542"/>
<source>Could not delete: {0}</source>
<translation>Não foi possível remover: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1563"/>
<location filename="../nw/core/project.py" line="1554"/>
<source>Could not make folder: {0}</source>
<translation>Não foi possível criar o diretório: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="326"/>
<location filename="../nw/core/project.py" line="319"/>
<source>Chapter {0}</source>
<translation>Capítulo {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="351"/>
<location filename="../nw/core/project.py" line="342"/>
<source>Scene {0}</source>
<translation>Cena {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="375"/>
<location filename="../nw/core/project.py" line="365"/>
<source>File not found: {0}</source>
<translation>Arquivo não encontrado: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="817"/>
<location filename="../nw/core/project.py" line="807"/>
<source>Backup from {0}</source>
<translation>Cópia de segurança de {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="826"/>
<location filename="../nw/core/project.py" line="816"/>
<source>Backup archive file written to: {0}</source>
<translation>Arquivo da cópia de segurança escrito em: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="841"/>
<location filename="../nw/core/project.py" line="831"/>
<source>Project backed up to &apos;{0}&apos;</source>
<translation>Cópia de segurança realizada para &apos;{0}&apos;</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1387"/>
<location filename="../nw/core/project.py" line="1377"/>
<source>Found {0} orphaned file(s) in project folder.</source>
<translation>Foram encontrados {0} arquivos-órfãos no diretório do projeto.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1416"/>
<location filename="../nw/core/project.py" line="1407"/>
<source>Recovered File {0}</source>
<translation>Arquivo Recuperado {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1504"/>
<location filename="../nw/core/project.py" line="1495"/>
<source>Not a folder: {0}</source>
<translation>Não é um diretório: {0}</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="478"/>
<location filename="../nw/core/project.py" line="468"/>
<source>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}.</source>
<translation>Format de arquivo de projeto do novelWriter desconhecido ou não-suportado. O projeto não pode ser aberto por essa versão do novelWriter. O arquivo foi salvo com a versão {0} do novelWriter.</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1411"/>
<location filename="../nw/core/project.py" line="1402"/>
<source>[{0}] {1}</source>
<translation></translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1574"/>
<location filename="../nw/core/project.py" line="1565"/>
<source>Could not move item {0} to {1}.</source>
<translation>Não foi possível mover o item {0} para {1}.</translation>
</message>
@@ -4538,7 +4550,7 @@
<translation>Por</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="1141"/>
<location filename="../nw/core/project.py" line="1131"/>
<source>and</source>
<translation>e</translation>
</message>
@@ -4548,7 +4560,7 @@
<translation>Capítulo</translation>
</message>
<message>
<location filename="../nw/core/project.py" line="492"/>
<location filename="../nw/core/project.py" line="482"/>
<source>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?</source>
<translation>O projeto foi salvo por uma versão mais nova do novelWriter, versão {0}. Esta é a versão {1}. Caso deseje continuar a abrir o projeto, alguns atributos e configurações podem não ser preservados, mas o projeto deve funcionar corretamente. Continuar a abrir o projeto?</translation>
</message>
-1
View File
@@ -1,6 +1,5 @@
SOURCES += \
i18n/qtbase.py \
nw/core/document.py \
nw/core/project.py \
nw/core/tokenizer.py \
nw/dialogs/about.py \
+32 -46
View File
@@ -27,31 +27,29 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
import os
from functools import partial
from PyQt5.QtCore import QCoreApplication
from nw.enum import nwAlert, nwItemLayout, nwItemClass
from nw.enum import nwItemLayout, nwItemClass
from nw.common import isHandle
logger = logging.getLogger(__name__)
class NWDoc():
def __init__(self, theProject):
def __init__(self, theProject, theHandle):
self.theProject = theProject
self.theParent = theProject.theParent
# Internal Variables
self._theItem = None # The currently open item
self._docHandle = None # The handle of the currently open item
self._fileLoc = None # The file location of the currently open item
self._docMeta = {} # The meta data of the currently open item
self._docError = "" # The latest encountered IO error
# Internal Mapping
self.makeAlert = self.theParent.makeAlert
self.tr = partial(QCoreApplication.translate, "NWDoc")
if isHandle(theHandle):
self._docHandle = theHandle
if self._docHandle is not None:
self._theItem = self.theProject.projTree[theHandle]
return
@@ -59,35 +57,19 @@ class NWDoc():
# Class Methods
##
def clearDocument(self):
"""Clear the document contents.
"""
self._theItem = None
self._docHandle = None
self._fileLoc = None
self._docMeta = {}
return
def readDocument(self, tHandle, isOrphan=False):
"""Read a document from handle, capturing potential file system
errors and parse meta data. If the document doesn't exist on
disk, return an empty string. If something went wrong, return
def readDocument(self, isOrphan=False):
"""Read a document from set handle, capturing potential file
system errors and parse meta data. If the document doesn't exist
on disk, return an empty string. If something went wrong, return
None.
"""
if not isHandle(tHandle):
self._docError = ""
if self._docHandle is None:
logger.error("No document handle set")
return None
# Always clear first, since the object will often be reused.
self.clearDocument()
self._docHandle = tHandle
if not isOrphan:
self._theItem = self.theProject.projTree[tHandle]
else:
self._theItem = None
if self._theItem is None and not isOrphan:
self.clearDocument()
logger.error("Unknown novelWriter document")
return None
docFile = self._docHandle+".nwd"
@@ -115,12 +97,9 @@ class NWDoc():
theText += inFile.read()
except Exception as e:
self.makeAlert([self.tr("Failed to open document file."), str(e)], nwAlert.ERROR)
# Note: Document must be cleared in case of an io error,
# or else the auto-save or save will try to overwrite it
# with an empty file. Return None to alert the caller.
self.clearDocument()
self._docError = str(e)
return None
else:
# The document file does not exist, so we assume it's a new
# document and initialise an empty text string.
@@ -133,7 +112,9 @@ class NWDoc():
"""Write the document. The file is saved via a temp file in case
of save failure. Returns True if successful, False if not.
"""
self._docError = ""
if self._docHandle is None:
logger.error("No document handle set")
return False
self.theProject.ensureFolderStructure()
@@ -159,7 +140,7 @@ class NWDoc():
outFile.write(docMeta)
outFile.write(docText)
except Exception as e:
self.makeAlert([self.tr("Could not save document."), str(e)], nwAlert.ERROR)
self._docError = str(e)
return False
# If we're here, the file was successfully saved, so we can
@@ -170,14 +151,16 @@ class NWDoc():
return True
def deleteDocument(self, tHandle):
def deleteDocument(self):
"""Permanently delete a document source file and related files
from the project data folder.
"""
if not isHandle(tHandle):
self._docError = ""
if self._docHandle is None:
logger.error("No document handle set")
return False
docFile = tHandle+".nwd"
docFile = self._docHandle+".nwd"
chkList = []
chkList.append(os.path.join(self.theProject.projContent, docFile))
@@ -189,9 +172,7 @@ class NWDoc():
os.unlink(chkFile)
logger.debug("Deleted: %s" % chkFile)
except Exception as e:
self.makeAlert(
[self.tr("Could not delete document file."), str(e)], nwAlert.ERROR
)
self._docError = str(e)
return False
return True
@@ -221,6 +202,11 @@ class NWDoc():
return theName, theParent, theClass, theLayout
def getError(self):
"""Return the last recorded exception.
"""
return self._docError
##
# Internal Functions
##
+3 -3
View File
@@ -115,8 +115,8 @@ class NWIndex():
if tItem.itemType != nwItemType.FILE:
return False
theDoc = NWDoc(self.theProject)
theText = theDoc.readDocument(tHandle)
theDoc = NWDoc(self.theProject, tHandle)
theText = theDoc.readDocument()
if theText:
self.scanText(tHandle, theText)
@@ -269,7 +269,7 @@ class NWIndex():
logger.debug("Indexing item with handle %s" % tHandle)
# Check file type, and reset its old index
# Also add a dummy entry T000000 in case the file has no title
# Also add a default entry T000000 in case the file has no title
self._refIndex[tHandle] = {}
self._refIndex[tHandle]["T000000"] = {
"tags" : [],
+10 -19
View File
@@ -265,9 +265,6 @@ class NWProject():
if self.bookAuthors:
titlePage = "%s%s %s\n" % (titlePage, self.tr("By"), self.getAuthors())
# Document object for writing files
aDoc = NWDoc(self)
if popMinimal:
# Creating a minimal project with a few root folders and a
# single chapter folder with a single file.
@@ -284,17 +281,14 @@ class NWProject():
self.projTree.setFileItemLayout(xHandle[5], nwItemLayout.TITLE)
self.projTree.setFileItemLayout(xHandle[7], nwItemLayout.CHAPTER)
aDoc.readDocument(xHandle[5])
aDoc = NWDoc(self, xHandle[5])
aDoc.writeDocument(titlePage)
aDoc.clearDocument()
aDoc.readDocument(xHandle[7])
aDoc = NWDoc(self, xHandle[7])
aDoc.writeDocument("## %s\n\n" % self.tr("New Chapter"))
aDoc.clearDocument()
aDoc.readDocument(xHandle[8])
aDoc = NWDoc(self, xHandle[8])
aDoc.writeDocument("### %s\n\n" % self.tr("New Scene"))
aDoc.clearDocument()
elif popCustom:
# Create a project structure based on selected root folders
@@ -311,9 +305,8 @@ class NWProject():
tHandle = self.newFile(self.tr("Title Page"), nwItemClass.NOVEL, nHandle)
self.projTree.setFileItemLayout(tHandle, nwItemLayout.TITLE)
aDoc.readDocument(tHandle)
aDoc = NWDoc(self, tHandle)
aDoc.writeDocument(titlePage)
aDoc.clearDocument()
# Create chapters and scenes
numChapters = projData.get("numChapters", 0)
@@ -331,9 +324,8 @@ class NWProject():
cHandle = self.newFile(chTitle, nwItemClass.NOVEL, pHandle)
self.projTree.setFileItemLayout(cHandle, nwItemLayout.CHAPTER)
aDoc.readDocument(cHandle)
aDoc = NWDoc(self, cHandle)
aDoc.writeDocument("## %s\n\n" % chTitle)
aDoc.clearDocument()
# Create chapter scenes
if numScenes > 0:
@@ -341,9 +333,8 @@ class NWProject():
scTitle = self.tr("Scene {0}").format(f"{ch+1:d}.{sc+1:d}")
sHandle = self.newFile(scTitle, nwItemClass.NOVEL, pHandle)
aDoc.readDocument(sHandle)
aDoc = NWDoc(self, sHandle)
aDoc.writeDocument("### %s\n\n" % scTitle)
aDoc.clearDocument()
# Create scenes (no chapters)
elif numScenes > 0:
@@ -351,9 +342,8 @@ class NWProject():
scTitle = self.tr("Scene {0}").format(f"{sc+1:d}")
sHandle = self.newFile(scTitle, nwItemClass.NOVEL, nHandle)
aDoc.readDocument(sHandle)
aDoc = NWDoc(self, sHandle)
aDoc.writeDocument("### %s\n\n" % scTitle)
aDoc.clearDocument()
# Finalise
if popCustom or popMinimal:
@@ -1393,7 +1383,6 @@ class NWProject():
return
# Handle orphans
aDoc = NWDoc(self)
nOrph = 0
noWhere = False
oPrefix = self.tr("Recovered")
@@ -1404,7 +1393,9 @@ class NWProject():
oParent = None
oClass = None
oLayout = None
if aDoc.readDocument(oHandle, isOrphan=True) is not None:
aDoc = NWDoc(self, oHandle)
if aDoc.readDocument(isOrphan=True) is not None:
oName, oParent, oClass, oLayout = aDoc.getMeta()
if oName:
+6 -6
View File
@@ -47,17 +47,17 @@ class NWSpellCheck():
return
def setLanguage(self, theLang, projectDict=None):
"""Dummy function.
"""Default function.
"""
return
def checkWord(self, theWord):
"""Dummy function.
"""Default function.
"""
return True
def suggestWords(self, theWord):
"""Dummy function.
"""Default function.
"""
return []
@@ -78,12 +78,12 @@ class NWSpellCheck():
return False
def listDictionaries(self):
"""Dummy function.
"""Default function.
"""
return []
def describeDict(self):
"""Dummy function.
"""Default function.
"""
return "", ""
@@ -136,7 +136,7 @@ class NWSpellEnchant(NWSpellCheck):
def setLanguage(self, theLang, projectDict=None):
"""Load a dictionary for the language specified in the config.
If that fails, we load a dummy dictionary so that lookups don't
If that fails, we load a mock dictionary so that lookups don't
crash.
"""
try:
+2 -2
View File
@@ -284,8 +284,8 @@ class Tokenizer():
self.theText = theText
else:
# Otherwise, load it from file
theDoc = NWDoc(self.theProject)
theText = theDoc.readDocument(theHandle)
theDoc = NWDoc(self.theProject, theHandle)
theText = theDoc.readDocument()
if theText:
self.theText = theText
+1 -1
View File
@@ -563,7 +563,7 @@ class ToOdt(Tokenizer):
##
if len(theText) != len(theFmt):
# Generate dummy format if there isn't any or it doesn't match
# Generate an empty format if there isn't any or it doesn't match
theFmt = " "*len(theText)
# XML functions
+26 -17
View File
@@ -105,40 +105,48 @@ class GuiDocMerge(QDialog):
self.theParent.makeAlert(
self.tr("No source documents found. Nothing to do."), nwAlert.ERROR
)
return
return False
theDoc = NWDoc(self.theProject)
theText = ""
for tHandle in finalOrder:
docText = theDoc.readDocument(tHandle).rstrip("\n")
inDoc = NWDoc(self.theProject, tHandle)
docText = inDoc.readDocument()
docErr = inDoc.getError()
if docText is None and docErr:
self.theParent.makeAlert(
[self.tr("Failed to open document file."), docErr], nwAlert.ERROR
)
if docText:
theText += docText+"\n\n"
theText += docText.rstrip("\n")+"\n\n"
if self.sourceItem is None:
self.theParent.makeAlert(
self.tr("No source document selected. Nothing to do."), nwAlert.ERROR
self.tr("No source folder selected. Nothing to do."), nwAlert.ERROR
)
return
return False
srcItem = self.theProject.projTree[self.sourceItem]
if srcItem is None:
self.theParent.makeAlert(
self.tr("Could not parse source document."), nwAlert.ERROR
)
return
self.theParent.makeAlert(self.tr("Internal error."), nwAlert.ERROR)
return False
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.itemParent)
newItem = self.theProject.projTree[nHandle]
newItem.setStatus(srcItem.itemStatus)
theDoc.readDocument(nHandle)
theDoc.writeDocument(theText)
outDoc = NWDoc(self.theProject, nHandle)
if not outDoc.writeDocument(theText):
self.theParent.makeAlert(
[self.tr("Could not save document."), outDoc.getError()], nwAlert.ERROR
)
return False
self.theParent.treeView.revealNewTreeItem(nHandle)
self.theParent.openDocument(nHandle, doScroll=True)
self._doClose()
return
return True
def _doClose(self):
"""Close the dialog window without doing anything.
@@ -159,16 +167,17 @@ class GuiDocMerge(QDialog):
tHandle = self.theParent.treeView.getSelectedHandle()
self.sourceItem = tHandle
if tHandle is None:
return
return False
nwItem = self.theProject.projTree[tHandle]
if nwItem is None:
return
return False
if nwItem.itemType is not nwItemType.FOLDER:
self.theParent.makeAlert(
self.tr("Element selected in the project tree must be a folder."), nwAlert.ERROR
)
return
return False
for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle):
newItem = QListWidgetItem()
@@ -179,6 +188,6 @@ class GuiDocMerge(QDialog):
newItem.setData(Qt.UserRole, sHandle)
self.listBox.addItem(newItem)
return
return True
# END Class GuiDocMerge
+32 -18
View File
@@ -118,17 +118,24 @@ class GuiDocSplit(QDialog):
self.theParent.makeAlert(
self.tr("No source document selected. Nothing to do."), nwAlert.ERROR
)
return
return False
srcItem = self.theProject.projTree[self.sourceItem]
if srcItem is None:
self.theParent.makeAlert(
self.tr("Could not parse source document."), nwAlert.ERROR
)
return
return False
inDoc = NWDoc(self.theProject, self.sourceItem)
theText = inDoc.readDocument()
docErr = inDoc.getError()
if theText is None and docErr:
self.theParent.makeAlert(
[self.tr("Failed to open document file."), docErr], nwAlert.ERROR
)
theDoc = NWDoc(self.theProject)
theText = theDoc.readDocument(self.sourceItem)
if theText is None:
theText = ""
@@ -153,7 +160,7 @@ class GuiDocSplit(QDialog):
self.theParent.makeAlert(
self.tr("No headers found. Nothing to do."), nwAlert.ERROR
)
return
return False
# Check that another folder can be created
parTree = self.theProject.projTree.getItemPath(srcItem.itemParent)
@@ -165,7 +172,7 @@ class GuiDocSplit(QDialog):
"Please move the file to another level in the project tree."
), nwAlert.ERROR
)
return
return False
msgYes = self.theParent.askQuestion(
self.tr("Split Document"),
@@ -179,7 +186,7 @@ class GuiDocSplit(QDialog):
)
)
if not msgYes:
return
return False
# Create the folder
fHandle = self.theProject.newFolder(
@@ -217,14 +224,19 @@ class GuiDocSplit(QDialog):
theText = "\n".join(theLines[iStart:iEnd])
theText = theText.rstrip("\n") + "\n\n"
theDoc.readDocument(nHandle)
theDoc.writeDocument(theText)
theDoc.clearDocument()
outDoc = NWDoc(self.theProject, nHandle)
if not outDoc.writeDocument(theText):
self.theParent.makeAlert(
[self.tr("Could not save document."), outDoc.getError()], nwAlert.ERROR
)
return False
self.theParent.treeView.revealNewTreeItem(nHandle)
self._doClose()
return
return True
def _doClose(self):
"""Close the dialog window without doing anything.
@@ -243,26 +255,28 @@ class GuiDocSplit(QDialog):
are then added to the list view in order. The list itself can be
reordered by the user.
"""
self.listBox.clear()
if self.sourceItem is None:
self.sourceItem = self.theParent.treeView.getSelectedHandle()
if self.sourceItem is None:
return
return False
nwItem = self.theProject.projTree[self.sourceItem]
if nwItem is None:
return
return False
if nwItem.itemType is not nwItemType.FILE:
self.theParent.makeAlert(
self.tr("Element selected in the project tree must be a file."), nwAlert.ERROR
)
return
return False
self.listBox.clear()
theDoc = NWDoc(self.theProject)
theText = theDoc.readDocument(self.sourceItem)
inDoc = NWDoc(self.theProject, self.sourceItem)
theText = inDoc.readDocument()
if theText is None:
theText = ""
return False
spLevel = self.splitLevel.currentData()
self.optState.setValue("GuiDocSplit", "spLevel", spLevel)
@@ -291,6 +305,6 @@ class GuiDocSplit(QDialog):
newItem.setData(Qt.UserRole, onLine)
self.listBox.addItem(newItem)
return
return True
# END Class GuiDocSplit
+40 -26
View File
@@ -75,7 +75,9 @@ class GuiDocEditor(QTextEdit):
self.theTheme = theParent.theTheme
self.theIndex = theParent.theIndex
self.theProject = theParent.theProject
self.nwDocument = NWDoc(self.theProject)
self.nwDocument = None
self.nwItem = None
self.docChanged = False # Flag for changed status of document
self.spellCheck = False # Flag for spell checking enabled
@@ -165,7 +167,7 @@ class GuiDocEditor(QTextEdit):
"""Clear the current document and reset all document related
flags and counters.
"""
self.nwDocument.clearDocument()
self.nwDocument = None
self.setReadOnly(True)
self.clear()
self.wcTimer.stop()
@@ -297,7 +299,10 @@ class GuiDocEditor(QTextEdit):
document is new (empty string), we set up the editor for editing
the file.
"""
theDoc = self.nwDocument.readDocument(tHandle)
self.nwDocument = NWDoc(self.theProject, tHandle)
self.nwItem = self.nwDocument.getCurrentItem()
theDoc = self.nwDocument.readDocument()
if theDoc is None:
# There was an io error
self.clearEditor()
@@ -350,16 +355,15 @@ class GuiDocEditor(QTextEdit):
self.updateDocMargins()
self.hLight.spellCheck = spTemp
theItem = self.nwDocument.getCurrentItem()
if tLine is None and theItem is not None:
if tLine is None and self.nwItem is not None:
# For large documents we queue the repositioning until the
# document layout has grown past the point we want to move
# the cursor to. This makes the loading significantly
# faster.
if docSize > 50000:
self.queuePos = theItem.cursorPos
self.queuePos = self.nwItem.cursorPos
else:
self.setCursorPosition(theItem.cursorPos)
self.setCursorPosition(self.nwItem.cursorPos)
else:
self.setCursorLine(tLine)
@@ -378,9 +382,9 @@ class GuiDocEditor(QTextEdit):
self.setCursorPosition(0)
# Update the status bar
if theItem is not None:
if self.nwItem is not None:
self.theParent.setStatus(
self.tr("Opened Document: {0}").format(theItem.itemName)
self.tr("Opened Document: {0}").format(self.nwItem.itemName)
)
return True
@@ -429,22 +433,33 @@ class GuiDocEditor(QTextEdit):
"""Save the text currently in the editor to the NWDoc object,
and update the NWItem meta data.
"""
theItem = self.nwDocument.getCurrentItem()
if theItem is None:
if self.nwItem is None or self.nwDocument is None:
logger.error("Cannot save text as no document is open")
return False
tHandle = self.nwItem.itemHandle
if self.theHandle != tHandle:
logger.error("Editor handle %s and item handle %s do not match" % (
self.theHandle, tHandle
))
return False
docText = self.getText()
tHandle = theItem.itemHandle
cC, wC, pC = countWords(docText)
self._updateCounts(cC, wC, pC)
theItem.setCharCount(self.charCount)
theItem.setWordCount(self.wordCount)
theItem.setParaCount(self.paraCount)
self.nwItem.setCharCount(self.charCount)
self.nwItem.setWordCount(self.wordCount)
self.nwItem.setParaCount(self.paraCount)
self.saveCursorPosition()
self.nwDocument.writeDocument(docText)
if not self.nwDocument.writeDocument(docText):
self.theParent.makeAlert([
self.tr("Could not save document."), self.nwDocument.getError()
], nwAlert.ERROR)
return False
self.setDocumentChanged(False)
self.theIndex.scanText(tHandle, docText)
@@ -465,7 +480,7 @@ class GuiDocEditor(QTextEdit):
# Update the status bar
self.theParent.setStatus(
self.tr("Saved Document: {0}").format(theItem.itemName)
self.tr("Saved Document: {0}").format(self.nwItem.itemName)
)
return True
@@ -592,10 +607,9 @@ class GuiDocEditor(QTextEdit):
def saveCursorPosition(self):
"""Save the cursor position to the current project item object.
"""
theItem = self.nwDocument.getCurrentItem()
if theItem is not None:
if self.nwItem is not None:
cursPos = self.getCursorPosition()
theItem.setCursorPos(cursPos)
self.nwItem.setCursorPos(cursPos)
return
def setCursorLine(self, theLine):
@@ -766,7 +780,7 @@ class GuiDocEditor(QTextEdit):
"""Tell the user where on the file system the file in the editor
is saved.
"""
if self.theHandle is None:
if self.nwDocument is None:
logger.error("No document open")
return False
@@ -1133,8 +1147,7 @@ class GuiDocEditor(QTextEdit):
def _updateCounts(self, cCount, wCount, pCount):
"""Slot for the word counter's finished signal
"""
theItem = self.nwDocument.getCurrentItem()
if self.theHandle is None or theItem is None:
if self.theHandle is None or self.nwItem is None:
return
logger.verbose("Updating word count")
@@ -1142,9 +1155,10 @@ class GuiDocEditor(QTextEdit):
self.charCount = cCount
self.wordCount = wCount
self.paraCount = pCount
theItem.setCharCount(cCount)
theItem.setWordCount(wCount)
theItem.setParaCount(pCount)
self.nwItem.setCharCount(cCount)
self.nwItem.setWordCount(wCount)
self.nwItem.setParaCount(pCount)
self.theParent.treeView.propagateCount(self.theHandle, wCount)
self.theParent.treeView.projectWordCount()
-1
View File
@@ -185,7 +185,6 @@ class GuiDocViewer(QTextBrowser):
logger.error("Failed to generate preview for document with handle '%s'" % tHandle)
nw.logException()
self.setText(self.tr("An error occurred while generating the preview."))
return False
# Refresh the tab stops
if self.mainConf.verQtValue >= 51000:
+9 -4
View File
@@ -286,8 +286,8 @@ class GuiProjectTree(QTreeWidget):
return True
# This is a new files, so let's add some content
newDoc = NWDoc(self.theProject)
curTxt = newDoc.readDocument(tHandle)
newDoc = NWDoc(self.theProject, tHandle)
curTxt = newDoc.readDocument()
if curTxt is None:
curTxt = ""
@@ -527,8 +527,13 @@ class GuiProjectTree(QTreeWidget):
if self.theParent.docEditor.theHandle == tHandle:
self.theParent.closeDocument()
theDoc = NWDoc(self.theProject)
theDoc.deleteDocument(tHandle)
delDoc = NWDoc(self.theProject, tHandle)
if not delDoc.deleteDocument():
self.makeAlert([
self.tr("Could not delete document file."), delDoc.getError()
], nwAlert.ERROR)
return False
self.theIndex.deleteHandle(tHandle)
self._deleteTreeItem(tHandle)
self._setTreeChanged(True)
+2 -2
View File
@@ -173,7 +173,7 @@ class GuiBuildNovel(QDialog):
if langIdx != -1:
self.buildLang.setCurrentIndex(langIdx)
# Dummy boxes due to QGridView and QLineEdit expand bug
# Wrapper boxes due to QGridView and QLineEdit expand bug
self.boxTitle = QHBoxLayout()
self.boxTitle.addWidget(self.fmtTitle)
self.boxChapter = QHBoxLayout()
@@ -245,7 +245,7 @@ class GuiBuildNovel(QDialog):
self.optState.getFloat("GuiBuildNovel", "lineHeight", 1.15)
)
# Dummy box due to QGridView and QLineEdit expand bug
# Wrapper box due to QGridView and QLineEdit expand bug
self.boxFont = QHBoxLayout()
self.boxFont.addWidget(self.textFont)
+6 -6
View File
@@ -25,7 +25,7 @@ import pytest
import shutil
import os
from dummy import DummyMain
from mock import MockGuiMain
from tools import cleanProject
sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
@@ -136,12 +136,12 @@ def fncConf(fncDir):
@pytest.fixture(scope="function")
def dummyGUI(monkeypatch, tmpConf):
"""Create a dummy instance of novelWriter's main GUI class.
"""Create a mock instance of novelWriter's main GUI class.
"""
monkeypatch.setattr("nw.CONFIG", tmpConf)
theDummy = DummyMain()
theDummy.mainConf = tmpConf
return theDummy
theGui = MockGuiMain()
theGui.mainConf = tmpConf
return theGui
@pytest.fixture(scope="function")
def nwGUI(qtbot, monkeypatch, fncDir, fncConf):
@@ -191,7 +191,7 @@ def nwMinimal(tmpDir):
@pytest.fixture(scope="function")
def nwLipsum(tmpDir):
"""A medium sized novelWriter example project with a lot of Lorem
Ipsum dummy text.
Ipsum text.
"""
tstDir = os.path.dirname(__file__)
srcDir = os.path.join(tstDir, "lipsum")
+12 -12
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
novelWriter Test Suite Dummy Classes
======================================
novelWriter Test Suite Mocked Classes
=======================================
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
@@ -24,14 +24,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
# Mock GUI
# =========================================================================== #
class DummyMain():
class MockGuiMain():
def __init__(self):
self.mainConf = None
self.hasProject = True
self.theIndex = None
self.theProject = None
self.statusBar = DummyStatusBar()
self.statusBar = MockStatusBar()
# Test Variables
self.askResponse = True
@@ -79,9 +79,9 @@ class DummyMain():
self.lastAlert = ""
return
# END Class DummyMain
# END Class MockGuiMain
class DummyStatusBar():
class MockStatusBar():
def __init__(self):
return
@@ -89,9 +89,9 @@ class DummyStatusBar():
def setStatus(self, theText):
return
# END Class DummyStatusBar
# END Class MockStatusBar
class DummyApp:
class MockApp:
def __init__(self):
return
@@ -99,15 +99,15 @@ class DummyApp:
def installTranslator(self, theLang):
return
# END Class DummyApp
# END Class MockApp
# =========================================================================== #
# Error Functions
# Dummy functions that will raise errors instead.
# Mock functions that will raise errors instead.
# =========================================================================== #
def causeOSError(*args, **kwargs):
raise OSError
raise OSError("OSError")
def causeException(*args, **kwargs):
raise Exception
raise Exception("Exception")
@@ -19,9 +19,9 @@
@char: Jane
This is a paragraph of dummy text.
This is a paragraph of nonsense text.
This is another paragraph of much longer dummy text. It is in fact 1 very very DUMB dummy text! We can also try replacing “quotes”, even single quotes are replaced. Isnt that nice? We can hyphen-ate, make dashes and even longer dashes — if we want. Ellipsis? Not a problem either … How about three hyphens — for long dash? It works too.
This is another paragraph of much longer nonsense text. It is in fact 1 very very NONSENSICAL nonsense text! We can also try replacing “quotes”, even single quotes are replaced. Isnt that nice? We can hyphen-ate, make dashes and even longer dashes — if we want. Ellipsis? Not a problem either … How about three hyphens — for long dash? It works too.
“Full line double quoted text.”
@@ -85,10 +85,10 @@
<status>New</status>
<exported>True</exported>
<layout>BOOK</layout>
<charCount>466</charCount>
<charCount>482</charCount>
<wordCount>83</wordCount>
<paraCount>4</paraCount>
<cursorPos>604</cursorPos>
<cursorPos>620</cursorPos>
</item>
<item handle="44cb730c42048" order="1" parent="None">
<name>Plot</name>
@@ -1,53 +0,0 @@
%%~name: Chapter One
%%~path: b3643d0f92e32/73475cb40a568
%%~kind: NOVEL/SCENE
## Chapter One
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.
### Scene One
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.
Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.
Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.
#### Scene One, Section Two
Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst.
Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend.
### Scene Two
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.
Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.
Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.
#### Scene Two, Section Two
Suspendisse potenti. Fusce tempus lorem nec laoreet suscipit. Fusce vulputate nisl ac diam tincidunt, nec malesuada quam pellentesque. Maecenas congue, tellus quis commodo rutrum, magna leo egestas arcu, quis suscipit ex risus id ligula. Suspendisse potenti. Morbi blandit lacus vitae laoreet vulputate. Donec vitae tellus eleifend, lobortis eros eu, tincidunt enim. Nullam et ullamcorper nisi. Vivamus tellus ex, lobortis quis rutrum ut, dapibus sit amet turpis. Phasellus pellentesque metus diam, commodo tristique ante commodo ac. Ut mollis ipsum nec diam blandit sollicitudin. Duis bibendum lacus nec commodo dapibus. Sed condimentum luctus ante, id ultricies urna varius nec. Nam convallis magna nec bibendum ultrices. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed auctor pharetra quam, vitae porta ex bibendum eu.
Vivamus ut venenatis lectus. Phasellus nec elit id sem dictum ornare. Quisque feugiat, diam eget sagittis ultricies, orci turpis efficitur nisi, et fringilla justo odio nec nibh. In hac habitasse platea dictumst. Sed tempus bibendum feugiat. Etiam luctus mauris arcu, non interdum ipsum ultrices id. Vivamus blandit urna sit amet scelerisque vulputate. Quisque in metus eget massa rutrum dictum sit amet sed nulla. Vivamus vel efficitur dolor.
Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.
@@ -1,15 +0,0 @@
%%~name: Scene One
%%~path: 0e17daca5f3e1/031b4af5197ec
%%~kind: NOVEL/SCENE
### Scene One
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.
Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.
Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.
@@ -1,13 +0,0 @@
%%~name: Chapter One
%%~path: 811786ad1ae74/25fc0e7096fc6
%%~kind: NOVEL/CHAPTER
## Chapter One
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.
@@ -1,17 +0,0 @@
%%~name: Scene Two
%%~path: 0e17daca5f3e1/2858dcd1057d3
%%~kind: NOVEL/SCENE
### Scene Two
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.
Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.
Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.
@@ -1,11 +0,0 @@
%%~name: Scene Two, Section Two
%%~path: 0e17daca5f3e1/2fca346db6561
%%~kind: NOVEL/SCENE
#### Scene Two, Section Two
Suspendisse potenti. Fusce tempus lorem nec laoreet suscipit. Fusce vulputate nisl ac diam tincidunt, nec malesuada quam pellentesque. Maecenas congue, tellus quis commodo rutrum, magna leo egestas arcu, quis suscipit ex risus id ligula. Suspendisse potenti. Morbi blandit lacus vitae laoreet vulputate. Donec vitae tellus eleifend, lobortis eros eu, tincidunt enim. Nullam et ullamcorper nisi. Vivamus tellus ex, lobortis quis rutrum ut, dapibus sit amet turpis. Phasellus pellentesque metus diam, commodo tristique ante commodo ac. Ut mollis ipsum nec diam blandit sollicitudin. Duis bibendum lacus nec commodo dapibus. Sed condimentum luctus ante, id ultricies urna varius nec. Nam convallis magna nec bibendum ultrices. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed auctor pharetra quam, vitae porta ex bibendum eu.
Vivamus ut venenatis lectus. Phasellus nec elit id sem dictum ornare. Quisque feugiat, diam eget sagittis ultricies, orci turpis efficitur nisi, et fringilla justo odio nec nibh. In hac habitasse platea dictumst. Sed tempus bibendum feugiat. Etiam luctus mauris arcu, non interdum ipsum ultrices id. Vivamus blandit urna sit amet scelerisque vulputate. Quisque in metus eget massa rutrum dictum sit amet sed nulla. Vivamus vel efficitur dolor.
Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.
@@ -1,21 +0,0 @@
%%~name: Scene One
%%~path: 811786ad1ae74/31489056e0916
%%~kind: NOVEL/SCENE
### Scene One
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.
Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.
Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.
#### Scene One, Section Two
Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst.
Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend.
@@ -1,9 +0,0 @@
%%~name: Scene One, Section Two
%%~path: 0e17daca5f3e1/41cfc0d1f2d12
%%~kind: NOVEL/SCENE
#### Scene One, Section Two
Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst.
Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend.
@@ -1,25 +0,0 @@
%%~name: Scene Two
%%~path: 811786ad1ae74/98010bd9270f9
%%~kind: NOVEL/SCENE
### Scene Two
@pov: Bod
@plot: Main
@location: Europe
% Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.
Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.
Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.
#### Scene Two, Section Two
Suspendisse potenti. Fusce tempus lorem nec laoreet suscipit. Fusce vulputate nisl ac diam tincidunt, nec malesuada quam pellentesque. Maecenas congue, tellus quis commodo rutrum, magna leo egestas arcu, quis suscipit ex risus id ligula. Suspendisse potenti. Morbi blandit lacus vitae laoreet vulputate. Donec vitae tellus eleifend, lobortis eros eu, tincidunt enim. Nullam et ullamcorper nisi. Vivamus tellus ex, lobortis quis rutrum ut, dapibus sit amet turpis. Phasellus pellentesque metus diam, commodo tristique ante commodo ac. Ut mollis ipsum nec diam blandit sollicitudin. Duis bibendum lacus nec commodo dapibus. Sed condimentum luctus ante, id ultricies urna varius nec. Nam convallis magna nec bibendum ultrices. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed auctor pharetra quam, vitae porta ex bibendum eu.
Vivamus ut venenatis lectus. Phasellus nec elit id sem dictum ornare. Quisque feugiat, diam eget sagittis ultricies, orci turpis efficitur nisi, et fringilla justo odio nec nibh. In hac habitasse platea dictumst. Sed tempus bibendum feugiat. Etiam luctus mauris arcu, non interdum ipsum ultrices id. Vivamus blandit urna sit amet scelerisque vulputate. Quisque in metus eget massa rutrum dictum sit amet sed nulla. Vivamus vel efficitur dolor.
Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.
+6 -6
View File
@@ -27,7 +27,7 @@ import configparser
from shutil import copyfile
from dummy import causeOSError, DummyApp
from mock import causeOSError, MockApp
from tools import cmpFiles, writeFile
from nw.config import Config
@@ -195,7 +195,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
writeFile(os.path.join(i18nDir, "nw_en_GB.ts"), "")
writeFile(os.path.join(i18nDir, "nw_abcd.qm"), "")
tstApp = DummyApp()
tstApp = MockApp()
tstConf.initLocalisation(tstApp)
theList = tstConf.listLanguages(tstConf.LANG_NW)
assert theList == [("en_GB", "British English")]
@@ -252,7 +252,7 @@ def testBaseConfig_RecentCache(monkeypatch, tmpConf, tmpDir, fncDir):
}
# Remove Non-Existent Entry
assert not tmpConf.removeFromRecentCache("dummy")
assert not tmpConf.removeFromRecentCache("stuff")
assert tmpConf.recentProj == {
pathOne: {"time": 1600002000, "title": "Proj One", "words": 100},
pathTwo: {"time": 1600005600, "title": "Proj Two", "words": 200},
@@ -490,7 +490,7 @@ def testBaseConfig_Internal(monkeypatch, tmpConf):
cnfParse = configparser.ConfigParser()
cnfParse.read_string(
"[Main]\n"
"val_string = dummy\n"
"val_string = stuff\n"
"val_int = 123\n"
"val_bool = True\n"
"val_list_string = A, B, C\n"
@@ -499,7 +499,7 @@ def testBaseConfig_Internal(monkeypatch, tmpConf):
assert tmpConf._parseLine(
cnfParse, "Main", "val_string", tmpConf.CNF_STR, "default"
) == "dummy"
) == "stuff"
assert tmpConf._parseLine(
cnfParse, "Main", "nope", tmpConf.CNF_STR, "default"
) == "default"
@@ -554,7 +554,7 @@ def testBaseConfig_Internal(monkeypatch, tmpConf):
assert tmpConf.hasEnchant is False
with monkeypatch.context() as mp:
mp.setattr("shutil.which", lambda *args: "dummy")
mp.setattr("shutil.which", lambda *args: "stuff")
tmpConf._checkOptionalPackages()
assert tmpConf.hasAssistant is True
+1 -1
View File
@@ -25,7 +25,7 @@ import pytest
from PyQt5.QtWidgets import qApp
from dummy import causeException
from mock import causeException
from nw.error import NWErrorMessage, exceptionHandler
+6 -6
View File
@@ -25,19 +25,19 @@ import pytest
import logging
import sys
from dummy import DummyMain
from mock import MockGuiMain
@pytest.mark.base
def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
"""Check launching the main GUI.
"""
monkeypatch.setattr("nw.guimain.GuiMain", DummyMain)
monkeypatch.setattr("nw.guimain.GuiMain", MockGuiMain)
# Testmode launch
nwGUI = nw.main(
["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
)
assert isinstance(nwGUI, DummyMain)
assert isinstance(nwGUI, MockGuiMain)
# Darwin launch
monkeypatch.setitem(sys.modules, "Foundation", None)
@@ -46,7 +46,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
nwGUI = nw.main(
["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
)
assert isinstance(nwGUI, DummyMain)
assert isinstance(nwGUI, MockGuiMain)
assert "Foundation" in caplog.messages[1]
nw.CONFIG.osDarwin = osDarwin
@@ -68,7 +68,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
def testBaseInit_Options(monkeypatch, tmpDir):
"""Test command line options for logging level.
"""
monkeypatch.setattr("nw.guimain.GuiMain", DummyMain)
monkeypatch.setattr("nw.guimain.GuiMain", MockGuiMain)
monkeypatch.setattr(sys, "argv", [
"novelWriter.py", "--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir
])
@@ -140,7 +140,7 @@ def testBaseInit_Options(monkeypatch, tmpDir):
def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
"""Check import error handling.
"""
monkeypatch.setattr("nw.guimain.GuiMain", DummyMain)
monkeypatch.setattr("nw.guimain.GuiMain", MockGuiMain)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.__init__", lambda *args: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec_", lambda *args: 0)
monkeypatch.setattr("PyQt5.QtWidgets.QErrorMessage.__init__", lambda *args: None)
+26 -24
View File
@@ -23,10 +23,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
import pytest
from dummy import causeOSError
from mock import causeOSError
from nw.core import NWProject, NWDoc
from nw.core.item import NWItem
from nw.enum import nwItemClass, nwItemLayout
@pytest.mark.core
@@ -37,39 +36,37 @@ def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
assert theProject.openProject(nwMinimal)
assert theProject.projPath == nwMinimal
theDoc = NWDoc(theProject)
sHandle = "8c659a11cd429"
# Not a valid handle
assert theDoc.readDocument("dummy") is None
theDoc = NWDoc(theProject, "stuff")
assert theDoc.readDocument() is None
# Non-existent handle
assert theDoc.readDocument("0000000000000") is None
theDoc = NWDoc(theProject, "0000000000000")
assert theDoc.readDocument() is None
# Cause open() to fail while loading
def dummyOpen(*args, **kwargs):
raise OSError
with monkeypatch.context() as mp:
mp.setattr("builtins.open", dummyOpen)
assert theDoc.readDocument(sHandle) is None
mp.setattr("builtins.open", causeOSError)
theDoc = NWDoc(theProject, sHandle)
assert theDoc.readDocument() is None
assert theDoc.getError() == "OSError"
# Load the text
assert theDoc.readDocument(sHandle) == "### New Scene\n\n"
theDoc = NWDoc(theProject, sHandle)
assert theDoc.readDocument() == "### New Scene\n\n"
# Try to open a new (non-existent) file
nHandle = theProject.projTree.findRoot(nwItemClass.NOVEL)
assert nHandle is not None
xHandle = theProject.newFile("New File", nwItemClass.NOVEL, nHandle)
assert theDoc.readDocument(xHandle) == ""
# Check cached item
assert isinstance(theDoc._theItem, NWItem)
assert theDoc.readDocument(xHandle, isOrphan=True) == ""
assert theDoc._theItem is None
theDoc = NWDoc(theProject, xHandle)
assert theDoc.readDocument() == ""
# Set handle and save again
theText = "### Test File\n\nText ...\n\n"
theDoc = NWDoc(theProject, xHandle)
assert theDoc.readDocument(xHandle) == ""
assert theDoc.writeDocument(theText)
@@ -98,22 +95,27 @@ def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal):
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert not theDoc.writeDocument(theText)
assert theDoc.getError() == "OSError"
# Saving with no handle
theDoc.clearDocument()
theDoc._docHandle = None
assert not theDoc.writeDocument(theText)
# Delete the last document
assert not theDoc.deleteDocument("dummy")
theDoc = NWDoc(theProject, "stuff")
assert not theDoc.deleteDocument()
assert os.path.isfile(docPath)
# Cause the delete to fail
with monkeypatch.context() as mp:
mp.setattr("os.unlink", causeOSError)
assert not theDoc.deleteDocument(xHandle)
theDoc = NWDoc(theProject, xHandle)
assert not theDoc.deleteDocument()
assert theDoc.getError() == "OSError"
# Make the delete pass
assert theDoc.deleteDocument(xHandle)
theDoc = NWDoc(theProject, xHandle)
assert theDoc.deleteDocument()
assert not os.path.isfile(docPath)
# END Test testCoreDocument_Load
@@ -126,11 +128,11 @@ def testCoreDocument_Methods(monkeypatch, dummyGUI, nwMinimal):
assert theProject.openProject(nwMinimal)
assert theProject.projPath == nwMinimal
theDoc = NWDoc(theProject)
sHandle = "8c659a11cd429"
theDoc = NWDoc(theProject, sHandle)
docPath = os.path.join(nwMinimal, "content", sHandle+".nwd")
assert theDoc.readDocument(sHandle) == "### New Scene\n\n"
assert theDoc.readDocument() == "### New Scene\n\n"
# Check location
assert theDoc.getFileLocation() == docPath
@@ -158,6 +160,6 @@ def testCoreDocument_Methods(monkeypatch, dummyGUI, nwMinimal):
"Text ...\n\n"
)
assert theDoc.readDocument(sHandle) == "### Test File\n\nText ...\n\n"
assert theDoc.readDocument() == "### Test File\n\nText ...\n\n"
# END Test testCoreDocument_Methods
+1 -1
View File
@@ -26,7 +26,7 @@ import json
from shutil import copyfile
from dummy import causeException
from mock import causeException
from tools import cmpFiles
from nw.core.project import NWProject
+1 -1
View File
@@ -24,7 +24,7 @@ import os
import json
import pytest
from dummy import causeOSError
from mock import causeOSError
from nw.core import NWProject
from nw.core.options import OptionState
+18 -18
View File
@@ -28,7 +28,7 @@ from zipfile import ZipFile
from lxml import etree
from tools import cmpFiles, writeFile, readFile
from dummy import causeOSError
from mock import causeOSError
from nw.core.project import NWProject
from nw.enum import nwItemClass, nwItemType, nwItemLayout
@@ -354,11 +354,11 @@ def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
oName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3]+"orig")
bName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3]+"bak")
os.rename(rName, oName)
writeFile(rName, "dummy")
writeFile(rName, "stuff")
assert theProject.openProject(nwMinimal) is False
# Also write a jun XML backup file
writeFile(bName, "dummy")
writeFile(bName, "stuff")
assert theProject.openProject(nwMinimal) is False
# Wrong root item
@@ -426,9 +426,9 @@ def testCoreProject_Open(monkeypatch, nwMinimal, dummyGUI):
os.rename(oName, rName)
# Add some legacy stuff that cannot be removed
writeFile(os.path.join(nwMinimal, "junk"), "dummy")
writeFile(os.path.join(nwMinimal, "junk"), "stuff")
os.mkdir(os.path.join(nwMinimal, "data_0"))
writeFile(os.path.join(nwMinimal, "data_0", "junk"), "dummy")
writeFile(os.path.join(nwMinimal, "data_0", "junk"), "stuff")
dummyGUI.clear()
assert theProject.openProject(nwMinimal) is True
assert "data_0" in dummyGUI.lastAlert
@@ -559,19 +559,19 @@ def testCoreProject_Helpers(monkeypatch, fncDir, dummyGUI):
# Create a file to block meta folder
metaDir = os.path.join(fncDir, "meta")
writeFile(metaDir, "dummy")
writeFile(metaDir, "stuff")
assert theProject.ensureFolderStructure() is False
os.unlink(metaDir)
# Create a file to block cache folder
cacheDir = os.path.join(fncDir, "cache")
writeFile(cacheDir, "dummy")
writeFile(cacheDir, "stuff")
assert theProject.ensureFolderStructure() is False
os.unlink(cacheDir)
# Create a file to block content folder
contentDir = os.path.join(fncDir, "content")
writeFile(contentDir, "dummy")
writeFile(contentDir, "stuff")
assert theProject.ensureFolderStructure() is False
os.unlink(contentDir)
@@ -977,7 +977,7 @@ def testCoreProject_OldFormat(dummyGUI, nwOldProj):
"""
theProject = NWProject(dummyGUI)
# Create dummy files for known legacy files
# Create mock files for known legacy files
deleteFiles = [
os.path.join(nwOldProj, "cache", "nwProject.nwx.0"),
os.path.join(nwOldProj, "cache", "nwProject.nwx.1"),
@@ -1005,7 +1005,7 @@ def testCoreProject_OldFormat(dummyGUI, nwOldProj):
os.mkdir(os.path.join(nwOldProj, "stuff"))
os.mkdir(os.path.join(nwOldProj, "data_1", "stuff"))
# Create dummy files
# Create mock files
os.mkdir(os.path.join(nwOldProj, "cache"))
for aFile in deleteFiles:
writeFile(aFile, "Hi")
@@ -1071,7 +1071,7 @@ def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
# Check behaviour of deprecated files function on OSError
tstFile = os.path.join(fncDir, "ToC.json")
writeFile(tstFile, "dummy")
writeFile(tstFile, "stuff")
assert os.path.isfile(tstFile)
with monkeypatch.context() as mp:
@@ -1083,7 +1083,7 @@ def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
# Check processing non-folders
tstFile = os.path.join(fncDir, "data_0")
writeFile(tstFile, "dummy")
writeFile(tstFile, "stuff")
assert os.path.isfile(tstFile)
errList = []
@@ -1128,12 +1128,12 @@ def testCoreProject_LegacyData(monkeypatch, dummyGUI, fncDir):
tstDoc3b = os.path.join(tstData, "tooshort003_main.bak")
os.mkdir(tstData)
writeFile(tstDoc1m, "dummy")
writeFile(tstDoc1b, "dummy")
writeFile(tstDoc2m, "dummy")
writeFile(tstDoc2b, "dummy")
writeFile(tstDoc3m, "dummy")
writeFile(tstDoc3b, "dummy")
writeFile(tstDoc1m, "stuff")
writeFile(tstDoc1b, "stuff")
writeFile(tstDoc2m, "stuff")
writeFile(tstDoc2b, "stuff")
writeFile(tstDoc3m, "stuff")
writeFile(tstDoc3b, "stuff")
# Make the above fail
with monkeypatch.context() as mp:
+4 -4
View File
@@ -24,7 +24,7 @@ import os
import sys
import pytest
from dummy import causeOSError
from mock import causeOSError
from tools import readFile, writeFile
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
@@ -38,7 +38,7 @@ def testCoreSpell_Super(monkeypatch, tmpDir):
spChk = NWSpellCheck()
# Check that dummy functions return results that reflects that spell
# Check that default functions return results that reflects that spell
# checking is effectively disabled
assert spChk.setLanguage("", "") is None
assert spChk.checkWord("")
@@ -47,7 +47,7 @@ def testCoreSpell_Super(monkeypatch, tmpDir):
assert spChk.describeDict() == ("", "")
# Add a word to the user's dictionary
assert spChk._readProjectDictionary("dummy") is False
assert spChk._readProjectDictionary("stuff") is False
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert spChk._readProjectDictionary(wList) is False
@@ -77,7 +77,7 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
wList = os.path.join(tmpDir, "wordlist.txt")
writeFile(wList, "a_word\nb_word\nc_word\n")
# Block the enchant package (and trigger the dummy class)
# Block the enchant package (and trigger the default class)
with monkeypatch.context() as mp:
mp.setitem(sys.modules, "enchant", None)
spChk = NWSpellEnchant()
+1 -1
View File
@@ -49,7 +49,7 @@ def testCoreStatus_Entries():
# Lookups
assert theStatus.lookupEntry(None) is None
assert theStatus.lookupEntry("dummy") is None
assert theStatus.lookupEntry("stuff") is None
assert theStatus.lookupEntry("Main") == 3
# Checks
+4 -6
View File
@@ -137,23 +137,21 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, dummyGUI):
)
docTextR = docText.replace("<A>", "this").replace("<B>", "that")
nDoc = NWDoc(theProject)
nDoc.readDocument(sHandle)
nDoc.writeDocument(docText)
nDoc.clearDocument()
nDoc = NWDoc(theProject, sHandle)
assert nDoc.writeDocument(docText)
theProject.setAutoReplace({"A": "this", "B": "that"})
assert theProject.saveProject()
# Root heading
assert theToken.addRootHeading("dummy") is False
assert theToken.addRootHeading("stuff") is False
assert theToken.addRootHeading(sHandle) is False
assert theToken.addRootHeading("7695ce551d265") is True
assert theToken.theMarkdown[-1] == "# Notes: Plot\n\n"
# Set text
assert theToken.setText("dummy") is False
assert theToken.setText("stuff") is False
assert theToken.setText(sHandle) is True
assert theToken.theText == docText
+11 -11
View File
@@ -31,7 +31,7 @@ from nw.constants import nwFiles
@pytest.fixture(scope="function")
def dummyItems(dummyGUI):
"""Create a list of dummy items.
"""Create a list of mock items.
"""
theProject = NWProject(dummyGUI)
@@ -176,7 +176,7 @@ def testCoreTree_BuildTree(dummyGUI, dummyItems):
assert len(theTree) == len(dummyItems) + 1
# Delete a non-existing item
del theTree["dummy"]
del theTree["stuff"]
assert len(theTree) == len(dummyItems) + 1
# Delete the last item
@@ -214,7 +214,7 @@ def testCoreTree_Methods(dummyGUI, dummyItems):
assert len(theTree) == len(dummyItems)
# Root item lookup
theTree._treeRoots.append("dummy")
theTree._treeRoots.append("stuff")
assert theTree.findRoot(nwItemClass.WORLD) is None
assert theTree.findRoot(nwItemClass.NOVEL) == "a000000000001"
assert theTree.findRoot(nwItemClass.CHARACTER) == "a000000000004"
@@ -229,16 +229,16 @@ def testCoreTree_Methods(dummyGUI, dummyItems):
assert theTree.getRootItem("b000000000001").itemHandle == "a000000000001"
assert theTree.getRootItem("c000000000001").itemHandle == "a000000000001"
assert theTree.getRootItem("c000000000002").itemHandle == "a000000000001"
assert theTree.getRootItem("dummy") is None
assert theTree.getRootItem("stuff") is None
# Get item path
assert theTree.getItemPath("dummy") == []
assert theTree.getItemPath("stuff") == []
assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001", "a000000000001"
]
# Break the folder parent handle
theTree["b000000000001"].itemParent = "dummy"
theTree["b000000000001"].itemParent = "stuff"
assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001"
]
@@ -249,7 +249,7 @@ def testCoreTree_Methods(dummyGUI, dummyItems):
]
# Change file layout
assert not theTree.setFileItemLayout("dummy", nwItemLayout.UNNUMBERED)
assert not theTree.setFileItemLayout("stuff", nwItemLayout.UNNUMBERED)
assert not theTree.setFileItemLayout("b000000000001", nwItemLayout.UNNUMBERED)
assert not theTree.setFileItemLayout("c000000000001", "stuff")
assert theTree.setFileItemLayout("c000000000001", nwItemLayout.UNNUMBERED)
@@ -424,7 +424,7 @@ def testCoreTree_Stats(dummyGUI, dummyItems):
theTree.append(tHandle, pHandle, nwItem)
assert len(theTree) == len(dummyItems)
theTree._treeOrder.append("dummy")
theTree._treeOrder.append("stuff")
# Count Words
novelWords, noteWords = theTree.sumWords()
@@ -461,10 +461,10 @@ def testCoreTree_Reorder(dummyGUI, dummyItems):
theTree.setOrder(bHandle)
assert theTree.handles() == bHandle
theTree.setOrder(bHandle + ["dummy"])
theTree.setOrder(bHandle + ["stuff"])
assert theTree.handles() == bHandle
theTree._treeOrder.append("dummy")
theTree._treeOrder.append("stuff")
theTree.setOrder(bHandle)
assert theTree.handles() == bHandle
@@ -536,7 +536,7 @@ def testCoreTree_ToCFile(monkeypatch, dummyGUI, dummyItems, tmpDir):
theTree.append(tHandle, pHandle, nwItem)
assert len(theTree) == len(dummyItems)
theTree._treeOrder.append("dummy")
theTree._treeOrder.append("stuff")
def dummyIsFile(fileName):
"""Return True for items that are files in novelWriter and
+182
View File
@@ -0,0 +1,182 @@
# -*- coding: utf-8 -*-
"""
novelWriter Merge and Split Dialog Classes Tester
===================================================
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
import os
from tools import getGuiItem, readFile, writeFile
from mock import causeOSError
from PyQt5.QtWidgets import QAction, QMessageBox, QDialog
from nw.dialogs import GuiDocMerge, GuiItemEditor
from nw.enum import nwItemType, nwWidget
from nw.core.tree import NWTree
keyDelay = 2
typeDelay = 1
stepDelay = 20
@pytest.mark.gui
def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the merge documents tool.
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok)
# Create a new project
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.newProject({"projPath": fncProj})
# Handles for new objects
hChapterDir = "31489056e0916"
hChapterOne = "98010bd9270f9"
hSceneOne = "0e17daca5f3e1"
hSceneTwo = "1a6562590ef19"
hSceneThree = "031b4af5197ec"
hSceneFour = "41cfc0d1f2d12"
hMergedDoc = "2858dcd1057d3"
# Add Project Content
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted)
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
assert nwGUI.saveProject() is True
assert nwGUI.closeProject() is True
tChapterOne = "## Chapter One\n\n% Chapter one comment\n"
tSceneOne = "### Scene One\n\nThere once was a man from Nantucket"
tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket."
tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man"
tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket."
contentDir = os.path.join(fncProj, "content")
writeFile(os.path.join(contentDir, hChapterOne+".nwd"), tChapterOne)
writeFile(os.path.join(contentDir, hSceneOne+".nwd"), tSceneOne)
writeFile(os.path.join(contentDir, hSceneTwo+".nwd"), tSceneTwo)
writeFile(os.path.join(contentDir, hSceneThree+".nwd"), tSceneThree)
writeFile(os.path.join(contentDir, hSceneFour+".nwd"), tSceneFour)
assert nwGUI.openProject(fncProj) is True
# Open the Merge tool
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
monkeypatch.setattr(GuiDocMerge, "exec_", lambda *a: None)
nwGUI.mainMenu.aMergeDocs.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocMerge") is not None, timeout=1000)
nwMerge = getGuiItem("GuiDocMerge")
assert isinstance(nwMerge, GuiDocMerge)
nwMerge.show()
qtbot.wait(stepDelay)
# Populate List
# =============
nwMerge.listBox.clear()
assert nwMerge.listBox.count() == 0
# No item selected
nwGUI.treeView.clearSelection()
assert nwMerge._populateList() is False
assert nwMerge.listBox.count() == 0
# Non-existing item
with monkeypatch.context() as mp:
mp.setattr(NWTree, "__getitem__", lambda *a: None)
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
assert nwMerge._populateList() is False
assert nwMerge.listBox.count() == 0
# Select a non-folder
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterOne).setSelected(True)
assert nwMerge._populateList() is False
assert nwMerge.listBox.count() == 0
# Select the chapter folder
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
assert nwMerge._populateList() is True
assert nwMerge.listBox.count() == 5
# Merge Documents
# ===============
# First, a successful merge
with monkeypatch.context() as mp:
mp.setattr(GuiDocMerge, "_doClose", lambda *a: None)
assert nwMerge._doMerge() is True
assert nwGUI.saveProject() is True
mergedFile = os.path.join(contentDir, hMergedDoc+".nwd")
assert os.path.isfile(mergedFile)
assert readFile(mergedFile) == (
"%%%%~name: New Chapter\n"
"%%%%~path: 73475cb40a568/2858dcd1057d3\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
"%s\n\n"
"%s\n\n"
"%s\n\n"
"%s\n\n"
) % (
tChapterOne.strip(),
tSceneOne.strip(),
tSceneTwo.strip(),
tSceneThree.strip(),
tSceneFour.strip(),
)
# OS error
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert nwMerge._doMerge() is False
# Can't find the source item
with monkeypatch.context() as mp:
mp.setattr(NWTree, "__getitem__", lambda *a: None)
assert nwMerge._doMerge() is False
# No source handle set
nwMerge.sourceItem = None
assert nwMerge._doMerge() is False
# No documents to merge
nwMerge.listBox.clear()
assert nwMerge._doMerge() is False
# Close up
nwMerge._doClose()
# qtbot.stopForInteraction()
# END Test testDlgMerge_Main
-185
View File
@@ -1,185 +0,0 @@
# -*- coding: utf-8 -*-
"""
novelWriter Merge and Split Dialog Classes Tester
===================================================
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
import os
from shutil import copyfile
from tools import cmpFiles, getGuiItem
from PyQt5.QtWidgets import QAction, QMessageBox
from nw.dialogs import GuiDocMerge, GuiDocSplit
keyDelay = 2
typeDelay = 1
stepDelay = 20
@pytest.mark.gui
def testDlgMergeSplit_Tools(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
"""Test the full merge and split tools.
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwLipsum)
qtbot.wait(stepDelay)
assert nwGUI.treeView.setSelectedHandle("45e6b01ca35c1")
qtbot.wait(stepDelay)
monkeypatch.setattr(GuiDocMerge, "exec_", lambda *args: None)
nwGUI.mainMenu.aMergeDocs.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocMerge") is not None, timeout=1000)
nwMerge = getGuiItem("GuiDocMerge")
assert isinstance(nwMerge, GuiDocMerge)
nwMerge.show()
qtbot.wait(stepDelay)
nwMerge._doMerge()
qtbot.wait(stepDelay)
assert nwGUI.theProject.projTree["73475cb40a568"] is not None
projFile = os.path.join(nwLipsum, "content", "73475cb40a568.nwd")
testFile = os.path.join(outDir, "guiMerge_73475cb40a568.nwd")
compFile = os.path.join(refDir, "guiMerge_73475cb40a568.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
# Split By Chapter
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
qtbot.wait(stepDelay)
monkeypatch.setattr(GuiDocSplit, "exec_", lambda *args: None)
nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000)
nwSplit = getGuiItem("GuiDocSplit")
assert isinstance(nwSplit, GuiDocSplit)
nwSplit.show()
qtbot.wait(stepDelay)
nwSplit.splitLevel.setCurrentIndex(1)
qtbot.wait(stepDelay)
nwSplit._doSplit()
assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None
# This should give us back the file as it was before
projFile = os.path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
testFile = os.path.join(outDir, "guiMerge_71ee45a3c0db9.nwd")
compFile = os.path.join(refDir, "guiMerge_73475cb40a568.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [1, 2, 3])
# Split By Scene
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
qtbot.wait(stepDelay)
nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000)
nwSplit = getGuiItem("GuiDocSplit")
assert isinstance(nwSplit, GuiDocSplit)
qtbot.wait(stepDelay)
nwSplit.splitLevel.setCurrentIndex(2)
qtbot.wait(stepDelay)
nwSplit._doSplit()
assert nwGUI.theProject.projTree["25fc0e7096fc6"] is not None
assert nwGUI.theProject.projTree["31489056e0916"] is not None
assert nwGUI.theProject.projTree["98010bd9270f9"] is not None
projFile = os.path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
testFile = os.path.join(outDir, "guiSplit_25fc0e7096fc6.nwd")
compFile = os.path.join(refDir, "guiSplit_25fc0e7096fc6.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
projFile = os.path.join(nwLipsum, "content", "31489056e0916.nwd")
testFile = os.path.join(outDir, "guiSplit_31489056e0916.nwd")
compFile = os.path.join(refDir, "guiSplit_31489056e0916.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
projFile = os.path.join(nwLipsum, "content", "98010bd9270f9.nwd")
testFile = os.path.join(outDir, "guiSplit_98010bd9270f9.nwd")
compFile = os.path.join(refDir, "guiSplit_98010bd9270f9.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
# Split By Section
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
qtbot.wait(stepDelay)
nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000)
nwSplit = getGuiItem("GuiDocSplit")
assert isinstance(nwSplit, GuiDocSplit)
qtbot.wait(stepDelay)
nwSplit.splitLevel.setCurrentIndex(3)
qtbot.wait(stepDelay)
nwSplit._doSplit()
assert nwGUI.theProject.projTree["1a6562590ef19"] is not None
assert nwGUI.theProject.projTree["031b4af5197ec"] is not None
assert nwGUI.theProject.projTree["41cfc0d1f2d12"] is not None
assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None
assert nwGUI.theProject.projTree["2fca346db6561"] is not None
projFile = os.path.join(nwLipsum, "content", "1a6562590ef19.nwd")
testFile = os.path.join(outDir, "guiSplit_1a6562590ef19.nwd")
compFile = os.path.join(refDir, "guiSplit_25fc0e7096fc6.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [1, 2, 3])
projFile = os.path.join(nwLipsum, "content", "031b4af5197ec.nwd")
testFile = os.path.join(outDir, "guiSplit_031b4af5197ec.nwd")
compFile = os.path.join(refDir, "guiSplit_031b4af5197ec.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
projFile = os.path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
testFile = os.path.join(outDir, "guiSplit_41cfc0d1f2d12.nwd")
compFile = os.path.join(refDir, "guiSplit_41cfc0d1f2d12.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
projFile = os.path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
testFile = os.path.join(outDir, "guiSplit_2858dcd1057d3.nwd")
compFile = os.path.join(refDir, "guiSplit_2858dcd1057d3.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
projFile = os.path.join(nwLipsum, "content", "2fca346db6561.nwd")
testFile = os.path.join(outDir, "guiSplit_2fca346db6561.nwd")
compFile = os.path.join(refDir, "guiSplit_2fca346db6561.nwd")
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
# qtbot.stopForInteraction()
# END Test testDlgMergeSplit_Tools
+261
View File
@@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
novelWriter Merge and Split Dialog Classes Tester
===================================================
This file is a part of novelWriter
Copyright 20182021, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
import os
from tools import getGuiItem, readFile, writeFile
from mock import causeOSError
from PyQt5.QtWidgets import QAction, QMessageBox, QDialog
from nw.dialogs import GuiDocSplit, GuiItemEditor
from nw.enum import nwItemType, nwWidget
from nw.core.document import NWDoc
from nw.core.tree import NWTree
keyDelay = 2
typeDelay = 1
stepDelay = 20
@pytest.mark.gui
def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"""Test the split document tool.
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok)
# Create a new project
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.newProject({"projPath": fncProj}) is True
# Handles for new objects
hNovelRoot = "73475cb40a568"
hChapterDir = "31489056e0916"
hToSplit = "1a6562590ef19"
hPartition = "41cfc0d1f2d12"
hChapterOne = "2858dcd1057d3"
hSceneOne = "2fca346db6561"
hSceneTwo = "02d20bbd7e394"
hSceneThree = "7688b6ef52555"
hSceneFour = "c837649cce43f"
hSceneFive = "6208ef0f7750c"
# Add Project Content
monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted)
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hNovelRoot).setSelected(True)
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
assert nwGUI.saveProject() is True
assert nwGUI.closeProject() is True
tPartition = "# Nantucket"
tChapterOne = "## Chapter One\n\n% Chapter one comment"
tSceneOne = "### Scene One\n\nThere once was a man from Nantucket"
tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket."
tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man"
tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket."
tSceneFive = "#### The End\n\nend"
tToSplit = (
f"{tPartition}\n\n{tChapterOne}\n\n"
f"{tSceneOne}\n\n{tSceneTwo}\n\n"
f"{tSceneThree}\n\n{tSceneFour}\n\n"
f"{tSceneFive}\n\n"
)
contentDir = os.path.join(fncProj, "content")
writeFile(os.path.join(contentDir, hToSplit+".nwd"), tToSplit)
assert nwGUI.openProject(fncProj) is True
# Open the Split tool
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hToSplit).setSelected(True)
monkeypatch.setattr(GuiDocSplit, "exec_", lambda *a: None)
nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000)
nwSplit = getGuiItem("GuiDocSplit")
assert isinstance(nwSplit, GuiDocSplit)
nwSplit.show()
qtbot.wait(stepDelay)
# Populate List
# =============
nwSplit.listBox.clear()
assert nwSplit.listBox.count() == 0
# No item selected
nwSplit.sourceItem = None
nwGUI.treeView.clearSelection()
assert nwSplit._populateList() is False
assert nwSplit.listBox.count() == 0
# Non-existing item
with monkeypatch.context() as mp:
mp.setattr(NWTree, "__getitem__", lambda *a: None)
nwSplit.sourceItem = None
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hToSplit).setSelected(True)
assert nwSplit._populateList() is False
assert nwSplit.listBox.count() == 0
# Select a non-file
nwSplit.sourceItem = None
nwGUI.treeView.clearSelection()
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
assert nwSplit._populateList() is False
assert nwSplit.listBox.count() == 0
# Error when reading documents
with monkeypatch.context() as mp:
mp.setattr(NWDoc, "readDocument", lambda *a: None)
nwSplit.sourceItem = hToSplit
assert nwSplit._populateList() is False
assert nwSplit.listBox.count() == 0
# Read properly, and check split levels
# Level 1
nwSplit.splitLevel.setCurrentIndex(0)
nwSplit.sourceItem = hToSplit
assert nwSplit._populateList() is True
assert nwSplit.listBox.count() == 1
# Level 2
nwSplit.splitLevel.setCurrentIndex(1)
nwSplit.sourceItem = hToSplit
assert nwSplit._populateList() is True
assert nwSplit.listBox.count() == 2
# Level 3
nwSplit.splitLevel.setCurrentIndex(2)
nwSplit.sourceItem = hToSplit
assert nwSplit._populateList() is True
assert nwSplit.listBox.count() == 6
# Level 4
nwSplit.splitLevel.setCurrentIndex(3)
nwSplit.sourceItem = hToSplit
assert nwSplit._populateList() is True
assert nwSplit.listBox.count() == 7
# Split Document
# ==============
# Test a proper split first
with monkeypatch.context() as mp:
mp.setattr(GuiDocSplit, "_doClose", lambda *a: None)
assert nwSplit._doSplit() is True
assert nwGUI.saveProject()
assert readFile(os.path.join(contentDir, hPartition+".nwd")) == (
"%%%%~name: Nantucket\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/PARTITION\n"
"%s\n\n"
) % (hPartition, tPartition)
assert readFile(os.path.join(contentDir, hChapterOne+".nwd")) == (
"%%%%~name: Chapter One\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/CHAPTER\n"
"%s\n\n"
) % (hChapterOne, tChapterOne)
assert readFile(os.path.join(contentDir, hSceneOne+".nwd")) == (
"%%%%~name: Scene One\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
) % (hSceneOne, tSceneOne)
assert readFile(os.path.join(contentDir, hSceneTwo+".nwd")) == (
"%%%%~name: Scene Two\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
) % (hSceneTwo, tSceneTwo)
assert readFile(os.path.join(contentDir, hSceneThree+".nwd")) == (
"%%%%~name: Scene Three\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
) % (hSceneThree, tSceneThree)
assert readFile(os.path.join(contentDir, hSceneFour+".nwd")) == (
"%%%%~name: Scene Four\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
) % (hSceneFour, tSceneFour)
assert readFile(os.path.join(contentDir, hSceneFive+".nwd")) == (
"%%%%~name: The End\n"
"%%%%~path: 031b4af5197ec/%s\n"
"%%%%~kind: NOVEL/SCENE\n"
"%s\n\n"
) % (hSceneFive, tSceneFive)
# OS error
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert nwSplit._doSplit() is False
# Select to not split
with monkeypatch.context() as mp:
mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No)
assert nwSplit._doSplit() is False
# Block folder creation by returning that the folder has a depth
# of 50 items in the tree
with monkeypatch.context() as mp:
mp.setattr(NWTree, "getItemPath", lambda *a: [""]*50)
assert nwSplit._doSplit() is False
# Clear the list
nwSplit.listBox.clear()
assert nwSplit._doSplit() is False
# Can't find sourcv item
with monkeypatch.context() as mp:
mp.setattr(NWTree, "__getitem__", lambda *a: None)
assert nwSplit._doSplit() is False
# No source item set
nwSplit.sourceItem = None
assert nwSplit._doSplit() is False
# Close up
nwSplit._doClose()
# qtbot.stopForInteraction()
# END Test testDlgSplit_Main
+1 -1
View File
@@ -26,7 +26,7 @@ from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QMessageBox, QAction
from tools import writeFile, readFile, getGuiItem
from dummy import causeOSError
from mock import causeOSError
from nw.dialogs import GuiWordList
from nw.constants import nwFiles
+3 -3
View File
@@ -249,14 +249,14 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir, outDi
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
for c in "This is a paragraph of dummy text.":
for c in "This is a paragraph of nonsense text.":
qtbot.keyClick(nwGUI.docEditor, c, delay=typeDelay)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
for c in (
"This is another paragraph of much longer dummy text. "
"It is in fact 1 very very DUMB dummy text! "
"This is another paragraph of much longer nonsense text. "
"It is in fact 1 very very NONSENSICAL nonsense text! "
):
qtbot.keyClick(nwGUI.docEditor, c, delay=typeDelay)
for c in "We can also try replacing \"quotes\", even single 'quotes' are replaced. ":
+1 -1
View File
@@ -165,7 +165,7 @@ def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir):
assert isinstance(anIcon, QIcon)
assert not anIcon.isNull()
# Add dummy icons and test alternative load paths
# Add test icons and test alternative load paths
theIcons.ICON_MAP["testicon1"] = (QStyle.SP_DriveHDIcon, None)
anIcon = theIcons.getIcon("testicon1")
assert isinstance(anIcon, QIcon)
+1 -1
View File
@@ -25,7 +25,7 @@ import json
import os
from tools import getGuiItem, writeFile
from dummy import causeOSError
from mock import causeOSError
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox