Compare commits

...

63 Commits

Author SHA1 Message Date
Veronica Berglyd Olsen
b6282772ae Release 2.2 (#1641) 2023-12-17 17:00:05 +01:00
Veronica Berglyd Olsen
bfecebc047 Update release notes 2023-12-17 16:56:43 +01:00
Veronica Berglyd Olsen
186737a170 Update file history info 2023-12-13 22:07:53 +01:00
Veronica Berglyd Olsen
f32383ea99 Update changelog 2023-12-13 21:25:26 +01:00
Veronica Berglyd Olsen
4097949c44 Update translations 2023-12-13 21:24:50 +01:00
Veronica Berglyd Olsen
10feafeab4 Bump version for release 2.2 2023-12-10 22:21:25 +01:00
Veronica Berglyd Olsen
399a867836 Update docs with 2.2 features (#1640) 2023-12-10 22:18:03 +01:00
Veronica Berglyd Olsen
6f3702f2df Update docs organising section 2023-12-10 22:12:59 +01:00
Veronica Berglyd Olsen
7dc9e65f68 Update docs using novelWriter section 2023-12-10 21:53:04 +01:00
Veronica Berglyd Olsen
1740bbedbd Update docs introduction section 2023-12-10 18:39:29 +01:00
Veronica Berglyd Olsen
8585334a51 Update buttons in viewer and editor (#1638) 2023-12-04 09:12:30 +01:00
Veronica Berglyd Olsen
553b76cafc Update en_US and nb_NO translations 2023-12-03 18:58:01 +01:00
Veronica Berglyd Olsen
c04e1035a7 Merge branch 'main' into gui_fixes 2023-12-03 18:48:26 +01:00
Veronica Berglyd Olsen
dfbb61a37e Add viewer panel importance info (#1639) 2023-12-03 18:47:09 +01:00
Veronica Berglyd Olsen
cb485c5c86 Revert deleting the view button in viewer panel, but keep the double click change 2023-12-03 18:37:47 +01:00
Veronica Berglyd Olsen
62a94850a6 Add tooltips to all entries in the viewer panel and update translation file 2023-12-03 18:24:55 +01:00
Veronica Berglyd Olsen
99c00f8b93 Update tests 2023-12-03 18:20:23 +01:00
Veronica Berglyd Olsen
cbb000a18f Drop the view column in the viewer panel 2023-12-03 18:18:00 +01:00
Veronica Berglyd Olsen
847d8ab726 Add importance column to document viewer panel (#1620) 2023-12-03 18:15:16 +01:00
Veronica Berglyd Olsen
9f1e2d322e Re-order formats menu to be consistent with toolbar 2023-12-03 17:55:12 +01:00
Veronica Berglyd Olsen
b7c657141f Update translations 2023-12-03 17:43:28 +01:00
Veronica Berglyd Olsen
023f6bed01 Update base translation file 2023-12-03 17:34:08 +01:00
Veronica Berglyd Olsen
fff6ba98bc Rename emph and strong to italic and bold for consistency and add tooltips to editor toolbar 2023-12-03 17:33:15 +01:00
Veronica Berglyd Olsen
776eedc5f2 Drop the markdown/shortcode toggle feature from editor toolbar and update icons (#1636, #1637) 2023-12-03 16:56:36 +01:00
Veronica Berglyd Olsen
f2eaaa09b6 Turn viewer footer button and label into text buttons (#1628) 2023-12-03 16:10:09 +01:00
Veronica Berglyd Olsen
60b0a4c901 Update extensions (#1634) 2023-11-29 22:35:02 +01:00
Veronica Berglyd Olsen
a6d346fcb6 Clean up and fix minor issues with GUI extensions 2023-11-29 22:21:56 +01:00
Veronica Berglyd Olsen
78a75d5719 Fix some minor issues (#1632) 2023-11-29 21:59:36 +01:00
Veronica Berglyd Olsen
f59317c2b5 Remove alternative apostrophe from auto select logic because it is already a letter 2023-11-29 21:55:07 +01:00
Veronica Berglyd Olsen
b203bcdcff Include apostrophes when auto selecting in editor (#1624) 2023-11-29 21:48:09 +01:00
Veronica Berglyd Olsen
a31f42b04c Clean up novel view and improve coverage 2023-11-29 21:24:07 +01:00
Veronica Berglyd Olsen
ce666d9d7a Scroll novel view when looping through documents (#1555) 2023-11-29 20:55:05 +01:00
Veronica Berglyd Olsen
ef93b41240 Clean up alert boxes and update event filters (#1631) 2023-11-29 16:12:08 +01:00
Veronica Berglyd Olsen
1118f01c91 Combine all event filters in one module, and apply the status tip filter to the sidebar as well 2023-11-29 16:05:58 +01:00
Veronica Berglyd Olsen
b526315084 Clean up some redundant code and fix annotations 2023-11-29 16:05:14 +01:00
Veronica Berglyd Olsen
1d1dae0c7e Remove caching of the alert object in the shared instance 2023-11-29 16:03:48 +01:00
Veronica Berglyd Olsen
1edfcfcd91 Add debug comment 2023-11-29 08:10:16 +01:00
Veronica Berglyd Olsen
82e9fb0c44 Fix minor optimisation issue 2023-11-29 08:06:56 +01:00
Veronica Berglyd Olsen
1b8d424b27 Filter menu status tips (#1630) 2023-11-29 00:05:06 +01:00
Veronica Berglyd Olsen
4ab2b04e6b Add an event filter to remove status tip updates 2023-11-28 23:57:41 +01:00
Veronica Berglyd Olsen
d291995c0e Add deleteLater to temporary widgets (#1629) 2023-11-28 23:27:36 +01:00
Veronica Berglyd Olsen
54510951de Rename lipsum button 2023-11-28 23:21:35 +01:00
Veronica Berglyd Olsen
52d1d87985 Add the new flag to the command line help 2023-11-28 23:20:49 +01:00
Veronica Berglyd Olsen
62847e55f0 Rewrite how lipsum text is inserted 2023-11-28 23:14:23 +01:00
Veronica Berglyd Olsen
bf6cefa840 Update dialog handling of all dialogs 2023-11-28 22:12:30 +01:00
Veronica Berglyd Olsen
4e1fa01562 Add widget diff info to help debug memory issues 2023-11-28 17:29:34 +01:00
Veronica Berglyd Olsen
83c9fb96e9 Add memory usage debug info for status bar 2023-11-28 16:44:01 +01:00
Veronica Berglyd Olsen
ff7f27ff97 Add closeEvents to dialogs and set the deleteLater command 2023-11-28 16:29:21 +01:00
Veronica Berglyd Olsen
50a9b5b5e2 Fix some annotations and add deleteLater to non-modal dialogs 2023-11-27 21:43:13 +01:00
Veronica Berglyd Olsen
4fa20273f7 Clean up dialogs 2023-11-27 17:10:29 +01:00
Veronica Berglyd Olsen
93b36406f1 Make sure context menus are deleted after use 2023-11-27 16:30:21 +01:00
Veronica Berglyd Olsen
a0e6f9cf82 Fix various bugs and minor issues (#1626) 2023-11-27 16:17:01 +01:00
Veronica Berglyd Olsen
1f9b6d7624 Fix icons not updating on theme switch in viewer panel 2023-11-27 16:08:34 +01:00
Veronica Berglyd Olsen
ccc444f355 Fix section sizes for viewer panel (#1627) 2023-11-27 16:08:00 +01:00
Veronica Berglyd Olsen
ba0198407f Change panel label back to "References" 2023-11-27 07:42:25 +01:00
Veronica Berglyd Olsen
918b077252 Drop the space in front of Synopsis and Short comments inserts 2023-11-26 22:12:23 +01:00
Veronica Berglyd Olsen
b348ba6aff Update Main GUI launch test 2023-11-26 22:02:01 +01:00
Veronica Berglyd Olsen
e521a30612 Remove warning for alpha releases 2023-11-26 21:43:32 +01:00
Veronica Berglyd Olsen
2e2ab5ad6f Update project load dialog 2023-11-26 21:40:51 +01:00
Veronica Berglyd Olsen
47781f981f Fix wrong keyboard shortcut for Short comment insert 2023-11-26 21:40:05 +01:00
Veronica Berglyd Olsen
0676056968 Update translations (#1625) 2023-11-26 20:58:25 +01:00
Veronica Berglyd Olsen
65562ae790 Update base translation, US English, Norwegian, and Japanese 2023-11-26 16:20:14 +01:00
Veronica Berglyd Olsen
623f74019f Fix wrong PR mentioned in changelog 2023-11-26 15:09:43 +01:00
136 changed files with 9882 additions and 8393 deletions

View File

@@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 KiB

After

Width:  |  Height:  |  Size: 542 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 335 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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`

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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.

View File

@@ -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"

View File

@@ -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.

View File

@@ -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:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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__)

View File

@@ -1,5 +1,6 @@
{
"Synopsis": "Synopsis",
"Short Description": "Short Description",
"Comment": "Comment",
"Notes": "Notes",
"Tag": "Tag",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -1,6 +1,7 @@
{
"Synopsis": "あらすじ",
"Comment": "コメント",
"Short Description": "短い説明",
"Comment": "コメント ",
"Notes": "ノート",
"Tag": "タグ",
"Point of View": "視点",

View File

@@ -1,5 +1,6 @@
{
"Synopsis": "Sammendrag",
"Short Description": "Kort beskrivelse",
"Comment": "Kommentar",
"Notes": "Notat",
"Tag": "Knagg",

View File

@@ -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

View 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

View File

@@ -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

View 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="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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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="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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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-opacity=".78039" stroke-opacity=".78039" stroke-width=".54782"/>
</svg>

After

Width:  |  Height:  |  Size: 994 B

View File

@@ -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

View 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="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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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="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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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
# =============================================================================================== #

View File

@@ -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")

View File

@@ -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

View File

@@ -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 = []

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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
##

View File

@@ -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

View File

@@ -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

View File

@@ -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
##

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More