Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6282772ae | ||
|
|
bfecebc047 | ||
|
|
186737a170 | ||
|
|
f32383ea99 | ||
|
|
4097949c44 | ||
|
|
10feafeab4 | ||
|
|
399a867836 | ||
|
|
6f3702f2df | ||
|
|
7dc9e65f68 | ||
|
|
1740bbedbd | ||
|
|
8585334a51 | ||
|
|
553b76cafc | ||
|
|
c04e1035a7 | ||
|
|
dfbb61a37e | ||
|
|
cb485c5c86 | ||
|
|
62a94850a6 | ||
|
|
99c00f8b93 | ||
|
|
cbb000a18f | ||
|
|
847d8ab726 | ||
|
|
9f1e2d322e | ||
|
|
b7c657141f | ||
|
|
023f6bed01 | ||
|
|
fff6ba98bc | ||
|
|
776eedc5f2 | ||
|
|
f2eaaa09b6 | ||
|
|
60b0a4c901 | ||
|
|
a6d346fcb6 | ||
|
|
78a75d5719 | ||
|
|
f59317c2b5 | ||
|
|
b203bcdcff | ||
|
|
a31f42b04c | ||
|
|
ce666d9d7a | ||
|
|
ef93b41240 | ||
|
|
1118f01c91 | ||
|
|
b526315084 | ||
|
|
1d1dae0c7e | ||
|
|
1edfcfcd91 | ||
|
|
82e9fb0c44 | ||
|
|
1b8d424b27 | ||
|
|
4ab2b04e6b | ||
|
|
d291995c0e | ||
|
|
54510951de | ||
|
|
52d1d87985 | ||
|
|
62847e55f0 | ||
|
|
bf6cefa840 | ||
|
|
4e1fa01562 | ||
|
|
83c9fb96e9 | ||
|
|
ff7f27ff97 | ||
|
|
50a9b5b5e2 | ||
|
|
4fa20273f7 | ||
|
|
93b36406f1 | ||
|
|
a0e6f9cf82 | ||
|
|
1f9b6d7624 | ||
|
|
ccc444f355 | ||
|
|
ba0198407f | ||
|
|
918b077252 | ||
|
|
b348ba6aff | ||
|
|
e521a30612 | ||
|
|
2e2ab5ad6f | ||
|
|
47781f981f | ||
|
|
0676056968 | ||
|
|
65562ae790 | ||
|
|
623f74019f |
102
CHANGELOG.md
@@ -1,5 +1,105 @@
|
||||
# novelWriter Changelog
|
||||
|
||||
## Version 2.2 [2023-12-17]
|
||||
|
||||
### Release Notes
|
||||
|
||||
This release comes with a number of new features. These are some highlights.
|
||||
|
||||
In addition to the common Markdown style formatting for bold, italic and strike through, a set of
|
||||
new shortcodes have been added. The shortcodes are far more flexible than the Markdown style
|
||||
syntax, and can be used for more complex formatting cases. Like when you need to add multiple,
|
||||
overlapping formats, or add emphasis to just a part of a word. The shortcodes also allow for
|
||||
underline, subscript and superscript, which the Markdown syntax does not. The new formats are
|
||||
available in the "Format" menu, and in a new toolbar in the editor that can be enabled by clicking
|
||||
the three dots in the top--left corner. The shortcode format was chosen because it can later be
|
||||
extended to include other requested features as well. Please have a look at the documentation for
|
||||
more details about the new shortcodes.
|
||||
|
||||
The Tags and References system has been improved. The tags themselves are no longer case sensitive
|
||||
when you use them in references, but they are still displayed as you typed them in the tag
|
||||
definition when they are displayed in the user interface. Starting to type the `@` symbol in the
|
||||
text editor, on a new line, will now open an auto-completer menu which will display available
|
||||
options. It may not display all of your tags if you have a lot of them, but starting to type more
|
||||
characters will filter the list down further.
|
||||
|
||||
You can now automatically create a note file for a new tag that you have added to a reference list
|
||||
in a document, but is not yet defined in a project note. So, for instance, if you come up with a
|
||||
new character while writing, and add a new tag to your `@char` references, you can right-click the
|
||||
new tag and create a new note for that entry directly. In addition, it is now also possible to
|
||||
right-click a heading in an open document and set the item label in the project tree to match the
|
||||
heading.
|
||||
|
||||
In addition to the changes in the editor, the "References" panel below the document viewer has also
|
||||
been completely redesigned. It now shows all the references to the document you are viewing as a
|
||||
list, with a lot more details than before. In addition, tabs in the panel will appear to show all
|
||||
the tags you have defined in your notes, sorted as one tab per category. Like for instance
|
||||
Characters, Locations, Objects, etc. You can also give each note a short description comment on the
|
||||
same format as the summary comments for chapters and scenes. The short description comment can be
|
||||
added from the "Insert" menu under "Special Comments".
|
||||
|
||||
The last major change in this release is the new multi-select feature in the project tree. You can
|
||||
now select multiple documents and folders using the mouse while pressing `Ctrl` or `Shift`. By
|
||||
right-clicking the selected items, you can perform a limited set of operations on all of them, like
|
||||
changing active status, and the status or importance labels. You can also drag and drop multiple
|
||||
items under the condition that all the selected items are in the same folder, at the same level.
|
||||
This restriction is in place due to limitations in the framework novelWriter is based on. But this
|
||||
should help in cases where multiple documents need to be moved in and out of folders or between
|
||||
folders. Note that adding the multi-select feature meant that the undo feature of the project tree
|
||||
had to be removed. It may be added back later.
|
||||
|
||||
_These Release Notes also include the changes from the 2.2 Beta 1 and 2.2 RC 1 releases._
|
||||
|
||||
### Detailed Changelog
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fix column widths for columns with no text in the viewer panel lists, and fix an issues where
|
||||
icons were not updated on theme switch. Issue #1627. PR #1626.
|
||||
* Fix auto-selection of words with apostrophes. Issue #1624. PR #1632.
|
||||
|
||||
**Usability**
|
||||
|
||||
* Use `Ctrl+K, H` for inserting short description comments (alias to synopsis), drop the space
|
||||
after the `%` symbol when inserting special comments, add a browse icon to the open open project
|
||||
dialog, and remove the popup warning for Alpha releases. PR #1626.
|
||||
* Menu entries no longer clear the status bar message when they are hovered. This was caused by a
|
||||
status tip feature in Qt, which prints a blank message to the status bar. PR #1630.
|
||||
* The novel view panel now scrolls to bring the current document into view when iteratively
|
||||
searching through documents in the project. Issue #1555. PR #1632.
|
||||
* The progress bar on the Manuscript Build dialog now stays for 3 seconds after completion instead
|
||||
of 1 second. PR #1634.
|
||||
* The document viewer panel now shows the importance label next to each entry, and double-clicking
|
||||
an entry will open it in the viewer. All entries also now show the content in tooltips so that
|
||||
the columns can be shrunk to only view the icon if there is too little space. Issue #16220.
|
||||
PR #1639.
|
||||
* The editor toolbar no longer uses the same buttons for markdown and shortcodes style formatting.
|
||||
They have each received their separate buttons. Some additional space has been added between the
|
||||
two types of buttons to visually separate them. Issues #1636 and #1637. PR #1638.
|
||||
* Convert the Synopsis and Comment buttons in the document viewer footer to buttons with both icon
|
||||
and text, and drop the label. Issue #1628. PR #1638.
|
||||
|
||||
**Internationalisation**
|
||||
|
||||
* Updated US English, Norwegian, Japanese, Latin American Spanish, French, and Italian
|
||||
translations. PRs #1625 and #1641.
|
||||
|
||||
**Documentation**
|
||||
|
||||
* The documentation has been updated to cover new features in 2.2. PR #1640.
|
||||
|
||||
**Code Improvements**
|
||||
|
||||
* Improve memory usage by making sure C++ objects are deleted when they are no longer used. There
|
||||
is an issue between the Python and Qt side of things where objects are left in memory and not
|
||||
properly garbage collected when they run out of scope. A number of deferred delete calls have
|
||||
been added that seems to solve most of these cases. A `--meminfo` flag has been added to the
|
||||
command line arguments to provide diagnostic data to help debug such issues. PR #1629.
|
||||
* Improve handling of alert boxes and their memory clean up, and refactor event filters. PR #1631.
|
||||
* Clean up unused methods in GUI extensions. PR #1634.
|
||||
|
||||
----
|
||||
|
||||
## Version 2.2 RC 1 [2023-11-26]
|
||||
|
||||
### Release Notes
|
||||
@@ -36,7 +136,7 @@ final release.
|
||||
effects some users may want to avoid. Issue #1602. PR #1605.
|
||||
* For Windows users, there is now an "Add Dictionaries" tool in the Tools menu where new spell
|
||||
check dictionaries can be added. Links are provided to sources for these dictionaries, and a file
|
||||
selector tool to import the files into novelWriter. Issue #982. PR #1610.
|
||||
selector tool to import the files into novelWriter. Issue #982. PR #1611.
|
||||
* You can now update the name of a document by right-clicking on any heading inside the document
|
||||
and select "Set as Document Name". This will open the Rename dialog with the text of the heading
|
||||
pre-filled. Issue #1503. PR #1614.
|
||||
|
||||
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 273 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 534 KiB After Width: | Height: | Size: 542 KiB |
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 562 KiB |
|
Before Width: | Height: | Size: 379 KiB After Width: | Height: | Size: 335 KiB |
@@ -7,7 +7,7 @@ Customisations
|
||||
.. _Enchant: https://abiword.github.io/enchant
|
||||
.. _Free Desktop: https://cgit.freedesktop.org/libreoffice/dictionaries/tree/
|
||||
|
||||
There are a few ways you can customise novelWriter youself. Currently, you can add new GUI themes,
|
||||
There are a few ways you can customise novelWriter yourself. Currently, you can add new GUI themes,
|
||||
your own syntax themes, and install additional dictionaries.
|
||||
|
||||
|
||||
@@ -22,23 +22,35 @@ may not load all installed spell check dictionaries automatically.
|
||||
Linux and MacOS
|
||||
---------------
|
||||
|
||||
On Linux and MacOS, you generally only have to install hunspell or aspell dictionaries on your
|
||||
system like you do for other applications. See your distro or OS documentation for how to do this.
|
||||
These dictionaries should show up as available spell check languages in novelWriter.
|
||||
On Linux and MacOS, you generally only have to install hunspell, aspell or myspell dictionaries on
|
||||
your system like you do for other applications. See your distro or OS documentation for how to do
|
||||
this. These dictionaries should show up as available spell check languages in novelWriter.
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
For Windows, English is included with the installation. For other languages you have to download
|
||||
and add dictionaries yourself. You can find the various dictionaries on the `Free Desktop`_
|
||||
website. You should find a folder for your language, if it is available at all, and download the
|
||||
files ending with ``.aff`` and ``.dic``. These files must then be copied to the following location:
|
||||
and add dictionaries yourself.
|
||||
|
||||
**Install Tool**
|
||||
|
||||
A small tool to assist with this can be found under :guilabel:`Tools > Add Dictionaries`. It will
|
||||
import spell checking dictionaries from Free Office or Libre Office extensions. The dictionaries
|
||||
are then installed in the install location for the Enchant library.
|
||||
|
||||
**Manual Install**
|
||||
|
||||
If you prefer to do this manually or want to use a different source than the ones mentioned above,
|
||||
You need to get compatible dictionary files for your language. You need two files files ending with
|
||||
``.aff`` and ``.dic``. These files must then be copied to the following location:
|
||||
|
||||
``C:\Users\<USER>\AppData\Local\enchant\hunspell``
|
||||
|
||||
This assumes your user profile is stored at ``C:\Users\<USER>``. The last one or two folders may
|
||||
not exist, so you may need to create them.
|
||||
|
||||
You can find the various dictionaries on the `Free Desktop`_ website.
|
||||
|
||||
.. note::
|
||||
The Free Desktop link points to a repository, and what may look like file links inside the
|
||||
dictionary folder are actually links to web pages. If you right-click and download those, you
|
||||
@@ -53,7 +65,7 @@ not exist, so you may need to create them.
|
||||
Syntax and GUI Themes
|
||||
=====================
|
||||
|
||||
Adding your own GUI and syntax themes is relatively easy, altough it requires that you manually
|
||||
Adding your own GUI and syntax themes is relatively easy, although it requires that you manually
|
||||
edit config files with colour values. The themes are defined by simple plain text config files with
|
||||
meta data and colour settings.
|
||||
|
||||
@@ -136,7 +148,7 @@ Omitted values are not loaded and will use default values.
|
||||
Custom Syntax Theme
|
||||
-------------------
|
||||
|
||||
A syntax theme ``.conf`` file consists of the follwing settings:
|
||||
A syntax theme ``.conf`` file consists of the following settings:
|
||||
|
||||
.. code-block:: cfg
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ Tips & Tricks
|
||||
This is a list of hopefully helpful little tips on how to get the most out of novelWriter.
|
||||
|
||||
.. note::
|
||||
This section will be expanded over time, and if you would like to have something added, feel
|
||||
free to contribute, or start a discussion on the project's `Discussions Page`_.
|
||||
This section will be expanded over time. If you would like to have something added, feel free to
|
||||
contribute, or start a discussion on the project's `Discussions Page`_.
|
||||
|
||||
|
||||
Managing the Project
|
||||
|
||||
@@ -13,8 +13,8 @@ formatting features available are limited to those relevant for this purpose. It
|
||||
for technical writing, and it is *not* a full-featured Markdown editor.
|
||||
|
||||
Your novel project is organised as a collection of separate plain text documents instead of a
|
||||
single, large document. The idea here is to make it easier to reorganise your project structure
|
||||
without having to cut and paste text between chapters.
|
||||
single, large document. The idea is to make it easier to reorganise your project structure without
|
||||
having to cut and paste text between chapters.
|
||||
|
||||
There are two kinds of documents in your project: :term:`Novel Documents` are documents that are
|
||||
part of your story. The other kind of documents are :term:`Project Notes`. These are intended for
|
||||
@@ -22,17 +22,17 @@ your notes about your characters, your world building, and so on.
|
||||
|
||||
You can at any point split the individual documents by their headers up into multiple documents, or
|
||||
merge multiple documents into single documents. This makes it easier to use variations of the
|
||||
Snowflake_ method for writing. You can focus on writing larger structure-focused documents, like
|
||||
Snowflake_ method for writing. You can start by writing larger structure-focused documents, like
|
||||
one per act for instance, and later effortlessly split these up into scenes by their headers.
|
||||
|
||||
Below are some key features of novelWriter.
|
||||
|
||||
**Focus on writing**
|
||||
The aim of the user interface is to let the user focus on writing instead of spending time
|
||||
formatting text. Formatting is therefore limited to a small set of formatting tags for simple
|
||||
things like text emphasis and paragraph alignment. When you really want to focus on just
|
||||
writing, you can switch the editor into :guilabel:`Focus Mode` where only the text editor panel
|
||||
itself is visible, and the project structure view is hidden away.
|
||||
The aim of the user interface is to let you focus on writing instead of spending time formatting
|
||||
text. Formatting is therefore limited to a small set of formatting tags for simple things like
|
||||
text emphasis and paragraph alignment. When you really want to focus on just writing, you can
|
||||
switch the editor into :guilabel:`Focus Mode` where only the text editor panel itself is
|
||||
visible, and the project structure view is hidden away.
|
||||
|
||||
**Keep an eye on your notes**
|
||||
The main window can optionally show a document viewer to the right of the editor. This view
|
||||
@@ -45,8 +45,8 @@ Below are some key features of novelWriter.
|
||||
build the project into a manuscript, they are all glued together in the top-to-bottom order in
|
||||
which they appear in the project tree. You can use as few text documents as you like, but
|
||||
splitting the project up into chapters and scenes means you can easily reorder them using the
|
||||
drag-and-drop feature. You can also start out with a few documents and then later split them
|
||||
into multiple documents based on their headers.
|
||||
drag-and-drop feature of the project tree. You can also start out with a few documents and then
|
||||
later split them into multiple documents based on their headers.
|
||||
|
||||
**Multi-novel project support**
|
||||
As of novelWriter 2.0, you can have multiple Novel type root folders in a project. This allows
|
||||
@@ -56,9 +56,9 @@ Below are some key features of novelWriter.
|
||||
**Keep track of your plot elements**
|
||||
All notes in your project can be assigned a :term:`tag` that you can :term:`reference` from any
|
||||
other document or note. In fact, you can add a new tag under each heading of a note if you need
|
||||
to be able to reference specific sections of ot.
|
||||
to be able to reference specific sections of it.
|
||||
|
||||
**Get an overview of your plot elements**
|
||||
**Get an overview of your story**
|
||||
In the :guilabel:`Outline View` on the main window you can see an outline of all the chapters,
|
||||
scenes, and sections of your project. If they have any references in them, these are listed in
|
||||
additional columns. You can also add a synopsis to each chapter or scene, which can be listed
|
||||
@@ -66,6 +66,12 @@ Below are some key features of novelWriter.
|
||||
subset of the outline information is also available in the :guilabel:`Novel View` as an
|
||||
alternative view to the project tree.
|
||||
|
||||
**Get an overview of your story elements**
|
||||
Under the document viewer panel you will find a series of tabs that shows the different story
|
||||
elements you have created tags for. The tabs are sorted into Characters, Plots, etc, depending
|
||||
on which categories you are using in your story. This panel can be hidden when you don't need it
|
||||
to free up space.
|
||||
|
||||
**Building your manuscript**
|
||||
Whether you want to assemble a manuscript, or export all your notes, or generate an outline of
|
||||
your chapters and scenes with a synopsis, you can use the :guilabel:`Build Manuscript` tool to
|
||||
@@ -83,9 +89,9 @@ Screenshots
|
||||
.. figure:: images/screenshot_default.png
|
||||
:class: dark-light
|
||||
|
||||
novelWriter with default theme
|
||||
novelWriter with light colour theme
|
||||
|
||||
.. figure:: images/screenshot_dark.png
|
||||
:class: dark-light
|
||||
|
||||
novelWriter with dark theme
|
||||
novelWriter with dark colour theme
|
||||
|
||||
@@ -36,15 +36,15 @@ read on.
|
||||
This chapter explains the basics of how the application works and what it can and cannot do.
|
||||
|
||||
:ref:`a_ui_project` – Recommended Reading
|
||||
This chapter will give you a more detailed explanation of how you can use the user interface components
|
||||
to organise and view your project work.
|
||||
This chapter will give you a more detailed explanation of how you can use the user interface
|
||||
components to organise and view your project work.
|
||||
|
||||
:ref:`a_ui_writing` – Recommended Reading
|
||||
This chapter will give you a more detailed explanation of how the text editor and viewer work.
|
||||
|
||||
:ref:`a_fmt` – Essential Information
|
||||
This chapter covers how you should format your text. The editor is plain text, so text
|
||||
formatting requires some basic markup. The structure of your novel is also inferred by how you
|
||||
formatting requires some basic markup. The structure of your novel is also inferred from how you
|
||||
use headings. Tags and references are implemented by special keywords.
|
||||
|
||||
:ref:`a_kb` – Optional / Lookup
|
||||
@@ -55,7 +55,7 @@ read on.
|
||||
:ref:`a_typ` – Optional
|
||||
This chapter gives you an overview of the special typographical symbols available in
|
||||
novelWriter. The auto-replace feature can handle the insertion of standard quote symbols for
|
||||
your language, and other special characters. If you use any symbols aside from these. their
|
||||
your language, and other special characters. If you use any symbols aside from these, their
|
||||
intended use is explained here.
|
||||
|
||||
:ref:`a_prjfmt` – Optional
|
||||
|
||||
@@ -14,8 +14,8 @@ Getting Started
|
||||
.. _Releases: https://github.com/vkbo/novelWriter/releases
|
||||
.. _AppImage: https://appimage.org/
|
||||
|
||||
Package installers for novelWriter are available for all major platforms, including Linux, Windows
|
||||
and MacOS. See below for install instructions for each platform.
|
||||
Ready-made packages and installers for novelWriter are available for all major platforms, including
|
||||
Linux, Windows and MacOS. See below for install instructions for each platform.
|
||||
|
||||
You can also install novelWriter from the Python Package Index (PyPi). See :ref:`a_started_pip`.
|
||||
Installing from PyPi does not set up icon launchers, so you will either have to do this yourself,
|
||||
|
||||
@@ -5,7 +5,7 @@ Novel Projects
|
||||
**************
|
||||
|
||||
New projects can be created from the :guilabel:`Project` menu by selecting :guilabel:`New Project`.
|
||||
This will open the :guilabel:`New Project Wizard` that will assist you in creating a barebone
|
||||
This will open the :guilabel:`New Project Wizard` that will assist you in creating a bare bone
|
||||
project suited to your needs.
|
||||
|
||||
A novelWriter project requires a dedicated folder for storing its files on the local file system.
|
||||
@@ -41,7 +41,7 @@ to reference them from other documents and notes. The intended usage of each typ
|
||||
listed below. However, aside from the :guilabel:`Novel` folder, no restrictions are applied by the
|
||||
application on what you put in them. You can use them however you want.
|
||||
|
||||
The root folder system is closesly connected to how the Tags and References system works. For more
|
||||
The root folder system is closely connected to how the Tags and References system works. For more
|
||||
details, see the :ref:`a_references` chapter.
|
||||
|
||||
:guilabel:`Novel`
|
||||
|
||||
@@ -28,7 +28,7 @@ Metadata in novelWriter
|
||||
|
||||
The structure of your novelWriter project is inferred from the :term:`headings` within the
|
||||
documents, not the documents themselves. See :ref:`a_struct_heads` for more details. Therefore,
|
||||
metadata is also associated with headings, and not documents.
|
||||
metadata is also associated with headings, and not the documents directly.
|
||||
|
||||
If you split your project into separate documents for each scene, this distinction may not matter.
|
||||
However, there are several benefits to using documents at a larger structural scale when starting
|
||||
@@ -51,9 +51,8 @@ by using the ``@tags`` :term:`keyword`. The full format of a tag is ``@tag: tagn
|
||||
``tagname`` is an identifier of your choosing. You can only set *one* tag per heading, and the tag
|
||||
has to be unique across all documents in the project.
|
||||
|
||||
.. note::
|
||||
In version 2.2, tags will be made case insensitive, but as of novelWriter 2.1 they are not. You
|
||||
should however avoid using tags that are only distinguished by case.
|
||||
.. versionadded:: 2.2
|
||||
Tags are now case insensitive.
|
||||
|
||||
After the tags have been defined, they can then be referenced in the novel documents, or
|
||||
cross-referenced in other notes. they will also show up in the :guilabel:`Outline View` and in the
|
||||
@@ -64,10 +63,10 @@ allowed, that is, the tag is unique. Duplicate tags should be detected as long a
|
||||
to date. An invalid tag should have a green wiggly line under it, and will not receive the syntax
|
||||
colour that valid tags do.
|
||||
|
||||
The tag is the only part of these notes that the novelWriter uses. The rest of the document content
|
||||
is there for the writer to use in whatever way they wish. Of course, the content of the documents
|
||||
can be added to the manuscript, or an outline document. If you want to compile a single document of
|
||||
all your notes, you can do this from the :guilabel:`Manuscript Build` tool.
|
||||
The tag is the only part of these notes that novelWriter uses. The rest of the document content is
|
||||
there for you to use in whatever way you wish. Of course, the content of the documents can be added
|
||||
to the manuscript, or an outline document. If you want to compile a single document of all your
|
||||
notes, you can do this from the :guilabel:`Manuscript Build` tool.
|
||||
|
||||
Example of a heading with a tag for a character of the story:
|
||||
|
||||
@@ -81,10 +80,13 @@ Example of a heading with a tag for a character of the story:
|
||||
|
||||
When this is done in a document in a :term:`Root Folder` of type "Characters", the tag is
|
||||
automatically treated as an available character in your project, and you will be able to reference
|
||||
it in any of your other documents using the reference keywords for characters.
|
||||
it in any of your other documents using the reference keywords for characters. It will also show up
|
||||
in the Character tab in the Reference panel below the document viewer, and in the reference
|
||||
auto-completer menu in the editor when you fill in references. See :ref:`a_ui_view` and
|
||||
:ref:`a_references_completer`.
|
||||
|
||||
It is the root folder type that defines what category of story elements the tag is indexed under.
|
||||
See the :ref:`a_proj_roots` section for an overview of availabe root folder types. They are also
|
||||
See the :ref:`a_proj_roots` section for an overview of available root folder types. They are also
|
||||
covered in the next section.
|
||||
|
||||
|
||||
@@ -148,6 +150,12 @@ that the tags referenced exist.
|
||||
In general, the index for a document is regenerated when it is saved, so this shouldn't normally
|
||||
be necessary.
|
||||
|
||||
.. tip::
|
||||
If you add a reference in the editor to a tag that doesn't yet exist, you can right-click it and
|
||||
select :guilabel:`Create Note for Tag`. This will generate a new project note automatically with
|
||||
the new tag defined. In order for this to be possible, a root folder for that category of
|
||||
references must already exist.
|
||||
|
||||
One note can also reference another note in the same way novel documents do. When the note is
|
||||
opened in the document viewer, the references become clickable links, making it easier to follow
|
||||
connections in the plot. You can follow links in the document editor by clicking them with the
|
||||
@@ -176,3 +184,19 @@ Example of a novel document with references to characters and plots:
|
||||
@plot: Main
|
||||
|
||||
Once upon a time ...
|
||||
|
||||
|
||||
.. _a_references_completer:
|
||||
|
||||
The References Auto-Completer
|
||||
-----------------------------
|
||||
|
||||
An auto-completer context menu will show up automatically in the document editor when you type the
|
||||
character ``@`` on a new line. It will first suggest tag or reference keywords for you to add, and
|
||||
after the ``:`` has been added, suggest references from the list of tags you have already defined.
|
||||
|
||||
You can use the auto-completer to add multiple references with a ``,`` between them, and even type
|
||||
new ones. New references can be created by right-clicking on them and selecting
|
||||
:guilabel:`Create Note for Tag` from the menu.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
@@ -23,6 +23,7 @@ at the same time provide useful features needed for writing a novel.
|
||||
|
||||
The main window does not have an editor toolbar like many other applications do. This reduces
|
||||
clutter, and since the documents are formatted with style tags, it is more or less redundant.
|
||||
|
||||
Most formatting features supported are available through convenient keyboard shortcuts. They are
|
||||
also available in the main menu, so you don't have to look up formatting codes every time you need
|
||||
them. For reference, a list of all shortcuts can be found in the :ref:`a_kb` chapter.
|
||||
@@ -36,13 +37,18 @@ On the left side of the main window, you will find a sidebar. This bar has butto
|
||||
views you can switch between, a quick link to the :guilabel:`Build Manuscript` tool, and a set of
|
||||
project-related tools and quick access to settings at the bottom.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
A number of new formatting options were added in 2.2 to allow for some special formatting cases.
|
||||
At the same time, a small formatting toolbar was added in the editor. It is hidden by default,
|
||||
but can be opened by pressing the three dots icon in the top right corner.
|
||||
|
||||
Project Tree View
|
||||
-----------------
|
||||
|
||||
Project Tree and Editor View
|
||||
----------------------------
|
||||
|
||||
.. figure:: images/fig_project_tree_view.png
|
||||
|
||||
A screenshot of the Project Tree View.
|
||||
A screenshot of the Project Tree and Editor View.
|
||||
|
||||
When in :guilabel:`Project Tree View` mode, the main work area of the main window is split in two,
|
||||
or optionally three, panels. The left-most panel contains the project tree and all the documents in
|
||||
@@ -59,8 +65,8 @@ the editor's header, or by pressing :kbd:`F8`. When :guilabel:`Focus Mode` is en
|
||||
interface elements other than the document editor itself are hidden away.
|
||||
|
||||
|
||||
Novel Tree View
|
||||
---------------
|
||||
Novel Tree and Editor View
|
||||
--------------------------
|
||||
|
||||
.. figure:: images/fig_novel_tree_view.png
|
||||
|
||||
@@ -134,7 +140,7 @@ This is a brief introduction to how you structure your writing projects. All of
|
||||
covered in more detail later.
|
||||
|
||||
The main point of novelWriter is that you are free to organise your project documents as you wish
|
||||
into subfolders or subdocuments, and split the text between these documents in whatever way suits
|
||||
into sub-folders or sub-documents, and split the text between these documents in whatever way suits
|
||||
you. All that matters to novelWriter is the linear order the documents appear at in the project
|
||||
tree (top to bottom). The chapters, scenes and sections of the novel are determined by the headings
|
||||
within those documents.
|
||||
@@ -153,8 +159,8 @@ The four heading levels (**H1** to **H4**) are treated as follows:
|
||||
The project tree will select an icon for the document based on the first heading in it.
|
||||
|
||||
This header level structure is only taken into account for :term:`novel documents`. For
|
||||
:term:`project notes`, the header levels have no structural meaning, and the user is free to do
|
||||
whatever they want. See :ref:`a_struct` and :ref:`a_references` for more details.
|
||||
:term:`project notes`, the header levels have no structural meaning, and you are free to use them
|
||||
however you want. See :ref:`a_struct` and :ref:`a_references` for more details.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
You can add documents as child items of other documents. This is often more useful than adding
|
||||
@@ -173,8 +179,9 @@ The project can at any time be assembled into a range of different formats throu
|
||||
various flavours of Markdown.
|
||||
|
||||
The HTML5 format is suitable for conversion by a number of other tools like Pandoc_, or for
|
||||
importing into word processors if the Open Document format isn't suitable. In addition, printing
|
||||
is also possible. Print to PDF is available from the print dialog.
|
||||
importing into word processors if the Open Document format isn't suitable. The Open Document format
|
||||
is supported by most Office type applications. In addition, printing is also possible. Print to PDF
|
||||
is available from the print dialog.
|
||||
|
||||
In addition, you can export the content of the project to a JSON file. This is useful if you want
|
||||
to write your own custom processing script in for instance Python, as the entire novel can be read
|
||||
|
||||
@@ -7,7 +7,8 @@ Formatting Your Text
|
||||
The novelWriter text editor is a plain text editor that uses formatting codes for setting meta data
|
||||
values and allowing for some text formatting. The syntax is based on Markdown, but novelWriter is
|
||||
*not* a Markdown editor. It supports basic formatting like emphasis (italic), strong importance
|
||||
(bold) and strikethrough text, as well as four levels of headings.
|
||||
(bold) and strike through text, as well as four levels of headings. Form some further complex
|
||||
formatting needs, a set of shortcodes can be used.
|
||||
|
||||
In addition to formatting codes, novelWriter allows for comments, a synopsis tag, and a set of
|
||||
keyword and value sets used for :term:`tags<tag>` and :term:`references<reference>`. There are also
|
||||
@@ -20,7 +21,7 @@ Syntax Highlighting
|
||||
===================
|
||||
|
||||
The editor has a syntax highlighter feature that is meant to help you know when you've used the
|
||||
formtatting tags or other features correctly. It will change the colour and font size of your
|
||||
formatting tags or other features correctly. It will change the colour and font size of your
|
||||
headings, change the text colour of emphasised text, and it can also show you where you have
|
||||
dialogue in your text.
|
||||
|
||||
@@ -94,7 +95,7 @@ A text paragraph is indicated by a blank line. That is, you need two line breaks
|
||||
fragments of text into two paragraphs. Single line breaks are treated as line breaks within a
|
||||
paragraph.
|
||||
|
||||
In addition, the editor supports a few additional types of whitespaces:
|
||||
In addition, the editor supports a few additional types of white spaces:
|
||||
|
||||
* A non-breaking space can be inserted with :kbd:`Ctrl+K`, :kbd:`Space`.
|
||||
* Thin spaces are also supported, and can be inserted with :kbd:`Ctrl+K`, :kbd:`Shift+Space`.
|
||||
@@ -126,7 +127,7 @@ A minimal set of text emphasis styles are supported for text paragraphs.
|
||||
The text is rendered as strongly important text (bold).
|
||||
|
||||
``~~text~~``
|
||||
Strikethrough text.
|
||||
Strike through text.
|
||||
|
||||
In Markdown guides it is often recommended to differentiate between strong importance and emphasis
|
||||
by using ``**`` for strong and ``_`` for emphasis, although Markdown generally also supports ``__``
|
||||
@@ -136,8 +137,8 @@ recommendation.
|
||||
|
||||
In addition, the following rules apply:
|
||||
|
||||
1. The emphasis and strikethrough formatting tags do not allow spaces between the words and the tag
|
||||
itself. That is, ``**text**`` is valid, ``**text **`` is not.
|
||||
1. The emphasis and strike through formatting tags do not allow spaces between the words and the
|
||||
tag itself. That is, ``**text**`` is valid, ``**text **`` is not.
|
||||
2. More generally, the delimiters must be on the outer edge of words. That is, ``some **text in
|
||||
bold** here`` is valid, ``some** text in bold** here`` is not.
|
||||
3. If using both ``**`` and ``_`` to wrap the same text, the underscore must be the *inner*
|
||||
@@ -146,7 +147,7 @@ In addition, the following rules apply:
|
||||
4. Text emphasis does not span past line breaks. If you need to add emphasis to multiple lines or
|
||||
paragraphs, you must apply it to each of them in turn.
|
||||
5. Text emphasis can only be used in plain paragraphs. Comments, titles, and meta data tags don't
|
||||
allow for formatting, and any formatting markup will be renderred as-is.
|
||||
allow for formatting, and any formatting markup will be rendered as-is.
|
||||
|
||||
.. tip::
|
||||
novelWriter supports standard escape syntax for the emphasis markup characters in case the
|
||||
@@ -155,6 +156,39 @@ In addition, the following rules apply:
|
||||
markup.
|
||||
|
||||
|
||||
.. _a_fmt_shortcodes:
|
||||
|
||||
Extended Formatting with Shortcodes
|
||||
===================================
|
||||
|
||||
For additional formatting options, you can use shortcodes. Shortcodes is a form of in-line codes
|
||||
that can be used to change the format of the text that follows and opening code, and last until
|
||||
that formatting region is ended with a closing code.
|
||||
|
||||
These shortcodes are intended for special formatting cases, or more complex cases that cannot be
|
||||
solved with simple Markdown-like formatting codes. Available shortcodes are listed below.
|
||||
|
||||
.. csv-table:: Shortcodes Formats
|
||||
:header: "Syntax", "Description"
|
||||
:widths: 40, 60
|
||||
:class: "tight-table"
|
||||
|
||||
"``[b]text[/b]``", "Text is rendered as bold text."
|
||||
"``[i]text[/i]``", "Text is rendered as italicised text."
|
||||
"``[s]text[/s]``", "Text is rendered as strike through text."
|
||||
"``[u]text[/u]``", "Text is rendered as underlined text."
|
||||
"``[sup]text[/sup]``", "Text is rendered as superscript text."
|
||||
"``[sub]text[/sub]``", "Text is rendered as subscript text."
|
||||
|
||||
Unlike Markdown style codes, these can be used anywhere within a paragraph. Even in the middle of a
|
||||
word if you need to. You can also freely combine them to form more complex formatting.
|
||||
|
||||
The shortcodes are available from the :guilabel:`Format` menu and in the editor toolbar, which can
|
||||
be activated by clicking the three dots in the editor header.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. _a_fmt_comm:
|
||||
|
||||
Comments and Synopsis
|
||||
@@ -169,19 +203,25 @@ in a special manner and will show up in the :ref:`a_ui_outline` in a dedicated c
|
||||
``synopsis`` is not case sensitive. If it is correctly formatted, the syntax highlighter will
|
||||
indicate this by altering the colour of the word.
|
||||
|
||||
``% text...``
|
||||
``% text ...``
|
||||
This is a comment. The text is not rendered by default (this can be overridden), seen in the
|
||||
document viewer, or counted towards word counts.
|
||||
|
||||
``% Synopsis: text...``
|
||||
``%Synopsis: text ...``
|
||||
This is a synopsis comment. It is generally treated in the same way as a regular comment, except
|
||||
that it is also captured by the indexing algorithm and displayed in the :ref:`a_ui_outline`. It
|
||||
can also be filtered separately when building the project to for instance generate an outline
|
||||
document of the whole project.
|
||||
|
||||
``%Short: text ...``
|
||||
This is a short description comment. It is identical to the synopsis comment, but is intended to
|
||||
be used for project notes. The text shows up in the Reference panel below the document viewer in
|
||||
the last column labelled :guilabel:`Short Description`.
|
||||
|
||||
.. note::
|
||||
Only one comment can be flagged as a synopsis comment for each heading. If multiple comments are
|
||||
flagged as synopsis comments, the last one will be used and the rest ignored.
|
||||
Only one comment can be flagged as a synopsis or short comment for each heading. If multiple
|
||||
comments are flagged as synopsis or short comments, the last one will be used and the rest
|
||||
ignored.
|
||||
|
||||
|
||||
.. _a_fmt_tags:
|
||||
@@ -204,8 +244,9 @@ References are in the form:
|
||||
``@keyword: value``
|
||||
A reference keyword followed by a value, or a comma separated list of values.
|
||||
|
||||
Tags andreferences are covered in detail in the :ref:`a_references` chapter. The keywords can be
|
||||
inserted at the cursor position in the editor via the :guilabel:`Insert` menu.
|
||||
Tags and references are covered in detail in the :ref:`a_references` chapter. The keywords can be
|
||||
inserted at the cursor position in the editor via the :guilabel:`Insert` menu. If you start typing
|
||||
an ``@`` on a new line, and auto-complete menu will also pop up suggesting keywords.
|
||||
|
||||
|
||||
.. _a_fmt_align:
|
||||
|
||||
@@ -28,7 +28,7 @@ the project, and has four columns.
|
||||
|
||||
**Column 2**
|
||||
The second column shows the word count of the document, or the sum of words of the child items
|
||||
for folders and documents with subdocuments. If the counts seem incorrect, they can be updated
|
||||
for folders and documents with sub-documents. If the counts seem incorrect, they can be updated
|
||||
by rebuilding the :term:`project index` from the :guilabel:`Tools` menu, or by pressing
|
||||
:kbd:`F9`.
|
||||
|
||||
@@ -62,6 +62,11 @@ Below the project tree you will find a small details panel showing the full info
|
||||
currently selected item. This panel also includes the latest paragraph and character counts in
|
||||
addition to the word count.
|
||||
|
||||
.. tip::
|
||||
If you want to set the label of a document to be the same as a header within it, you can
|
||||
right-click a header in the document when it is open in the editor and select
|
||||
:guilabel:`Set as Document Name` from the context menu.
|
||||
|
||||
|
||||
.. _a_ui_tree_split_merge:
|
||||
|
||||
@@ -73,6 +78,7 @@ will find several options on how to change a document or folder. This includes c
|
||||
document and note, but also splitting them into multiple documents, or merging child items into a
|
||||
single document.
|
||||
|
||||
|
||||
Splitting Documents
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -91,6 +97,7 @@ hierarchy of documents. That is, put sections under scenes, and scenes under cha
|
||||
The source document *is not* deleted in the process, but you have the option to let the tool move
|
||||
the source document to the :guilabel:`Trash` folder.
|
||||
|
||||
|
||||
Merging Documents
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -137,10 +144,14 @@ The project tree allows drag & drop to a certain extent to allow you to reorder
|
||||
folders. Moving a document in the project tree will affect the text's position when you assemble
|
||||
your manuscript in the :guilabel:`Manuscript Build` tool.
|
||||
|
||||
Drag & drop has only limited support for moving documents. In general, bulk actions are not
|
||||
allowed. This is deliberate to avoid accidentally messing up your project. If you make a mistake,
|
||||
the last move action can be undone by pressing :kbd:`Ctrl+Shift+Z` or from the menu icon in the
|
||||
project tree's toolbar.
|
||||
.. versionadded:: 2.2
|
||||
You can now select multiple items in the project tree by holding down the :kbd:`Ctrl` or
|
||||
:kbd:`Shift` key while selecting items.
|
||||
|
||||
You can drag and drop documents and regular folders, but not root folders. If you select multiple
|
||||
items, they can only be dragged and dropped if they are siblings. That is, they have the same
|
||||
parent item in the project. This is due to the way drag and drop is implemented in the user
|
||||
interface framework novelWriter is built upon.
|
||||
|
||||
Documents and their folders can be rearranged freely within their root folders. If you move a Novel
|
||||
document out of a Novel folder, it will be converted to a project note. Notes can be moved freely
|
||||
@@ -149,8 +160,8 @@ folder, its "Importance" setting will be switched with a "Status" setting. See
|
||||
:ref:`a_ui_tree_status`. The old value will not be overwritten though, and should be restored if
|
||||
you move it back at some point.
|
||||
|
||||
Root folders in the project tree cannot be dragged & dropped at all. If you want to reorder them,
|
||||
you can move them up or down with respect to eachother from the arrow buttons at the top of the
|
||||
Root folders in the project tree cannot be dragged and dropped at all. If you want to reorder them,
|
||||
you can move them up or down with respect to each other from the arrow buttons at the top of the
|
||||
project tree, or by pressing :kbd:`Ctrl+Shift+Up` or :kbd:`Ctrl+Shift+Down` when they are selected.
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ Text Formatting Shortcuts
|
||||
":kbd:`Ctrl+8`", "Add a left margin to the block"
|
||||
":kbd:`Ctrl+9`", "Add a right margin to the block"
|
||||
":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+D`", "Strike through selected text, or word under cursor"
|
||||
":kbd:`Ctrl+I`", "Format selected text, or word under cursor, with emphasis (italic)"
|
||||
":kbd:`Ctrl+Shift+/`", "Remove block formatting for block under cursor"
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ Single and Double Prime
|
||||
Both single and double prime symbols are available in the :guilabel:`Insert` menu. These symbols
|
||||
are the correct symbols to use for unit symbols for feet, inches, minutes, and seconds. The usage
|
||||
of these is described in more detail on the Wikipedia Prime_ page. They look very similar to single
|
||||
and double straight quotes, and may be renderred similarly by the font, but they have different
|
||||
and double straight quotes, and may be rendered similarly by the font, but they have different
|
||||
codes. Using these correctly will also prevent the auto-replace and dialogue highlighting features
|
||||
misunderstanding their meaning in the text.
|
||||
|
||||
@@ -74,7 +74,7 @@ even if it is intended as an apostrophe. This also includes the syntax highlight
|
||||
assume the first following apostrophe is the closing symbol of a single quoted region of text.
|
||||
|
||||
To get around this, an alternative apostrophe is available. It is a special Unicode character that
|
||||
is not categorised as punctuation, but as a modifier. It is usually renderred the same way as the
|
||||
is not categorised as punctuation, but as a modifier. It is usually rendered the same way as the
|
||||
right single quotation marks, depending on the font. There is a Wikipedia article for the
|
||||
`Modifier letter apostrophe`_ with more details.
|
||||
|
||||
|
||||
@@ -24,9 +24,8 @@ Markdown-like syntax for some features, and a novelWriter-specific syntax for ot
|
||||
format is described in the :ref:`a_fmt` chapter.
|
||||
|
||||
The editor has a maximise button (toggles the :guilabel:`Focus Mode`) and a close button in the
|
||||
top--right corner. On the top--left side you will find an edit button that opens the
|
||||
:guilabel:`Item Label` dialog for the currently open document, and a search button to open the
|
||||
search dialog.
|
||||
top--right corner. On the top--left side you will find a tools button that opens a toolbar with a
|
||||
few buttons for applying text formatting, and a search button to open the search dialog.
|
||||
|
||||
Both the document editor and viewer will show the label of the currently open document in the
|
||||
header at the top of the edit or view panel. Optionally, the full project path to the document can
|
||||
@@ -40,6 +39,18 @@ Any :term:`references<reference>` in the editor can be opened in the viewer by m
|
||||
the label and pressing :kbd:`Ctrl+Return`. You can also control-click them with your mouse.
|
||||
|
||||
|
||||
Editor Auto-Completer
|
||||
---------------------
|
||||
|
||||
If you type the character ``@`` on a new line, a context menu will appear showing the different
|
||||
available keywords. The list will shorten as you type. Once a keyword command has been selected or
|
||||
typed, the editor may suggest further content based on your project content. See
|
||||
:ref:`a_references_completer` for more details.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
The auto-completer feature was added.
|
||||
|
||||
|
||||
.. _a_ui_view:
|
||||
|
||||
Viewing a Document
|
||||
@@ -68,11 +79,10 @@ buttons, these can be used as well. They work just like the backward and forward
|
||||
browser.
|
||||
|
||||
At the bottom of the view panel there is a :guilabel:`References` panel. (If it is hidden, click
|
||||
the icon next to it to reveal it.) This panel will show links to all documents referring back to
|
||||
the one you're currently viewing, if any has been defined. The :guilabel:`Sticky` button will
|
||||
freeze the content of the panel to the current document, even if you navigate to another document.
|
||||
This is convenient if you want to quickly look through all documents in the list in the
|
||||
:guilabel:`References` panel without losing the list in the process.
|
||||
the button on the left side of the footer area to reveal it.) This panel contains a References tab
|
||||
with links to all documents referring back to the one you're currently viewing, if any has been
|
||||
defined. If you have created root folders and tags for various story elements like characters and
|
||||
plot points, these will appear as additional tabs in this panel.
|
||||
|
||||
.. note::
|
||||
The :guilabel:`References` panel relies on an up-to-date :term:`index<project index>` of the
|
||||
@@ -80,6 +90,9 @@ This is convenient if you want to quickly look through all documents in the list
|
||||
the index can always be rebuilt by selecting :guilabel:`Rebuild Index` from the
|
||||
:guilabel:`Tools` menu, or by pressing :kbd:`F9`.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
The reference panel was redesigned and the additional tabs added.
|
||||
|
||||
|
||||
.. _a_ui_edit_search:
|
||||
|
||||
|
||||
2156
i18n/nw_base.ts
2126
i18n/nw_en_US.ts
2128
i18n/nw_es_419.ts
2422
i18n/nw_fr_FR.ts
2128
i18n/nw_it_IT.ts
2428
i18n/nw_ja_JP.ts
2124
i18n/nw_nb_NO.ts
@@ -42,9 +42,9 @@ __license__ = "GPLv3"
|
||||
__author__ = "Veronica Berglyd Olsen"
|
||||
__maintainer__ = "Veronica Berglyd Olsen"
|
||||
__email__ = "code@vkbo.net"
|
||||
__version__ = "2.2-rc1"
|
||||
__hexversion__ = "0x020200c1"
|
||||
__date__ = "2023-11-26"
|
||||
__version__ = "2.2"
|
||||
__hexversion__ = "0x020200f0"
|
||||
__date__ = "2023-12-17"
|
||||
__status__ = "Stable"
|
||||
__domain__ = "novelwriter.io"
|
||||
|
||||
@@ -76,6 +76,7 @@ def main(sysArgs: list | None = None):
|
||||
"config=",
|
||||
"data=",
|
||||
"testmode",
|
||||
"meminfo"
|
||||
]
|
||||
|
||||
helpMsg = (
|
||||
@@ -92,6 +93,7 @@ def main(sysArgs: list | None = None):
|
||||
" -v, --version Print program version and exit.\n"
|
||||
" --info Print additional runtime information.\n"
|
||||
" --debug Print debug output. Includes --info.\n"
|
||||
" --meminfo Show memory usage information in the status bar.\n"
|
||||
" --style= Sets Qt5 style flag. Defaults to 'Fusion'.\n"
|
||||
" --config= Alternative config file.\n"
|
||||
" --data= Alternative user data path.\n"
|
||||
@@ -127,6 +129,7 @@ def main(sysArgs: list | None = None):
|
||||
elif inOpt == "--info":
|
||||
logLevel = logging.INFO
|
||||
elif inOpt == "--debug":
|
||||
CONFIG.isDebug = True
|
||||
logLevel = logging.DEBUG
|
||||
logFormat = "[{asctime:}] {filename:>17}:{lineno:<4d} {levelname:8} {message:}"
|
||||
elif inOpt == "--style":
|
||||
@@ -137,6 +140,8 @@ def main(sysArgs: list | None = None):
|
||||
dataPath = inArg
|
||||
elif inOpt == "--testmode":
|
||||
testMode = True
|
||||
elif inOpt == "--meminfo":
|
||||
CONFIG.memInfo = True
|
||||
|
||||
# Setup Logging
|
||||
pkgLogger = logging.getLogger(__package__)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"Synopsis": "Synopsis",
|
||||
"Short Description": "Short Description",
|
||||
"Comment": "Comment",
|
||||
"Notes": "Notes",
|
||||
"Tag": "Tag",
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"Synopsis": "Sinopsis",
|
||||
"Short Description": "Breve Descripción",
|
||||
"Comment": "Comentario",
|
||||
"Notes": "Notas",
|
||||
"Tag": "Etiqueta",
|
||||
"Point of View": "Punto de Vista",
|
||||
"Focus": "Foco",
|
||||
"Characters": "Personajes",
|
||||
"Plot": "Argumento",
|
||||
"Timeline": "Línea de Tiempo",
|
||||
"Locations": "Lugares",
|
||||
"Objects": "Objetos",
|
||||
"Entities": "Entidades",
|
||||
"Custom": "Otros",
|
||||
"0": "Cero",
|
||||
"1": "Uno",
|
||||
"2": "Dos",
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"Synopsis": "Synopsis",
|
||||
"Short Description": "Description sommaire",
|
||||
"Comment": "Commentaire",
|
||||
"Notes": "Notes",
|
||||
"Tag": "Étiquette",
|
||||
"Point of View": "Point de vue",
|
||||
"Focus": "Focus",
|
||||
"Characters": "Personnages",
|
||||
"Plot": "Intrigue",
|
||||
"Timeline": "Chronologie",
|
||||
"Locations": "Lieux",
|
||||
"Objects": "Objets",
|
||||
"Entities": "Entités",
|
||||
"Custom": "Personnalisé",
|
||||
"0": "Zero",
|
||||
"1": "Un",
|
||||
"2": "Deux",
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"Synopsis": "Sinossi",
|
||||
"Short Description": "Breve descrizione",
|
||||
"Comment": "Commento",
|
||||
"Notes": "Note",
|
||||
"Tag": "Etichetta",
|
||||
"Point of View": "Punto di vista",
|
||||
"Focus": "Focus",
|
||||
"Characters": "Personaggi",
|
||||
"Plot": "Trama",
|
||||
"Timeline": "Sequenza temporale",
|
||||
"Locations": "Luoghi",
|
||||
"Objects": "Oggetti",
|
||||
"Entities": "Enti",
|
||||
"Custom": "Personalizzato",
|
||||
"0": "Zero",
|
||||
"1": "Uno",
|
||||
"2": "Due",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"Synopsis": "あらすじ",
|
||||
"Comment": "コメント",
|
||||
"Short Description": "短い説明",
|
||||
"Comment": "コメント ",
|
||||
"Notes": "ノート",
|
||||
"Tag": "タグ",
|
||||
"Point of View": "視点",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"Synopsis": "Sammendrag",
|
||||
"Short Description": "Kort beskrivelse",
|
||||
"Comment": "Kommentar",
|
||||
"Notes": "Notat",
|
||||
"Tag": "Knagg",
|
||||
|
||||
@@ -47,10 +47,11 @@ down = typ_chevron-down.svg
|
||||
edit = typ_pencil.svg
|
||||
export = typ_export.svg
|
||||
fmt_bold = nw_tb-bold.svg
|
||||
fmt_bold-md = nw_tb-bold-md.svg
|
||||
fmt_italic = nw_tb-italic.svg
|
||||
fmt_mode-md = nw_tb-markdown.svg
|
||||
fmt_mode-sc = nw_tb-shortcode.svg
|
||||
fmt_italic-md = nw_tb-italic-md.svg
|
||||
fmt_strike = nw_tb-strike.svg
|
||||
fmt_strike-md = nw_tb-strike-md.svg
|
||||
fmt_subscript = nw_tb-subscript.svg
|
||||
fmt_superscript = nw_tb-superscript.svg
|
||||
fmt_underline = nw_tb-underline.svg
|
||||
|
||||
4
novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3672 5.5562v-4.7625h1.6289q0.37252 0 0.68662 0.058435 0.32139 0.051131 0.55513 0.18991 0.24104 0.13878 0.37252 0.36522 0.13878 0.22644 0.13878 0.56975 0 0.1607-0.043826 0.32139t-0.12417 0.29948q-0.080349 0.13878-0.19721 0.24835-0.10957 0.10957-0.25565 0.1607v0.029218q0.18261 0.043827 0.33601 0.13878 0.1534 0.087653 0.27027 0.22644 0.11687 0.13878 0.18261 0.3287 0.065739 0.18261 0.065739 0.42365 0 0.36522-0.14608 0.62818-0.13878 0.26295-0.39444 0.43826-0.24835 0.168-0.58435 0.25565-0.33601 0.080349-0.72313 0.080349zm1.0737-2.8561h0.50401q0.39444 0 0.56975-0.1534 0.18261-0.1534 0.18261-0.40905 0-0.27757-0.18261-0.39444t-0.56244-0.11687h-0.51131zm0 2.0233h0.60626q0.88383 0 0.88383-0.64279 0-0.31408-0.21914-0.44557-0.21914-0.13878-0.6647-0.13878h-0.60626z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54782"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 987 B |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3672 5.5562v-4.7625h1.6289q0.37252 0 0.68662 0.058435 0.32139 0.051131 0.55513 0.18991 0.24104 0.13878 0.37252 0.36522 0.13878 0.22644 0.13878 0.56975 0 0.1607-0.043826 0.32139-0.043826 0.16069-0.12417 0.29948-0.080349 0.13878-0.19721 0.24835-0.10957 0.10957-0.25565 0.1607v0.029218q0.18261 0.043827 0.33601 0.13878 0.1534 0.087653 0.27027 0.22644 0.11687 0.13878 0.18261 0.3287 0.065739 0.18261 0.065739 0.42365 0 0.36522-0.14608 0.62818-0.13878 0.26295-0.39444 0.43826-0.24835 0.168-0.58435 0.25565-0.33601 0.080349-0.72313 0.080349zm1.0737-2.8561h0.50401q0.39444 0 0.56975-0.1534 0.18261-0.1534 0.18261-0.40905 0-0.27757-0.18261-0.39444-0.18261-0.11687-0.56244-0.11687h-0.51131zm0 2.0233h0.60626q0.88383 0 0.88383-0.64279 0-0.31408-0.21914-0.44557-0.21914-0.13878-0.6647-0.13878h-0.60626z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54782"/>
|
||||
<path d="m1.568 5.2917v-4.2333h1.4479q0.33113 0 0.61033 0.051942 0.28568 0.04545 0.49345 0.16881 0.21426 0.12336 0.33113 0.32464 0.12336 0.20128 0.12336 0.50644 0 0.14284-0.038957 0.28568-0.038956 0.14284-0.11037 0.2662-0.071421 0.12336-0.1753 0.22076-0.097396 0.097396-0.22724 0.14284v0.025972q0.16232 0.038957 0.29868 0.12336 0.13636 0.077914 0.24024 0.20128 0.10388 0.12336 0.16232 0.29218 0.058435 0.16232 0.058435 0.37658 0 0.32464-0.12985 0.55838-0.12336 0.23373-0.35061 0.38956-0.22076 0.14933-0.51942 0.22724-0.29868 0.071422-0.64278 0.071422zm0.9544-2.5388h0.44801q0.35061 0 0.50644-0.13636 0.16232-0.13636 0.16232-0.3636 0-0.24673-0.16232-0.35061-0.16232-0.10388-0.49995-0.10388h-0.4545zm0 1.7985h0.5389q0.78563 0 0.78563-0.57137 0-0.27918-0.19479-0.39606-0.19479-0.12336-0.59084-0.12336h-0.5389z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".48695"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1017 B After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.3084 5.5562 0.94666-4.7625h0.78646l-0.94666 4.7625z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54615"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 277 B |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.3084 5.5562 0.94666-4.7625h0.78646l-0.94666 4.7625z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54615"/>
|
||||
<path d="m2.417 5.2917 0.84148-4.2333h0.69908l-0.84148 4.2333z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".48547"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 515 B |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#aeaeae" stroke-width="1.1">
|
||||
<path d="m0.79397 2.8846-0.29357-0.21175 0.28393-0.5005-0.51975-0.23582 0.11068-0.3465 0.55825 0.1155 0.062562-0.56787h0.37057l0.062562 0.57268 0.55343-0.12032 0.1155 0.3465-0.51975 0.23582 0.28393 0.5005-0.29356 0.21175-0.385-0.42832z"/>
|
||||
<path d="m2.8219 3.15-0.09999 0.37496h0.86866l-0.09374-0.37496q-0.08749-0.30622-0.16873-0.64993-0.081241-0.34372-0.16248-0.66243h-0.024997q-0.074992 0.32496-0.15623 0.66868-0.074992 0.33747-0.16248 0.64369zm-1.4749 2.0623 1.2749-4.0746h1.1062l1.2749 4.0746h-0.97489l-0.24997-0.96865h-1.2437l-0.24997 0.96865z"/>
|
||||
<path d="m4.7812 2.8846-0.29357-0.21175 0.28394-0.5005-0.51975-0.23582 0.11069-0.3465 0.55825 0.1155 0.062562-0.56787h0.37056l0.062562 0.57268 0.55343-0.12032 0.1155 0.3465-0.51975 0.23582 0.28393 0.5005-0.29356 0.21175-0.385-0.42832z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 988 B |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#aeaeae" stroke-width="1.3799">
|
||||
<path d="m0.52917 5.2683v-4.1866h1.0272v0.37972h-0.49167v3.4272h0.49167v0.37972z"/>
|
||||
<path d="m2.9 2.9219-0.077889 0.29209h0.67667l-0.073022-0.29209q-0.068154-0.23854-0.13144-0.50628-0.063285-0.26775-0.12657-0.51601h-0.019472q-0.058417 0.25314-0.1217 0.52088-0.058417 0.26288-0.12657 0.50141zm-1.1489 1.6065 0.9931-3.174h0.86166l0.9931 3.174h-0.75942l-0.19472-0.75455h-0.96876l-0.19472 0.75455z"/>
|
||||
<path d="m4.7937 5.2683v-0.37972h0.49654v-3.4272h-0.49654v-0.37972h1.0272v4.1866z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 684 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1785 5.5562q-0.46361 0-0.89912-0.17561-0.42848-0.17561-0.75863-0.49873l0.47766-0.55492q0.24585 0.2318 0.56195 0.37931 0.3161 0.14049 0.63219 0.14049 0.39336 0 0.59707-0.16156t0.20371-0.42848q0-0.14049-0.056194-0.23883-0.04917-0.098341-0.14751-0.16858-0.091316-0.077267-0.22478-0.14049-0.12644-0.063219-0.28097-0.12644l-0.63219-0.27395q-0.16858-0.070243-0.33717-0.17561-0.16156-0.10537-0.29502-0.25288t-0.21775-0.34419q-0.077268-0.19668-0.077268-0.44956 0-0.27395 0.11239-0.50575 0.11941-0.23883 0.32312-0.41444t0.48468-0.27395q0.288-0.098341 0.62517-0.098341 0.40039 0 0.77268 0.16156 0.37229 0.15454 0.63921 0.42146l-0.41444 0.5198q-0.22478-0.18263-0.46361-0.288t-0.53385-0.10537q-0.33014 0-0.52683 0.14751-0.19668 0.14049-0.19668 0.39336 0 0.13346 0.056194 0.2318 0.063219 0.091316 0.16156 0.16858 0.10537 0.070244 0.23883 0.13346 0.13346 0.056194 0.27395 0.11239l0.62516 0.2599q0.20371 0.084291 0.37229 0.19668 0.16858 0.11239 0.288 0.2599 0.12644 0.14751 0.19668 0.34419 0.070244 0.18966 0.070244 0.44253 0 0.28097-0.11239 0.52683-0.11239 0.24585-0.33015 0.43551-0.21073 0.18263-0.5198 0.29502-0.30205 0.10536-0.68838 0.10536zm-2.3848-2.6458h4.7625v0.52917h-4.7625z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".52683"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1785 5.5562q-0.46361 0-0.89912-0.17561-0.42848-0.17561-0.75863-0.49873l0.47766-0.55492q0.24585 0.2318 0.56195 0.37931 0.3161 0.14049 0.63219 0.14049 0.39336 0 0.59707-0.16156 0.20371-0.16156 0.20371-0.42848 0-0.14049-0.056194-0.23883-0.04917-0.098341-0.14751-0.16858-0.091316-0.077267-0.22478-0.14049-0.12644-0.063219-0.28097-0.12644l-0.63219-0.27395q-0.16858-0.070243-0.33717-0.17561-0.16156-0.10537-0.29502-0.25288-0.13346-0.14751-0.21775-0.34419-0.077268-0.19668-0.077268-0.44956 0-0.27395 0.11239-0.50575 0.11941-0.23883 0.32312-0.41444 0.20371-0.17561 0.48468-0.27395 0.288-0.098341 0.62517-0.098341 0.40039 0 0.77268 0.16156 0.37229 0.15454 0.63921 0.42146l-0.41444 0.5198q-0.22478-0.18263-0.46361-0.288-0.23883-0.10537-0.53385-0.10537-0.33014 0-0.52683 0.14751-0.19668 0.14049-0.19668 0.39336 0 0.13346 0.056194 0.2318 0.063219 0.091316 0.16156 0.16858 0.10537 0.070244 0.23883 0.13346 0.13346 0.056194 0.27395 0.11239l0.62516 0.2599q0.20371 0.084291 0.37229 0.19668 0.16858 0.11239 0.288 0.2599 0.12644 0.14751 0.19668 0.34419 0.070244 0.18966 0.070244 0.44253 0 0.28097-0.11239 0.52683-0.11239 0.24585-0.33015 0.43551-0.21073 0.18263-0.5198 0.29502-0.30205 0.10536-0.68838 0.10536zm-2.3848-2.6458h4.7625v0.52917h-4.7625z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".52683"/>
|
||||
<path d="m3.1782 5.2917q-0.4121 0-0.79922-0.1561-0.38087-0.1561-0.67434-0.44331l0.42459-0.49326q0.21853 0.20604 0.49951 0.33716 0.28098 0.12488 0.56195 0.12488 0.34965 0 0.53073-0.14361 0.18108-0.14361 0.18108-0.38087 0-0.12488-0.04995-0.21229-0.043707-0.087414-0.13112-0.14985-0.08117-0.068682-0.1998-0.12488-0.11239-0.056194-0.24975-0.11239l-0.56195-0.24351q-0.14985-0.062438-0.29971-0.1561-0.14361-0.093662-0.26224-0.22478-0.11863-0.13112-0.19356-0.30595-0.068682-0.17483-0.068682-0.39961 0-0.24351 0.099902-0.44955 0.10614-0.21229 0.28722-0.36839 0.18108-0.1561 0.43083-0.24351 0.256-0.087414 0.55571-0.087414 0.3559 0 0.68683 0.14361 0.33092 0.13737 0.56819 0.37463l-0.36839 0.46204q-0.1998-0.16234-0.4121-0.256-0.21229-0.093662-0.47453-0.093662-0.29346 0-0.46829 0.13112-0.17483 0.12488-0.17483 0.34965 0 0.11863 0.04995 0.20604 0.056194 0.08117 0.14361 0.14985 0.093662 0.062439 0.21229 0.11863 0.11863 0.04995 0.24351 0.099902l0.5557 0.23102q0.18108 0.074925 0.33092 0.17483 0.14985 0.099902 0.256 0.23102 0.11239 0.13112 0.17483 0.30595 0.062439 0.16859 0.062439 0.39336 0 0.24975-0.099902 0.46829-0.099902 0.21853-0.29347 0.38712-0.18732 0.16234-0.46204 0.26224-0.26849 0.093653-0.61189 0.093653zm-2.1198-2.3518h4.2333v0.47037h-4.2333z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".46829"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.124 3.0221-0.16749 0.58257h1.2161l-0.16749-0.58257q-0.11651-0.37867-0.22575-0.77919-0.10195-0.40052-0.2039-0.79375h-0.029128q-0.10195 0.40052-0.2039 0.80103-0.10195 0.39323-0.21846 0.7719zm-1.5948 2.5342 1.5511-4.7625h0.99037l1.5511 4.7625h-0.88842l-0.37139-1.2889h-1.6021l-0.37139 1.2889z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54616"/>
|
||||
<path d="m4.101 5.5562v-2.3812h0.75354q0.18388 0 0.3353 0.032769 0.15503 0.029128 0.2668 0.098307 0.11538 0.065538 0.17667 0.17841 0.064898 0.11287 0.064898 0.27671 0 0.17113-0.086529 0.31676-0.086529 0.14564-0.24156 0.20026v0.014565q0.19469 0.043691 0.32088 0.18569 0.12979 0.13836 0.12979 0.37867 0 0.17841-0.068503 0.30948-0.068502 0.13107-0.19108 0.21846-0.11899 0.087383-0.28483 0.13107-0.16585 0.04005-0.36054 0.04005zm0.41823-1.3981h0.29925q0.24878 0 0.35693-0.091024 0.11177-0.091025 0.11177-0.24394 0-0.17477-0.11538-0.24759-0.11538-0.072819-0.34612-0.072819h-0.30646zm0 1.0705h0.35334q0.25959 0 0.4002-0.094666 0.14061-0.098307 0.14061-0.29856 0-0.18933-0.13701-0.27308-0.13701-0.087384-0.40381-0.087384h-0.35334z" fill="#69c" stroke-opacity=".78039" stroke-width=".27174"/>
|
||||
<path d="m2.2992 3.0475-0.13958 0.48548h1.0134l-0.13958-0.48548q-0.097092-0.31556-0.18812-0.64932-0.084958-0.33377-0.16992-0.66146h-0.024273q-0.084958 0.33377-0.16992 0.66752-0.084958 0.32769-0.18205 0.64325zm-1.329 2.1118 1.2926-3.9688h0.82531l1.2926 3.9688h-0.74035l-0.30949-1.0741h-1.3351l-0.30949 1.0741z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".45513"/>
|
||||
<path d="m3.9467 5.1593v-1.9843h0.62795q0.15323 0 0.27942 0.027308 0.12919 0.024273 0.22233 0.081922 0.09615 0.054615 0.14722 0.14868 0.054082 0.094058 0.054082 0.23059 0 0.14261-0.072107 0.26397-0.072108 0.12137-0.2013 0.16688v0.012137q0.16224 0.036409 0.2674 0.15474 0.10816 0.1153 0.10816 0.31556 0 0.14868-0.057086 0.2579-0.057085 0.10922-0.15923 0.18205-0.099158 0.072819-0.23736 0.10922-0.13821 0.033375-0.30045 0.033375zm0.34852-1.1651h0.24938q0.20732 0 0.29744-0.075853 0.093142-0.075854 0.093142-0.20328 0-0.14564-0.09615-0.20632-0.09615-0.060682-0.28843-0.060682h-0.25538zm0 0.89208h0.29445q0.21632 0 0.3335-0.078888 0.11718-0.081923 0.11718-0.2488 0-0.15778-0.11418-0.22757-0.11418-0.07282-0.33651-0.07282h-0.29445z" fill="#fff" stroke-opacity=".78039" stroke-width=".22645"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.124 3.0221-0.16749 0.58257h1.2161l-0.16749-0.58257q-0.11651-0.37867-0.22575-0.77919-0.10195-0.40052-0.2039-0.79375h-0.029128q-0.10195 0.40052-0.2039 0.80103-0.10195 0.39323-0.21846 0.7719zm-1.5948 2.5342 1.5511-4.7625h0.99037l1.5511 4.7625h-0.88842l-0.37139-1.2889h-1.6021l-0.37139 1.2889z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".54616"/>
|
||||
<path d="m4.101 3.175v-2.3812h0.75352q0.18389 0 0.33531 0.032768 0.15503 0.029128 0.2668 0.098307 0.11538 0.065538 0.17667 0.17841 0.064898 0.11287 0.064898 0.27671 0 0.17113-0.086528 0.31676-0.086528 0.14564-0.24156 0.20026v0.014565q0.19469 0.043691 0.32088 0.1857 0.12979 0.13836 0.12979 0.37867 0 0.17841-0.068503 0.30948t-0.19108 0.21845q-0.11897 0.087382-0.28482 0.13107-0.16585 0.04005-0.36054 0.04005zm0.41824-1.3981h0.29924q0.24878 0 0.35693-0.091024 0.11177-0.091024 0.11177-0.24394 0-0.17477-0.11538-0.24759-0.11538-0.072818-0.34612-0.072818h-0.30646zm0 1.0705h0.35332q0.25959 0 0.4002-0.094666 0.14061-0.098307 0.14061-0.29855 0-0.18932-0.13701-0.27307-0.13701-0.087383-0.40381-0.087383h-0.35332z" fill="#69c" stroke-opacity=".78039" stroke-width=".27173"/>
|
||||
<path d="m3.9467 3.175v-1.9843h0.62793q0.15324 0 0.27942 0.027307 0.12919 0.024274 0.22233 0.081922 0.09615 0.054615 0.14722 0.14868 0.054082 0.094058 0.054082 0.23059 0 0.14261-0.072107 0.26397-0.072107 0.12137-0.2013 0.16688v0.012138q0.16224 0.03641 0.2674 0.15475 0.10816 0.1153 0.10816 0.31556 0 0.14868-0.057086 0.2579-0.057085 0.10922-0.15923 0.18204-0.099142 0.072818-0.23735 0.10922-0.13821 0.033375-0.30045 0.033375zm0.34853-1.1651h0.24937q0.20732 0 0.29744-0.075853 0.093141-0.075853 0.093141-0.20328 0-0.14564-0.09615-0.20632-0.09615-0.060682-0.28843-0.060682h-0.25538zm0 0.89208h0.29443q0.21632 0 0.3335-0.078888 0.11718-0.081923 0.11718-0.24879 0-0.15777-0.11418-0.22756-0.11418-0.07282-0.33651-0.07282h-0.29443z" fill="#fff" stroke-opacity=".78039" stroke-width=".25475"/>
|
||||
<path d="m2.2992 3.0475-0.13958 0.48548h1.0134l-0.13958-0.48548q-0.097092-0.31556-0.18812-0.64932-0.084958-0.33377-0.16992-0.66146h-0.024273q-0.084958 0.33377-0.16992 0.66753-0.084958 0.32769-0.18205 0.64325zm-1.329 2.1118 1.2926-3.9688h0.82531l1.2926 3.9688h-0.74035l-0.30949-1.0741h-1.3351l-0.30949 1.0741z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".45513"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1782 5.0271q-0.36231 0-0.6547-0.1017-0.28603-0.10806-0.49579-0.33689-0.2034-0.22883-0.31782-0.58479-0.10806-0.36231-0.10806-0.87717v-2.3328h0.73733v2.3899q0 0.33689 0.057206 0.57207 0.063563 0.22883 0.17162 0.36866 0.11441 0.13984 0.26697 0.2034 0.15255 0.057206 0.34324 0.057206 0.19068 0 0.3496-0.057206 0.15891-0.063564 0.27332-0.2034 0.11441-0.13984 0.17798-0.36866 0.063564-0.23519 0.063564-0.57207v-2.3899h0.70555v2.3328q0 0.51487-0.10806 0.87717-0.10806 0.35595-0.31782 0.58479-0.2034 0.22883-0.49579 0.33689-0.28603 0.1017-0.64835 0.1017z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".47673"/>
|
||||
<rect x="1.0583" y="5.2917" width="4.2333" height=".52917" fill="#aeaeae" stroke-width="1.2172"/>
|
||||
<path d="m3.1778 4.846q-0.32417 0-0.58578-0.090994-0.25592-0.096685-0.4436-0.30143-0.18199-0.20474-0.28436-0.52323-0.096684-0.32417-0.096684-0.78483v-2.0872h0.65971v2.1383q0 0.30143 0.051184 0.51185 0.056872 0.20474 0.15355 0.32985 0.10237 0.12512 0.23887 0.18199 0.13649 0.051184 0.30711 0.051184 0.17061 0 0.3128-0.051184 0.14218-0.056873 0.24455-0.18199 0.10237-0.12512 0.15924-0.32985 0.056873-0.21043 0.056873-0.51185v-2.1383h0.63128v2.0872q0 0.46067-0.096685 0.78483-0.096684 0.31848-0.28436 0.52323-0.18199 0.20474-0.4436 0.30143-0.25592 0.090994-0.5801 0.090994z" fill="#aeaeae" stroke-opacity=".78039" stroke-width=".42654"/>
|
||||
<rect x="1.5875" y="5.0271" width="3.175" height=".39688" fill="#aeaeae" stroke-width=".91291"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#69c" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#69c" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 871 B After Width: | Height: | Size: 1.1 KiB |
@@ -47,10 +47,11 @@ down = typ_chevron-down.svg
|
||||
edit = typ_pencil.svg
|
||||
export = typ_export.svg
|
||||
fmt_bold = nw_tb-bold.svg
|
||||
fmt_bold-md = nw_tb-bold-md.svg
|
||||
fmt_italic = nw_tb-italic.svg
|
||||
fmt_mode-md = nw_tb-markdown.svg
|
||||
fmt_mode-sc = nw_tb-shortcode.svg
|
||||
fmt_italic-md = nw_tb-italic-md.svg
|
||||
fmt_strike = nw_tb-strike.svg
|
||||
fmt_strike-md = nw_tb-strike-md.svg
|
||||
fmt_subscript = nw_tb-subscript.svg
|
||||
fmt_superscript = nw_tb-superscript.svg
|
||||
fmt_underline = nw_tb-underline.svg
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3672 5.5562v-4.7625h1.6289q0.37252 0 0.68662 0.058435 0.32139 0.051131 0.55513 0.18991 0.24104 0.13878 0.37252 0.36522 0.13878 0.22644 0.13878 0.56975 0 0.1607-0.043826 0.32139t-0.12417 0.29948q-0.080349 0.13878-0.19721 0.24835-0.10957 0.10957-0.25565 0.1607v0.029218q0.18261 0.043827 0.33601 0.13878 0.1534 0.087653 0.27027 0.22644 0.11687 0.13878 0.18261 0.3287 0.065739 0.18261 0.065739 0.42365 0 0.36522-0.14608 0.62818-0.13878 0.26295-0.39444 0.43826-0.24835 0.168-0.58435 0.25565-0.33601 0.080349-0.72313 0.080349zm1.0737-2.8561h0.50401q0.39444 0 0.56975-0.1534 0.18261-0.1534 0.18261-0.40905 0-0.27757-0.18261-0.39444t-0.56244-0.11687h-0.51131zm0 2.0233h0.60626q0.88383 0 0.88383-0.64279 0-0.31408-0.21914-0.44557-0.21914-0.13878-0.6647-0.13878h-0.60626z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54782"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 994 B |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3672 5.5562v-4.7625h1.6289q0.37252 0 0.68662 0.058435 0.32139 0.051131 0.55513 0.18991 0.24104 0.13878 0.37252 0.36522 0.13878 0.22644 0.13878 0.56975 0 0.1607-0.043826 0.32139-0.043826 0.16069-0.12417 0.29948-0.080349 0.13878-0.19721 0.24835-0.10957 0.10957-0.25565 0.1607v0.029218q0.18261 0.043827 0.33601 0.13878 0.1534 0.087653 0.27027 0.22644 0.11687 0.13878 0.18261 0.3287 0.065739 0.18261 0.065739 0.42365 0 0.36522-0.14608 0.62818-0.13878 0.26295-0.39444 0.43826-0.24835 0.168-0.58435 0.25565-0.33601 0.080349-0.72313 0.080349zm1.0737-2.8561h0.50401q0.39444 0 0.56975-0.1534 0.18261-0.1534 0.18261-0.40905 0-0.27757-0.18261-0.39444-0.18261-0.11687-0.56244-0.11687h-0.51131zm0 2.0233h0.60626q0.88383 0 0.88383-0.64279 0-0.31408-0.21914-0.44557-0.21914-0.13878-0.6647-0.13878h-0.60626z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54782"/>
|
||||
<path d="m1.568 5.2917v-4.2333h1.4479q0.33113 0 0.61033 0.051942 0.28568 0.04545 0.49345 0.16881 0.21426 0.12336 0.33113 0.32464 0.12336 0.20128 0.12336 0.50644 0 0.14284-0.038957 0.28568-0.038956 0.14284-0.11037 0.2662-0.071421 0.12336-0.1753 0.22076-0.097396 0.097396-0.22724 0.14284v0.025972q0.16232 0.038957 0.29868 0.12336 0.13636 0.077914 0.24024 0.20128 0.10388 0.12336 0.16232 0.29218 0.058435 0.16232 0.058435 0.37658 0 0.32464-0.12985 0.55838-0.12336 0.23373-0.35061 0.38956-0.22076 0.14933-0.51942 0.22724-0.29868 0.071422-0.64278 0.071422zm0.9544-2.5388h0.44801q0.35061 0 0.50644-0.13636 0.16232-0.13636 0.16232-0.3636 0-0.24673-0.16232-0.35061-0.16232-0.10388-0.49995-0.10388h-0.4545zm0 1.7985h0.5389q0.78563 0 0.78563-0.57137 0-0.27918-0.19479-0.39606-0.19479-0.12336-0.59084-0.12336h-0.5389z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".48695"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.3084 5.5562 0.94666-4.7625h0.78646l-0.94666 4.7625z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54615"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 284 B |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.3084 5.5562 0.94666-4.7625h0.78646l-0.94666 4.7625z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54615"/>
|
||||
<path d="m2.417 5.2917 0.84148-4.2333h0.69908l-0.84148 4.2333z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".48547"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 528 B |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill-opacity=".78039" stroke-width="1.1">
|
||||
<path d="m0.79397 2.8846-0.29357-0.21175 0.28393-0.5005-0.51975-0.23582 0.11068-0.3465 0.55825 0.1155 0.062562-0.56787h0.37057l0.062562 0.57268 0.55343-0.12032 0.1155 0.3465-0.51975 0.23582 0.28393 0.5005-0.29356 0.21175-0.385-0.42832z"/>
|
||||
<path d="m2.8219 3.15-0.09999 0.37496h0.86866l-0.09374-0.37496q-0.08749-0.30622-0.16873-0.64993-0.081241-0.34372-0.16248-0.66243h-0.024997q-0.074992 0.32496-0.15623 0.66868-0.074992 0.33747-0.16248 0.64369zm-1.4749 2.0623 1.2749-4.0746h1.1062l1.2749 4.0746h-0.97489l-0.24997-0.96865h-1.2437l-0.24997 0.96865z"/>
|
||||
<path d="m4.7812 2.8846-0.29357-0.21175 0.28394-0.5005-0.51975-0.23582 0.11069-0.3465 0.55825 0.1155 0.062562-0.56787h0.37056l0.062562 0.57268 0.55343-0.12032 0.1155 0.3465-0.51975 0.23582 0.28393 0.5005-0.29356 0.21175-0.385-0.42832z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 995 B |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill-opacity=".78039" stroke-width="1.3799">
|
||||
<path d="m0.52917 5.2683v-4.1866h1.0272v0.37972h-0.49167v3.4272h0.49167v0.37972z"/>
|
||||
<path d="m2.9 2.9219-0.077889 0.29209h0.67667l-0.073022-0.29209q-0.068154-0.23854-0.13144-0.50628-0.063285-0.26775-0.12657-0.51601h-0.019472q-0.058417 0.25314-0.1217 0.52088-0.058417 0.26288-0.12657 0.50141zm-1.1489 1.6065 0.9931-3.174h0.86166l0.9931 3.174h-0.75942l-0.19472-0.75455h-0.96876l-0.19472 0.75455z"/>
|
||||
<path d="m4.7937 5.2683v-0.37972h0.49654v-3.4272h-0.49654v-0.37972h1.0272v4.1866z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 691 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1785 5.5562q-0.46361 0-0.89912-0.17561-0.42848-0.17561-0.75863-0.49873l0.47766-0.55492q0.24585 0.2318 0.56195 0.37931 0.3161 0.14049 0.63219 0.14049 0.39336 0 0.59707-0.16156t0.20371-0.42848q0-0.14049-0.056194-0.23883-0.04917-0.098341-0.14751-0.16858-0.091316-0.077267-0.22478-0.14049-0.12644-0.063219-0.28097-0.12644l-0.63219-0.27395q-0.16858-0.070243-0.33717-0.17561-0.16156-0.10537-0.29502-0.25288t-0.21775-0.34419q-0.077268-0.19668-0.077268-0.44956 0-0.27395 0.11239-0.50575 0.11941-0.23883 0.32312-0.41444t0.48468-0.27395q0.288-0.098341 0.62517-0.098341 0.40039 0 0.77268 0.16156 0.37229 0.15454 0.63921 0.42146l-0.41444 0.5198q-0.22478-0.18263-0.46361-0.288t-0.53385-0.10537q-0.33014 0-0.52683 0.14751-0.19668 0.14049-0.19668 0.39336 0 0.13346 0.056194 0.2318 0.063219 0.091316 0.16156 0.16858 0.10537 0.070244 0.23883 0.13346 0.13346 0.056194 0.27395 0.11239l0.62516 0.2599q0.20371 0.084291 0.37229 0.19668 0.16858 0.11239 0.288 0.2599 0.12644 0.14751 0.19668 0.34419 0.070244 0.18966 0.070244 0.44253 0 0.28097-0.11239 0.52683-0.11239 0.24585-0.33015 0.43551-0.21073 0.18263-0.5198 0.29502-0.30205 0.10536-0.68838 0.10536zm-2.3848-2.6458h4.7625v0.52917h-4.7625z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".52683"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1785 5.5562q-0.46361 0-0.89912-0.17561-0.42848-0.17561-0.75863-0.49873l0.47766-0.55492q0.24585 0.2318 0.56195 0.37931 0.3161 0.14049 0.63219 0.14049 0.39336 0 0.59707-0.16156 0.20371-0.16156 0.20371-0.42848 0-0.14049-0.056194-0.23883-0.04917-0.098341-0.14751-0.16858-0.091316-0.077267-0.22478-0.14049-0.12644-0.063219-0.28097-0.12644l-0.63219-0.27395q-0.16858-0.070243-0.33717-0.17561-0.16156-0.10537-0.29502-0.25288-0.13346-0.14751-0.21775-0.34419-0.077268-0.19668-0.077268-0.44956 0-0.27395 0.11239-0.50575 0.11941-0.23883 0.32312-0.41444 0.20371-0.17561 0.48468-0.27395 0.288-0.098341 0.62517-0.098341 0.40039 0 0.77268 0.16156 0.37229 0.15454 0.63921 0.42146l-0.41444 0.5198q-0.22478-0.18263-0.46361-0.288-0.23883-0.10537-0.53385-0.10537-0.33014 0-0.52683 0.14751-0.19668 0.14049-0.19668 0.39336 0 0.13346 0.056194 0.2318 0.063219 0.091316 0.16156 0.16858 0.10537 0.070244 0.23883 0.13346 0.13346 0.056194 0.27395 0.11239l0.62516 0.2599q0.20371 0.084291 0.37229 0.19668 0.16858 0.11239 0.288 0.2599 0.12644 0.14751 0.19668 0.34419 0.070244 0.18966 0.070244 0.44253 0 0.28097-0.11239 0.52683-0.11239 0.24585-0.33015 0.43551-0.21073 0.18263-0.5198 0.29502-0.30205 0.10536-0.68838 0.10536zm-2.3848-2.6458h4.7625v0.52917h-4.7625z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".52683"/>
|
||||
<path d="m3.1782 5.2917q-0.4121 0-0.79922-0.1561-0.38087-0.1561-0.67434-0.44331l0.42459-0.49326q0.21853 0.20604 0.49951 0.33716 0.28098 0.12488 0.56195 0.12488 0.34965 0 0.53073-0.14361 0.18108-0.14361 0.18108-0.38087 0-0.12488-0.04995-0.21229-0.043707-0.087414-0.13112-0.14985-0.08117-0.068682-0.1998-0.12488-0.11239-0.056194-0.24975-0.11239l-0.56195-0.24351q-0.14985-0.062438-0.29971-0.1561-0.14361-0.093662-0.26224-0.22478-0.11863-0.13112-0.19356-0.30595-0.068682-0.17483-0.068682-0.39961 0-0.24351 0.099902-0.44955 0.10614-0.21229 0.28722-0.36839 0.18108-0.1561 0.43083-0.24351 0.256-0.087414 0.55571-0.087414 0.3559 0 0.68683 0.14361 0.33092 0.13737 0.56819 0.37463l-0.36839 0.46204q-0.1998-0.16234-0.4121-0.256-0.21229-0.093662-0.47453-0.093662-0.29346 0-0.46829 0.13112-0.17483 0.12488-0.17483 0.34965 0 0.11863 0.04995 0.20604 0.056194 0.08117 0.14361 0.14985 0.093662 0.062439 0.21229 0.11863 0.11863 0.04995 0.24351 0.099902l0.5557 0.23102q0.18108 0.074925 0.33092 0.17483 0.14985 0.099902 0.256 0.23102 0.11239 0.13112 0.17483 0.30595 0.062439 0.16859 0.062439 0.39336 0 0.24975-0.099902 0.46829-0.099902 0.21853-0.29347 0.38712-0.18732 0.16234-0.46204 0.26224-0.26849 0.093653-0.61189 0.093653zm-2.1198-2.3518h4.2333v0.47037h-4.2333z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".46829"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.124 3.0221-0.16749 0.58257h1.2161l-0.16749-0.58257q-0.11651-0.37867-0.22575-0.77919-0.10195-0.40052-0.2039-0.79375h-0.029128q-0.10195 0.40052-0.2039 0.80103-0.10195 0.39323-0.21846 0.7719zm-1.5948 2.5342 1.5511-4.7625h0.99037l1.5511 4.7625h-0.88842l-0.37139-1.2889h-1.6021l-0.37139 1.2889z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54616"/>
|
||||
<path d="m4.101 5.5562v-2.3812h0.75354q0.18388 0 0.3353 0.032769 0.15503 0.029128 0.2668 0.098307 0.11538 0.065538 0.17667 0.17841 0.064898 0.11287 0.064898 0.27671 0 0.17113-0.086529 0.31676-0.086529 0.14564-0.24156 0.20026v0.014565q0.19469 0.043691 0.32088 0.18569 0.12979 0.13836 0.12979 0.37867 0 0.17841-0.068503 0.30948-0.068502 0.13107-0.19108 0.21846-0.11899 0.087383-0.28483 0.13107-0.16585 0.04005-0.36054 0.04005zm0.41823-1.3981h0.29925q0.24878 0 0.35693-0.091024 0.11177-0.091025 0.11177-0.24394 0-0.17477-0.11538-0.24759-0.11538-0.072819-0.34612-0.072819h-0.30646zm0 1.0705h0.35334q0.25959 0 0.4002-0.094666 0.14061-0.098307 0.14061-0.29856 0-0.18933-0.13701-0.27308-0.13701-0.087384-0.40381-0.087384h-0.35334z" fill="#4271ae" stroke-opacity=".78039" stroke-width=".27174"/>
|
||||
<path d="m2.2992 3.0475-0.13958 0.48548h1.0134l-0.13958-0.48548q-0.097092-0.31556-0.18812-0.64932-0.084958-0.33377-0.16992-0.66146h-0.024273q-0.084958 0.33377-0.16992 0.66752-0.084958 0.32769-0.18205 0.64325zm-1.329 2.1118 1.2926-3.9688h0.82531l1.2926 3.9688h-0.74035l-0.30949-1.0741h-1.3351l-0.30949 1.0741z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".45513"/>
|
||||
<path d="m3.9467 5.1593v-1.9843h0.62795q0.15323 0 0.27942 0.027308 0.12919 0.024273 0.22233 0.081922 0.09615 0.054615 0.14722 0.14868 0.054082 0.094058 0.054082 0.23059 0 0.14261-0.072107 0.26397-0.072108 0.12137-0.2013 0.16688v0.012137q0.16224 0.036409 0.2674 0.15474 0.10816 0.1153 0.10816 0.31556 0 0.14868-0.057086 0.2579-0.057085 0.10922-0.15923 0.18205-0.099158 0.072819-0.23736 0.10922-0.13821 0.033375-0.30045 0.033375zm0.34852-1.1651h0.24938q0.20732 0 0.29744-0.075853 0.093142-0.075854 0.093142-0.20328 0-0.14564-0.09615-0.20632-0.09615-0.060682-0.28843-0.060682h-0.25538zm0 0.89208h0.29445q0.21632 0 0.3335-0.078888 0.11718-0.081923 0.11718-0.2488 0-0.15778-0.11418-0.22757-0.11418-0.07282-0.33651-0.07282h-0.29445z" stroke-opacity=".78039" stroke-width=".22645"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.124 3.0221-0.16749 0.58257h1.2161l-0.16749-0.58257q-0.11651-0.37867-0.22575-0.77919-0.10195-0.40052-0.2039-0.79375h-0.029128q-0.10195 0.40052-0.2039 0.80103-0.10195 0.39323-0.21846 0.7719zm-1.5948 2.5342 1.5511-4.7625h0.99037l1.5511 4.7625h-0.88842l-0.37139-1.2889h-1.6021l-0.37139 1.2889z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".54616"/>
|
||||
<path d="m4.101 3.175v-2.3812h0.75352q0.18389 0 0.33531 0.032768 0.15503 0.029128 0.2668 0.098307 0.11538 0.065538 0.17667 0.17841 0.064898 0.11287 0.064898 0.27671 0 0.17113-0.086528 0.31676-0.086528 0.14564-0.24156 0.20026v0.014565q0.19469 0.043691 0.32088 0.1857 0.12979 0.13836 0.12979 0.37867 0 0.17841-0.068503 0.30948t-0.19108 0.21845q-0.11897 0.087382-0.28482 0.13107-0.16585 0.04005-0.36054 0.04005zm0.41824-1.3981h0.29924q0.24878 0 0.35693-0.091024 0.11177-0.091024 0.11177-0.24394 0-0.17477-0.11538-0.24759-0.11538-0.072818-0.34612-0.072818h-0.30646zm0 1.0705h0.35332q0.25959 0 0.4002-0.094666 0.14061-0.098307 0.14061-0.29855 0-0.18932-0.13701-0.27307-0.13701-0.087383-0.40381-0.087383h-0.35332z" fill="#4271ae" stroke-opacity=".78039" stroke-width=".27173"/>
|
||||
<path d="m3.9467 3.175v-1.9843h0.62793q0.15324 0 0.27942 0.027307 0.12919 0.024274 0.22233 0.081922 0.09615 0.054615 0.14722 0.14868 0.054082 0.094058 0.054082 0.23059 0 0.14261-0.072107 0.26397-0.072107 0.12137-0.2013 0.16688v0.012138q0.16224 0.03641 0.2674 0.15475 0.10816 0.1153 0.10816 0.31556 0 0.14868-0.057086 0.2579-0.057085 0.10922-0.15923 0.18204-0.099142 0.072818-0.23735 0.10922-0.13821 0.033375-0.30045 0.033375zm0.34853-1.1651h0.24937q0.20732 0 0.29744-0.075853 0.093141-0.075853 0.093141-0.20328 0-0.14564-0.09615-0.20632-0.09615-0.060682-0.28843-0.060682h-0.25538zm0 0.89208h0.29443q0.21632 0 0.3335-0.078888 0.11718-0.081923 0.11718-0.24879 0-0.15777-0.11418-0.22756-0.11418-0.07282-0.33651-0.07282h-0.29443z" stroke-opacity=".78039" stroke-width=".25475"/>
|
||||
<path d="m2.2992 3.0475-0.13958 0.48548h1.0134l-0.13958-0.48548q-0.097092-0.31556-0.18812-0.64932-0.084958-0.33377-0.16992-0.66146h-0.024273q-0.084958 0.33377-0.16992 0.66753-0.084958 0.32769-0.18205 0.64325zm-1.329 2.1118 1.2926-3.9688h0.82531l1.2926 3.9688h-0.74035l-0.30949-1.0741h-1.3351l-0.30949 1.0741z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".45513"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m3.1782 5.0271q-0.36231 0-0.6547-0.1017-0.28603-0.10806-0.49579-0.33689-0.2034-0.22883-0.31782-0.58479-0.10806-0.36231-0.10806-0.87717v-2.3328h0.73733v2.3899q0 0.33689 0.057206 0.57207 0.063563 0.22883 0.17162 0.36866 0.11441 0.13984 0.26697 0.2034 0.15255 0.057206 0.34324 0.057206 0.19068 0 0.3496-0.057206 0.15891-0.063564 0.27332-0.2034 0.11441-0.13984 0.17798-0.36866 0.063564-0.23519 0.063564-0.57207v-2.3899h0.70555v2.3328q0 0.51487-0.10806 0.87717-0.10806 0.35595-0.31782 0.58479-0.2034 0.22883-0.49579 0.33689-0.28603 0.1017-0.64835 0.1017z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".47673"/>
|
||||
<rect x="1.0583" y="5.2917" width="4.2333" height=".52917" fill-opacity=".78039" stroke-width="1.2172"/>
|
||||
<path d="m3.1778 4.846q-0.32417 0-0.58578-0.090994-0.25592-0.096685-0.4436-0.30143-0.18199-0.20474-0.28436-0.52323-0.096684-0.32417-0.096684-0.78483v-2.0872h0.65971v2.1383q0 0.30143 0.051184 0.51185 0.056872 0.20474 0.15355 0.32985 0.10237 0.12512 0.23887 0.18199 0.13649 0.051184 0.30711 0.051184 0.17061 0 0.3128-0.051184 0.14218-0.056873 0.24455-0.18199 0.10237-0.12512 0.15924-0.32985 0.056873-0.21043 0.056873-0.51185v-2.1383h0.63128v2.0872q0 0.46067-0.096685 0.78483-0.096684 0.31848-0.28436 0.52323-0.18199 0.20474-0.4436 0.30143-0.25592 0.090994-0.5801 0.090994z" fill-opacity=".78039" stroke-opacity=".78039" stroke-width=".42654"/>
|
||||
<rect x="1.5875" y="5.0271" width="3.175" height=".39688" fill-opacity=".78039" stroke-width=".91291"/>
|
||||
<path d="m4.9555 5.5562v-0.43195h0.54619v-3.8986h-0.54619v-0.43195h1.1299v4.7624z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
<path d="m0.26458 5.5562v-4.7624h1.1299v0.43195h-0.54083v3.8986h0.54083v0.43195z" fill="#4271ae" stroke-width="1.1186"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 1.1 KiB |
@@ -2,14 +2,47 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<h2>Release Notes for 2.2 RC 1</h2>
|
||||
<p><i>Released on 26 November 2023</i></p>
|
||||
<h2>Release Notes for 2.2</h2>
|
||||
<p><i>Released on 17 December 2023</i></p>
|
||||
|
||||
<p>This is a release candidate of the next release version, and is intended for testing purposes.
|
||||
Please be careful when using this version on live writing projects, and make sure you take frequent
|
||||
backups.</p>
|
||||
<p>Please check the changelog for an overview of changes. The full release notes will be added to
|
||||
the final release.</p>
|
||||
<p>This release comes with a number of new features. These are some highlights.</p>
|
||||
<p>In addition to the common Markdown style formatting for bold, italic and strike through, a set
|
||||
of new shortcodes have been added. The shortcodes are far more flexible than the Markdown style
|
||||
syntax, and can be used for more complex formatting cases. Like when you need to add multiple,
|
||||
overlapping formats, or add emphasis to just a part of a word. The shortcodes also allow for
|
||||
underline, subscript and superscript, which the Markdown syntax does not. The new formats are
|
||||
available in the "Format" menu, and in a new toolbar in the editor that can be enabled by clicking
|
||||
the three dots in the top–left corner. The shortcode format was chosen because it can later be
|
||||
extended to include other requested features as well. Please have a look at the documentation for
|
||||
more details about the new shortcodes.</p>
|
||||
<p>The Tags and References system has been improved. The tags themselves are no longer case
|
||||
sensitive when you use them in references, but they are still displayed as you typed them in the
|
||||
tag definition when they are displayed in the user interface. Starting to type the '@' symbol in
|
||||
the text editor, on a new line, will now open an auto-completer menu which will display available
|
||||
options. It may not display all of your tags if you have a lot of them, but starting to type more
|
||||
characters will filter the list down further.</p>
|
||||
<p>You can now automatically create a note file for a new tag that you have added to a reference
|
||||
list in a document, but is not yet defined in a project note. So, for instance, if you come up with
|
||||
a new character while writing, and add a new tag to your '@char' references, you can right-click
|
||||
the new tag and create a new note for that entry directly. In addition, it is now also possible to
|
||||
right-click a heading in an open document and set the item label in the project tree to match the
|
||||
heading.</p>
|
||||
<p>In addition to the changes in the editor, the "References" panel below the document viewer has
|
||||
also been completely redesigned. It now shows all the references to the document you are viewing as
|
||||
a list, with a lot more details than before. In addition, tabs in the panel will appear to show all
|
||||
the tags you have defined in your notes, sorted as one tab per category. Like for instance
|
||||
Characters, Locations, Objects, etc. You can also give each note a short description comment on the
|
||||
same format as the summary comments for chapters and scenes. The short description comment can be
|
||||
added from the "Insert" menu under "Special Comments".</p>
|
||||
<p>The last major change in this release is the new multi-select feature in the project tree. You
|
||||
can now select multiple documents and folders using the mouse while pressing 'Ctrl' or 'Shift'. By
|
||||
right-clicking the selected items, you can perform a limited set of operations on all of them, like
|
||||
changing active status, and the status or importance labels. You can also drag and drop multiple
|
||||
items under the condition that all the selected items are in the same folder, at the same level.
|
||||
This restriction is in place due to limitations in the framework novelWriter is based on. But this
|
||||
should help in cases where multiple documents need to be moved in and out of folders or between
|
||||
folders. Note that adding the multi-select feature meant that the undo feature of the project tree
|
||||
had to be removed. It may be added back later.</p>
|
||||
|
||||
<p><i>See also the <a href="https://github.com/vkbo/novelWriter/releases">Releases</a> page.</i></p>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Common Functions
|
||||
==============================
|
||||
|
||||
File History:
|
||||
Created: 2019-05-12 [0.1]
|
||||
Created: 2019-05-12 [0.1.0]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -38,7 +38,6 @@ from urllib.request import pathname2url
|
||||
|
||||
from PyQt5.QtGui import QDesktopServices
|
||||
from PyQt5.QtCore import QCoreApplication, QUrl
|
||||
from PyQt5.QtWidgets import QWidget, qApp
|
||||
|
||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||
from novelwriter.error import logException
|
||||
@@ -508,18 +507,6 @@ def openExternalPath(path: Path) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
# Other Functions
|
||||
# =============================================================================================== #
|
||||
|
||||
def getGuiItem(objName: str) -> QWidget | None:
|
||||
"""Returns a QtWidget based on its objectName."""
|
||||
for qWidget in qApp.topLevelWidgets():
|
||||
if qWidget.objectName() == objName:
|
||||
return qWidget
|
||||
return None
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
# Classes
|
||||
# =============================================================================================== #
|
||||
|
||||
@@ -225,7 +225,8 @@ class Config:
|
||||
# Other System Info
|
||||
self.hostName = QSysInfo.machineHostName()
|
||||
self.kernelVer = QSysInfo.kernelVersion()
|
||||
self.isDebug = False
|
||||
self.isDebug = False # True if running in debug mode
|
||||
self.memInfo = False # True if displaying mem info in status bar
|
||||
|
||||
# Packages
|
||||
self.hasEnchant = False # The pyenchant package
|
||||
@@ -485,7 +486,6 @@ class Config:
|
||||
|
||||
self._recentObj.loadCache()
|
||||
self._checkOptionalPackages()
|
||||
self.isDebug = logger.getEffectiveLevel() == logging.DEBUG
|
||||
|
||||
logger.debug("Config instance initialised")
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ File History:
|
||||
Created: 2022-10-02 [2.0rc1] DocMerger
|
||||
Created: 2022-10-11 [2.0rc1] DocSplitter
|
||||
Created: 2022-11-03 [2.0rc2] ProjectBuilder
|
||||
Created: 2023-07-20 [2.1b1] DocDuplicator
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -551,7 +551,7 @@ class NWIndex:
|
||||
return 0
|
||||
|
||||
def getTableOfContents(
|
||||
self, rHandle: str, maxDepth: int, skipExcl: bool = True
|
||||
self, rHandle: str | None, maxDepth: int, skipExcl: bool = True
|
||||
) -> list[tuple[str, int, str, int]]:
|
||||
"""Generate a table of contents up to a maximum depth."""
|
||||
tOrder = []
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Project Item Class
|
||||
================================
|
||||
|
||||
File History:
|
||||
Created: 2018-10-27 [0.0.1]
|
||||
Created: 2018-10-27 [0.0.1] NWItem
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,8 +3,8 @@ novelWriter – Project Options Cache
|
||||
===================================
|
||||
|
||||
File History:
|
||||
Created: 2019-10-21 [0.3.1]
|
||||
Rewritten: 2020-02-19 [0.4.5]
|
||||
Created: 2019-10-21 [0.3.1] OptionState
|
||||
Rewritten: 2020-02-19 [0.4.5] OptionState
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Project Wrapper
|
||||
=============================
|
||||
|
||||
File History:
|
||||
Created: 2018-09-29 [0.0.1]
|
||||
Created: 2018-09-29 [0.0.1] NWProject
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -80,7 +80,7 @@ class NWProject:
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: NWProject")
|
||||
return
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Project Data Class
|
||||
================================
|
||||
|
||||
File History:
|
||||
Created: 2022-10-30 [2.0rc2]
|
||||
Created: 2022-10-30 [2.0rc2] NWProjectData
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Project Session Log Class
|
||||
=======================================
|
||||
|
||||
File History:
|
||||
Created: 2023-06-11 [2.1b1]
|
||||
Created: 2023-06-11 [2.1b1] NWSessionLog
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,8 @@ novelWriter – Spell Check Classes
|
||||
=================================
|
||||
|
||||
File History:
|
||||
Created: 2019-06-11 [0.1.5]
|
||||
Created: 2019-06-11 [0.1.5] NWSpellEnchant
|
||||
Created: 2023-06-13 [2.1b1] UserDictionary
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -56,7 +57,7 @@ class NWSpellEnchant:
|
||||
logger.debug("Ready: NWSpellEnchant")
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: NWSpellEnchant")
|
||||
return
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ novelWriter – Project Item Status Class
|
||||
=======================================
|
||||
|
||||
File History:
|
||||
Created: 2019-05-19 [0.1.3]
|
||||
Rewritten: 2022-04-05 [2.0b1]
|
||||
Created: 2019-05-19 [0.1.3] NWStatus
|
||||
Rewritten: 2022-04-05 [2.0b1] NWStatus
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – HTML Text Converter
|
||||
=================================
|
||||
|
||||
File History:
|
||||
Created: 2019-05-07 [0.0.1]
|
||||
Created: 2019-05-07 [0.0.1] ToHtml
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Markdown Text Converter
|
||||
=====================================
|
||||
|
||||
File History:
|
||||
Created: 2021-02-06 [1.2b1]
|
||||
Created: 2021-02-06 [1.2b1] ToMarkdown
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Project Tree Class
|
||||
================================
|
||||
|
||||
File History:
|
||||
Created: 2020-05-07 [0.4.5]
|
||||
Created: 2020-05-07 [0.4.5] NWTree
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI About Box
|
||||
===========================
|
||||
|
||||
File History:
|
||||
Created: 2020-05-21 [0.5.2]
|
||||
Created: 2020-05-21 [0.5.2] GuiAbout
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -28,7 +28,7 @@ import novelwriter
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt5.QtGui import QCursor
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
qApp, QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTabWidget,
|
||||
@@ -44,7 +44,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiAbout(QDialog):
|
||||
|
||||
def __init__(self, parent: QWidget):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiAbout")
|
||||
@@ -101,7 +101,7 @@ class GuiAbout(QDialog):
|
||||
|
||||
# OK Button
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
|
||||
self.buttonBox.accepted.connect(self._doClose)
|
||||
self.buttonBox.accepted.connect(self.close)
|
||||
|
||||
self.outerBox.addLayout(self.innerBox)
|
||||
self.outerBox.addWidget(self.buttonBox)
|
||||
@@ -111,13 +111,12 @@ class GuiAbout(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiAbout")
|
||||
return
|
||||
|
||||
def populateGUI(self):
|
||||
"""Populate tabs with text.
|
||||
"""
|
||||
def populateGUI(self) -> None:
|
||||
"""Populate tabs with text."""
|
||||
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
|
||||
self._setStyleSheet()
|
||||
self._fillAboutPage()
|
||||
@@ -127,19 +126,27 @@ class GuiAbout(QDialog):
|
||||
qApp.restoreOverrideCursor()
|
||||
return
|
||||
|
||||
def showReleaseNotes(self):
|
||||
"""Show the release notes.
|
||||
"""
|
||||
def showReleaseNotes(self) -> None:
|
||||
"""Show the release notes."""
|
||||
self.tabBox.setCurrentWidget(self.pageNotes)
|
||||
return
|
||||
|
||||
##
|
||||
# Events
|
||||
##
|
||||
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _fillAboutPage(self):
|
||||
"""Generate the content for the About page.
|
||||
"""
|
||||
def _fillAboutPage(self) -> None:
|
||||
"""Generate the content for the About page."""
|
||||
aboutMsg = (
|
||||
"<h2>{title1}</h2>"
|
||||
"<p>{copy}</p>"
|
||||
@@ -181,9 +188,8 @@ class GuiAbout(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _fillNotesPage(self):
|
||||
"""Load the content for the Release Notes page.
|
||||
"""
|
||||
def _fillNotesPage(self) -> None:
|
||||
"""Load the content for the Release Notes page."""
|
||||
docPath = CONFIG.assetPath("text") / "release_notes.htm"
|
||||
docText = readTextFile(docPath)
|
||||
if docText:
|
||||
@@ -192,9 +198,8 @@ class GuiAbout(QDialog):
|
||||
self.pageNotes.setHtml("Error loading release notes text ...")
|
||||
return
|
||||
|
||||
def _fillCreditsPage(self):
|
||||
"""Load the content for the Credits page.
|
||||
"""
|
||||
def _fillCreditsPage(self) -> None:
|
||||
"""Load the content for the Credits page."""
|
||||
docPath = CONFIG.assetPath("text") / "credits_en.htm"
|
||||
docText = readTextFile(docPath)
|
||||
if docText:
|
||||
@@ -203,9 +208,8 @@ class GuiAbout(QDialog):
|
||||
self.pageCredits.setHtml("Error loading credits text ...")
|
||||
return
|
||||
|
||||
def _fillLicensePage(self):
|
||||
"""Load the content for the Licence page.
|
||||
"""
|
||||
def _fillLicensePage(self) -> None:
|
||||
"""Load the content for the Licence page."""
|
||||
docPath = CONFIG.assetPath("text") / "gplv3_en.htm"
|
||||
docText = readTextFile(docPath)
|
||||
if docText:
|
||||
@@ -214,9 +218,8 @@ class GuiAbout(QDialog):
|
||||
self.pageLicense.setHtml("Error loading licence text ...")
|
||||
return
|
||||
|
||||
def _setStyleSheet(self):
|
||||
"""Set stylesheet for all browser tabs
|
||||
"""
|
||||
def _setStyleSheet(self) -> None:
|
||||
"""Set stylesheet for all browser tabs."""
|
||||
styleSheet = (
|
||||
"h1, h2, h3, h4 {{"
|
||||
" color: rgb({hColR},{hColG},{hColB});"
|
||||
@@ -242,8 +245,4 @@ class GuiAbout(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _doClose(self):
|
||||
self.close()
|
||||
return
|
||||
|
||||
# END Class GuiAbout
|
||||
|
||||
@@ -3,8 +3,8 @@ novelWriter – GUI Doc Merge Dialog
|
||||
==================================
|
||||
|
||||
File History:
|
||||
Created: 2020-01-23 [0.4.3]
|
||||
Rewritten: 2022-10-06 [2.0rc1]
|
||||
Created: 2020-01-23 [0.4.3] GuiDocMerge
|
||||
Rewritten: 2022-10-06 [2.0rc1] GuiDocMerge
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -26,7 +26,8 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QDialog, QDialogButtonBox, QGridLayout, QLabel,
|
||||
QListWidget, QListWidgetItem, QVBoxLayout, QWidget
|
||||
@@ -108,13 +109,12 @@ class GuiDocMerge(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiDocMerge")
|
||||
return
|
||||
|
||||
def getData(self):
|
||||
"""Return the user's choices.
|
||||
"""
|
||||
def getData(self) -> dict:
|
||||
"""Return the user's choices."""
|
||||
finalItems = []
|
||||
for i in range(self.listBox.count()):
|
||||
item = self.listBox.item(i)
|
||||
@@ -127,12 +127,22 @@ class GuiDocMerge(QDialog):
|
||||
return self._data
|
||||
|
||||
##
|
||||
# Slots
|
||||
# Events
|
||||
##
|
||||
|
||||
def _resetList(self):
|
||||
"""Reset the content of the list box to its original state.
|
||||
"""
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _resetList(self) -> None:
|
||||
"""Reset the content of the list box to its original state."""
|
||||
logger.debug("Resetting list box content")
|
||||
sHandle = self._data.get("sHandle", None)
|
||||
itemList = self._data.get("origItems", [])
|
||||
@@ -143,9 +153,8 @@ class GuiDocMerge(QDialog):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _loadContent(self, sHandle, itemList):
|
||||
"""Load content from a given list of items.
|
||||
"""
|
||||
def _loadContent(self, sHandle: str, itemList: list[str]) -> None:
|
||||
"""Load content from a given list of items."""
|
||||
self._data = {}
|
||||
self._data["sHandle"] = sHandle
|
||||
self._data["origItems"] = itemList
|
||||
|
||||
@@ -3,8 +3,8 @@ novelWriter – GUI Doc Split Dialog
|
||||
==================================
|
||||
|
||||
File History:
|
||||
Created: 2020-02-01 [0.4.3]
|
||||
Rewritten: 2022-10-12 [2.0rc1]
|
||||
Created: 2020-02-01 [0.4.3] GuiDocSplit
|
||||
Rewritten: 2022-10-12 [2.0rc1] GuiDocSplit
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -26,10 +26,11 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtCore import Qt, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
|
||||
QListWidgetItem, QDialogButtonBox, QLabel, QGridLayout
|
||||
QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGridLayout,
|
||||
QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -45,7 +46,7 @@ class GuiDocSplit(QDialog):
|
||||
LEVEL_ROLE = Qt.ItemDataRole.UserRole + 1
|
||||
LABEL_ROLE = Qt.ItemDataRole.UserRole + 2
|
||||
|
||||
def __init__(self, parent, sHandle):
|
||||
def __init__(self, parent: QWidget, sHandle: str) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiDocSplit")
|
||||
@@ -138,11 +139,11 @@ class GuiDocSplit(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiDocSplit")
|
||||
return
|
||||
|
||||
def getData(self):
|
||||
def getData(self) -> tuple[dict, list]:
|
||||
"""Return the user's choices. Also save the users options for
|
||||
the next time the dialog is used.
|
||||
"""
|
||||
@@ -167,6 +168,7 @@ class GuiDocSplit(QDialog):
|
||||
self._data["docHierarchy"] = docHierarchy
|
||||
self._data["moveToTrash"] = moveToTrash
|
||||
|
||||
logger.debug("Saving State: GuiDocSplit")
|
||||
pOptions = SHARED.project.options
|
||||
pOptions.setValue("GuiDocSplit", "spLevel", spLevel)
|
||||
pOptions.setValue("GuiDocSplit", "intoFolder", intoFolder)
|
||||
@@ -175,12 +177,22 @@ class GuiDocSplit(QDialog):
|
||||
return self._data, self._text
|
||||
|
||||
##
|
||||
# Slots
|
||||
# Events
|
||||
##
|
||||
|
||||
def _reloadList(self):
|
||||
"""Reload the content of the list box.
|
||||
"""
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _reloadList(self) -> None:
|
||||
"""Reload the content of the list box."""
|
||||
sHandle = self._data.get("sHandle", None)
|
||||
self._loadContent(sHandle)
|
||||
return
|
||||
@@ -189,9 +201,8 @@ class GuiDocSplit(QDialog):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _loadContent(self, sHandle):
|
||||
"""Load content from a given source item.
|
||||
"""
|
||||
def _loadContent(self, sHandle: str) -> None:
|
||||
"""Load content from a given source item."""
|
||||
self._data = {}
|
||||
self._data["sHandle"] = sHandle
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – Edit Label Dialog
|
||||
===============================
|
||||
|
||||
File History:
|
||||
Created: 2022-06-11 [2.0rc1]
|
||||
Created: 2022-06-11 [2.0rc1] GuiEditLabel
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -26,7 +26,8 @@ from __future__ import annotations
|
||||
import logging
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QLineEdit, QLabel, QDialogButtonBox, QHBoxLayout
|
||||
QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout,
|
||||
QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG
|
||||
@@ -36,9 +37,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiEditLabel(QDialog):
|
||||
|
||||
def __init__(self, parent, text=""):
|
||||
def __init__(self, parent: QWidget, text: str = "") -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiEditLabel")
|
||||
self.setObjectName("GuiEditLabel")
|
||||
self.setWindowTitle(self.tr("Item Label"))
|
||||
|
||||
@@ -70,16 +72,26 @@ class GuiEditLabel(QDialog):
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
logger.debug("Ready: GuiEditLabel")
|
||||
|
||||
return
|
||||
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiEditLabel")
|
||||
return
|
||||
|
||||
@property
|
||||
def itemLabel(self):
|
||||
def itemLabel(self) -> str:
|
||||
return self.labelValue.text()
|
||||
|
||||
@classmethod
|
||||
def getLabel(cls, parent, text):
|
||||
def getLabel(cls, parent: QWidget, text: str) -> tuple[str, bool]:
|
||||
"""Pop the dialog and return the result."""
|
||||
cls = GuiEditLabel(parent, text=text)
|
||||
cls.exec_()
|
||||
return cls.itemLabel, cls.result() == QDialog.Accepted
|
||||
label = cls.itemLabel
|
||||
accepted = cls.result() == QDialog.Accepted
|
||||
cls.deleteLater()
|
||||
return label, accepted
|
||||
|
||||
# END Class GuiEditLabel
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Preferences
|
||||
=============================
|
||||
|
||||
File History:
|
||||
Created: 2019-06-10 [0.1.5]
|
||||
Created: 2019-06-10 [0.1.5] GuiPreferences
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -25,11 +25,11 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtCore import Qt, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QFont
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QWidget, QComboBox, QSpinBox, QPushButton, QDialogButtonBox,
|
||||
QLineEdit, QFileDialog, QFontDialog, QDoubleSpinBox
|
||||
QLineEdit, QFileDialog, QFontDialog, QDoubleSpinBox, qApp
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -43,6 +43,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiPreferences(NPagedDialog):
|
||||
|
||||
newPreferencesReady = pyqtSignal(bool, bool, bool, bool)
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
@@ -66,9 +68,10 @@ class GuiPreferences(NPagedDialog):
|
||||
self.addTab(self.tabAuto, self.tr("Automation"))
|
||||
self.addTab(self.tabQuote, self.tr("Quotes"))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self)
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.rejected.connect(self.close)
|
||||
self.rejected.connect(self.close)
|
||||
self.addControls(self.buttonBox)
|
||||
|
||||
self.resize(*CONFIG.preferencesWinSize)
|
||||
@@ -83,29 +86,21 @@ class GuiPreferences(NPagedDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiPreferences")
|
||||
return
|
||||
|
||||
##
|
||||
# Properties
|
||||
# Events
|
||||
##
|
||||
|
||||
@property
|
||||
def updateTheme(self) -> bool:
|
||||
return self._updateTheme
|
||||
|
||||
@property
|
||||
def updateSyntax(self) -> bool:
|
||||
return self._updateSyntax
|
||||
|
||||
@property
|
||||
def needsRestart(self) -> bool:
|
||||
return self._needsRestart
|
||||
|
||||
@property
|
||||
def refreshTree(self) -> bool:
|
||||
return self._refreshTree
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
logger.debug("Close: GuiPreferences")
|
||||
self._saveWindowSize()
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
@@ -113,11 +108,7 @@ class GuiPreferences(NPagedDialog):
|
||||
|
||||
@pyqtSlot()
|
||||
def _doSave(self) -> None:
|
||||
"""Trigger all the save functions in the tabs, and collect the
|
||||
status of the saves.
|
||||
"""
|
||||
logger.debug("Saving new preferences")
|
||||
|
||||
"""Trigger save functions in the tabs and emit ready signal."""
|
||||
self.tabGeneral.saveValues()
|
||||
self.tabProjects.saveValues()
|
||||
self.tabDocs.saveValues()
|
||||
@@ -126,19 +117,15 @@ class GuiPreferences(NPagedDialog):
|
||||
self.tabAuto.saveValues()
|
||||
self.tabQuote.saveValues()
|
||||
|
||||
self._saveWindowSize()
|
||||
CONFIG.saveConfig()
|
||||
self.accept()
|
||||
self.newPreferencesReady.emit(
|
||||
self._needsRestart, self._refreshTree, self._updateTheme, self._updateSyntax
|
||||
)
|
||||
qApp.processEvents()
|
||||
self.close()
|
||||
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _doClose(self) -> None:
|
||||
"""Close the preferences without saving the changes."""
|
||||
self._saveWindowSize()
|
||||
self.reject()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
@@ -169,7 +156,7 @@ class GuiPreferencesGeneral(QWidget):
|
||||
minWidth = CONFIG.pxInt(200)
|
||||
|
||||
# Select Locale
|
||||
self.guiLocale = QComboBox()
|
||||
self.guiLocale = QComboBox(self)
|
||||
self.guiLocale.setMinimumWidth(minWidth)
|
||||
theLangs = CONFIG.listLanguages(CONFIG.LANG_NW)
|
||||
for lang, langName in theLangs:
|
||||
@@ -187,7 +174,7 @@ class GuiPreferencesGeneral(QWidget):
|
||||
)
|
||||
|
||||
# Select Theme
|
||||
self.guiTheme = QComboBox()
|
||||
self.guiTheme = QComboBox(self)
|
||||
self.guiTheme.setMinimumWidth(minWidth)
|
||||
self.theThemes = SHARED.theme.listThemes()
|
||||
for themeDir, themeName in self.theThemes:
|
||||
@@ -203,7 +190,7 @@ class GuiPreferencesGeneral(QWidget):
|
||||
)
|
||||
|
||||
# Editor Theme
|
||||
self.guiSyntax = QComboBox()
|
||||
self.guiSyntax = QComboBox(self)
|
||||
self.guiSyntax.setMinimumWidth(CONFIG.pxInt(200))
|
||||
self.theSyntaxes = SHARED.theme.listSyntax()
|
||||
for syntaxFile, syntaxName in self.theSyntaxes:
|
||||
@@ -219,11 +206,11 @@ class GuiPreferencesGeneral(QWidget):
|
||||
)
|
||||
|
||||
# Font Family
|
||||
self.guiFont = QLineEdit()
|
||||
self.guiFont = QLineEdit(self)
|
||||
self.guiFont.setReadOnly(True)
|
||||
self.guiFont.setFixedWidth(CONFIG.pxInt(162))
|
||||
self.guiFont.setText(CONFIG.guiFont)
|
||||
self.fontButton = QPushButton("...")
|
||||
self.fontButton = QPushButton("...", self)
|
||||
self.fontButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
|
||||
self.fontButton.clicked.connect(self._selectFont)
|
||||
self.mainForm.addRow(
|
||||
@@ -378,7 +365,7 @@ class GuiPreferencesProjects(QWidget):
|
||||
|
||||
# Backup Path
|
||||
self.backupPath = CONFIG.backupPath()
|
||||
self.backupGetPath = QPushButton(self.tr("Browse"))
|
||||
self.backupGetPath = QPushButton(self.tr("Browse"), self)
|
||||
self.backupGetPath.clicked.connect(self._backupFolder)
|
||||
self.backupPathRow = self.mainForm.addRow(
|
||||
self.tr("Backup storage location"),
|
||||
@@ -421,7 +408,7 @@ class GuiPreferencesProjects(QWidget):
|
||||
)
|
||||
|
||||
# Inactive time for idle
|
||||
self.userIdleTime = QDoubleSpinBox()
|
||||
self.userIdleTime = QDoubleSpinBox(self)
|
||||
self.userIdleTime.setMinimum(0.5)
|
||||
self.userIdleTime.setMaximum(600.0)
|
||||
self.userIdleTime.setSingleStep(0.5)
|
||||
@@ -496,11 +483,11 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.mainForm.addGroupLabel(self.tr("Text Style"))
|
||||
|
||||
# Font Family
|
||||
self.textFont = QLineEdit()
|
||||
self.textFont = QLineEdit(self)
|
||||
self.textFont.setReadOnly(True)
|
||||
self.textFont.setFixedWidth(CONFIG.pxInt(162))
|
||||
self.textFont.setText(CONFIG.textFont)
|
||||
self.fontButton = QPushButton("...")
|
||||
self.fontButton = QPushButton("...", self)
|
||||
self.fontButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
|
||||
self.fontButton.clicked.connect(self._selectFont)
|
||||
self.mainForm.addRow(
|
||||
@@ -960,7 +947,7 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.mainForm.addGroupLabel(self.tr("Automatic Padding"))
|
||||
|
||||
# Pad Before
|
||||
self.fmtPadBefore = QLineEdit()
|
||||
self.fmtPadBefore = QLineEdit(self)
|
||||
self.fmtPadBefore.setMaxLength(32)
|
||||
self.fmtPadBefore.setText(CONFIG.fmtPadBefore)
|
||||
self.mainForm.addRow(
|
||||
@@ -970,7 +957,7 @@ class GuiPreferencesAutomation(QWidget):
|
||||
)
|
||||
|
||||
# Pad After
|
||||
self.fmtPadAfter = QLineEdit()
|
||||
self.fmtPadAfter = QLineEdit(self)
|
||||
self.fmtPadAfter.setMaxLength(32)
|
||||
self.fmtPadAfter.setText(CONFIG.fmtPadAfter)
|
||||
self.mainForm.addRow(
|
||||
@@ -1046,13 +1033,13 @@ class GuiPreferencesQuotes(QWidget):
|
||||
self.quoteSym = {}
|
||||
|
||||
# Single Quote Style
|
||||
self.quoteSym["SO"] = QLineEdit()
|
||||
self.quoteSym["SO"] = QLineEdit(self)
|
||||
self.quoteSym["SO"].setMaxLength(1)
|
||||
self.quoteSym["SO"].setReadOnly(True)
|
||||
self.quoteSym["SO"].setFixedWidth(qWidth)
|
||||
self.quoteSym["SO"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["SO"].setText(CONFIG.fmtSQuoteOpen)
|
||||
self.btnSingleStyleO = QPushButton("...")
|
||||
self.btnSingleStyleO = QPushButton("...", self)
|
||||
self.btnSingleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
|
||||
self.mainForm.addRow(
|
||||
@@ -1062,13 +1049,13 @@ class GuiPreferencesQuotes(QWidget):
|
||||
button=self.btnSingleStyleO
|
||||
)
|
||||
|
||||
self.quoteSym["SC"] = QLineEdit()
|
||||
self.quoteSym["SC"] = QLineEdit(self)
|
||||
self.quoteSym["SC"].setMaxLength(1)
|
||||
self.quoteSym["SC"].setReadOnly(True)
|
||||
self.quoteSym["SC"].setFixedWidth(qWidth)
|
||||
self.quoteSym["SC"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["SC"].setText(CONFIG.fmtSQuoteClose)
|
||||
self.btnSingleStyleC = QPushButton("...")
|
||||
self.btnSingleStyleC = QPushButton("...", self)
|
||||
self.btnSingleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
|
||||
self.mainForm.addRow(
|
||||
@@ -1079,13 +1066,13 @@ class GuiPreferencesQuotes(QWidget):
|
||||
)
|
||||
|
||||
# Double Quote Style
|
||||
self.quoteSym["DO"] = QLineEdit()
|
||||
self.quoteSym["DO"] = QLineEdit(self)
|
||||
self.quoteSym["DO"].setMaxLength(1)
|
||||
self.quoteSym["DO"].setReadOnly(True)
|
||||
self.quoteSym["DO"].setFixedWidth(qWidth)
|
||||
self.quoteSym["DO"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["DO"].setText(CONFIG.fmtDQuoteOpen)
|
||||
self.btnDoubleStyleO = QPushButton("...")
|
||||
self.btnDoubleStyleO = QPushButton("...", self)
|
||||
self.btnDoubleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
|
||||
self.mainForm.addRow(
|
||||
@@ -1095,13 +1082,13 @@ class GuiPreferencesQuotes(QWidget):
|
||||
button=self.btnDoubleStyleO
|
||||
)
|
||||
|
||||
self.quoteSym["DC"] = QLineEdit()
|
||||
self.quoteSym["DC"] = QLineEdit(self)
|
||||
self.quoteSym["DC"].setMaxLength(1)
|
||||
self.quoteSym["DC"].setReadOnly(True)
|
||||
self.quoteSym["DC"].setFixedWidth(qWidth)
|
||||
self.quoteSym["DC"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["DC"].setText(CONFIG.fmtDQuoteClose)
|
||||
self.btnDoubleStyleC = QPushButton("...")
|
||||
self.btnDoubleStyleC = QPushButton("...", self)
|
||||
self.btnDoubleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
|
||||
self.mainForm.addRow(
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Project Details
|
||||
=================================
|
||||
|
||||
File History:
|
||||
Created: 2021-01-03 [1.1rc1]
|
||||
Created: 2021-01-03 [1.1rc1] GuiProjectDetails
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -26,8 +26,8 @@ from __future__ import annotations
|
||||
import math
|
||||
import logging
|
||||
|
||||
from PyQt5.QtGui import QCloseEvent, QFont
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel,
|
||||
QLineEdit, QSpinBox, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
||||
@@ -45,7 +45,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiProjectDetails(NPagedDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiProjectDetails")
|
||||
@@ -71,43 +71,41 @@ class GuiProjectDetails(NPagedDialog):
|
||||
self.addTab(self.tabContents, self.tr("Contents"))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
self.buttonBox.button(QDialogButtonBox.Close)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.rejected.connect(self.close)
|
||||
self.rejected.connect(self.close)
|
||||
self.addControls(self.buttonBox)
|
||||
|
||||
logger.debug("Ready: GuiProjectDetails")
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiProjectDetails")
|
||||
return
|
||||
|
||||
def updateValues(self):
|
||||
"""Set all the values of the pages.
|
||||
"""
|
||||
def updateValues(self) -> None:
|
||||
"""Set all the values of the pages."""
|
||||
self.tabMain.updateValues()
|
||||
self.tabContents.updateValues()
|
||||
return
|
||||
|
||||
##
|
||||
# Slots
|
||||
# Events
|
||||
##
|
||||
|
||||
def _doClose(self):
|
||||
"""Save settings and close the dialog.
|
||||
"""
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
self._saveGuiSettings()
|
||||
self.close()
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _saveGuiSettings(self):
|
||||
"""Save GUI settings.
|
||||
"""
|
||||
def _saveGuiSettings(self) -> None:
|
||||
"""Save GUI settings."""
|
||||
winWidth = CONFIG.rpxInt(self.width())
|
||||
winHeight = CONFIG.rpxInt(self.height())
|
||||
|
||||
@@ -122,6 +120,7 @@ class GuiProjectDetails(NPagedDialog):
|
||||
countFrom = self.tabContents.poValue.value()
|
||||
clearDouble = self.tabContents.dblValue.isChecked()
|
||||
|
||||
logger.debug("Saving State: GuiProjectDetails")
|
||||
pOptions = SHARED.project.options
|
||||
pOptions.setValue("GuiProjectDetails", "winWidth", winWidth)
|
||||
pOptions.setValue("GuiProjectDetails", "winHeight", winHeight)
|
||||
@@ -141,7 +140,7 @@ class GuiProjectDetails(NPagedDialog):
|
||||
|
||||
class GuiProjectDetailsMain(QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
fPx = SHARED.theme.fontPixelSize
|
||||
@@ -270,7 +269,7 @@ class GuiProjectDetailsContents(QWidget):
|
||||
C_PAGE = 3
|
||||
C_PROG = 4
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
# Internal
|
||||
@@ -406,9 +405,8 @@ class GuiProjectDetailsContents(QWidget):
|
||||
|
||||
return
|
||||
|
||||
def getColumnSizes(self):
|
||||
"""Return the column widths for the tree columns.
|
||||
"""
|
||||
def getColumnSizes(self) -> list[int]:
|
||||
"""Return the column widths for the tree columns."""
|
||||
retVals = [
|
||||
self.tocTree.columnWidth(0),
|
||||
self.tocTree.columnWidth(1),
|
||||
@@ -418,24 +416,21 @@ class GuiProjectDetailsContents(QWidget):
|
||||
]
|
||||
return retVals
|
||||
|
||||
def updateValues(self):
|
||||
"""Populate the tree.
|
||||
"""
|
||||
def updateValues(self) -> None:
|
||||
"""Populate the tree."""
|
||||
self._currentRoot = None
|
||||
self.novelValue.updateList()
|
||||
self.novelValue.setHandle(self.novelValue.firstHandle)
|
||||
self._prepareData(self.novelValue.firstHandle)
|
||||
self._populateTree()
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _prepareData(self, rootHandle):
|
||||
"""Extract the information from the project index.
|
||||
"""
|
||||
def _prepareData(self, rootHandle: str | None) -> None:
|
||||
"""Extract the information from the project index."""
|
||||
logger.debug("Populating ToC from handle '%s'", rootHandle)
|
||||
self._theToC = SHARED.project.index.getTableOfContents(rootHandle, 2)
|
||||
self._theToC.append(("", 0, self.tr("END"), 0))
|
||||
@@ -446,9 +441,8 @@ class GuiProjectDetailsContents(QWidget):
|
||||
##
|
||||
|
||||
@pyqtSlot(str)
|
||||
def _novelValueChanged(self, tHandle):
|
||||
"""Refresh the tree with another root item.
|
||||
"""
|
||||
def _novelValueChanged(self, tHandle: str) -> None:
|
||||
"""Refresh the tree with another root item."""
|
||||
if tHandle != self._currentRoot:
|
||||
self._prepareData(tHandle)
|
||||
self._populateTree()
|
||||
@@ -456,9 +450,8 @@ class GuiProjectDetailsContents(QWidget):
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _populateTree(self):
|
||||
"""Set the content of the chapter/page tree.
|
||||
"""
|
||||
def _populateTree(self) -> None:
|
||||
"""Set the content of the chapter/page tree."""
|
||||
dblPages = self.dblValue.isChecked()
|
||||
wpPage = self.wpValue.value()
|
||||
fstPage = self.poValue.value() - 1
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Open Project
|
||||
==============================
|
||||
|
||||
File History:
|
||||
Created: 2020-02-26 [0.4.5]
|
||||
Created: 2020-02-26 [0.4.5] GuiProjectLoad
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -29,8 +29,8 @@ from typing import TYPE_CHECKING
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt5.QtGui import QKeySequence
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtGui import QCloseEvent, QKeySequence
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QTreeWidget,
|
||||
QAbstractItemView, QTreeWidgetItem, QDialogButtonBox, QLabel, QShortcut,
|
||||
@@ -112,8 +112,7 @@ class GuiProjectLoad(QDialog):
|
||||
self.selPath = QLineEdit("")
|
||||
self.selPath.setReadOnly(True)
|
||||
|
||||
self.browseButton = QPushButton("...")
|
||||
self.browseButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
|
||||
self.browseButton = QPushButton(SHARED.theme.getIcon("browse"), "", self)
|
||||
self.browseButton.clicked.connect(self._doBrowse)
|
||||
|
||||
self.projectForm.addWidget(self.lblRecent, 0, 0, 1, 3)
|
||||
@@ -154,17 +153,17 @@ class GuiProjectLoad(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiProjectLoad")
|
||||
return
|
||||
|
||||
##
|
||||
# Buttons
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
def _doOpenRecent(self):
|
||||
"""Close the dialog window with a recent project selected.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doOpenRecent(self) -> None:
|
||||
"""Close the dialog window with a recent project selected."""
|
||||
self._saveSettings()
|
||||
|
||||
self.openPath = None
|
||||
@@ -178,17 +177,17 @@ class GuiProjectLoad(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _doSelectRecent(self):
|
||||
"""A recent item has been selected.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doSelectRecent(self) -> None:
|
||||
"""Update path when a recent item has been selected."""
|
||||
selList = self.listBox.selectedItems()
|
||||
if selList:
|
||||
self.selPath.setText(selList[0].data(self.C_NAME, self.D_PATH))
|
||||
return
|
||||
|
||||
def _doBrowse(self):
|
||||
"""Browse for a folder path.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doBrowse(self) -> None:
|
||||
"""Browse for a folder path."""
|
||||
extFilter = [
|
||||
self.tr("novelWriter Project File ({0})").format(nwFiles.PROJ_FILE),
|
||||
self.tr("All files ({0})").format("*"),
|
||||
@@ -205,26 +204,26 @@ class GuiProjectLoad(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _doCancel(self):
|
||||
"""Close the dialog window without doing anything.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doCancel(self) -> None:
|
||||
"""Close the dialog window without doing anything."""
|
||||
self.openPath = None
|
||||
self.openState = self.NONE_STATE
|
||||
self.close()
|
||||
return
|
||||
|
||||
def _doNewProject(self):
|
||||
"""Create a new project.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doNewProject(self) -> None:
|
||||
"""Create a new project."""
|
||||
self._saveSettings()
|
||||
self.openPath = None
|
||||
self.openState = self.NEW_STATE
|
||||
self.accept()
|
||||
return
|
||||
|
||||
def _doDeleteRecent(self):
|
||||
"""Remove an entry from the recent projects list.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doDeleteRecent(self) -> None:
|
||||
"""Remove an entry from the recent projects list."""
|
||||
selList = self.listBox.selectedItems()
|
||||
if selList:
|
||||
projName = selList[0].text(self.C_NAME)
|
||||
@@ -244,20 +243,18 @@ class GuiProjectLoad(QDialog):
|
||||
# Events
|
||||
##
|
||||
|
||||
def closeEvent(self, theEvent):
|
||||
"""Capture the user closing the dialog so we can save settings.
|
||||
"""
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the user closing the dialog and save settings."""
|
||||
self._saveSettings()
|
||||
theEvent.accept()
|
||||
event.accept()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _saveSettings(self):
|
||||
"""Save the changes made to the dialog.
|
||||
"""
|
||||
def _saveSettings(self) -> None:
|
||||
"""Save the changes made to the dialog."""
|
||||
colWidths = [0, 0, 0]
|
||||
colWidths[self.C_NAME] = self.listBox.columnWidth(self.C_NAME)
|
||||
colWidths[self.C_COUNT] = self.listBox.columnWidth(self.C_COUNT)
|
||||
@@ -265,9 +262,8 @@ class GuiProjectLoad(QDialog):
|
||||
CONFIG.setProjLoadColWidths(colWidths)
|
||||
return
|
||||
|
||||
def _populateList(self):
|
||||
"""Populate the list box with recent project data.
|
||||
"""
|
||||
def _populateList(self) -> None:
|
||||
"""Populate the list box with recent project data."""
|
||||
self.listBox.clear()
|
||||
dataList = CONFIG.recentProjects.listEntries()
|
||||
sortList = sorted(dataList, key=lambda x: x[3], reverse=True)
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Project Settings
|
||||
==================================
|
||||
|
||||
File History:
|
||||
Created: 2018-09-29 [0.0.1]
|
||||
Created: 2018-09-29 [0.0.1] GuiProjectSettings
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -27,11 +27,11 @@ import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtGui import QIcon, QPixmap, QColor
|
||||
from PyQt5.QtCore import Qt, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QIcon, QPixmap, QColor
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QColorDialog, QComboBox, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit,
|
||||
QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
||||
QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget, qApp
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -53,6 +53,8 @@ class GuiProjectSettings(NPagedDialog):
|
||||
TAB_IMPORT = 2
|
||||
TAB_REPLACE = 3
|
||||
|
||||
newProjectSettingsReady = pyqtSignal()
|
||||
|
||||
def __init__(self, mainGui: GuiMain, focusTab: int = TAB_MAIN) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
@@ -86,7 +88,8 @@ class GuiProjectSettings(NPagedDialog):
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.rejected.connect(self.close)
|
||||
self.rejected.connect(self.close)
|
||||
self.addControls(self.buttonBox)
|
||||
|
||||
# Focus Tab
|
||||
@@ -100,6 +103,13 @@ class GuiProjectSettings(NPagedDialog):
|
||||
logger.debug("Delete: GuiProjectSettings")
|
||||
return
|
||||
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
self._saveGuiSettings()
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
@@ -137,18 +147,12 @@ class GuiProjectSettings(NPagedDialog):
|
||||
newList = self.tabReplace.getNewList()
|
||||
project.data.setAutoReplace(newList)
|
||||
|
||||
self._saveGuiSettings()
|
||||
self.accept()
|
||||
self.newProjectSettingsReady.emit()
|
||||
qApp.processEvents()
|
||||
self.close()
|
||||
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _doClose(self) -> None:
|
||||
"""Save settings and close the dialog."""
|
||||
self._saveGuiSettings()
|
||||
self.reject()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
@@ -173,6 +177,7 @@ class GuiProjectSettings(NPagedDialog):
|
||||
statusColW = CONFIG.rpxInt(self.tabStatus.listBox.columnWidth(0))
|
||||
importColW = CONFIG.rpxInt(self.tabImport.listBox.columnWidth(0))
|
||||
|
||||
logger.debug("Saving State: GuiProjectSettings")
|
||||
pOptions = SHARED.project.options
|
||||
pOptions.setValue("GuiProjectSettings", "winWidth", winWidth)
|
||||
pOptions.setValue("GuiProjectSettings", "winHeight", winHeight)
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Quotes Dialog
|
||||
===============================
|
||||
|
||||
File History:
|
||||
Created: 2020-06-18 [0.9]
|
||||
Created: 2020-06-18 [0.9.0] GuiQuoteSelect
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -25,11 +25,11 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtGui import QFontMetrics
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtGui import QCloseEvent, QFontMetrics
|
||||
from PyQt5.QtCore import QSize, Qt, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QLabel, QVBoxLayout, QHBoxLayout, QDialog, QDialogButtonBox,
|
||||
QListWidget, QListWidgetItem, QFrame
|
||||
QDialog, QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget,
|
||||
QListWidgetItem, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG
|
||||
@@ -44,9 +44,12 @@ class GuiQuoteSelect(QDialog):
|
||||
|
||||
D_KEY = Qt.ItemDataRole.UserRole
|
||||
|
||||
def __init__(self, parent=None, currentQuote='"'):
|
||||
def __init__(self, parent: QWidget, currentQuote: str = '"') -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiQuoteSelect")
|
||||
self.setObjectName("GuiQuoteSelect")
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.innerBox = QHBoxLayout()
|
||||
self.labelBox = QVBoxLayout()
|
||||
@@ -87,8 +90,8 @@ class GuiQuoteSelect(QDialog):
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.accepted.connect(self._doAccept)
|
||||
self.buttonBox.rejected.connect(self._doReject)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
# Assemble
|
||||
self.labelBox.addWidget(self.previewLabel, 0, Qt.AlignTop)
|
||||
@@ -102,15 +105,31 @@ class GuiQuoteSelect(QDialog):
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
logger.debug("Ready: GuiQuoteSelect")
|
||||
|
||||
return
|
||||
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiQuoteSelect")
|
||||
return
|
||||
|
||||
##
|
||||
# Slots
|
||||
# Events
|
||||
##
|
||||
|
||||
def _selectedSymbol(self):
|
||||
"""Update the preview label and the selected quote style.
|
||||
"""
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _selectedSymbol(self) -> None:
|
||||
"""Update the preview label and the selected quote style."""
|
||||
selItems = self.listBox.selectedItems()
|
||||
if selItems:
|
||||
theSymbol = selItems[0].data(self.D_KEY)
|
||||
@@ -118,16 +137,4 @@ class GuiQuoteSelect(QDialog):
|
||||
self.selectedQuote = theSymbol
|
||||
return
|
||||
|
||||
def _doAccept(self):
|
||||
"""Ok button clicked.
|
||||
"""
|
||||
self.accept()
|
||||
return
|
||||
|
||||
def _doReject(self):
|
||||
"""Cancel button clicked.
|
||||
"""
|
||||
self.reject()
|
||||
return
|
||||
|
||||
# END Class GuiQuoteSelect
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Updates
|
||||
=========================
|
||||
|
||||
File History:
|
||||
Created: 2021-08-21 [1.5b1]
|
||||
Created: 2021-08-21 [1.5b1] GuiUpdates
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -30,7 +30,7 @@ from datetime import datetime
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor
|
||||
from PyQt5.QtCore import Qt, pyqtSlot
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, qApp, QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, QLabel
|
||||
)
|
||||
@@ -95,7 +95,7 @@ class GuiUpdates(QDialog):
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.rejected.connect(self.close)
|
||||
|
||||
# Assemble
|
||||
self.innerBox = QHBoxLayout()
|
||||
@@ -169,14 +169,4 @@ class GuiUpdates(QDialog):
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _doClose(self) -> None:
|
||||
"""Close the dialog."""
|
||||
self.close()
|
||||
return
|
||||
|
||||
# END Class GuiUpdates
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI User Wordlist
|
||||
===============================
|
||||
|
||||
File History:
|
||||
Created: 2021-02-12 [1.2rc1]
|
||||
Created: 2021-02-12 [1.2rc1] GuiWordList
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -27,10 +27,11 @@ import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QDialog, QDialogButtonBox, QHBoxLayout, QLabel,
|
||||
QLineEdit, QListWidget, QListWidgetItem, QPushButton, QVBoxLayout
|
||||
QLineEdit, QListWidget, QListWidgetItem, QPushButton, QVBoxLayout, qApp
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -44,7 +45,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiWordList(QDialog):
|
||||
|
||||
def __init__(self, mainGui: GuiMain):
|
||||
newWordListReady = pyqtSignal()
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
logger.debug("Create: GuiWordList")
|
||||
@@ -87,7 +90,7 @@ class GuiWordList(QDialog):
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close)
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.rejected.connect(self.close)
|
||||
|
||||
# Assemble
|
||||
# ========
|
||||
@@ -108,15 +111,27 @@ class GuiWordList(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiWordList")
|
||||
return
|
||||
|
||||
##
|
||||
# Slots
|
||||
# Events
|
||||
##
|
||||
|
||||
def _doAdd(self):
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the close event and perform cleanup."""
|
||||
self._saveGuiSettings()
|
||||
event.accept()
|
||||
self.deleteLater()
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _doAdd(self) -> None:
|
||||
"""Add a new word to the word list."""
|
||||
word = self.newEntry.text().strip()
|
||||
if word == "":
|
||||
@@ -134,16 +149,17 @@ class GuiWordList(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _doDelete(self):
|
||||
@pyqtSlot()
|
||||
def _doDelete(self) -> None:
|
||||
"""Delete the selected item."""
|
||||
selItem = self.listBox.selectedItems()
|
||||
if selItem:
|
||||
self.listBox.takeItem(self.listBox.row(selItem[0]))
|
||||
return
|
||||
|
||||
def _doSave(self):
|
||||
@pyqtSlot()
|
||||
def _doSave(self) -> None:
|
||||
"""Save the new word list and close."""
|
||||
self._saveGuiSettings()
|
||||
userDict = UserDictionary(SHARED.project)
|
||||
for i in range(self.listBox.count()):
|
||||
item = self.listBox.item(i)
|
||||
@@ -152,20 +168,16 @@ class GuiWordList(QDialog):
|
||||
if word:
|
||||
userDict.add(word)
|
||||
userDict.save()
|
||||
self.accept()
|
||||
return True
|
||||
|
||||
def _doClose(self):
|
||||
"""Close without saving the word list."""
|
||||
self._saveGuiSettings()
|
||||
self.reject()
|
||||
self.newWordListReady.emit()
|
||||
qApp.processEvents()
|
||||
self.close()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _loadWordList(self):
|
||||
def _loadWordList(self) -> None:
|
||||
"""Load the project's word list, if it exists."""
|
||||
userDict = UserDictionary(SHARED.project)
|
||||
userDict.load()
|
||||
@@ -175,11 +187,12 @@ class GuiWordList(QDialog):
|
||||
self.listBox.addItem(word)
|
||||
return
|
||||
|
||||
def _saveGuiSettings(self):
|
||||
def _saveGuiSettings(self) -> None:
|
||||
"""Save GUI settings."""
|
||||
winWidth = CONFIG.rpxInt(self.width())
|
||||
winHeight = CONFIG.rpxInt(self.height())
|
||||
|
||||
logger.debug("Saving State: GuiWordList")
|
||||
pOptions = SHARED.project.options
|
||||
pOptions.setValue("GuiWordList", "winWidth", winWidth)
|
||||
pOptions.setValue("GuiWordList", "winHeight", winHeight)
|
||||
|
||||
@@ -95,9 +95,9 @@ class nwDocAction(Enum):
|
||||
CUT = 3
|
||||
COPY = 4
|
||||
PASTE = 5
|
||||
EMPH = 6
|
||||
STRONG = 7
|
||||
STRIKE = 8
|
||||
MD_ITALIC = 6
|
||||
MD_BOLD = 7
|
||||
MD_STRIKE = 8
|
||||
S_QUOTE = 9
|
||||
D_QUOTE = 10
|
||||
SEL_ALL = 11
|
||||
@@ -140,6 +140,7 @@ class nwDocInsert(Enum):
|
||||
NEW_PAGE = 7
|
||||
VSPACE_S = 8
|
||||
VSPACE_M = 9
|
||||
LIPSUM = 10
|
||||
|
||||
# END Enum nwDocInsert
|
||||
|
||||
|
||||
@@ -59,10 +59,7 @@ class NConfigLayout(QGridLayout):
|
||||
def setHelpTextStyle(self, color: QColor | list | tuple,
|
||||
fontScale: float = FONT_SCALE) -> None:
|
||||
"""Set the text color for the help text."""
|
||||
if isinstance(color, QColor):
|
||||
self._helpCol = color
|
||||
else:
|
||||
self._helpCol = QColor(*color)
|
||||
self._helpCol = color if isinstance(color, QColor) else QColor(*color)
|
||||
self._fontScale = fontScale
|
||||
return
|
||||
|
||||
@@ -74,12 +71,6 @@ class NConfigLayout(QGridLayout):
|
||||
qHelp.setText(text)
|
||||
return
|
||||
|
||||
def setLabelText(self, row: int, text: str) -> None:
|
||||
"""Set the text for the main label."""
|
||||
if row in self._itemMap:
|
||||
self._itemMap[row](0).setText(text)
|
||||
return
|
||||
|
||||
##
|
||||
# Class Methods
|
||||
##
|
||||
@@ -211,10 +202,7 @@ class NHelpLabel(QLabel):
|
||||
fontSize: float = FONT_SCALE) -> None:
|
||||
super().__init__(text)
|
||||
|
||||
if isinstance(color, QColor):
|
||||
qCol = color
|
||||
else:
|
||||
qCol = QColor(*color)
|
||||
qCol = color if isinstance(color, QColor) else QColor(*color)
|
||||
|
||||
lblCol = self.palette()
|
||||
lblCol.setColor(QPalette.WindowText, qCol)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""
|
||||
novelWriter – Custom Object: Wheel Event Filter
|
||||
===============================================
|
||||
novelWriter – Custom Objects: Event Filters
|
||||
===========================================
|
||||
|
||||
File History:
|
||||
Created: 2023-08-31 [2.1rc1]
|
||||
Created: 2023-08-31 [2.1rc1] WheelEventFilter
|
||||
Created: 2023-11-28 [2.2] StatusTipFilter
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -23,7 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from PyQt5.QtGui import QWheelEvent
|
||||
from PyQt5.QtGui import QStatusTipEvent, QWheelEvent
|
||||
from PyQt5.QtCore import QEvent, QObject
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
@@ -63,3 +64,12 @@ class WheelEventFilter(QObject):
|
||||
return False
|
||||
|
||||
# END Class WheelEventFilter
|
||||
|
||||
|
||||
class StatusTipFilter(QObject):
|
||||
|
||||
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
||||
"""Filter out status tip events on menus."""
|
||||
return True if isinstance(event, QStatusTipEvent) else super().eventFilter(obj, event)
|
||||
|
||||
# END Class StatusTipFilter
|
||||
@@ -65,10 +65,7 @@ class NPagedSideBar(QToolBar):
|
||||
|
||||
def setLabelColor(self, color: list | QColor) -> None:
|
||||
"""Set the text color for the labels."""
|
||||
if isinstance(color, list):
|
||||
self._labelCol = QColor(*color)
|
||||
elif isinstance(color, QColor):
|
||||
self._labelCol = color
|
||||
self._labelCol = color if isinstance(color, QColor) else QColor(*color)
|
||||
return
|
||||
|
||||
def addSeparator(self) -> None:
|
||||
|
||||
@@ -41,14 +41,13 @@ class NProgressSimple(QProgressBar):
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Custom painter for the progress bar."""
|
||||
if self.value() == 0:
|
||||
return
|
||||
progress = ceil(self.width()*float(self.value())/self.maximum())
|
||||
qPaint = QPainter(self)
|
||||
qPaint.setRenderHint(QPainter.Antialiasing, True)
|
||||
qPaint.setPen(self.palette().highlight().color())
|
||||
qPaint.setBrush(self.palette().highlight())
|
||||
qPaint.drawRect(0, 0, progress, self.height())
|
||||
if (value := self.value()) > 0:
|
||||
progress = ceil(self.width()*float(value)/self.maximum())
|
||||
qPaint = QPainter(self)
|
||||
qPaint.setRenderHint(QPainter.Antialiasing, True)
|
||||
qPaint.setPen(self.palette().highlight().color())
|
||||
qPaint.setBrush(self.palette().highlight())
|
||||
qPaint.drawRect(0, 0, progress, self.height())
|
||||
return
|
||||
|
||||
# END Class NProgressSimple
|
||||
|
||||
@@ -134,10 +134,10 @@ class NSwitch(QAbstractButton):
|
||||
qPaint.setBrush(thumbBrush)
|
||||
qPaint.drawEllipse(self._offset - self._rR, self._rB, self._rH, self._rH)
|
||||
|
||||
theFont = qPaint.font()
|
||||
theFont.setPixelSize(self._xT)
|
||||
font = qPaint.font()
|
||||
font.setPixelSize(self._xT)
|
||||
qPaint.setPen(textColor)
|
||||
qPaint.setFont(theFont)
|
||||
qPaint.setFont(font)
|
||||
qPaint.drawText(
|
||||
QRectF(self._offset - self._rR, self._rB, self._rH, self._rH),
|
||||
Qt.AlignCenter, thumbText
|
||||
|
||||
@@ -106,11 +106,6 @@ class NSwitchBox(QScrollArea):
|
||||
self._bumpIndex()
|
||||
return
|
||||
|
||||
def setInnerContentsMargins(self, left: int, top: int, right: int, bottom: int) -> None:
|
||||
"""Set the contents margins of the inner layout."""
|
||||
self._content.setContentsMargins(left, top, right, bottom)
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
@@ -58,10 +58,11 @@ from novelwriter.common import minmax, transferCase
|
||||
from novelwriter.constants import nwKeyWords, nwLabels, nwShortcode, nwUnicode, trConst
|
||||
from novelwriter.core.item import NWItem
|
||||
from novelwriter.core.index import countWords
|
||||
from novelwriter.tools.lipsum import GuiLipsum
|
||||
from novelwriter.core.document import NWDocument
|
||||
from novelwriter.gui.dochighlight import GuiDocHighlighter
|
||||
from novelwriter.gui.editordocument import GuiTextDocument
|
||||
from novelwriter.extensions.wheeleventfilter import WheelEventFilter
|
||||
from novelwriter.extensions.eventfilters import WheelEventFilter
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
@@ -717,11 +718,11 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self.copy()
|
||||
elif action == nwDocAction.PASTE:
|
||||
self.paste()
|
||||
elif action == nwDocAction.EMPH:
|
||||
elif action == nwDocAction.MD_ITALIC:
|
||||
self._toggleFormat(1, "_")
|
||||
elif action == nwDocAction.STRONG:
|
||||
elif action == nwDocAction.MD_BOLD:
|
||||
self._toggleFormat(2, "*")
|
||||
elif action == nwDocAction.STRIKE:
|
||||
elif action == nwDocAction.MD_STRIKE:
|
||||
self._toggleFormat(2, "~")
|
||||
elif action == nwDocAction.S_QUOTE:
|
||||
self._wrapSelection(self._typSQuoteO, self._typSQuoteC)
|
||||
@@ -831,11 +832,11 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
elif insert == nwDocInsert.QUOTE_RD:
|
||||
text = self._typDQuoteC
|
||||
elif insert == nwDocInsert.SYNOPSIS:
|
||||
text = "% Synopsis: "
|
||||
text = "%Synopsis: "
|
||||
newBlock = True
|
||||
goAfter = True
|
||||
elif insert == nwDocInsert.SHORT:
|
||||
text = "% Short: "
|
||||
text = "%Short: "
|
||||
newBlock = True
|
||||
goAfter = True
|
||||
elif insert == nwDocInsert.NEW_PAGE:
|
||||
@@ -850,18 +851,23 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
text = "[vspace:2]"
|
||||
newBlock = True
|
||||
goAfter = False
|
||||
elif insert == nwDocInsert.LIPSUM:
|
||||
text = GuiLipsum.getLipsum(self)
|
||||
newBlock = True
|
||||
goAfter = False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
if newBlock:
|
||||
self.insertNewBlock(text, defaultAfter=goAfter)
|
||||
else:
|
||||
cursor = self.textCursor()
|
||||
cursor.beginEditBlock()
|
||||
cursor.insertText(text)
|
||||
cursor.endEditBlock()
|
||||
if text:
|
||||
if newBlock:
|
||||
self.insertNewBlock(text, defaultAfter=goAfter)
|
||||
else:
|
||||
cursor = self.textCursor()
|
||||
cursor.beginEditBlock()
|
||||
cursor.insertText(text)
|
||||
cursor.endEditBlock()
|
||||
|
||||
return True
|
||||
|
||||
@@ -1144,6 +1150,7 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
|
||||
# Execute the context menu
|
||||
ctxMenu.exec_(self.viewport().mapToGlobal(pos))
|
||||
ctxMenu.deleteLater()
|
||||
|
||||
return
|
||||
|
||||
@@ -2005,20 +2012,25 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
cPos = cursor.position()
|
||||
bPos = cursor.block().position()
|
||||
bLen = cursor.block().length()
|
||||
apos = nwUnicode.U_APOS + nwUnicode.U_RSQUO
|
||||
|
||||
# Scan backwards
|
||||
# Scan backward
|
||||
sPos = cPos
|
||||
for i in range(cPos - bPos):
|
||||
sPos = cPos - i - 1
|
||||
if not self._qDocument.characterAt(sPos).isalnum():
|
||||
cOne = self._qDocument.characterAt(sPos)
|
||||
cTwo = self._qDocument.characterAt(sPos - 1)
|
||||
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
|
||||
sPos += 1
|
||||
break
|
||||
|
||||
# Scan forwards
|
||||
# Scan forward
|
||||
ePos = cPos
|
||||
for i in range(bPos + bLen - cPos):
|
||||
ePos = cPos + i
|
||||
if not self._qDocument.characterAt(ePos).isalnum():
|
||||
cOne = self._qDocument.characterAt(ePos)
|
||||
cTwo = self._qDocument.characterAt(ePos + 1)
|
||||
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
|
||||
break
|
||||
|
||||
if ePos - sPos <= 0:
|
||||
@@ -2225,39 +2237,65 @@ class GuiDocToolBar(QWidget):
|
||||
# General Buttons
|
||||
# ===============
|
||||
|
||||
self.tbMode = QToolButton(self)
|
||||
self.tbMode.setToolTip(self.tr("Toggle Markdown or Shortcodes Mode"))
|
||||
self.tbMode.setIconSize(iconSize)
|
||||
self.tbMode.setCheckable(True)
|
||||
self.tbMode.setChecked(CONFIG.useShortcodes)
|
||||
self.tbMode.toggled.connect(self._toggleFormatMode)
|
||||
self.tbBoldMD = QToolButton(self)
|
||||
self.tbBoldMD.setIconSize(iconSize)
|
||||
self.tbBoldMD.setToolTip(self.tr("Markdown Bold"))
|
||||
self.tbBoldMD.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
|
||||
)
|
||||
|
||||
self.tbItalicMD = QToolButton(self)
|
||||
self.tbItalicMD.setIconSize(iconSize)
|
||||
self.tbItalicMD.setToolTip(self.tr("Markdown Italic"))
|
||||
self.tbItalicMD.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
|
||||
)
|
||||
|
||||
self.tbStrikeMD = QToolButton(self)
|
||||
self.tbStrikeMD.setIconSize(iconSize)
|
||||
self.tbStrikeMD.setToolTip(self.tr("Markdown Strikethrough"))
|
||||
self.tbStrikeMD.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
|
||||
)
|
||||
|
||||
self.tbBold = QToolButton(self)
|
||||
self.tbBold.setIconSize(iconSize)
|
||||
self.tbBold.clicked.connect(self._formatBold)
|
||||
self.tbBold.setToolTip(self.tr("Shortcode Bold"))
|
||||
self.tbBold.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
|
||||
)
|
||||
|
||||
self.tbItalic = QToolButton(self)
|
||||
self.tbItalic.setIconSize(iconSize)
|
||||
self.tbItalic.clicked.connect(self._formatItalic)
|
||||
self.tbItalic.setToolTip(self.tr("Shortcode Italic"))
|
||||
self.tbItalic.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
||||
)
|
||||
|
||||
self.tbStrike = QToolButton(self)
|
||||
self.tbStrike.setIconSize(iconSize)
|
||||
self.tbStrike.clicked.connect(self._formatStrike)
|
||||
self.tbStrike.setToolTip(self.tr("Shortcode Strikethrough"))
|
||||
self.tbStrike.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_STRIKE)
|
||||
)
|
||||
|
||||
self.tbUnderline = QToolButton(self)
|
||||
self.tbUnderline.setIconSize(iconSize)
|
||||
self.tbUnderline.setToolTip(self.tr("Shortcode Underline"))
|
||||
self.tbUnderline.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_ULINE)
|
||||
)
|
||||
|
||||
self.tbSuperscript = QToolButton(self)
|
||||
self.tbSuperscript.setIconSize(iconSize)
|
||||
self.tbSuperscript.setToolTip(self.tr("Shortcode Superscript"))
|
||||
self.tbSuperscript.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_SUP)
|
||||
)
|
||||
|
||||
self.tbSubscript = QToolButton(self)
|
||||
self.tbSubscript.setIconSize(iconSize)
|
||||
self.tbSubscript.setToolTip(self.tr("Shortcode Subscript"))
|
||||
self.tbSubscript.clicked.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_SUB)
|
||||
)
|
||||
@@ -2266,7 +2304,10 @@ class GuiDocToolBar(QWidget):
|
||||
# ========
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addWidget(self.tbMode)
|
||||
self.outerBox.addWidget(self.tbBoldMD)
|
||||
self.outerBox.addWidget(self.tbItalicMD)
|
||||
self.outerBox.addWidget(self.tbStrikeMD)
|
||||
self.outerBox.addSpacing(cM)
|
||||
self.outerBox.addWidget(self.tbBold)
|
||||
self.outerBox.addWidget(self.tbItalic)
|
||||
self.outerBox.addWidget(self.tbStrike)
|
||||
@@ -2294,8 +2335,9 @@ class GuiDocToolBar(QWidget):
|
||||
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
||||
self.setPalette(palette)
|
||||
|
||||
tPx = int(0.8*SHARED.theme.fontPixelSize)
|
||||
self.tbMode.setIcon(SHARED.theme.getToggleIcon("fmt_mode", (tPx, tPx)))
|
||||
self.tbBoldMD.setIcon(SHARED.theme.getIcon("fmt_bold-md"))
|
||||
self.tbItalicMD.setIcon(SHARED.theme.getIcon("fmt_italic-md"))
|
||||
self.tbStrikeMD.setIcon(SHARED.theme.getIcon("fmt_strike-md"))
|
||||
self.tbBold.setIcon(SHARED.theme.getIcon("fmt_bold"))
|
||||
self.tbItalic.setIcon(SHARED.theme.getIcon("fmt_italic"))
|
||||
self.tbStrike.setIcon(SHARED.theme.getIcon("fmt_strike"))
|
||||
@@ -2305,40 +2347,6 @@ class GuiDocToolBar(QWidget):
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def _toggleFormatMode(self, checked: bool) -> None:
|
||||
"""Toggle the formatting mode."""
|
||||
CONFIG.useShortcodes = checked
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _formatBold(self):
|
||||
"""Call the bold format action."""
|
||||
self.requestDocAction.emit(
|
||||
nwDocAction.SC_BOLD if self.tbMode.isChecked() else nwDocAction.STRONG
|
||||
)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _formatItalic(self):
|
||||
"""Call the italic format action."""
|
||||
self.requestDocAction.emit(
|
||||
nwDocAction.SC_ITALIC if self.tbMode.isChecked() else nwDocAction.EMPH
|
||||
)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _formatStrike(self):
|
||||
"""Call the strikethrough format action."""
|
||||
self.requestDocAction.emit(
|
||||
nwDocAction.SC_STRIKE if self.tbMode.isChecked() else nwDocAction.STRIKE
|
||||
)
|
||||
return
|
||||
|
||||
# END Class GuiDocToolBar
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ novelWriter – GUI Syntax Highlighter
|
||||
====================================
|
||||
|
||||
File History:
|
||||
Created: 2019-04-06 [0.0.1]
|
||||
Created: 2019-04-06 [0.0.1] GuiDocHighlighter
|
||||
Created: 2023-09-10 [2.2b1] TextBlockData
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -46,7 +46,7 @@ from novelwriter.enum import nwItemType, nwDocAction, nwDocMode
|
||||
from novelwriter.error import logException
|
||||
from novelwriter.constants import nwUnicode
|
||||
from novelwriter.core.tohtml import ToHtml
|
||||
from novelwriter.extensions.wheeleventfilter import WheelEventFilter
|
||||
from novelwriter.extensions.eventfilters import WheelEventFilter
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
@@ -378,33 +378,34 @@ class GuiDocViewer(QTextBrowser):
|
||||
userCursor = self.textCursor()
|
||||
userSelection = userCursor.hasSelection()
|
||||
|
||||
mnuContext = QMenu(self)
|
||||
ctxMenu = QMenu(self)
|
||||
|
||||
if userSelection:
|
||||
mnuCopy = QAction(self.tr("Copy"), mnuContext)
|
||||
mnuCopy = QAction(self.tr("Copy"), ctxMenu)
|
||||
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
||||
mnuContext.addAction(mnuCopy)
|
||||
ctxMenu.addAction(mnuCopy)
|
||||
|
||||
mnuContext.addSeparator()
|
||||
ctxMenu.addSeparator()
|
||||
|
||||
mnuSelAll = QAction(self.tr("Select All"), mnuContext)
|
||||
mnuSelAll = QAction(self.tr("Select All"), ctxMenu)
|
||||
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
||||
mnuContext.addAction(mnuSelAll)
|
||||
ctxMenu.addAction(mnuSelAll)
|
||||
|
||||
mnuSelWord = QAction(self.tr("Select Word"), mnuContext)
|
||||
mnuSelWord = QAction(self.tr("Select Word"), ctxMenu)
|
||||
mnuSelWord.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.SelectionType.WordUnderCursor, point)
|
||||
)
|
||||
mnuContext.addAction(mnuSelWord)
|
||||
ctxMenu.addAction(mnuSelWord)
|
||||
|
||||
mnuSelPara = QAction(self.tr("Select Paragraph"), mnuContext)
|
||||
mnuSelPara = QAction(self.tr("Select Paragraph"), ctxMenu)
|
||||
mnuSelPara.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.SelectionType.BlockUnderCursor, point)
|
||||
)
|
||||
mnuContext.addAction(mnuSelPara)
|
||||
ctxMenu.addAction(mnuSelPara)
|
||||
|
||||
# Open the context menu
|
||||
mnuContext.exec_(self.viewport().mapToGlobal(point))
|
||||
ctxMenu.exec_(self.viewport().mapToGlobal(point))
|
||||
ctxMenu.deleteLater()
|
||||
|
||||
return
|
||||
|
||||
@@ -861,8 +862,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self._docHandle = None
|
||||
|
||||
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
||||
bSp = CONFIG.pxInt(2)
|
||||
hSp = CONFIG.pxInt(8)
|
||||
hSp = CONFIG.pxInt(4)
|
||||
|
||||
# Main Widget Settings
|
||||
self.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -872,64 +872,41 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showHide = QToolButton(self)
|
||||
self.showHide.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||
self.showHide.setIconSize(QSize(fPx, fPx))
|
||||
self.showHide.setFixedSize(QSize(fPx, fPx))
|
||||
self.showHide.clicked.connect(lambda: self.docViewer.togglePanelVisibility.emit())
|
||||
self.showHide.setToolTip(self.tr("Show/Hide Viewer Panel"))
|
||||
|
||||
# Show Comments
|
||||
self.showComments = QToolButton(self)
|
||||
self.showComments.setText(self.tr("Comments"))
|
||||
self.showComments.setCheckable(True)
|
||||
self.showComments.setChecked(CONFIG.viewComments)
|
||||
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||
self.showComments.setIconSize(QSize(fPx, fPx))
|
||||
self.showComments.setFixedSize(QSize(fPx, fPx))
|
||||
self.showComments.toggled.connect(self._doToggleComments)
|
||||
self.showComments.setToolTip(self.tr("Show Comments"))
|
||||
|
||||
# Show Synopsis
|
||||
self.showSynopsis = QToolButton(self)
|
||||
self.showSynopsis.setText(self.tr("Synopsis"))
|
||||
self.showSynopsis.setCheckable(True)
|
||||
self.showSynopsis.setChecked(CONFIG.viewSynopsis)
|
||||
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||
self.showSynopsis.setIconSize(QSize(fPx, fPx))
|
||||
self.showSynopsis.setFixedSize(QSize(fPx, fPx))
|
||||
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
||||
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
||||
|
||||
# Labels
|
||||
self.lblComments = QLabel(self.tr("Comments"))
|
||||
self.lblComments.setBuddy(self.showComments)
|
||||
self.lblComments.setIndent(0)
|
||||
self.lblComments.setMargin(0)
|
||||
self.lblComments.setContentsMargins(0, 0, 0, 0)
|
||||
self.lblComments.setAutoFillBackground(True)
|
||||
self.lblComments.setFixedHeight(fPx)
|
||||
self.lblComments.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
||||
|
||||
self.lblSynopsis = QLabel(self.tr("Synopsis"))
|
||||
self.lblSynopsis.setBuddy(self.showSynopsis)
|
||||
self.lblSynopsis.setIndent(0)
|
||||
self.lblSynopsis.setMargin(0)
|
||||
self.lblSynopsis.setContentsMargins(0, 0, 0, 0)
|
||||
self.lblSynopsis.setAutoFillBackground(True)
|
||||
self.lblSynopsis.setFixedHeight(fPx)
|
||||
self.lblSynopsis.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
||||
|
||||
lblFont = self.font()
|
||||
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
||||
self.lblComments.setFont(lblFont)
|
||||
self.lblSynopsis.setFont(lblFont)
|
||||
self.showComments.setFont(lblFont)
|
||||
self.showSynopsis.setFont(lblFont)
|
||||
|
||||
# Assemble Layout
|
||||
self.outerBox = QHBoxLayout()
|
||||
self.outerBox.setSpacing(bSp)
|
||||
self.outerBox.addWidget(self.showHide, 0)
|
||||
self.outerBox.addStretch(1)
|
||||
self.outerBox.addWidget(self.showComments, 0)
|
||||
self.outerBox.addWidget(self.lblComments, 0)
|
||||
self.outerBox.addSpacing(hSp)
|
||||
self.outerBox.addWidget(self.showSynopsis, 0)
|
||||
self.outerBox.addWidget(self.lblSynopsis, 0)
|
||||
self.outerBox.setSpacing(hSp)
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
# Fix Margins and Size
|
||||
@@ -983,8 +960,6 @@ class GuiDocViewFooter(QWidget):
|
||||
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
||||
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
||||
self.setPalette(palette)
|
||||
self.lblComments.setPalette(palette)
|
||||
self.lblSynopsis.setPalette(palette)
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
@@ -57,7 +57,7 @@ class GuiDocViewerPanel(QWidget):
|
||||
self.tabBackRefs = _ViewPanelBackRefs(self)
|
||||
|
||||
self.mainTabs = QTabWidget(self)
|
||||
self.mainTabs.addTab(self.tabBackRefs, self.tr("Backreferences"))
|
||||
self.mainTabs.addTab(self.tabBackRefs, self.tr("References"))
|
||||
|
||||
self.kwTabs: dict[str, _ViewPanelKeyWords] = {}
|
||||
self.idTabs: dict[str, int] = {}
|
||||
@@ -73,7 +73,7 @@ class GuiDocViewerPanel(QWidget):
|
||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
self.updateTheme()
|
||||
self.updateTheme(updateTabs=False)
|
||||
|
||||
logger.debug("Ready: GuiDocViewerPanel")
|
||||
|
||||
@@ -83,7 +83,7 @@ class GuiDocViewerPanel(QWidget):
|
||||
# Methods
|
||||
##
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
def updateTheme(self, updateTabs: bool = True) -> None:
|
||||
"""Update theme elements."""
|
||||
vPx = CONFIG.pxInt(4)
|
||||
lPx = CONFIG.pxInt(2)
|
||||
@@ -102,6 +102,11 @@ class GuiDocViewerPanel(QWidget):
|
||||
self.mainTabs.setStyleSheet(styleSheet)
|
||||
self.updateHandle(self._lastHandle)
|
||||
|
||||
if updateTabs:
|
||||
self.tabBackRefs.updateTheme()
|
||||
for tab in self.kwTabs.values():
|
||||
tab.updateTheme()
|
||||
|
||||
return
|
||||
|
||||
def openProjectTasks(self) -> None:
|
||||
@@ -118,6 +123,7 @@ class GuiDocViewerPanel(QWidget):
|
||||
widths = {}
|
||||
for key, tab in self.kwTabs.items():
|
||||
widths[key] = tab.getColumnWidths()
|
||||
logger.debug("Saving State: GuiDocViewerPanel")
|
||||
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", widths)
|
||||
return
|
||||
|
||||
@@ -218,12 +224,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
# Set Header Sizes
|
||||
treeHeader = self.header()
|
||||
treeHeader.setStretchLastSection(True)
|
||||
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
||||
treeHeader.setSectionResizeMode(self.C_DOC, QHeaderView.ResizeMode.ResizeToContents)
|
||||
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.ResizeToContents)
|
||||
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
||||
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
||||
treeHeader.setSectionsMovable(False)
|
||||
|
||||
# Cache Icons Locally
|
||||
self._editIcon = SHARED.theme.getIcon("edit")
|
||||
@@ -235,6 +243,16 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
|
||||
return
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
"""Update theme elements."""
|
||||
self._editIcon = SHARED.theme.getIcon("edit")
|
||||
self._viewIcon = SHARED.theme.getIcon("view")
|
||||
for i in range(self.topLevelItemCount()):
|
||||
if item := self.topLevelItem(i):
|
||||
item.setIcon(self.C_EDIT, self._editIcon)
|
||||
item.setIcon(self.C_VIEW, self._viewIcon)
|
||||
return
|
||||
|
||||
def clearContent(self) -> None:
|
||||
"""Clear the widget."""
|
||||
self.clear()
|
||||
@@ -276,7 +294,7 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
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:
|
||||
if index.column() not in (self.C_EDIT, self.C_VIEW):
|
||||
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
||||
return
|
||||
|
||||
@@ -299,10 +317,12 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
|
||||
trItem.setIcon(self.C_DOC, docIcon)
|
||||
trItem.setText(self.C_DOC, nwItem.itemName)
|
||||
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
||||
trItem.setIcon(self.C_EDIT, self._editIcon)
|
||||
trItem.setIcon(self.C_VIEW, self._viewIcon)
|
||||
trItem.setText(self.C_TITLE, hItem.title)
|
||||
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
||||
trItem.setText(self.C_TITLE, hItem.title)
|
||||
trItem.setToolTip(self.C_TITLE, hItem.title)
|
||||
trItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
|
||||
|
||||
if tKey not in self._treeMap:
|
||||
@@ -316,13 +336,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
||||
|
||||
class _ViewPanelKeyWords(QTreeWidget):
|
||||
|
||||
C_DATA = 0
|
||||
C_NAME = 0
|
||||
C_EDIT = 1
|
||||
C_VIEW = 2
|
||||
C_DOC = 3
|
||||
C_TITLE = 4
|
||||
C_SHORT = 5
|
||||
C_DATA = 0
|
||||
C_NAME = 0
|
||||
C_EDIT = 1
|
||||
C_VIEW = 2
|
||||
C_IMPORT = 3
|
||||
C_DOC = 4
|
||||
C_TITLE = 5
|
||||
C_SHORT = 6
|
||||
|
||||
D_TAG = Qt.ItemDataRole.UserRole
|
||||
|
||||
@@ -330,13 +351,14 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self._parent = parent
|
||||
self._class = itemClass
|
||||
self._treeMap: dict[str, QTreeWidgetItem] = {}
|
||||
|
||||
iPx = SHARED.theme.baseIconSize
|
||||
cMg = CONFIG.pxInt(6)
|
||||
|
||||
self.setHeaderLabels([
|
||||
self.tr("Tag"), "", "", self.tr("Document"),
|
||||
self.tr("Tag"), "", "", self.tr("Importance"), self.tr("Document"),
|
||||
self.tr("Heading"), self.tr("Short Description")
|
||||
])
|
||||
self.setIndentation(0)
|
||||
@@ -351,7 +373,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
# Set Header Sizes
|
||||
treeHeader = self.header()
|
||||
treeHeader.setStretchLastSection(True)
|
||||
treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.ResizeToContents)
|
||||
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
||||
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
||||
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
||||
@@ -369,6 +391,17 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
|
||||
return
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
"""Update theme elements."""
|
||||
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[self._class])
|
||||
self._editIcon = SHARED.theme.getIcon("edit")
|
||||
self._viewIcon = SHARED.theme.getIcon("view")
|
||||
for i in range(self.topLevelItemCount()):
|
||||
if item := self.topLevelItem(i):
|
||||
item.setIcon(self.C_EDIT, self._editIcon)
|
||||
item.setIcon(self.C_VIEW, self._viewIcon)
|
||||
return
|
||||
|
||||
def countEntries(self) -> int:
|
||||
"""Return the number of items in the list."""
|
||||
return self.topLevelItemCount()
|
||||
@@ -386,22 +419,30 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
nwItem.itemType, nwItem.itemClass,
|
||||
nwItem.itemLayout, nwItem.mainHeading
|
||||
)
|
||||
impLabel, impIcon = nwItem.getImportStatus(incIcon=True)
|
||||
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
|
||||
hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
|
||||
|
||||
# This can not use a get call to the dictionary as that creates
|
||||
# some weird issue with Qt, so we need to do this with an if
|
||||
# This can not use a get call to the dictionary as that would create an
|
||||
# instance of the QTreeWidgetItem, which has some weird side effects
|
||||
trItem = self._treeMap[tag] if tag in self._treeMap else QTreeWidgetItem()
|
||||
|
||||
trItem.setText(self.C_NAME, name)
|
||||
trItem.setIcon(self.C_NAME, self._classIcon)
|
||||
trItem.setText(self.C_NAME, name)
|
||||
trItem.setToolTip(self.C_NAME, name)
|
||||
trItem.setIcon(self.C_EDIT, self._editIcon)
|
||||
trItem.setIcon(self.C_VIEW, self._viewIcon)
|
||||
trItem.setIcon(self.C_IMPORT, impIcon)
|
||||
trItem.setText(self.C_IMPORT, impLabel)
|
||||
trItem.setToolTip(self.C_IMPORT, impLabel)
|
||||
trItem.setIcon(self.C_DOC, docIcon)
|
||||
trItem.setText(self.C_DOC, nwItem.itemName)
|
||||
trItem.setText(self.C_TITLE, hItem.title)
|
||||
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
||||
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
||||
trItem.setText(self.C_TITLE, hItem.title)
|
||||
trItem.setToolTip(self.C_TITLE, hItem.title)
|
||||
trItem.setText(self.C_SHORT, hItem.synopsis)
|
||||
trItem.setToolTip(self.C_SHORT, hItem.synopsis)
|
||||
trItem.setData(self.C_DATA, self.D_TAG, tag)
|
||||
|
||||
if tag not in self._treeMap:
|
||||
@@ -420,14 +461,18 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
|
||||
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)))
|
||||
if isinstance(widths, list) and len(widths) >= 4:
|
||||
self.setColumnWidth(self.C_NAME, CONFIG.pxInt(checkInt(widths[0], 100)))
|
||||
self.setColumnWidth(self.C_IMPORT, CONFIG.pxInt(checkInt(widths[1], 100)))
|
||||
self.setColumnWidth(self.C_DOC, CONFIG.pxInt(checkInt(widths[2], 100)))
|
||||
self.setColumnWidth(self.C_TITLE, CONFIG.pxInt(checkInt(widths[3], 100)))
|
||||
return
|
||||
|
||||
def getColumnWidths(self) -> list[int]:
|
||||
"""Get the widths of the user-adjustable columns."""
|
||||
return [
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_NAME)),
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_IMPORT)),
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_DOC)),
|
||||
CONFIG.rpxInt(self.columnWidth(self.C_TITLE)),
|
||||
]
|
||||
@@ -450,7 +495,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
||||
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:
|
||||
if index.column() not in (self.C_EDIT, self.C_VIEW):
|
||||
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
||||
return
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Text Document
|
||||
===============================
|
||||
|
||||
File History:
|
||||
Created: 2023-09-07 [2.2b1]
|
||||
Created: 2023-09-07 [2.2b1] GuiTextDocument
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -50,7 +50,7 @@ class GuiTextDocument(QTextDocument):
|
||||
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
def __del__(self) -> None: # pragma: no cover
|
||||
logger.debug("Delete: GuiTextDocument")
|
||||
return
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Item Details Panel
|
||||
====================================
|
||||
|
||||
File History:
|
||||
Created: 2019-04-24 [0.0.1]
|
||||
Created: 2019-04-24 [0.0.1] GuiItemDetails
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
@@ -3,7 +3,7 @@ novelWriter – GUI Main Menu
|
||||
===========================
|
||||
|
||||
File History:
|
||||
Created: 2019-04-27 [0.0.1]
|
||||
Created: 2019-04-27 [0.0.1] GuiMainMenu
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
@@ -36,6 +36,7 @@ from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.enum import nwDocAction, nwDocInsert, nwWidget
|
||||
from novelwriter.common import openExternalPath
|
||||
from novelwriter.constants import nwConst, trConst, nwKeyWords, nwLabels, nwUnicode
|
||||
from novelwriter.extensions.eventfilters import StatusTipFilter
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
@@ -73,6 +74,8 @@ class GuiMainMenu(QMenuBar):
|
||||
self._buildToolsMenu()
|
||||
self._buildHelpMenu()
|
||||
|
||||
self.installEventFilter(StatusTipFilter(mainGui))
|
||||
|
||||
logger.debug("Ready: GuiMainMenu")
|
||||
|
||||
return
|
||||
@@ -154,12 +157,12 @@ class GuiMainMenu(QMenuBar):
|
||||
# Project > Project Settings
|
||||
self.aProjectSettings = self.projMenu.addAction(self.tr("Project Settings"))
|
||||
self.aProjectSettings.setShortcut("Ctrl+Shift+,")
|
||||
self.aProjectSettings.triggered.connect(lambda: self.mainGui.showProjectSettingsDialog())
|
||||
self.aProjectSettings.triggered.connect(self.mainGui.showProjectSettingsDialog)
|
||||
|
||||
# Project > Project Details
|
||||
self.aProjectDetails = self.projMenu.addAction(self.tr("Project Details"))
|
||||
self.aProjectDetails.setShortcut("Shift+F6")
|
||||
self.aProjectDetails.triggered.connect(lambda: self.mainGui.showProjectDetailsDialog())
|
||||
self.aProjectDetails.triggered.connect(self.mainGui.showProjectDetailsDialog)
|
||||
|
||||
# Project > Separator
|
||||
self.projMenu.addSeparator()
|
||||
@@ -566,7 +569,7 @@ class GuiMainMenu(QMenuBar):
|
||||
|
||||
# Insert > Short Description Comment
|
||||
self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment"))
|
||||
self.aInsShort.setShortcut("Ctrl+K, U")
|
||||
self.aInsShort.setShortcut("Ctrl+K, H")
|
||||
self.aInsShort.triggered.connect(
|
||||
lambda: self.requestDocInsert.emit(nwDocInsert.SHORT)
|
||||
)
|
||||
@@ -593,8 +596,10 @@ class GuiMainMenu(QMenuBar):
|
||||
)
|
||||
|
||||
# Insert > Placeholder Text
|
||||
self.aLipsumText = self.mInsBreaks.addAction(self.tr("Placeholder Text"))
|
||||
self.aLipsumText.triggered.connect(lambda: self.mainGui.showLoremIpsumDialog())
|
||||
self.aLipsumText = self.insMenu.addAction(self.tr("Placeholder Text"))
|
||||
self.aLipsumText.triggered.connect(
|
||||
lambda: self.requestDocInsert.emit(nwDocInsert.LIPSUM)
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@@ -603,25 +608,25 @@ class GuiMainMenu(QMenuBar):
|
||||
# Format
|
||||
self.fmtMenu = self.addMenu(self.tr("&Format"))
|
||||
|
||||
# Format > Emphasis
|
||||
self.aFmtEmph = self.fmtMenu.addAction(self.tr("Emphasis"))
|
||||
self.aFmtEmph.setShortcut("Ctrl+I")
|
||||
self.aFmtEmph.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.EMPH)
|
||||
# Format > Bold
|
||||
self.aFmtBold = self.fmtMenu.addAction(self.tr("Bold"))
|
||||
self.aFmtBold.setShortcut("Ctrl+B")
|
||||
self.aFmtBold.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
|
||||
)
|
||||
|
||||
# Format > Strong Emphasis
|
||||
self.aFmtStrong = self.fmtMenu.addAction(self.tr("Strong Emphasis"))
|
||||
self.aFmtStrong.setShortcut("Ctrl+B")
|
||||
self.aFmtStrong.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.STRONG)
|
||||
# Format > Italic
|
||||
self.aFmtItalic = self.fmtMenu.addAction(self.tr("Italic"))
|
||||
self.aFmtItalic.setShortcut("Ctrl+I")
|
||||
self.aFmtItalic.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
|
||||
)
|
||||
|
||||
# Format > Strikethrough
|
||||
self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough"))
|
||||
self.aFmtStrike.setShortcut("Ctrl+D")
|
||||
self.aFmtStrike.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.STRIKE)
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
|
||||
)
|
||||
|
||||
# Edit > Separator
|
||||
@@ -647,18 +652,18 @@ class GuiMainMenu(QMenuBar):
|
||||
# Shortcodes
|
||||
self.mShortcodes = self.fmtMenu.addMenu(self.tr("More Formats ..."))
|
||||
|
||||
# Shortcode Italic
|
||||
self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
|
||||
self.aScItalic.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
||||
)
|
||||
|
||||
# Shortcode Bold
|
||||
self.aScBold = self.mShortcodes.addAction(self.tr("Bold (Shortcode)"))
|
||||
self.aScBold.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
|
||||
)
|
||||
|
||||
# Shortcode Italic
|
||||
self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
|
||||
self.aScItalic.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
||||
)
|
||||
|
||||
# Shortcode Strikethrough
|
||||
self.aScStrike = self.mShortcodes.addAction(self.tr("Strikethrough (Shortcode)"))
|
||||
self.aScStrike.triggered.connect(
|
||||
@@ -872,7 +877,7 @@ class GuiMainMenu(QMenuBar):
|
||||
|
||||
# Tools > Project Word List
|
||||
self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List"))
|
||||
self.aEditWordList.triggered.connect(lambda: self.mainGui.showProjectWordListDialog())
|
||||
self.aEditWordList.triggered.connect(self.mainGui.showProjectWordListDialog)
|
||||
|
||||
# Tools > Add Dictionaries
|
||||
if CONFIG.osWindows or CONFIG.isDebug:
|
||||
@@ -902,13 +907,13 @@ class GuiMainMenu(QMenuBar):
|
||||
# Tools > Writing Statistics
|
||||
self.aWritingStats = self.toolsMenu.addAction(self.tr("Writing Statistics"))
|
||||
self.aWritingStats.setShortcut("F6")
|
||||
self.aWritingStats.triggered.connect(lambda: self.mainGui.showWritingStatsDialog())
|
||||
self.aWritingStats.triggered.connect(self.mainGui.showWritingStatsDialog)
|
||||
|
||||
# Tools > Preferences
|
||||
self.aPreferences = self.toolsMenu.addAction(self.tr("Preferences"))
|
||||
self.aPreferences.setShortcut("Ctrl+,")
|
||||
self.aPreferences.setMenuRole(QAction.PreferencesRole)
|
||||
self.aPreferences.triggered.connect(lambda: self.mainGui.showPreferencesDialog())
|
||||
self.aPreferences.triggered.connect(self.mainGui.showPreferencesDialog)
|
||||
|
||||
return
|
||||
|
||||
@@ -920,12 +925,12 @@ class GuiMainMenu(QMenuBar):
|
||||
# Help > About
|
||||
self.aAboutNW = self.helpMenu.addAction(self.tr("About novelWriter"))
|
||||
self.aAboutNW.setMenuRole(QAction.AboutRole)
|
||||
self.aAboutNW.triggered.connect(lambda: self.mainGui.showAboutNWDialog())
|
||||
self.aAboutNW.triggered.connect(self.mainGui.showAboutNWDialog)
|
||||
|
||||
# Help > About Qt5
|
||||
self.aAboutQt = self.helpMenu.addAction(self.tr("About Qt5"))
|
||||
self.aAboutQt.setMenuRole(QAction.AboutQtRole)
|
||||
self.aAboutQt.triggered.connect(lambda: self.mainGui.showAboutQtDialog())
|
||||
self.aAboutQt.triggered.connect(self.mainGui.showAboutQtDialog)
|
||||
|
||||
# Help > Separator
|
||||
self.helpMenu.addSeparator()
|
||||
@@ -961,7 +966,7 @@ class GuiMainMenu(QMenuBar):
|
||||
|
||||
# Document > Check for Updates
|
||||
self.aUpdates = self.helpMenu.addAction(self.tr("Check for New Release"))
|
||||
self.aUpdates.triggered.connect(lambda: self.mainGui.showUpdatesDialog())
|
||||
self.aUpdates.triggered.connect(self.mainGui.showUpdatesDialog)
|
||||
|
||||
return
|
||||
|
||||
|
||||