Merge branch 'dev' into release_2.2rc1
This commit is contained in:
+43
-43
@@ -32,14 +32,14 @@ final release.
|
||||
that tag will appear in the menu. On selection, it will create a note in the first root folder of
|
||||
the correct kind, and set the title and tag to match the undefined reference, making it instantly
|
||||
defined. Issues #1580 and #823. PR #1582.
|
||||
* Shortcodes have been added to the Document Editor. Shorcodes are HTML-like syntax, but uses
|
||||
* Shortcodes have been added to the Document Editor. Shortcodes are HTML-like syntax, but uses
|
||||
square brackets instead of angular brackets. So `[b]text[/b]` will make the word "text" appear as
|
||||
bold. Shortcodes currently support bold, italic, striketrough, underline, superscript and
|
||||
bold. Shortcodes currently support bold, italic, strike trough, underline, superscript and
|
||||
subscript text. The first three are complimentary to the Markdown-like syntax that. The benefit
|
||||
of the shortcode emphasis syntax, however, is that it does not care about word boundaries, and
|
||||
can therefore be used any place in the text. Including in the middle of words. Issues #1337 and
|
||||
#1444. PRs #1540 and #1583.
|
||||
* A show/hide toolbar has been added to the editor where toolbuttons for formatting options are
|
||||
* A show/hide toolbar has been added to the editor where tool buttons for formatting options are
|
||||
available. The toolbar is hidden by default, but can be activated from a three dots icon in the
|
||||
top left corner of the editor. Issue #1585. PR #1584.
|
||||
* Build Definitions in the Manuscript Build tool can now be re-ordered, and the order is preserved
|
||||
@@ -105,7 +105,7 @@ changes have been fixed as well. See the full changelog for more details.
|
||||
Qt 5.15.8. In particular, it is possible to drop items on the root level, and it's possible to
|
||||
move root items to other locations. Neither should be possible and will severely mess up the
|
||||
project if done. Issue #1569. PR #1570.
|
||||
* Add a custom autoscroll feature when dragging an item in the project tree to near the top or
|
||||
* Add a custom auto-scroll feature when dragging an item in the project tree to near the top or
|
||||
bottom. This is actually a default feature of the tree widget in the Qt library, but this too is
|
||||
broken in some versions of Qt 5.15.x. The default feature has been permanently disabled and
|
||||
replaced by a custom written feature that behaves similarly. Issue #1561. PR #1571.
|
||||
@@ -327,7 +327,7 @@ This is a patch release that fixes a few issues and adds a Japanese translation.
|
||||
|
||||
The issues were mostly related to spell checking. In particular, issues with finding the word
|
||||
boundary when using underscore characters for italics markup. These issues should now be resolved.
|
||||
In addition, escaped markup characters are now renderred properly in HTML and ODT build formats.
|
||||
In addition, escaped markup characters are now rendered properly in HTML and ODT build formats.
|
||||
|
||||
A few usability improvements have also been made. The Add Item menu in the project tree no longer
|
||||
shows the options to create Novel Documents when an item in the tree is selected that cannot hold
|
||||
@@ -487,7 +487,7 @@ This is a patch release that fixes a few bugs and usability issues. The editing
|
||||
importance labels in Project Settings should now be a bit more intuitive. Opening a document from
|
||||
the Outline View that is already open in the editor should now switch to the editor view. The
|
||||
convert folder to note or document feature in the project tree has also been fixed. Some icons have
|
||||
been updated and a renderring issue with one of them fixed. Chinese, Norwegian, US English, German
|
||||
been updated and a rendering issue with one of them fixed. Chinese, Norwegian, US English, German
|
||||
and Spanish translations have been updated as well. A new credits tab has been added to the About
|
||||
dialog box, replacing the Credits section on the main About tab.
|
||||
|
||||
@@ -757,7 +757,7 @@ opened, a request to update the file format will show up.
|
||||
PR #1212.
|
||||
* The GUI theme now determines which icon theme is to be loaded. It is no longer a separate
|
||||
setting. The icon theme can also be reloaded without restart. Issue #1172. PR #1212.
|
||||
* The block formating features in the Format menu now also works on empty lines. Issue #1178.
|
||||
* The block formatting features in the Format menu now also works on empty lines. Issue #1178.
|
||||
PR #1214.
|
||||
* There is now a Format menu entry and shortcut code for synopsis comments. Issue #1177. PR #1214.
|
||||
* The split document dialog now has the option to move teh source document to trash. Issue #1179.
|
||||
@@ -794,7 +794,7 @@ opened, a request to update the file format will show up.
|
||||
correct type information. PR #1197.
|
||||
* Saving and loading of XML data is now handled by a separate set of reader and writer classes. The
|
||||
reader class is capable of reading all file formats that have been used thus far. The various
|
||||
data classes have been improved, and a new XML file formart version 1.5 added. Issue #1189.
|
||||
data classes have been improved, and a new XML file format version 1.5 added. Issue #1189.
|
||||
PRs #1221 and #1232.
|
||||
* The index is now automatically rebuilt when the project file format is updated. Issue #1235.
|
||||
PR #1236.
|
||||
@@ -987,8 +987,8 @@ final release.
|
||||
setting is preserved. Previously, the Importance setting would overwrite it during the
|
||||
conversion. PR #1030.
|
||||
* Item labels, Status labels, and other labels on the GUI are now run through a "simplify" function
|
||||
before being accepted. This functions strips out all whitespaces and consecutive whitespaces and
|
||||
replace them with single plain whitespaces. This is a safer format to store in XML, and also
|
||||
before being accepted. This functions strips out all white spaces and consecutive white spaces
|
||||
and replace them with single plain white spaces. This is a safer format to store in XML, and also
|
||||
makes sure there aren't invisible characters floating around in the labels. PR #1038.
|
||||
* Due to the changes to how drag and drop works, there are no longer any restrictions on folders
|
||||
and documents. Only root folders remain restricted in terms of moving. Root folders can only be
|
||||
@@ -1494,7 +1494,7 @@ checking enabled if there is something wrong with the spell check package.
|
||||
**Bugfixes**
|
||||
|
||||
* When the HTML converter replaced grater than or smaller than symbols with the corresponding HTML
|
||||
entities. the poisition of the formatting tags following in the text would be shifted, but the
|
||||
entities. the position of the formatting tags following in the text would be shifted, but the
|
||||
positions were not updated. This is now solved by updating these positions when such a symbol is
|
||||
encountered. This issue has been backported from 1.6 development. Issue #929.
|
||||
* If the pyenchant package is installed, but the underlying enchant library is broken in one way or
|
||||
@@ -1659,7 +1659,7 @@ backups.
|
||||
the case. Having two alternative spell checkers complicated the code a great deal, and the
|
||||
internal spell checker also required full word lists to be distributed with novelWriter. PR #875.
|
||||
* Added a setting in Preferences to change how the word count on the status bar is calculated. The
|
||||
new setting allows the project notes to be filetred out, leaving only the word count for novel
|
||||
new setting allows the project notes to be filtered out, leaving only the word count for novel
|
||||
files. Feature request #857. PR #882.
|
||||
|
||||
**Installation and Packaging**
|
||||
@@ -1678,7 +1678,7 @@ backups.
|
||||
|
||||
**Internationalisation**
|
||||
|
||||
* The US English and Nowregian translation files have been updated. PR #884.
|
||||
* The US English and Norwegian translation files have been updated. PR #884.
|
||||
|
||||
**Documentation**
|
||||
|
||||
@@ -1709,7 +1709,7 @@ careful when using this version on live writing projects, and make sure you take
|
||||
|
||||
**Internationalisation**
|
||||
|
||||
* The US English and Nowregian translation files have been updated. PR #870.
|
||||
* The US English and Norwegian translation files have been updated. PR #870.
|
||||
|
||||
**Documentation**
|
||||
|
||||
@@ -2297,7 +2297,7 @@ buttons were blocked when they shouldn't. This release resolves these issues.
|
||||
This release is mainly focused on the Build Novel Project tool. Completely new export classes have
|
||||
been written to support Open Document and Markdown exports. In addition, the way document layouts
|
||||
are handled have been automated a little to assist the user in keeping header levels and document
|
||||
layout flags in sync. The third new additoion is the ability to record and log idle time during a
|
||||
layout flags in sync. The third new addition is the ability to record and log idle time during a
|
||||
writing session to improve the writing statistics information as requested by several users.
|
||||
Finally, it is now possible to directly edit the project dictionary via a new, simple GUI dialog.
|
||||
|
||||
@@ -2390,7 +2390,7 @@ _These Release Notes also include the changes from 1.2 Beta 1 and RC 1._
|
||||
the index on next load. For earlier versions of novelWriter before 1.1.1, it would also cause a
|
||||
crash. Invalid keywords are now rejected during indexing. Issue #688. PR #689.
|
||||
* The "Empty Trash" option was no longer working due to an earlier fix that added a requirement
|
||||
that the project tree has focus to allow the emptying to procede. Since the Empty Trash feature
|
||||
that the project tree has focus to allow the emptying to proceed. Since the Empty Trash feature
|
||||
opens a dialog, the tree loses focus, and the deletions are therefore ignored. The focus check is
|
||||
no longer considered when emptying the trash. Issue #701. PR #702.
|
||||
|
||||
@@ -2450,7 +2450,7 @@ _The Release Notes have been moved and merged into the 1.2 RC 1 notes._
|
||||
* A full Markdown exporter has been written and added for the Build Novel Project tool. This too
|
||||
replaces a Qt feature that was used to save the content of the preview window into a markdown
|
||||
file. The exporter allows for both standard markdown and GitHub flavour markdown. The only
|
||||
relevant difference being that the latter allows strikethrough text. Issue #617. PR #650.
|
||||
relevant difference being that the latter allows strike through text. Issue #617. PR #650.
|
||||
* The Build Novel Project tool now has a "Line height" property that is applied to the preview, and
|
||||
to the HTML5 and Open Document export formats. Discussion #653. Issue #654. PR #660.
|
||||
* The Build Novel Project tool now has an option to convert Unicode characters to HTML entities on
|
||||
@@ -2531,7 +2531,7 @@ but is still lacking in functionality compared to Enchant.
|
||||
exclude negative word counts is active. Previously, the entries with negative counts were
|
||||
filtered out, but the change in count was still applied to the next line, altering the value.
|
||||
Now, the GUI will instead just drop the lines that are negative and keep the other lines
|
||||
unchanged. This is more intutitive, but it also means that the total count now longer matches the
|
||||
unchanged. This is more intuitive, but it also means that the total count now longer matches the
|
||||
sum of the lines. PR #659.
|
||||
* The keyboard shortcut for deleting entries in the project tree has been changed from `Ctrl+Del`
|
||||
to `Ctrl+Shift+Del`. The `Ctrl+Del` shortcut is thus free to be used exclusively by the editor to
|
||||
@@ -2544,7 +2544,7 @@ but is still lacking in functionality compared to Enchant.
|
||||
given a significant speed improvement by caching the imported dictionary as a Python `set`
|
||||
instead of a `list`. The `set` has a hashed key lookup algorithm that is significantly faster.
|
||||
PR #668.
|
||||
* Sessions shortar than 5 minutes, and with no word count changes, are no longer recorded in the
|
||||
* Sessions shorter than 5 minutes, and with no word count changes, are no longer recorded in the
|
||||
session stats log file. PR #685.
|
||||
|
||||
**Installation**
|
||||
@@ -3009,7 +3009,7 @@ issues are discovered, the next release will be the final version 1.0 release.
|
||||
|
||||
* The tests for the core classes of novelWriter have been completely rewritten. Every class or
|
||||
source file of the core functionality (everything handling the actual project data and documents,
|
||||
as well as the meta data) is now covered by its own testmodule with a 100% coverage for each
|
||||
as well as the meta data) is now covered by its own test module with a 100% coverage for each
|
||||
module. PR #512.
|
||||
* Likewise, the base tests have been rewritten to cover the `Config` class, the `main` function
|
||||
that launches the app, and the error handling class. The structure matches the core tests from
|
||||
@@ -3041,7 +3041,7 @@ The "Typewriter Mode" of the editor has been improved. Essentially, this feature
|
||||
scroll. It tries to keep the cursor stationary in the vertical direction, and will try to scroll
|
||||
the document up when the cursor skips to a new line while typing (or down in case of backspaces).
|
||||
This is similar to the way a typewriter scrolls the paper when hitting the return key. It improves
|
||||
the writing experience as the current active line will stay at the same eye heightlevel on the
|
||||
the writing experience as the current active line will stay at the same eye height level on the
|
||||
screen.
|
||||
|
||||
Previously, the feature would lock the cursor to a given vertical position defined by the user.
|
||||
@@ -3089,7 +3089,7 @@ Switching main GUI theme still requires a restart.
|
||||
handled by the various tools, but they shouldn't even trigger when there is no project or
|
||||
document to perform the action on. PR #492.
|
||||
* Clarify the message of the Close Project and Exit novelWriter dialogs. Previously, it may have
|
||||
seemed to some users that clicking "No" would allow the closing to procede without saving
|
||||
seemed to some users that clicking "No" would allow the closing to proceed without saving
|
||||
changes. This is not true as changes are saved automatically when editing a project. The dialog
|
||||
text should now make this clearer. Issue #494, PR #495.
|
||||
|
||||
@@ -3134,7 +3134,7 @@ Switching main GUI theme still requires a restart.
|
||||
**User Interface**
|
||||
|
||||
* An option has been added in Preferences to hide horizontal or vertical scroll bars on the main
|
||||
GUI. These optons will hide scroll bars on the Project Tree, Document Editor, Document Viewer,
|
||||
GUI. These options will hide scroll bars on the Project Tree, Document Editor, Document Viewer,
|
||||
Outline Tab and on the controls of the Build Novel Project tool. Scroll bars take up space, and
|
||||
as long as the project doesn't contain very long documents, scrolling with the mouse wheel is
|
||||
enough. The feature is of course entirely optional. PRs #468 and #469.
|
||||
@@ -3154,7 +3154,7 @@ Switching main GUI theme still requires a restart.
|
||||
* When applying a format from the format menu to a selection of multiple paragraphs (or lines),
|
||||
only the first paragraph (or line) receives the formatting. The editor doesn't allow markdown
|
||||
formatting to span multiple lines. Issue #451, PR #475.
|
||||
* The syntax highlighter no longer uses the same colour to highlight strikethrough text as for
|
||||
* The syntax highlighter no longer uses the same colour to highlight strike through text as for
|
||||
emphasised text. The colour is intended to stand out, which makes little sense for such text.
|
||||
Instead, the highlighter uses the same colour as for comments. PR #476.
|
||||
|
||||
@@ -3305,7 +3305,7 @@ Switching main GUI theme still requires a restart.
|
||||
|
||||
**Code Improvements**
|
||||
|
||||
* Minor improvemenmts have been made to the core project classes to improve encapsulation and
|
||||
* Minor improvements have been made to the core project classes to improve encapsulation and
|
||||
better ensure consistency between the different data structures that store the novel project in
|
||||
memory. PR #447.
|
||||
* Some unused or redundant code has been removed, and in some places, functions have been merged to
|
||||
@@ -3322,9 +3322,9 @@ Switching main GUI theme still requires a restart.
|
||||
**Bugfixes**
|
||||
|
||||
* If the horizontal scroll bar appeared at the bottom of the document editor or viewer, for
|
||||
instance if a long, un-wrapable line was entered, the scroll bar would sit on top of the document
|
||||
footer. The footer bar now properly moves out of the way when the horizontal scroll bar appears.
|
||||
Issue #433, PR #434.
|
||||
instance if a long, un-wrappable line was entered, the scroll bar would sit on top of the
|
||||
document footer. The footer bar now properly moves out of the way when the horizontal scroll bar
|
||||
appears. Issue #433, PR #434.
|
||||
|
||||
**New Features**
|
||||
|
||||
@@ -3446,7 +3446,7 @@ Switching main GUI theme still requires a restart.
|
||||
leading line break. This was previously handled entirely by the Qt library, which does this for
|
||||
some reason. Issue #395, PR #405.
|
||||
* A chapter heading in a file with a different layout than `Unnumbered` can now also be flagged as
|
||||
an unnumbered chapter heading by adding an asterisk to the begfinning of the title text. This
|
||||
an unnumbered chapter heading by adding an asterisk to the beginning of the title text. This
|
||||
only affects the number assignment and counter when running the Build Novel Project tool. The
|
||||
rest of the app ignores the asterisk. Issue #402, PR #406.
|
||||
|
||||
@@ -3461,7 +3461,7 @@ Switching main GUI theme still requires a restart.
|
||||
create a copy of the example project from the source code. Either from the `sample` folder in the
|
||||
source, or from a `sample.zip` file generated by the `setup.py` script and saved to the
|
||||
`nw/assets` folder. PR #366.
|
||||
* When the user clicked cancel on the colour dialog in Project Settins, the icon would be reset to
|
||||
* When the user clicked cancel on the colour dialog in Project Settings, the icon would be reset to
|
||||
black. Instead, the colour should remain unchanged. A check that the user actually selected a
|
||||
colour has now been added. Issue #395, PR #403.
|
||||
|
||||
@@ -3537,7 +3537,7 @@ planned by GitHub. See their [notes](https://github.com/github/renaming) for mor
|
||||
[novelwriter.readthedocs.io](https://novelwriter.readthedocs.io/) has been rewritten. It was
|
||||
drifting out of sync with the development of the code. In addition, many improvements have been
|
||||
made to the reStructuredText formatting of the documentation source by providing better
|
||||
cross-reference linking and highlightings. The main repository README file has been updated to
|
||||
cross-reference linking and highlighting. The main repository README file has been updated to
|
||||
match. PRs #375, #382, and #384.
|
||||
* The main `setup.py` script has been updated to also build documentation for the Qt Assistant when
|
||||
given a `qthelp` flag. The compiled help files are copied into the `nw/assets/help` folder, and
|
||||
@@ -3635,7 +3635,7 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
has been removed from the main window status bar. PR #348.
|
||||
* The document editor footer can optionally be hidden in Distraction Free mode. PR #351.
|
||||
* The Italic and Bold menu entries have been renamed to Emphasis and Strong Emphasis, which is more
|
||||
in line with what they represent in Markdown and HTML. They are still renderred as Italic and
|
||||
in line with what they represent in Markdown and HTML. They are still rendered as Italic and
|
||||
Bold in the document viewer, but the HTML export is using the `<em>` and `<strong>` tags.
|
||||
PR #350.
|
||||
* Due to several issues with the formatting of emphasised text using `*`, `**`, and `***` wrappers,
|
||||
@@ -3648,9 +3648,9 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
for emphasis and strong is commonly recommended when writing Markdown anyway, so it is a sensible
|
||||
compromise between speed and flexibility. This PR partially reverses PR #310. Issue #353,
|
||||
PR #355.
|
||||
* The syntax highlighter now properly highlights overlapping formattings, including emphasised text
|
||||
* The syntax highlighter now properly highlights overlapping formatting, including emphasised text
|
||||
inside of highlighted quotes. PR #355.
|
||||
* The colour highlighting of emphasis, strong and strikethrough, can now be switch off in
|
||||
* The colour highlighting of emphasis, strong and strike through, can now be switch off in
|
||||
Preferences. The syntax highlighter will still apply the italic, bold and strike effects.
|
||||
PR #357.
|
||||
* The project path in the Details tab of Project Settings can now be selected and copied to
|
||||
@@ -3681,7 +3681,7 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
visible in the tree. It is called when you for instance click the header of an open document. It
|
||||
was also activated when opening a document from the tree view with either double-click by mouse,
|
||||
or by using the Enter key. This meant that the tree view would often move, which made it hard to
|
||||
mouse click on items after eachother since you ended up chasing a moving target. This feature is
|
||||
mouse click on items after each other since you ended up chasing a moving target. This feature is
|
||||
now disabled for document open. In addition, the scroll into view feature has been added to the
|
||||
search/replace call to move into the next document when reaching the end of the current document.
|
||||
This was requested in Issue #332. PR #334.
|
||||
@@ -3692,7 +3692,7 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
**Documentation**
|
||||
|
||||
* The documentation has been updated to clarify the correct formatting for italic, bold and
|
||||
strikethrough formatting tags. Issue #220, PR #338.
|
||||
strike through formatting tags. Issue #220, PR #338.
|
||||
|
||||
----
|
||||
|
||||
@@ -3711,11 +3711,11 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
|
||||
* Underline text formatting has been removed. It is not standard HTML5, nor Markdown, and was
|
||||
previously implemented using the double underscore notation that in standard Markdown is
|
||||
renderred as bold text. Instead, novelWriter now renders a single `*` or `_` wrapping a piece of
|
||||
rendered as bold text. Instead, novelWriter now renders a single `*` or `_` wrapping a piece of
|
||||
text _within_ a paragraphs as italicised text, and a double `**` or `__` as bold text. The
|
||||
keyboard shortcuts and automatic features _only_ support the `*` notation. A triple set of `***`
|
||||
are treated as both bold and italicised. PR #310.
|
||||
* Strikethrough formatting has been added back into novelWriter using the standard Markdown `~~`
|
||||
* Strike through formatting has been added back into novelWriter using the standard Markdown `~~`
|
||||
wrapping. PR #310.
|
||||
* Added support for thin spaces and non-breaking thin spaces. PR #319.
|
||||
* The `Ctrl+Z` key sequence (undo) would not go through the wrapper function for document action
|
||||
@@ -3732,7 +3732,7 @@ longer be read by an earlier version due to the change of how autoReplace settin
|
||||
PR #309.
|
||||
* The text emphasis functions, either selected from the menu or via keyboard shortcuts, will now
|
||||
try to respond to the command in a more meaningful way. That is, the text editor will try to
|
||||
toggle the bold or italics features independently of eachother on the selected text. A menu entry
|
||||
toggle the bold or italics features independently of each other on the selected text. A menu entry
|
||||
to apply both at the same time has also been added. PR #310.
|
||||
* The document editor search tool has been completely rewritten. It now appears as a search box at
|
||||
the top of the document, and has a number of toggle switches added to it. You can modify the
|
||||
@@ -4102,7 +4102,7 @@ that I can spend more time using it than creating it.
|
||||
**Additional thanks** to @countjocular for PRs #173 and #174, and to @johnblommers for all the
|
||||
helpful feedback and issue reports for the new features added in this, and previous releases.
|
||||
|
||||
### Noteable Changes
|
||||
### Notable Changes
|
||||
|
||||
* The Timeline View dialog is now gone. Instead, the main window area has been split into two tabs.
|
||||
The first, the "Editor", contains the Document Editor and Viewer panels. The second, the
|
||||
@@ -4253,7 +4253,7 @@ helpful feedback and issue reports for the new features added in this, and previ
|
||||
**Bug Fixes**
|
||||
|
||||
* Fixed an issue when closing the import file dialog without selecting a file, the import would
|
||||
procede, but fail on file not found. The import is now cancelled when there is no file selected.
|
||||
proceed, but fail on file not found. The import is now cancelled when there is no file selected.
|
||||
PR #149.
|
||||
* Fixed an issue with markdown export where it did not take into account hard line breaks. Issue
|
||||
#151, PR #152.
|
||||
@@ -4663,7 +4663,7 @@ This is the initial release of a working version of novelWriter, but with very l
|
||||
capabilities. So far, the following has been implemented:
|
||||
|
||||
* A document tree with a set of pre-defined root folders of a given set of classes for different
|
||||
purposes for novel writing. That is, a root item for the novel itself, one for charcaters, plot
|
||||
purposes for novel writing. That is, a root item for the novel itself, one for characters, plot
|
||||
elements, timeline, locations, objects, and a custom one.
|
||||
* A plain text editor with a simplified markdown format that allows for four levels of titles, and
|
||||
bold, italics and underline text.
|
||||
@@ -4671,7 +4671,7 @@ capabilities. So far, the following has been implemented:
|
||||
* It also allows for keyword/value sets staring with the character `@`. These will later be used
|
||||
to link documents together as tags point to other documents. For instance, a scene file can
|
||||
point the keyword `@POV:name` to a character file with the keyword `@THIS:name`.
|
||||
* The text editor has a set of autoreplace features:
|
||||
* The text editor has a set of auto replace features:
|
||||
* Dashes are made by combining two or three hyphens.
|
||||
* Three dots are replaced with the ellipsis.
|
||||
* Straight quotes with your quote format of choice.
|
||||
|
||||
@@ -46,21 +46,21 @@ Project Tree Shortcuts
|
||||
.. csv-table::
|
||||
:header: "Shortcut", "Description"
|
||||
|
||||
":kbd:`F2`", "Edit the label of the selected item"
|
||||
":kbd:`Return`", "Open the selected document in the editor"
|
||||
":kbd:`Alt+Up`", "Jump or go to the previous item at same level in the tree"
|
||||
":kbd:`Alt+Down`", "Jump or go to the next item at same level in the tree"
|
||||
":kbd:`Alt+Left`", "Jump to the parent item in the tree"
|
||||
":kbd:`Alt+Right`", "Jump to the first child item in the project tree"
|
||||
":kbd:`Ctrl+.`", "Open the context menu on the selected item"
|
||||
":kbd:`Ctrl+L`", "Open the :guilabel:`Quick Links` menu"
|
||||
":kbd:`Ctrl+N`", "Open the :guilabel:`Create New Item` menu"
|
||||
":kbd:`Ctrl+O`", "Open selected document"
|
||||
":kbd:`Ctrl+R`", "Open the selected document in the viewer"
|
||||
":kbd:`Ctrl+Up`", "Move selected item one step up in the tree"
|
||||
":kbd:`Ctrl+Down`", "Move selected item one step down in the tree"
|
||||
":kbd:`Ctrl+Del`", "Move the selected item to Trash"
|
||||
":kbd:`Ctrl+Shift+Z`", "Undo the last move of a project item, if possible"
|
||||
":kbd:`F2`", "Edit the label of the selected item"
|
||||
":kbd:`Return`", "Open the selected document in the editor"
|
||||
":kbd:`Alt+Up`", "Jump or go to the previous item at same level in the tree"
|
||||
":kbd:`Alt+Down`", "Jump or go to the next item at same level in the tree"
|
||||
":kbd:`Alt+Left`", "Jump to the parent item in the tree"
|
||||
":kbd:`Alt+Right`", "Jump to the first child item in the project tree"
|
||||
":kbd:`Ctrl+.`", "Open the context menu on the selected item"
|
||||
":kbd:`Ctrl+L`", "Open the :guilabel:`Quick Links` menu"
|
||||
":kbd:`Ctrl+N`", "Open the :guilabel:`Create New Item` menu"
|
||||
":kbd:`Ctrl+O`", "Open selected document"
|
||||
":kbd:`Ctrl+R`", "Open the selected document in the viewer"
|
||||
":kbd:`Ctrl+Up`", "Move selected item one step up in the tree"
|
||||
":kbd:`Ctrl+Down`", "Move selected item one step down in the tree"
|
||||
":kbd:`Ctrl+Shift+Del`", "Move the selected item to Trash"
|
||||
":kbd:`Ctrl+Shift+Z`", "Undo the last move of a project item, if possible"
|
||||
|
||||
|
||||
.. _a_kb_editor:
|
||||
@@ -90,6 +90,8 @@ Text Formatting Shortcuts
|
||||
.. csv-table::
|
||||
:header: "Shortcut", "Description"
|
||||
|
||||
":kbd:`Ctrl+'`", "Wrap selected text, or word under cursor, in single quotes"
|
||||
":kbd:`Ctrl+""`", "Wrap selected text, or word under cursor, in double quotes"
|
||||
":kbd:`Ctrl+/`", "Toggle block format as comment"
|
||||
":kbd:`Ctrl+0`", "Remove block formatting for block under cursor"
|
||||
":kbd:`Ctrl+1`", "Change block format to header level 1"
|
||||
@@ -104,8 +106,6 @@ Text Formatting Shortcuts
|
||||
":kbd:`Ctrl+B`", "Format selected text, or word under cursor, with strong emphasis (bold)"
|
||||
":kbd:`Ctrl+D`", "Strikethrough selected text, or word under cursor"
|
||||
":kbd:`Ctrl+I`", "Format selected text, or word under cursor, with emphasis (italic)"
|
||||
":kbd:`Ctrl+'`", "Wrap selected text, or word under cursor, in single quotes"
|
||||
":kbd:`Ctrl+""`", "Wrap selected text, or word under cursor, in double quotes"
|
||||
":kbd:`Ctrl+Shift+/`", "Remove block formatting for block under cursor"
|
||||
|
||||
|
||||
@@ -127,10 +127,10 @@ Other Editor Shortcuts
|
||||
":kbd:`Ctrl+X`", "Cut selected text to clipboard"
|
||||
":kbd:`Ctrl+Y`", "Redo latest undo"
|
||||
":kbd:`Ctrl+Z`", "Undo latest changes"
|
||||
":kbd:`Ctrl+Del`", "Delete the word after the cursor"
|
||||
":kbd:`Ctrl+Backspace`", "Delete the word before the cursor"
|
||||
":kbd:`Ctrl+Return`", "Open the tag or reference under the cursor in the viewer"
|
||||
":kbd:`Ctrl+Del`", "Delete the word after the cursor"
|
||||
":kbd:`Ctrl+F7`", "Toggle spell checking"
|
||||
":kbd:`Ctrl+Return`", "Open the tag or reference under the cursor in the viewer"
|
||||
":kbd:`Ctrl+Shift+A`", "Select all text in the current paragraph"
|
||||
":kbd:`Ctrl+Shift+I`", "Import text to the current document from a text file"
|
||||
|
||||
@@ -147,39 +147,40 @@ a key or key combination for the inserted content.
|
||||
.. csv-table::
|
||||
:header: "Shortcut", "Description"
|
||||
|
||||
":kbd:`Ctrl+K`, :kbd:`−`", "Insert a short dash (en dash)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Space`", "Insert a non-breaking space"
|
||||
":kbd:`Ctrl+K`, :kbd:`_`", "Insert a long dash (em dash)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+_`", "Insert a horizontal bar (quotation dash)"
|
||||
":kbd:`Ctrl+K`, :kbd:`.`", "Insert an ellipsis"
|
||||
":kbd:`Ctrl+K`, :kbd:`'`", "Insert a modifier apostrophe"
|
||||
":kbd:`Ctrl+K`, :kbd:`*`", "Insert a list bullet"
|
||||
":kbd:`Ctrl+K`, :kbd:`%`", "Insert a per mille symbol"
|
||||
":kbd:`Ctrl+K`, :kbd:`~`", "Insert a figure dash (same width as a number)"
|
||||
":kbd:`Ctrl+K`, :kbd:`−`", "Insert a short dash (en dash)"
|
||||
":kbd:`Ctrl+K`, :kbd:`1`", "Insert a left single quote"
|
||||
":kbd:`Ctrl+K`, :kbd:`2`", "Insert a right single quote"
|
||||
":kbd:`Ctrl+K`, :kbd:`3`", "Insert a left double quote"
|
||||
":kbd:`Ctrl+K`, :kbd:`4`", "Insert a right double quote"
|
||||
":kbd:`Ctrl+K`, :kbd:`'`", "Insert a modifier apostrophe"
|
||||
":kbd:`Ctrl+K`, :kbd:`.`", "Insert an ellipsis"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+'`", "Insert a prime"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+""`", "Insert a double prime"
|
||||
":kbd:`Ctrl+K`, :kbd:`Space`", "Insert a non-breaking space"
|
||||
":kbd:`Ctrl+K`, :kbd:`Shift+Space`", "Insert a thin space"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+Space`", "Insert a thin non-breaking space"
|
||||
":kbd:`Ctrl+K`, :kbd:`*`", "Insert a list bullet"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+−`", "Insert a hyphen bullet (alternative bullet)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+*`", "Insert a flower mark (alternative bullet)"
|
||||
":kbd:`Ctrl+K`, :kbd:`%`", "Insert a per mille symbol"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+O`", "Insert a degree symbol"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+X`", "Insert a times sign"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+D`", "Insert a division sign"
|
||||
":kbd:`Ctrl+K`, :kbd:`G`", "Insert a ``@tag`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`V`", "Insert a ``@pov`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`F`", "Insert a ``@focus`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`C`", "Insert a ``@char`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`E`", "Insert an ``@entity`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`F`", "Insert a ``@focus`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`G`", "Insert a ``@tag`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`H`", "Insert a short description comment"
|
||||
":kbd:`Ctrl+K`, :kbd:`L`", "Insert a ``@location`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`O`", "Insert an ``@object`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`P`", "Insert a ``@plot`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`S`", "Insert a synopsis comment"
|
||||
":kbd:`Ctrl+K`, :kbd:`T`", "Insert a ``@time`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`L`", "Insert a ``@location`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`O`", "Insert an ``@object`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`E`", "Insert an ``@entity`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`V`", "Insert a ``@pov`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`X`", "Insert a ``@custom`` keyword"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+Space`", "Insert a thin non-breaking space"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+_`", "Insert a horizontal bar (quotation dash)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+'`", "Insert a prime"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+""`", "Insert a double prime"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+*`", "Insert a flower mark (alternative bullet)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+−`", "Insert a hyphen bullet (alternative bullet)"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+D`", "Insert a division sign"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+O`", "Insert a degree symbol"
|
||||
":kbd:`Ctrl+K`, :kbd:`Ctrl+X`", "Insert a times sign"
|
||||
":kbd:`Ctrl+K`, :kbd:`Shift+Space`", "Insert a thin space"
|
||||
|
||||
|
||||
.. _a_kb_viewer:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"Synopsis": "Synopsis",
|
||||
"Short Description": "Short Description",
|
||||
"Comment": "Comment",
|
||||
"Notes": "Notes",
|
||||
"Tag": "Tag",
|
||||
|
||||
@@ -406,6 +406,7 @@ class ProjectBuilder:
|
||||
|
||||
chSynop = self.tr("Summary of the chapter.")
|
||||
scSynop = self.tr("Summary of the scene.")
|
||||
bfNote = self.tr("A short description.")
|
||||
|
||||
# Create chapters
|
||||
if numChapters > 0:
|
||||
@@ -446,7 +447,11 @@ class ProjectBuilder:
|
||||
aHandle = project.newFile(noteTitles[newRoot], rHandle)
|
||||
ntTag = simplified(noteTitles[newRoot]).replace(" ", "")
|
||||
aDoc = project.storage.getDocument(aHandle)
|
||||
aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n")
|
||||
aDoc.writeDocument(
|
||||
f"# {noteTitles[newRoot]}\n\n"
|
||||
f"@tag: {ntTag}\n\n"
|
||||
f"% Short: {bfNote}\n\n"
|
||||
)
|
||||
|
||||
# Also add the archive and trash folders
|
||||
project.newRoot(nwItemClass.ARCHIVE)
|
||||
|
||||
+22
-10
@@ -36,7 +36,7 @@ from typing import TYPE_CHECKING, ItemsView, Iterable, Iterator
|
||||
from pathlib import Path
|
||||
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||
from novelwriter.enum import nwComment, nwItemClass, nwItemType, nwItemLayout
|
||||
from novelwriter.error import logException
|
||||
from novelwriter.common import checkInt, isHandle, isItemClass, isTitleTag, jsonEncode
|
||||
from novelwriter.constants import nwFiles, nwKeyWords, nwRegEx, nwUnicode, nwHeaders
|
||||
@@ -338,14 +338,9 @@ class NWIndex:
|
||||
|
||||
elif line.startswith("%"):
|
||||
if cTitle != TT_NONE:
|
||||
toCheck = line[1:].lstrip()
|
||||
synTag = toCheck[:9].lower()
|
||||
tLen = len(line)
|
||||
cLen = len(toCheck)
|
||||
cOff = tLen - cLen
|
||||
if synTag == "synopsis:":
|
||||
sText = line[cOff+9:].strip()
|
||||
self._itemIndex.setHeadingSynopsis(tHandle, cTitle, sText)
|
||||
cStyle, cText, _ = processComment(line)
|
||||
if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT):
|
||||
self._itemIndex.setHeadingSynopsis(tHandle, cTitle, cText)
|
||||
|
||||
# Count words for remaining text after last heading
|
||||
if pTitle != TT_NONE:
|
||||
@@ -1269,9 +1264,26 @@ class IndexHeading:
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
# Simple Word Counter
|
||||
# Text Processing Functions
|
||||
# =============================================================================================== #
|
||||
|
||||
CLASSIFIERS = {
|
||||
"short": nwComment.SHORT,
|
||||
"synopsis": nwComment.SYNOPSIS,
|
||||
}
|
||||
|
||||
|
||||
def processComment(text: str) -> tuple[nwComment, str, int]:
|
||||
"""Extract comment style and text. Should only be called on text
|
||||
starting with a %.
|
||||
"""
|
||||
check = text[1:].lstrip()
|
||||
classifier, _, content = check.partition(":")
|
||||
if content and (clean := classifier.strip().lower()) in CLASSIFIERS:
|
||||
return CLASSIFIERS[clean], content.strip(), text.find(":") + 1
|
||||
return nwComment.PLAIN, check, 0
|
||||
|
||||
|
||||
def countWords(text: str) -> tuple[int, int, int]:
|
||||
"""Count words in a piece of text, skipping special syntax and
|
||||
comments.
|
||||
|
||||
@@ -69,6 +69,9 @@ VALID_MAP = {
|
||||
"GuiManuscriptBuild": {
|
||||
"winWidth", "winHeight", "fmtWidth", "sumWidth",
|
||||
},
|
||||
"GuiDocViewerPanel": {
|
||||
"colWidths",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -287,7 +287,10 @@ class ToHtml(Tokenizer):
|
||||
para.append(stripEscape(tTemp.rstrip()))
|
||||
|
||||
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
||||
lines.append(self._formatSynopsis(tText))
|
||||
lines.append(self._formatSynopsis(tText, True))
|
||||
|
||||
elif tType == self.T_SHORT and self._doSynopsis:
|
||||
lines.append(self._formatSynopsis(tText, False))
|
||||
|
||||
elif tType == self.T_COMMENT and self._doComments:
|
||||
lines.append(self._formatComments(tText))
|
||||
@@ -454,9 +457,12 @@ class ToHtml(Tokenizer):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _formatSynopsis(self, text: str) -> str:
|
||||
def _formatSynopsis(self, text: str, synopsis: bool) -> str:
|
||||
"""Apply HTML formatting to synopsis."""
|
||||
sSynop = self._localLookup("Synopsis")
|
||||
if synopsis:
|
||||
sSynop = self._localLookup("Synopsis")
|
||||
else:
|
||||
sSynop = self._localLookup("Short Description")
|
||||
if self._genMode == self.M_PREVIEW:
|
||||
return f"<p class='comment'><span class='synopsis'>{sSynop}:</span> {text}</p>\n"
|
||||
else:
|
||||
|
||||
@@ -34,8 +34,9 @@ from pathlib import Path
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||
from novelwriter.core.index import processComment
|
||||
|
||||
from novelwriter.enum import nwItemLayout
|
||||
from novelwriter.enum import nwComment, nwItemLayout
|
||||
from novelwriter.common import formatTimeStamp, numberToRoman, checkInt
|
||||
from novelwriter.constants import nwHeadFmt, nwRegEx, nwShortcode, nwUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
@@ -79,17 +80,18 @@ class Tokenizer(ABC):
|
||||
# Block Type
|
||||
T_EMPTY = 1 # Empty line (new paragraph)
|
||||
T_SYNOPSIS = 2 # Synopsis comment
|
||||
T_COMMENT = 3 # Comment line
|
||||
T_KEYWORD = 4 # Command line
|
||||
T_TITLE = 5 # Title
|
||||
T_UNNUM = 6 # Unnumbered
|
||||
T_HEAD1 = 7 # Header 1
|
||||
T_HEAD2 = 8 # Header 2
|
||||
T_HEAD3 = 9 # Header 3
|
||||
T_HEAD4 = 10 # Header 4
|
||||
T_TEXT = 11 # Text line
|
||||
T_SEP = 12 # Scene separator
|
||||
T_SKIP = 13 # Paragraph break
|
||||
T_SHORT = 3 # Short description comment
|
||||
T_COMMENT = 4 # Comment line
|
||||
T_KEYWORD = 5 # Command line
|
||||
T_TITLE = 6 # Title
|
||||
T_UNNUM = 7 # Unnumbered
|
||||
T_HEAD1 = 8 # Header 1
|
||||
T_HEAD2 = 9 # Header 2
|
||||
T_HEAD3 = 10 # Header 3
|
||||
T_HEAD4 = 11 # Header 4
|
||||
T_TEXT = 12 # Text line
|
||||
T_SEP = 13 # Scene separator
|
||||
T_SKIP = 14 # Paragraph break
|
||||
|
||||
# Block Style
|
||||
A_NONE = 0x0000 # No special style
|
||||
@@ -461,17 +463,22 @@ class Tokenizer(ABC):
|
||||
continue
|
||||
|
||||
if aLine[0] == "%":
|
||||
cLine = aLine[1:].lstrip()
|
||||
synTag = cLine[:9].lower()
|
||||
if synTag == "synopsis:":
|
||||
cStyle, cText, _ = processComment(aLine)
|
||||
if cStyle == nwComment.SYNOPSIS:
|
||||
self._tokens.append((
|
||||
self.T_SYNOPSIS, nHead, cLine[9:].strip(), None, sAlign
|
||||
self.T_SYNOPSIS, nHead, cText, None, sAlign
|
||||
))
|
||||
if self._doSynopsis and self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
elif cStyle == nwComment.SHORT:
|
||||
self._tokens.append((
|
||||
self.T_SHORT, nHead, cText, None, sAlign
|
||||
))
|
||||
if self._doSynopsis and self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
else:
|
||||
self._tokens.append((
|
||||
self.T_COMMENT, nHead, aLine[1:].strip(), None, sAlign
|
||||
self.T_COMMENT, nHead, cText, None, sAlign
|
||||
))
|
||||
if self._doComments and self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
@@ -170,6 +170,10 @@ class ToMarkdown(Tokenizer):
|
||||
label = self._localLookup("Synopsis")
|
||||
lines.append(f"**{label}:** {tText}\n\n")
|
||||
|
||||
elif tType == self.T_SHORT and self._doSynopsis:
|
||||
label = self._localLookup("Short Description")
|
||||
lines.append(f"**{label}:** {tText}\n\n")
|
||||
|
||||
elif tType == self.T_COMMENT and self._doComments:
|
||||
label = self._localLookup("Comment")
|
||||
lines.append(f"**{label}:** {tText}\n\n")
|
||||
|
||||
@@ -481,7 +481,11 @@ class ToOdt(Tokenizer):
|
||||
pFmt.append(tFormat)
|
||||
|
||||
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
||||
tTemp, fTemp = self._formatSynopsis(tText)
|
||||
tTemp, fTemp = self._formatSynopsis(tText, True)
|
||||
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
|
||||
|
||||
elif tType == self.T_SHORT and self._doSynopsis:
|
||||
tTemp, fTemp = self._formatSynopsis(tText, False)
|
||||
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
|
||||
|
||||
elif tType == self.T_COMMENT and self._doComments:
|
||||
@@ -552,9 +556,12 @@ class ToOdt(Tokenizer):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _formatSynopsis(self, text: str) -> tuple[str, list[tuple[int, int]]]:
|
||||
def _formatSynopsis(self, text: str, synopsis: bool) -> tuple[str, list[tuple[int, int]]]:
|
||||
"""Apply formatting to synopsis lines."""
|
||||
name = self._localLookup("Synopsis")
|
||||
if synopsis:
|
||||
name = self._localLookup("Synopsis")
|
||||
else:
|
||||
name = self._localLookup("Short Description")
|
||||
rTxt = f"{name}: {text}"
|
||||
rFmt = [(0, self.FMT_B_B), (len(name) + 1, self.FMT_B_E)]
|
||||
return rTxt, rFmt
|
||||
|
||||
+13
-3
@@ -61,6 +61,15 @@ class nwItemLayout(Enum):
|
||||
# END Enum nwItemLayout
|
||||
|
||||
|
||||
class nwComment(Enum):
|
||||
|
||||
PLAIN = 0
|
||||
SYNOPSIS = 1
|
||||
SHORT = 2
|
||||
|
||||
# END Enum nwComment
|
||||
|
||||
|
||||
class nwTrinary(Enum):
|
||||
|
||||
NEGATIVE = -1
|
||||
@@ -127,9 +136,10 @@ class nwDocInsert(Enum):
|
||||
QUOTE_LD = 3
|
||||
QUOTE_RD = 4
|
||||
SYNOPSIS = 5
|
||||
NEW_PAGE = 6
|
||||
VSPACE_S = 7
|
||||
VSPACE_M = 8
|
||||
SHORT = 6
|
||||
NEW_PAGE = 7
|
||||
VSPACE_S = 8
|
||||
VSPACE_M = 9
|
||||
|
||||
# END Enum nwDocInsert
|
||||
|
||||
|
||||
@@ -834,6 +834,10 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
text = "% Synopsis: "
|
||||
newBlock = True
|
||||
goAfter = True
|
||||
elif insert == nwDocInsert.SHORT:
|
||||
text = "% Short: "
|
||||
newBlock = True
|
||||
goAfter = True
|
||||
elif insert == nwDocInsert.NEW_PAGE:
|
||||
text = "[newpage]"
|
||||
newBlock = True
|
||||
|
||||
@@ -36,6 +36,8 @@ from PyQt5.QtGui import (
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import checkInt
|
||||
from novelwriter.constants import nwRegEx, nwUnicode
|
||||
from novelwriter.core.index import processComment
|
||||
from novelwriter.enum import nwComment
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -352,16 +354,12 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
|
||||
elif text.startswith("%"): # Comments
|
||||
self.setCurrentBlockState(self.BLOCK_TEXT)
|
||||
toCheck = text[1:].lstrip()
|
||||
synTag = toCheck[:9].lower()
|
||||
tLen = len(text)
|
||||
cLen = len(toCheck)
|
||||
cOff = tLen - cLen
|
||||
if synTag == "synopsis:":
|
||||
self.setFormat(0, cOff+9, self._hStyles["modifier"])
|
||||
self.setFormat(cOff+9, tLen, self._hStyles["hidden"])
|
||||
cStyle, _, cPos = processComment(text)
|
||||
if cStyle == nwComment.PLAIN:
|
||||
self.setFormat(0, len(text), self._hStyles["hidden"])
|
||||
else:
|
||||
self.setFormat(0, tLen, self._hStyles["hidden"])
|
||||
self.setFormat(0, cPos, self._hStyles["modifier"])
|
||||
self.setFormat(cPos, len(text), self._hStyles["hidden"])
|
||||
|
||||
else: # Text Paragraph
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.enum import nwDocMode, nwItemClass
|
||||
from novelwriter.common import checkInt
|
||||
from novelwriter.constants import nwHeaders, nwLabels, nwLists, trConst
|
||||
from novelwriter.core.index import IndexHeading, IndexItem
|
||||
from novelwriter.enum import nwDocMode, nwItemClass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -103,6 +104,23 @@ class GuiDocViewerPanel(QWidget):
|
||||
|
||||
return
|
||||
|
||||
def openProjectTasks(self) -> None:
|
||||
"""Run open project tasks."""
|
||||
widths = SHARED.project.options.getValue("GuiDocViewerPanel", "colWidths", {})
|
||||
if isinstance(widths, dict):
|
||||
for key, value in widths.items():
|
||||
if key in self.kwTabs and isinstance(value, list):
|
||||
self.kwTabs[key].setColumnWidths(value)
|
||||
return
|
||||
|
||||
def closeProjectTasks(self) -> None:
|
||||
"""Run close project tasks."""
|
||||
widths = {}
|
||||
for key, tab in self.kwTabs.items():
|
||||
widths[key] = tab.getColumnWidths()
|
||||
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", widths)
|
||||
return
|
||||
|
||||
##
|
||||
# Public Slots
|
||||
##
|
||||
@@ -213,6 +231,7 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
|
||||
# Signals
|
||||
self.clicked.connect(self._treeItemClicked)
|
||||
self.doubleClicked.connect(self._treeItemDoubleClicked)
|
||||
|
||||
return
|
||||
|
||||
@@ -253,6 +272,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
||||
return
|
||||
|
||||
@pyqtSlot("QModelIndex")
|
||||
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
||||
"""Emit follow tag signal on user double click."""
|
||||
tHandle = index.siblingAtColumn(self.C_DATA).data(self.D_HANDLE)
|
||||
if index.column() == self.C_DOC:
|
||||
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
@@ -295,6 +322,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
C_VIEW = 2
|
||||
C_DOC = 3
|
||||
C_TITLE = 4
|
||||
C_SHORT = 5
|
||||
|
||||
D_TAG = Qt.ItemDataRole.UserRole
|
||||
|
||||
@@ -307,11 +335,16 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
iPx = SHARED.theme.baseIconSize
|
||||
cMg = CONFIG.pxInt(6)
|
||||
|
||||
self.setHeaderLabels([self.tr("Tag"), "", "", self.tr("Document"), self.tr("Heading")])
|
||||
self.setHeaderLabels([
|
||||
self.tr("Tag"), "", "", self.tr("Document"),
|
||||
self.tr("Heading"), self.tr("Short Description")
|
||||
])
|
||||
self.setIndentation(0)
|
||||
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
|
||||
self.setIconSize(QSize(iPx, iPx))
|
||||
self.setFrameStyle(QFrame.Shape.NoFrame)
|
||||
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
|
||||
self.setExpandsOnDoubleClick(False)
|
||||
self.setDragEnabled(False)
|
||||
self.setSortingEnabled(True)
|
||||
self.sortByColumn(self.C_NAME, Qt.SortOrder.AscendingOrder)
|
||||
|
||||
@@ -321,9 +354,9 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.ResizeToContents)
|
||||
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.setSectionResizeMode(self.C_DOC, QHeaderView.ResizeMode.ResizeToContents)
|
||||
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
||||
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
||||
treeHeader.setSectionsMovable(False)
|
||||
|
||||
# Cache Icons Locally
|
||||
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass])
|
||||
@@ -332,6 +365,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
|
||||
# Signals
|
||||
self.clicked.connect(self._treeItemClicked)
|
||||
self.doubleClicked.connect(self._treeItemDoubleClicked)
|
||||
|
||||
return
|
||||
|
||||
@@ -367,6 +401,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
trItem.setText(self.C_DOC, nwItem.itemName)
|
||||
trItem.setText(self.C_TITLE, hItem.title)
|
||||
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
||||
trItem.setText(self.C_SHORT, hItem.synopsis)
|
||||
trItem.setData(self.C_DATA, self.D_TAG, tag)
|
||||
|
||||
if tag not in self._treeMap:
|
||||
@@ -383,6 +418,20 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
return True
|
||||
return False
|
||||
|
||||
def setColumnWidths(self, widths: list[int]) -> None:
|
||||
"""Set the column widths."""
|
||||
if isinstance(widths, list) and len(widths) >= 2:
|
||||
self.setColumnWidth(self.C_DOC, CONFIG.pxInt(checkInt(widths[0], 100)))
|
||||
self.setColumnWidth(self.C_TITLE, CONFIG.pxInt(checkInt(widths[1], 100)))
|
||||
return
|
||||
|
||||
def getColumnWidths(self) -> list[int]:
|
||||
"""Get the widths of the user-adjustable columns."""
|
||||
return [
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_DOC)),
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_TITLE)),
|
||||
]
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
@@ -397,4 +446,12 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
||||
return
|
||||
|
||||
@pyqtSlot("QModelIndex")
|
||||
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
||||
"""Emit follow tag signal on user double click."""
|
||||
tag = index.siblingAtColumn(self.C_DATA).data(self.D_TAG)
|
||||
if index.column() == self.C_NAME:
|
||||
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
||||
return
|
||||
|
||||
# END Class _ViewPanelKeyWords
|
||||
|
||||
@@ -171,7 +171,7 @@ class GuiMainMenu(QMenuBar):
|
||||
|
||||
# Project > Delete
|
||||
self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
|
||||
self.aDeleteItem.setShortcuts(["Ctrl+Del", "Ctrl+Shift+Del"]) # Latter is deprecated
|
||||
self.aDeleteItem.setShortcut("Ctrl+Shift+Del") # Cannot be Ctrl+Del, see #629
|
||||
self.aDeleteItem.triggered.connect(lambda: self.mainGui.projView.requestDeleteItem(None))
|
||||
|
||||
# Project > Empty Trash
|
||||
@@ -564,6 +564,13 @@ class GuiMainMenu(QMenuBar):
|
||||
lambda: self.requestDocInsert.emit(nwDocInsert.SYNOPSIS)
|
||||
)
|
||||
|
||||
# Insert > Short Description Comment
|
||||
self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment"))
|
||||
self.aInsShort.setShortcut("Ctrl+K, U")
|
||||
self.aInsShort.triggered.connect(
|
||||
lambda: self.requestDocInsert.emit(nwDocInsert.SHORT)
|
||||
)
|
||||
|
||||
# Insert > Symbols
|
||||
self.mInsBreaks = self.insMenu.addMenu(self.tr("Page Break and Space"))
|
||||
|
||||
|
||||
@@ -345,11 +345,11 @@ class GuiMain(QMainWindow):
|
||||
logger.debug("Ready: GUI")
|
||||
|
||||
if __hexversion__[-2] == "a" and not CONFIG.isDebug:
|
||||
SHARED.warn(self.tr(
|
||||
SHARED.warn(
|
||||
"You are running an untested development version of novelWriter. "
|
||||
"Please be careful when working on a live project "
|
||||
"Please be careful when you are working on live projects "
|
||||
"and make sure you take regular backups."
|
||||
))
|
||||
)
|
||||
|
||||
logger.info("novelWriter is ready ...")
|
||||
self.mainStatus.setStatusMessage(self.tr("novelWriter is ready ..."))
|
||||
@@ -454,6 +454,7 @@ class GuiMain(QMainWindow):
|
||||
self.docViewer.clearNavHistory()
|
||||
self.closeDocViewer(byUser=False)
|
||||
|
||||
self.docViewerPanel.closeProjectTasks()
|
||||
self.outlineView.closeProjectTasks()
|
||||
self.novelView.closeProjectTasks()
|
||||
self.projView.clearProjectView()
|
||||
@@ -527,6 +528,7 @@ class GuiMain(QMainWindow):
|
||||
self.projView.openProjectTasks()
|
||||
self.novelView.openProjectTasks()
|
||||
self.outlineView.openProjectTasks()
|
||||
self.docViewerPanel.openProjectTasks()
|
||||
self._updateStatusWordCount()
|
||||
|
||||
# Restore previously open documents, if any
|
||||
@@ -1164,10 +1166,7 @@ class GuiMain(QMainWindow):
|
||||
"""Capture the closing event of the GUI and call the close
|
||||
function to handle all the close process steps.
|
||||
"""
|
||||
if self.closeMain():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
event.accept() if self.closeMain() else event.ignore()
|
||||
return
|
||||
|
||||
##
|
||||
@@ -1462,6 +1461,7 @@ class GuiMain(QMainWindow):
|
||||
self.addAction(self.mainMenu.aInsTimes)
|
||||
self.addAction(self.mainMenu.aInsDivide)
|
||||
self.addAction(self.mainMenu.aInsSynopsis)
|
||||
self.addAction(self.mainMenu.aInsShort)
|
||||
|
||||
for mAction, _ in self.mainMenu.mInsKWItems.values():
|
||||
self.addAction(mAction)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
%%~name: John Smith
|
||||
%%~path: f7e2d9f330615/14298de4d9524
|
||||
%%~kind: CHARACTER/NOTE
|
||||
%%~hash: 259eff30f10e101cf93e27e8764e851d356d54b8
|
||||
%%~date: Unknown/2023-08-25 16:52:03
|
||||
%%~hash: fda91c416d874aa41a47fceaedb3d62f040c7e32
|
||||
%%~date: Unknown/2023-11-25 18:16:13
|
||||
# John Smith
|
||||
|
||||
@tag: John
|
||||
|
||||
He’s pretty cool. Not Brad Pitt though.
|
||||
% Short: The sidekick
|
||||
|
||||
He’s pretty cool. Not Brad Pitt though.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
%%~name: Jane Smith
|
||||
%%~path: f7e2d9f330615/bb2c23b3c42cc
|
||||
%%~kind: CHARACTER/NOTE
|
||||
%%~hash: a69e4ca6ceede2536c8d364f88e6b62ef0ec36c3
|
||||
%%~date: Unknown/2023-08-25 16:52:04
|
||||
%%~hash: b7291713899bd0356617a36ae606b08e5fee1b65
|
||||
%%~date: Unknown/2023-11-25 18:16:07
|
||||
# Jane Smith
|
||||
|
||||
@tag: Jane
|
||||
|
||||
She’s pretty cool. Not Angelina Jolie though.
|
||||
% Short: The heroine
|
||||
|
||||
She’s pretty cool. Not Angelina Jolie though.
|
||||
|
||||
@@ -102,11 +102,11 @@
|
||||
<name status="sf12341" import="ia857f0">Main Characters</name>
|
||||
</item>
|
||||
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
||||
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="65" />
|
||||
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="48" />
|
||||
<name status="sf12341" import="icfb3a5" active="yes">John Smith</name>
|
||||
</item>
|
||||
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
||||
<meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="71" />
|
||||
<meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="47" />
|
||||
<name status="sf12341" import="i2d7a54" active="yes">Jane Smith</name>
|
||||
</item>
|
||||
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
|
||||
|
||||
@@ -29,9 +29,9 @@ from mocked import causeException
|
||||
from novelwriter.core.item import NWItem
|
||||
from tools import C, buildTestProject, cmpFiles, writeFile
|
||||
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout
|
||||
from novelwriter.enum import nwComment, nwItemClass, nwItemLayout
|
||||
from novelwriter.constants import nwFiles
|
||||
from novelwriter.core.index import IndexItem, NWIndex, countWords, TagsIndex
|
||||
from novelwriter.core.index import IndexItem, NWIndex, countWords, TagsIndex, processComment
|
||||
from novelwriter.core.project import NWProject
|
||||
|
||||
|
||||
@@ -1264,7 +1264,36 @@ def testCoreIndex_ItemIndex(mockGUI, fncPath, mockRnd):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CountWords():
|
||||
def testCoreIndex_processComment():
|
||||
"""Test the comment processing function."""
|
||||
# Regular comment
|
||||
assert processComment("%Hi") == (nwComment.PLAIN, "Hi", 0)
|
||||
assert processComment("% Hi") == (nwComment.PLAIN, "Hi", 0)
|
||||
assert processComment("% Hi:You") == (nwComment.PLAIN, "Hi:You", 0)
|
||||
|
||||
# Synopsis
|
||||
assert processComment("%synopsis:") == (nwComment.PLAIN, "synopsis:", 0)
|
||||
assert processComment("%synopsis: Hi") == (nwComment.SYNOPSIS, "Hi", 10)
|
||||
assert processComment("% synopsis: Hi") == (nwComment.SYNOPSIS, "Hi", 11)
|
||||
assert processComment("% synopsis : Hi") == (nwComment.SYNOPSIS, "Hi", 13)
|
||||
assert processComment("% Synopsis : Hi") == (nwComment.SYNOPSIS, "Hi", 15)
|
||||
assert processComment("% \t SYNOPSIS : Hi") == (nwComment.SYNOPSIS, "Hi", 16)
|
||||
assert processComment("% \t SYNOPSIS : Hi:You") == (nwComment.SYNOPSIS, "Hi:You", 16)
|
||||
|
||||
# Short Description
|
||||
assert processComment("%short:") == (nwComment.PLAIN, "short:", 0)
|
||||
assert processComment("%short: Hi") == (nwComment.SHORT, "Hi", 7)
|
||||
assert processComment("% short: Hi") == (nwComment.SHORT, "Hi", 8)
|
||||
assert processComment("% short : Hi") == (nwComment.SHORT, "Hi", 10)
|
||||
assert processComment("% Short : Hi") == (nwComment.SHORT, "Hi", 12)
|
||||
assert processComment("% \t SHORT : Hi") == (nwComment.SHORT, "Hi", 13)
|
||||
assert processComment("% \t SHORT : Hi:You") == (nwComment.SHORT, "Hi:You", 13)
|
||||
|
||||
# END Test testCoreIndex_processComment
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_countWords():
|
||||
"""Test the word counter and the exclusion filers."""
|
||||
# Non-Text
|
||||
assert countWords(None) == (0, 0, 0) # type: ignore
|
||||
@@ -1362,4 +1391,4 @@ def testCoreIndex_CountWords():
|
||||
assert wC == 14
|
||||
assert pC == 2
|
||||
|
||||
# END Test testCoreIndex_CountWords
|
||||
# END Test testCoreIndex_countWords
|
||||
|
||||
@@ -149,7 +149,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
|
||||
"<p class='break'>Line one<br/>Line two<br/>Line three</p>\n"
|
||||
)
|
||||
|
||||
# Synopsis
|
||||
# Synopsis, Short
|
||||
html._text = "%synopsis: The synopsis ...\n"
|
||||
html.tokenizeText()
|
||||
html.doConvert()
|
||||
@@ -163,6 +163,14 @@ def testCoreToHtml_ConvertFormat(mockGUI):
|
||||
"<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n"
|
||||
)
|
||||
|
||||
html.setSynopsis(True)
|
||||
html._text = "%short: A short description ...\n"
|
||||
html.tokenizeText()
|
||||
html.doConvert()
|
||||
assert html.theResult == (
|
||||
"<p class='synopsis'><strong>Short Description:</strong> A short description ...</p>\n"
|
||||
)
|
||||
|
||||
# Comment
|
||||
html._text = "% A comment ...\n"
|
||||
html.tokenizeText()
|
||||
@@ -610,9 +618,12 @@ def testCoreToHtml_Format(mockGUI):
|
||||
# Export Mode
|
||||
# ===========
|
||||
|
||||
assert html._formatSynopsis("synopsis text") == (
|
||||
assert html._formatSynopsis("synopsis text", True) == (
|
||||
"<p class='synopsis'><strong>Synopsis:</strong> synopsis text</p>\n"
|
||||
)
|
||||
assert html._formatSynopsis("short text", False) == (
|
||||
"<p class='synopsis'><strong>Short Description:</strong> short text</p>\n"
|
||||
)
|
||||
assert html._formatComments("comment text") == (
|
||||
"<p class='comment'><strong>Comment:</strong> comment text</p>\n"
|
||||
)
|
||||
@@ -632,9 +643,12 @@ def testCoreToHtml_Format(mockGUI):
|
||||
|
||||
html.setPreview(True, True)
|
||||
|
||||
assert html._formatSynopsis("synopsis text") == (
|
||||
assert html._formatSynopsis("synopsis text", True) == (
|
||||
"<p class='comment'><span class='synopsis'>Synopsis:</span> synopsis text</p>\n"
|
||||
)
|
||||
assert html._formatSynopsis("short text", False) == (
|
||||
"<p class='comment'><span class='synopsis'>Short Description:</span> short text</p>\n"
|
||||
)
|
||||
assert html._formatComments("comment text") == (
|
||||
"<p class='comment'>comment text</p>\n"
|
||||
)
|
||||
|
||||
@@ -471,6 +471,20 @@ def testCoreToken_MetaFormat(mockGUI):
|
||||
tokens.tokenizeText()
|
||||
assert tokens.theMarkdown[-1] == "% synopsis: The synopsis\n\n"
|
||||
|
||||
# Short
|
||||
tokens.setSynopsis(False)
|
||||
tokens._text = "% short: A short description\n"
|
||||
tokens.tokenizeText()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_SHORT, 0, "A short description", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert tokens.theMarkdown[-1] == "\n"
|
||||
|
||||
tokens.setSynopsis(True)
|
||||
tokens.tokenizeText()
|
||||
assert tokens.theMarkdown[-1] == "% short: A short description\n\n"
|
||||
|
||||
# Keyword
|
||||
tokens._text = "@char: Bod\n"
|
||||
tokens.tokenizeText()
|
||||
|
||||
@@ -106,7 +106,7 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
|
||||
theMD.doConvert()
|
||||
assert theMD.theResult == "Line one \nLine two \nLine three\n\n"
|
||||
|
||||
# Synopsis
|
||||
# Synopsis, Short
|
||||
theMD._text = "%synopsis: The synopsis ...\n"
|
||||
theMD.tokenizeText()
|
||||
theMD.doConvert()
|
||||
@@ -118,6 +118,12 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
|
||||
theMD.doConvert()
|
||||
assert theMD.theResult == "**Synopsis:** The synopsis ...\n\n"
|
||||
|
||||
theMD.setSynopsis(True)
|
||||
theMD._text = "%short: A description ...\n"
|
||||
theMD.tokenizeText()
|
||||
theMD.doConvert()
|
||||
assert theMD.theResult == "**Short Description:** A description ...\n\n"
|
||||
|
||||
# Comment
|
||||
theMD._text = "% A comment ...\n"
|
||||
theMD.tokenizeText()
|
||||
|
||||
@@ -447,12 +447,13 @@ def testCoreToOdt_Convert(mockGUI):
|
||||
'</office:text>'
|
||||
)
|
||||
|
||||
# Synopsis, Comment, Keywords
|
||||
# Synopsis, Short, Comment, Keywords
|
||||
odt._text = (
|
||||
"### Scene\n\n"
|
||||
"@pov: Jane\n\n"
|
||||
"% synopsis: So it begins\n\n"
|
||||
"% a plain comment\n\n"
|
||||
"% short: Then what\n\n"
|
||||
"% A plain comment\n\n"
|
||||
)
|
||||
odt.setSynopsis(True)
|
||||
odt.setComments(True)
|
||||
@@ -470,7 +471,9 @@ def testCoreToOdt_Convert(mockGUI):
|
||||
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||
'Synopsis:</text:span> So it begins</text:p>'
|
||||
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||
'Comment:</text:span> a plain comment</text:p>'
|
||||
'Short Description:</text:span> Then what</text:p>'
|
||||
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||
'Comment:</text:span> A plain comment</text:p>'
|
||||
'</office:text>'
|
||||
)
|
||||
|
||||
@@ -804,9 +807,12 @@ def testCoreToOdt_Format(mockGUI):
|
||||
project = NWProject()
|
||||
odt = ToOdt(project, isFlat=True)
|
||||
|
||||
assert odt._formatSynopsis("synopsis text") == (
|
||||
assert odt._formatSynopsis("synopsis text", True) == (
|
||||
"Synopsis: synopsis text", [(0, ToOdt.FMT_B_B), (9, ToOdt.FMT_B_E)]
|
||||
)
|
||||
assert odt._formatSynopsis("short text", False) == (
|
||||
"Short Description: short text", [(0, ToOdt.FMT_B_B), (18, ToOdt.FMT_B_E)]
|
||||
)
|
||||
assert odt._formatComments("comment text") == (
|
||||
"Comment: comment text", [(0, ToOdt.FMT_B_B), (8, ToOdt.FMT_B_E)]
|
||||
)
|
||||
|
||||
@@ -102,6 +102,12 @@ def testGuiViewerPanel_BackRefs(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||
tabBackRefs._treeItemClicked(tabBackRefs.model().index(0, tabBackRefs.C_VIEW))
|
||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||
|
||||
# Double-Click
|
||||
nwGUI.viewDocument(hJane)
|
||||
assert nwGUI.docViewer.docHandle == hJane
|
||||
tabBackRefs._treeItemDoubleClicked(tabBackRefs.model().index(0, tabBackRefs.C_DOC))
|
||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||
|
||||
# qtbot.stop()
|
||||
|
||||
# END Test testGuiViewerPanel_BackRefs
|
||||
@@ -189,6 +195,8 @@ def testGuiViewerPanel_Tags(qtbot, monkeypatch, caplog, nwGUI, projPath, mockRnd
|
||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||
charTab._treeItemClicked(charTab.model().index(1, charTab.C_VIEW))
|
||||
assert nwGUI.docViewer.docHandle == hJohn
|
||||
charTab._treeItemDoubleClicked(charTab.model().index(0, charTab.C_NAME))
|
||||
assert nwGUI.docViewer.docHandle == hJane
|
||||
|
||||
# qtbot.stop()
|
||||
|
||||
|
||||
@@ -593,6 +593,10 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
||||
nwGUI.mainMenu.aInsSynopsis.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == "Stuff\n% Synopsis: \n"
|
||||
|
||||
nwGUI.docEditor.setPlainText("Stuff\n")
|
||||
nwGUI.mainMenu.aInsShort.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == "Stuff\n% Short: \n"
|
||||
|
||||
# Insert Break or Space
|
||||
# =====================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user