Merge branch 'main' into unicode_fix
This commit is contained in:
+22
-8
@@ -55,19 +55,33 @@ The following libraries are dependencies of novelWriter:
|
||||
* **Enchant** by Dom Lachowicz
|
||||
* **PyEnchant** by Dimitri Merejkowsky
|
||||
|
||||
## Assets
|
||||
## Icon Themes
|
||||
|
||||
Some of the assets bundled with novelWriter were adapted from the following sources:
|
||||
The following icon themes are bundles with novelWriter:
|
||||
|
||||
* **Material Symbols** icons by Google Inc (Apache 2.0)
|
||||
* **Remix** icons by RemixIcon (Apache 2.0)
|
||||
* **Font Awesome** icons by Fonticons Inc (CC BY 4.0)
|
||||
* **Tomorrow** syntax themes by Chris Kempson (MIT License)
|
||||
* **Owl** syntax themes by Sarah Drasner (MIT License)
|
||||
* **Solarized** themes by Ethan Schoonover (MIT License)
|
||||
* **Cyberpunk Night** theme by Anders Lemvigh (CC BY-SA 4.0)
|
||||
* **Dracula** theme by Zeno Rocha (MIT License)
|
||||
* **Snazzy Light** theme by Florian Reuschel (MIT License)
|
||||
|
||||
## Colour Themes
|
||||
|
||||
Some colour themes included with novelWriter were adapted from the following sources:
|
||||
|
||||
* **Dracula** theme by Zeno Rocha
|
||||
* **Espresso** theme by Sainnhe Park and Antoine Cotten
|
||||
* **Noctis** themes by Liviu Schera, and contributors
|
||||
* **Owl** themes by Sarah Drasner
|
||||
* **Primer** themes by GitHub Inc and Myian
|
||||
* **Snazzy Light** theme by Florian Reuschel
|
||||
* **Solarized** themes by Ethan Schoonover
|
||||
* **Tango** themes by the Tango Desktop Project
|
||||
* **Tomorrow** themes by Chris Kempson
|
||||
|
||||
Other themes were created for novelWriter:
|
||||
|
||||
* **Blue Streak** themes by Veronica Berglyd Olsen
|
||||
* **Cyberpunk Night** theme by Anders Lemvigh
|
||||
* **LCARS** theme by Veronica Berglyd Olsen
|
||||
|
||||
## Fonts
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ Text Formatting Shortcuts
|
||||
":kbd:`Ctrl+B`", "Format selected text, or word under cursor, with bold"
|
||||
":kbd:`Ctrl+D`", "Format selected text, or word under cursor, with strike through"
|
||||
":kbd:`Ctrl+I`", "Format selected text, or word under cursor, with italic"
|
||||
":kbd:`Ctrl+M`", "Highlight selected text, or word under cursor"
|
||||
":kbd:`Ctrl+Shift+/`", "Remove format for block or selected text"
|
||||
":kbd:`Ctrl+Shift+D`", "Toggle ignored text format for block or selected text"
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ storage for robustness.
|
||||
|
||||
more/counting
|
||||
more/typography
|
||||
more/dictionaries
|
||||
more/customise
|
||||
more/handling_errors
|
||||
more/project_format
|
||||
|
||||
+196
-170
@@ -1,94 +1,35 @@
|
||||
.. _docs_more_custom:
|
||||
|
||||
**************
|
||||
Customisations
|
||||
**************
|
||||
*************
|
||||
Custom Themes
|
||||
*************
|
||||
|
||||
.. _Enchant: https://rrthomas.github.io/enchant/
|
||||
.. _Free Desktop: https://cgit.freedesktop.org/libreoffice/dictionaries/tree/
|
||||
|
||||
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.
|
||||
|
||||
|
||||
.. _docs_more_custom_dict:
|
||||
|
||||
Spell Check Dictionaries
|
||||
========================
|
||||
|
||||
novelWriter uses Enchant_ as the spell checking tool. Depending on your operating system, it may or
|
||||
may not load all installed spell check dictionaries automatically.
|
||||
|
||||
|
||||
Linux and MacOS
|
||||
---------------
|
||||
|
||||
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.
|
||||
|
||||
**Install Tool**
|
||||
|
||||
A small tool to assist with this can be found under **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 and should thus work for any application
|
||||
that uses Enchant for spell checking.
|
||||
|
||||
**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
|
||||
get HTML files, not dictionaries!
|
||||
|
||||
In order to download the actual dictionary files, right-click the "plain" label at the end of
|
||||
each line and download that.
|
||||
There are a few ways you can customise novelWriter yourself. Currently, you can relatively easily
|
||||
add new GUI themes. You can also add new icon themes, although this is not as straightforward.
|
||||
|
||||
|
||||
.. _docs_more_custom_theme:
|
||||
|
||||
Syntax and GUI Themes
|
||||
=====================
|
||||
Colour Themes
|
||||
=============
|
||||
|
||||
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.
|
||||
Adding your own colour 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.
|
||||
|
||||
In order to make your own versions, first copy one of the existing files to your local computer and
|
||||
modify it as you like.
|
||||
|
||||
* The existing syntax themes are stored in
|
||||
`novelwriter/assets/syntax <https://github.com/vkbo/novelWriter/tree/main/novelwriter/assets/syntax>`_.
|
||||
* The existing GUI themes are stored in
|
||||
`novelwriter/assets/themes <https://github.com/vkbo/novelWriter/tree/main/novelwriter/assets/themes>`_.
|
||||
* The existing icon themes are stored in
|
||||
`novelwriter/assets/icons <https://github.com/vkbo/novelWriter/tree/main/novelwriter/assets/icons>`_.
|
||||
The existing colour themes are stored in
|
||||
`novelwriter/assets/themes <https://github.com/vkbo/novelWriter/tree/main/novelwriter/assets/themes>`_.
|
||||
|
||||
Remember to also change the name of your theme by modifying the ``name`` setting at the top of the
|
||||
file, otherwise you may not be able to distinguish them in **Preferences**.
|
||||
|
||||
For novelWriter to be able to locate the custom theme files, you must copy them to the
|
||||
:ref:`docs_technical_locations_data` location in your home or user area. There should be a folder there named
|
||||
``syntax`` for syntax themes, just ``themes`` for GUI themes, and ``icons`` for icon themes. These
|
||||
folders are created the first time you start novelWriter.
|
||||
:ref:`docs_technical_locations_data` location in your home or user area. There should be a folder
|
||||
there named ``themes`` for colour themes. These folders are created the first time you start
|
||||
novelWriter.
|
||||
|
||||
Once the files are copied there, they should show up in **Preferences** with the label you
|
||||
set as ``name`` inside the file.
|
||||
@@ -99,71 +40,130 @@ set as ``name`` inside the file.
|
||||
files up to date.
|
||||
|
||||
|
||||
Custom GUI and Icons Theme
|
||||
--------------------------
|
||||
The Theme File Format
|
||||
---------------------
|
||||
|
||||
A GUI theme ``.conf`` file consists of the following settings:
|
||||
A colour theme ``.conf`` file consists of the following settings:
|
||||
|
||||
.. code-block:: cfg
|
||||
:caption: The theme file for the "Default Light Theme"
|
||||
|
||||
[Main]
|
||||
name = My Custom Theme
|
||||
description = A description of my custom theme
|
||||
author = Jane Doe
|
||||
credit = John Doe
|
||||
url = https://example.com
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
name = Default Light Theme
|
||||
mode = light
|
||||
description = The novelWriter standard light theme
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Icons]
|
||||
default = 100, 100, 100
|
||||
faded = 100, 100, 100
|
||||
red = 255, 0, 0
|
||||
orange = 255, 128, 0
|
||||
yellow = 255, 255, 0
|
||||
green = 0, 255, 0
|
||||
aqua = 0, 255, 255
|
||||
blue = 0, 0, 255
|
||||
purple = 255, 0, 255
|
||||
[Base]
|
||||
base = #fcfcfc
|
||||
default = #303030
|
||||
faded = #6c6c6c
|
||||
red = #a62a2d
|
||||
orange = #b36829
|
||||
yellow = #a39c34
|
||||
green = #296629
|
||||
cyan = #269999
|
||||
blue = #3a70a6
|
||||
purple = #b35ab3
|
||||
|
||||
[Project]
|
||||
root = 0, 255, 255
|
||||
folder = 255, 255, 0
|
||||
file = 100, 100, 100
|
||||
title = 0, 255, 0
|
||||
chapter = 255, 0, 0
|
||||
scene = 0, 0, 255
|
||||
note = 255, 255, 0
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 100, 100, 100
|
||||
windowtext = 100, 100, 100
|
||||
base = 100, 100, 100
|
||||
alternatebase = 100, 100, 100
|
||||
text = 100, 100, 100
|
||||
tooltipbase = 100, 100, 100
|
||||
tooltiptext = 100, 100, 100
|
||||
button = 100, 100, 100
|
||||
buttontext = 100, 100, 100
|
||||
brighttext = 100, 100, 100
|
||||
highlight = 100, 100, 100
|
||||
highlightedtext = 100, 100, 100
|
||||
link = 100, 100, 100
|
||||
linkvisited = 100, 100, 100
|
||||
window = base:D105
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #e0e0e0
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #efefef
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #3087c6
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #3087c6
|
||||
|
||||
[GUI]
|
||||
helptext = 0, 0, 0
|
||||
fadedtext = 128, 128, 128
|
||||
errortext = 255, 0, 0
|
||||
helptext = #5c5c5c
|
||||
fadedtext = #6c6c6c
|
||||
errortext = red
|
||||
|
||||
In the Main section you must at least define the ``name`` settings.
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = green
|
||||
headertag = green:L135
|
||||
emphasis = orange
|
||||
dialog = blue
|
||||
altdialog = blue
|
||||
note = yellow:D125
|
||||
hidden = faded
|
||||
shortcode = green
|
||||
keyword = red
|
||||
tag = green
|
||||
value = blue
|
||||
optional = green
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = green
|
||||
modifier = green
|
||||
texthighlight = yellow:72
|
||||
|
||||
The Palette values correspond to the Qt enum values for ``QPalette::ColorRole``, see the
|
||||
`Qt documentation <https://doc.qt.io/qt-6/qpalette.html#ColorRole-enum>`_ for more details. The
|
||||
colour values are RGB numbers on the format ``r, g, b`` where each is an integer from ``0`` to
|
||||
``255``. Omitted values are not loaded and will use default values. If the ``helptext`` colour is
|
||||
not defined, it is computed as a colour between the ``window`` and ``windowtext`` colour.
|
||||
Additional shades of some of the colours are also computed. These are mainly used for 3D effects.
|
||||
|
||||
Theme Sections
|
||||
--------------
|
||||
|
||||
.. _ColorRole: https://doc.qt.io/qt-6/qpalette.html#ColorRole-enum
|
||||
|
||||
The theme file is made up of different sections depending on what part of novelWriter the theme
|
||||
affects.
|
||||
|
||||
.. csv-table:: Theme Sections Overview
|
||||
:header: "Section", "Description"
|
||||
:class: "tight-table"
|
||||
|
||||
"``[Main]``", "Meta data about the theme, You must at least set ``name``, ``mode`` and ``author``, and ``mode`` must be either ``light`` or ``dark``."
|
||||
"``[Base]``", "The base colours of the theme. These are also selectable colours in various places inside the app, like for icon colours in **Preferences**."
|
||||
"``[Project]``", "The colours used for icons and markers for the different project item types."
|
||||
"``[Palette]``", "The colours used for styling the user interface. The values correspond to the ColorRole_ values in the Qt library."
|
||||
"``[GUI]``", "The colours used for styling additional elements of the user interface."
|
||||
"``[Syntax]``", "The colours used for syntax highlighting in documents."
|
||||
|
||||
|
||||
Colour Value Formats
|
||||
--------------------
|
||||
|
||||
There are several ways to enter colour values:
|
||||
|
||||
.. csv-table:: Colour Formats
|
||||
:header: "Syntax", "Description"
|
||||
:widths: 15, 85
|
||||
:class: "tight-table"
|
||||
|
||||
"``#RRGGBB``", "A CSS style hexadecimal values, like ``#ff0000`` for red."
|
||||
"``#RRGGBBAA``", "A CSS style hexadecimal values with transparency, like ``#ff00007f`` for half-transparent red."
|
||||
"``name``", "A name referring to one of the colours already specified under the ``[Base]`` section, like ``red``. Note that you should not use named colours in the ``[Base]`` section itself as that may have unintended results."
|
||||
"``name:255``", "A name referring to one of the colours already specified under the ``[Base]`` section, with a transparency value added. The value must be in the range ``0`` to ``255``, like ``red:127`` for half-transparent red."
|
||||
"``name:L100``", "A name referring to one of the colours already specified under the ``[Base]`` section, where the L-number is a percentage value that makes it lighter. The value must be greater than ``0``. ``L100`` means no change."
|
||||
"``name:D100``", "A name referring to one of the colours already specified under the ``[Base]`` section, where the D-number is a percentage value that makes it darker. The value must be greater than ``0``. ``D100`` means no change."
|
||||
"``r, g, b``", "A set of red, green and blue numbers in the range ``0`` to ``255``, like ``255, 0, 0`` for red."
|
||||
"``r, g, b, a``", "A set of red, green, blue and alpha numbers in the range ``0`` to ``255``, like ``255, 0, 0, 127`` for half-transparent red."
|
||||
|
||||
.. versionadded:: 2.5
|
||||
The ``fadedtext`` and ``errortext`` theme colour entries were added.
|
||||
@@ -172,60 +172,86 @@ Additional shades of some of the colours are also computed. These are mainly use
|
||||
The ``icontheme`` setting was dropped as the icon theme is now its own setting.
|
||||
The ``[Icons]`` and ``[Project]`` sections were added, and the ``status*`` settings removed.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
The ``[Syntax]`` section was moved into the main theme file. Previously, these settings were in
|
||||
their own file. The ``[Icons]`` section was renamed to ``[Base]``. Added the ``line`` setting.
|
||||
Dropped the ``license`` and ``licenseurl`` settings. The ``description`` and ``author`` fields
|
||||
are now required if the theme is included in the app, but not for user themes.
|
||||
|
||||
Custom Syntax Theme
|
||||
-------------------
|
||||
|
||||
A syntax theme ``.conf`` file consists of the following settings:
|
||||
Icon Themes
|
||||
===========
|
||||
|
||||
Icon themes are *not* straightforward to add, but if you want to make the effort, this section
|
||||
describes how to do it.
|
||||
|
||||
The existing icon themes are stored in
|
||||
`novelwriter/assets/icons <https://github.com/vkbo/novelWriter/tree/main/novelwriter/assets/icons>`_.
|
||||
|
||||
As with colour themes, remember to change the name of your theme by modifying the ``name`` setting
|
||||
at the top of the file, otherwise you may not be able to distinguish them in **Preferences**.
|
||||
|
||||
For novelWriter to be able to locate the custom theme files, you must copy them to the
|
||||
:ref:`docs_technical_locations_data` location in your home or user area. There should be a folder
|
||||
there ``icons`` for icon themes. These folders are created the first time you start novelWriter.
|
||||
|
||||
|
||||
The Icons File Format
|
||||
---------------------
|
||||
|
||||
Icon themes are kept in files with the ``.icons`` file extension. The file format is a custom
|
||||
format with entries on the form ``section:key = value``.
|
||||
|
||||
.. code-block:: cfg
|
||||
:caption: The icons file for "Material Symbols - Rounded Medium" (truncated)
|
||||
|
||||
[Main]
|
||||
name = My Syntax Theme
|
||||
author = Jane Doe
|
||||
credit = John Doe
|
||||
url = https://example.com
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
# Meta
|
||||
meta:name = Material Symbols - Rounded Medium
|
||||
meta:author = Google Inc
|
||||
meta:license = Apache 2.0
|
||||
|
||||
[Syntax]
|
||||
background = 255, 255, 255
|
||||
text = 0, 0, 0
|
||||
link = 0, 0, 0
|
||||
headertext = 0, 0, 0
|
||||
headertag = 0, 0, 0
|
||||
emphasis = 0, 0, 0
|
||||
dialog = 0, 0, 0
|
||||
altdialog = 0, 0, 0
|
||||
note = 0, 0, 0
|
||||
hidden = 0, 0, 0
|
||||
shortcode = 0, 0, 0
|
||||
keyword = 0, 0, 0
|
||||
tag = 0, 0, 0
|
||||
value = 0, 0, 0
|
||||
optional = 0, 0, 0
|
||||
spellcheckline = 0, 0, 0
|
||||
errorline = 0, 0, 0
|
||||
replacetag = 0, 0, 0
|
||||
modifier = 0, 0, 0
|
||||
texthighlight = 255, 255, 255, 128
|
||||
# Icons
|
||||
icon:alert_error = <svg ...>
|
||||
icon:alert_info = <svg ...>
|
||||
icon:alert_question = <svg ...>
|
||||
icon:alert_warn = <svg ...>
|
||||
icon:cls_archive = <svg ...>
|
||||
icon:cls_character = <svg ...>
|
||||
icon:cls_custom = <svg ...>
|
||||
icon:cls_entity = <svg ...>
|
||||
icon:cls_none = <svg ...>
|
||||
icon:cls_novel = <svg ...>
|
||||
icon:cls_object = <svg ...>
|
||||
icon:cls_plot = <svg ...>
|
||||
icon:cls_template = <svg ...>
|
||||
icon:cls_timeline = <svg ...>
|
||||
icon:cls_trash = <svg ...>
|
||||
icon:cls_world = <svg ...>
|
||||
|
||||
In the Main section, you must define at least the ``name`` setting. The Syntax colour values are
|
||||
RGB(A) numbers of the format ``r, g, b, a`` where each is an integer from ``0`` to ``255``. The
|
||||
fourth value is the alpha channel, which can be omitted.
|
||||
The icon keys are associated with icon placement locations inside novelWriter, and the template for
|
||||
them is defined in the script that generates the default icon themes.
|
||||
|
||||
Omitted syntax colours default to black, except ``background`` which defaults to white, and
|
||||
``texthighlight`` which defaults to white with half transparency.
|
||||
The script can be found under
|
||||
`utils/icon_themes.py <https://github.com/vkbo/novelWriter/blob/main/utils/icon_themes.py>`__
|
||||
in the source code.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
The ``shortcode`` syntax colour entry was added.
|
||||
This file includes all the code needed to generate the themes that are included in novelWriter. The
|
||||
icon keys are mapped to icon keys from the specific themes in JSON files in the ``icon_themes``
|
||||
folder next to the script. This is the recommended way to generate these themes. Doing it manually
|
||||
is not advisable.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
The ``optional`` syntax colour entry was added.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
The ``texthighlight`` syntax colour entry was added.
|
||||
Icon Value Format
|
||||
-----------------
|
||||
|
||||
.. versionadded:: 2.5
|
||||
The ``dialog``, ``altdialog``, ``note`` and ``tag`` syntax colour entries were added.
|
||||
``straightquotes``, ``doublequotes`` and ``singlequotes`` were removed.
|
||||
As can be seen from the example, an icon is defined in the ``icon`` section with a key and an
|
||||
in-line SVG XML block. The XML must fit on one line and obey the following rules:
|
||||
|
||||
#. It must be single colour, that is, the fill colour attribute must be able to colourise the
|
||||
entire icon.
|
||||
#. The fill colour attribute *must* be defined and must be set to: ``fill="#000000"``. This value
|
||||
is replaced by the relevant theme colour when the icon is processed in novelWriter.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
The icon theme files were added. Previously, icons were stored as individual SVG files with a
|
||||
config file mapping the file names to the internal icon keys.
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
.. _docs_more_dictionaries:
|
||||
|
||||
************************
|
||||
Spell Check Dictionaries
|
||||
************************
|
||||
|
||||
.. _Enchant: https://rrthomas.github.io/enchant/
|
||||
.. _Free Desktop: https://cgit.freedesktop.org/libreoffice/dictionaries/tree/
|
||||
|
||||
Spell checking is provided by the Enchant_ library. Depending on your operating system, it may or
|
||||
may not load all installed spell check dictionaries automatically.
|
||||
|
||||
|
||||
Linux and MacOS
|
||||
===============
|
||||
|
||||
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.
|
||||
|
||||
**Install Tool**
|
||||
|
||||
A small tool to assist with this can be found under **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 and should thus work for any application
|
||||
that uses Enchant for spell checking.
|
||||
|
||||
**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
|
||||
get HTML files, not dictionaries!
|
||||
|
||||
In order to download the actual dictionary files, right-click the "plain" label at the end of
|
||||
each line and download that.
|
||||
@@ -55,7 +55,7 @@ edited from the **Project Word List** tool available from the **Tools** menu.
|
||||
.. note::
|
||||
|
||||
Generally, spell checking dictionaries are collected from your operating system, but on Windows
|
||||
they are not. See :ref:`docs_more_custom_dict` for how to add spell checking dictionaries on
|
||||
they are not. See :ref:`docs_more_dictionaries` for how to add spell checking dictionaries on
|
||||
Windows.
|
||||
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ __license__ = "GPLv3"
|
||||
__author__ = "Veronica Berglyd Olsen"
|
||||
__maintainer__ = "Veronica Berglyd Olsen"
|
||||
__email__ = "code@vkbo.net"
|
||||
__version__ = "2.7.2"
|
||||
__hexversion__ = "0x020702f0"
|
||||
__date__ = "2025-06-24"
|
||||
__version__ = "2.8a1"
|
||||
__hexversion__ = "0x020800a1"
|
||||
__date__ = "2025-06-13"
|
||||
__status__ = "Stable"
|
||||
__domain__ = "novelwriter.io"
|
||||
|
||||
@@ -296,7 +296,8 @@ def _createApp(style: str) -> QApplication:
|
||||
"""Create the app. This is done in a function to make it easier to
|
||||
block app creation during testing.
|
||||
"""
|
||||
app = QApplication([CONFIG.appName, f"-style={style}"])
|
||||
app = QApplication([CONFIG.appName])
|
||||
app.setStyle(style)
|
||||
app.setApplicationName(CONFIG.appName)
|
||||
app.setApplicationVersion(__version__)
|
||||
app.setOrganizationDomain(__domain__)
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#000000" height="128" width="128"><path d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160L0 416c0 53 43 96 96 96l256 0c53 0 96-43 96-96l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 96c0 17.7-14.3 32-32 32L96 448c-17.7 0-32-14.3-32-32l0-256c0-17.7 14.3-32 32-32l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L96 64z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#000000" height="128" width="128"><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" fill="#000000" height="128" width="128"><path d="M160 80c0-26.5 21.5-48 48-48l32 0c26.5 0 48 21.5 48 48l0 352c0 26.5-21.5 48-48 48l-32 0c-26.5 0-48-21.5-48-48l0-352zM0 272c0-26.5 21.5-48 48-48l32 0c26.5 0 48 21.5 48 48l0 160c0 26.5-21.5 48-48 48l-32 0c-26.5 0-48-21.5-48-48L0 272zM368 96l32 0c26.5 0 48 21.5 48 48l0 288c0 26.5-21.5 48-48 48l-32 0c-26.5 0-48-21.5-48-48l0-288c0-26.5 21.5-48 48-48z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#000000" height="128" width="128"><path d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" viewBox="-64 0 512 512" fill="#000000" height="128" width="128"><path d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#000000" height="128" width="128"><path d="M448 256c0-106-86-192-192-192l0 384c106 0 192-86 192-192zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512" fill="#000000" height="128" width="128"><path d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" viewBox="-64 0 512 512" fill="#000000" height="128" width="128"><path d="M0 48V487.7C0 501.1 10.9 512 24.3 512c5 0 9.9-1.5 14-4.4L192 400 345.7 507.6c4.1 2.9 9 4.4 14 4.4c13.4 0 24.3-10.9 24.3-24.3V48c0-26.5-21.5-48-48-48H48C21.5 0 0 21.5 0 48z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" viewBox="32 0 512 512" fill="#000000" height="128" width="128"><path d="M88.7 223.8L0 375.8 0 96C0 60.7 28.7 32 64 32l117.5 0c17 0 33.3 6.7 45.3 18.7l26.5 26.5c12 12 28.3 18.7 45.3 18.7L416 96c35.3 0 64 28.7 64 64l0 32-336 0c-22.8 0-43.8 12.1-55.3 31.8zm27.6 16.1C122.1 230 132.6 224 144 224l400 0c11.5 0 22 6.1 27.7 16.1s5.7 22.2-.1 32.1l-112 192C453.9 474 443.4 480 432 480L32 480c-11.5 0-22-6.1-27.7-16.1s-5.7-22.2 .1-32.1l112-192z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M556.61-113.78v-63.74q0-10.83 4.13-20.31 4.13-9.47 11.83-17.17L781-423q10.7-10.7 23.67-15.54 12.98-4.85 26.24-4.85 14.26 0 27.24 5.35 12.98 5.34 23.68 16.04l37 37q9.69 10.7 15.04 23.67 5.35 12.98 5.35 26.24 0 13.83-4.85 27.03-4.85 13.19-15.54 23.89l-208 208q-7.7 7.69-17.18 11.54-9.48 3.85-20.3 3.85h-63.74q-22.09 0-37.54-15.46-15.46-15.46-15.46-37.54Zm279.96-187.96 31.34-33.35-37-37-32.34 32.35 38 38ZM166.78-140.78q-44.3 0-75.15-30.85-30.85-30.85-30.85-75.15v-466.44q0-44.3 30.85-75.15 30.85-30.85 75.15-30.85h181q21.09 0 40.39 7.98 19.31 7.98 34.26 22.94L480-730.74h313.22q44.3 0 75.15 30.85 30.85 30.85 30.85 75.15v57q0 21.96-17.89 35.22-17.89 13.26-40.85 9.13-9.78-.57-19.35.28-9.57.85-18.78 3.68-21.79 2.82-41.76 12.82-19.98 10-36.59 26.61L507.52-263.52q-14.95 14.95-22.93 33.98-7.98 19.02-7.98 40.67v1.31q0 19.82-13.48 33.3-13.48 13.48-33.3 13.48H166.78Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M375.48-307q-114.09 0-193.55-79.46-79.45-79.45-79.45-193.54 0-114.09 79.45-193.54Q261.39-853 375.48-853q114.09 0 193.54 79.46 79.46 79.45 79.46 193.54 0 45.13-12.87 83.28T601-429.7l219.48 220.05q14.96 15.52 14.96 37.32 0 21.81-15.53 36.77-14.95 14.95-37.04 14.95t-37.04-14.95L526.91-354.48q-29.43 21.74-68.15 34.61Q420.04-307 375.48-307Zm0-106q69.91 0 118.45-48.54 48.55-48.55 48.55-118.46t-48.55-118.46Q445.39-747 375.48-747t-118.46 48.54Q208.48-649.91 208.48-580t48.54 118.46Q305.57-413 375.48-413Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M694.7-140.78q-22.09 0-37.55-15.46-15.45-15.46-15.45-37.54v-201.13q0-22.09 15.45-37.55 15.46-15.45 37.55-15.45h71.52q22.08 0 37.54 15.45 15.46 15.46 15.46 37.55v201.13q0 22.08-15.46 37.54t-37.54 15.46H694.7Zm-250.18 0q-22.09 0-37.54-15.46-15.46-15.46-15.46-37.54v-572.44q0-22.08 15.46-37.54 15.45-15.46 37.54-15.46h70.96q22.09 0 37.54 15.46 15.46 15.46 15.46 37.54v572.44q0 22.08-15.46 37.54-15.45 15.46-37.54 15.46h-70.96Zm-250.74 0q-22.08 0-37.54-15.46t-15.46-37.54v-372.44q0-22.08 15.46-37.54t37.54-15.46h71.52q22.09 0 37.55 15.46 15.45 15.46 15.45 37.54v372.44q0 22.08-15.45 37.54-15.46 15.46-37.55 15.46h-71.52Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-280q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-427q-22.09 0-37.54-15.46Q27-457.91 27-480t15.46-37.54Q57.91-533 80-533h80q22.09 0 37.54 15.46Q213-502.09 213-480t-15.46 37.54Q182.09-427 160-427H80Zm720 0q-22.09 0-37.54-15.46Q747-457.91 747-480t15.46-37.54Q777.91-533 800-533h80q22.09 0 37.54 15.46Q933-502.09 933-480t-15.46 37.54Q902.09-427 880-427h-80ZM480-747q-22.09 0-37.54-15.46Q427-777.91 427-800v-80q0-22.09 15.46-37.54Q457.91-933 480-933t37.54 15.46Q533-902.09 533-880v80q0 22.09-15.46 37.54Q502.09-747 480-747Zm0 720q-22.09 0-37.54-15.46Q427-57.91 427-80v-80q0-22.09 15.46-37.54Q457.91-213 480-213t37.54 15.46Q533-182.09 533-160v80q0 22.09-15.46 37.54Q502.09-27 480-27ZM216.96-668.39l-43-42Q158-725.35 158.5-747.43q.5-22.09 15.46-38.61Q189.35-802 211.43-802q22.09 0 37.61 15.96l42.57 43q14.96 15.39 14.67 36.76-.28 21.37-14.67 37.32-14.96 15.96-36.83 16.03-21.87.06-37.82-15.46Zm494 494.43-42.57-43q-14.96-15.39-14.96-36.97 0-21.59 14.96-37.11 14.96-15.96 36.83-15.46 21.87.5 37.82 15.46l43 41.43q15.96 14.96 15.46 37.04-.5 22.09-15.46 38.61Q770.65-158 748.57-158q-22.09 0-37.61-15.96Zm-42-494.43Q653-683.35 653.5-705.22q.5-21.87 15.46-37.82l41.43-43q14.96-15.96 37.04-15.46 22.09.5 38.61 15.46Q802-770.65 802-748.57q0 22.09-15.96 37.61l-43 42.57q-15.39 14.96-36.76 14.67-21.37-.28-37.32-14.67Zm-495 494.43Q158-189.35 158-211.43q0-22.09 15.96-37.61l43-42.57q15.39-14.96 36.97-14.96 21.59 0 37.11 14.96 15.96 14.96 15.46 36.83-.5 21.87-15.46 37.82l-41.43 43Q234.65-158 212.57-158.5q-22.09-.5-38.61-15.46Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480.57-111.52q-157.22 0-263.14-105.63Q111.52-322.78 111.52-480q0-128.39 77.57-229.89 77.56-101.5 214.17-129.24 18.65-5.39 33.74-1.59 15.09 3.81 25.04 13.37 10.52 9.57 14.13 23.83 3.61 14.26-1 30.35-9.65 23.74-15.6 47.08-5.96 23.35-5.96 48 0 93.96 66.11 159.79 66.11 65.82 160.63 65.82 24.78 0 49.63-5.32 24.85-5.33 46.02-14.55 15.52-4.17 28.72-.85 13.19 3.33 22.19 11.72 9.44 8.39 13.24 22.63 3.81 14.24-1.02 33.33Q814.96-276 713.72-193.76q-101.24 82.24-233.15 82.24Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M479.95-60.78q-86.91 0-163.3-32.91-76.39-32.92-133.22-89.74-56.82-56.83-89.74-133.27-32.91-76.44-32.91-163.35t32.91-163.3q32.92-76.39 89.74-133.22 56.83-56.82 133.27-89.74 76.44-32.91 163.35-32.91t163.3 32.91q76.39 32.92 133.22 89.74 56.82 56.83 89.74 133.27 32.91 76.44 32.91 163.35t-32.91 163.3q-32.92 76.39-89.74 133.22-56.83 56.82-133.27 89.74-76.44 32.91-163.35 32.91Zm46.83-110.13Q641.26-188.17 717.24-274t75.98-206q0-118.63-75.98-204.94-75.98-86.32-190.46-103.58v617.61Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M427-427H233.78q-22.08 0-37.54-15.46-15.46-15.45-15.46-37.54t15.46-37.54Q211.7-533 233.78-533H427v-193.22q0-22.08 15.46-37.54 15.45-15.46 37.54-15.46t37.54 15.46Q533-748.3 533-726.22V-533h193.22q22.08 0 37.54 15.46 15.46 15.45 15.46 37.54t-15.46 37.54Q748.3-427 726.22-427H533v193.22q0 22.08-15.46 37.54-15.45 15.46-37.54 15.46t-37.54-15.46Q427-211.7 427-233.78V-427Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M387-150.39 241.04-86.87q-53 22.65-100.87-8.48-47.87-31.13-47.87-88.83v-461.34q0-44.3 30.85-75.15 30.85-30.85 75.15-30.85h377.39q44.31 0 75.16 30.85 30.85 30.85 30.85 75.15v461.34q0 57.7-47.87 88.83-47.87 31.13-100.88 8.48L387-150.39Zm427.7-27.13q-22.09 0-37.55-15.46-15.45-15.46-15.45-37.54v-601h-441q-22.09 0-37.55-15.46-15.45-15.45-15.45-37.54t15.45-37.55q15.46-15.45 37.55-15.45h441q44.3 0 75.15 30.85 30.85 30.84 30.85 75.15v601q0 22.08-15.46 37.54t-37.54 15.46Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M166.78-140.78q-44.3 0-75.15-30.85-30.85-30.85-30.85-75.15v-466.44q0-44.87 30.85-75.43 30.85-30.57 75.15-30.57h181q21.09 0 40.39 7.98 19.31 7.98 34.26 22.94L480-730.74h366.22q22.08 0 37.54 15.46 15.46 15.45 15.46 37.54t-15.46 37.54q-15.46 15.46-37.54 15.46H340.57q-69.35 0-121.57 43.52-52.22 43.53-52.22 110.31v226.95l70.52-226.82q10.83-33.35 38.55-53.65 27.72-20.31 62.76-20.31h471.91q54 0 85.7 43.52 31.69 43.53 15.61 94.53l-53.92 174.43q-14.78 45.78-46.17 68.63-31.39 22.85-78.31 22.85H166.78Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M560-120v-66q0-8 3-15.5t9-13.5l209-208q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q8 9 12.5 20t4.5 22q0 11-4 22.5T903-300L695-92q-6 6-13.5 9T666-80h-66q-17 0-28.5-11.5T560-120Zm263-184 37-39-37-37-38 38 38 38ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h320q33 0 56.5 23.5T880-640v83q0 18-14.5 29t-33.5 8h-11q-28 0-52.5 10T724-480L503-259q-11 11-17 25.5t-6 30.5v3q0 17-11.5 28.5T440-160H160Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M380-320q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l224 224q11 11 11 28t-11 28q-11 11-28 11t-28-11L532-372q-30 24-69 38t-83 14Zm0-80q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M680-160q-17 0-28.5-11.5T640-200v-200q0-17 11.5-28.5T680-440h80q17 0 28.5 11.5T800-400v200q0 17-11.5 28.5T760-160h-80Zm-240 0q-17 0-28.5-11.5T400-200v-560q0-17 11.5-28.5T440-800h80q17 0 28.5 11.5T560-760v560q0 17-11.5 28.5T520-160h-80Zm-240 0q-17 0-28.5-11.5T160-200v-360q0-17 11.5-28.5T200-600h80q17 0 28.5 11.5T320-560v360q0 17-11.5 28.5T280-160h-80Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-280q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-440q-17 0-28.5-11.5T40-480q0-17 11.5-28.5T80-520h80q17 0 28.5 11.5T200-480q0 17-11.5 28.5T160-440H80Zm720 0q-17 0-28.5-11.5T760-480q0-17 11.5-28.5T800-520h80q17 0 28.5 11.5T920-480q0 17-11.5 28.5T880-440h-80ZM480-760q-17 0-28.5-11.5T440-800v-80q0-17 11.5-28.5T480-920q17 0 28.5 11.5T520-880v80q0 17-11.5 28.5T480-760Zm0 720q-17 0-28.5-11.5T440-80v-80q0-17 11.5-28.5T480-200q17 0 28.5 11.5T520-160v80q0 17-11.5 28.5T480-40ZM226-678l-43-42q-12-11-11.5-28t11.5-29q12-12 29-12t28 12l42 43q11 12 11 28t-11 28q-11 12-27.5 11.5T226-678Zm494 495-42-43q-11-12-11-28.5t11-27.5q11-12 27.5-11.5T734-282l43 42q12 11 11.5 28T777-183q-12 12-29 12t-28-12Zm-42-495q-12-11-11.5-27.5T678-734l42-43q11-12 28-11.5t29 11.5q12 12 12 29t-12 28l-43 42q-12 11-28 11t-28-11ZM183-183q-12-12-12-29t12-28l43-42q12-11 28.5-11t27.5 11q12 11 11.5 27.5T282-226l-42 43q-11 12-28 11.5T183-183Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-120q-151 0-255.5-104.5T120-480q0-138 90-239.5T440-838q13-2 23 3.5t16 14.5q6 9 6.5 21t-7.5 23q-17 26-25.5 55t-8.5 61q0 90 63 153t153 63q31 0 61.5-9t54.5-25q11-7 22.5-6.5T819-479q10 5 15.5 15t3.5 24q-14 138-117.5 229T480-120Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm40-83q119-15 199.5-104.5T800-480q0-123-80.5-212.5T520-797v634Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M440-440H240q-17 0-28.5-11.5T200-480q0-17 11.5-28.5T240-520h200v-200q0-17 11.5-28.5T480-760q17 0 28.5 11.5T520-720v200h200q17 0 28.5 11.5T760-480q0 17-11.5 28.5T720-440H520v200q0 17-11.5 28.5T480-200q-17 0-28.5-11.5T440-240v-200Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M400-160 232-88q-40 17-76-6.5T120-161v-519q0-33 23.5-56.5T200-760h400q33 0 56.5 23.5T680-680v519q0 43-36 66.5T568-88l-168-72Zm400 0q-17 0-28.5-11.5T760-200v-640H280q-17 0-28.5-11.5T240-880q0-17 11.5-28.5T280-920h480q33 0 56.5 23.5T840-840v640q0 17-11.5 28.5T800-160Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H314q-62 0-108 39t-46 99v262l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M569.23-152.31v-42.92q0-6.46 2.23-12.04 2.23-5.58 7.46-10.81l203.62-202.61q5.92-5.16 12.31-7.62 6.38-2.46 12.77-2.46 6.61 0 13.38 2.58 6.77 2.57 11.92 7.73l37 37.77q4.93 5.92 7.5 12.31Q880-364 880-357.62q0 6.39-2.08 12.89-2.07 6.5-8 12.42L667.31-129.69q-5.23 5.23-10.81 7.46-5.58 2.23-12.04 2.23h-42.92q-13.92 0-23.12-9.19-9.19-9.19-9.19-23.12Zm238.39-167.07 37-38.24-37-37.76-38 38 38 38ZM184.62-200q-27.62 0-46.12-18.5Q120-237 120-264.62v-430.76q0-27.62 18.5-46.12Q157-760 184.62-760H357q12.92 0 25.12 5.23 12.19 5.23 20.88 13.92L463.85-680h311.53q27.62 0 46.12 18.5Q840-643 840-615.38v61.46q0 12.61-9.88 20.92-9.89 8.31-22.74 6.85H804.85q-22.62 0-44.43 8.46-21.8 8.46-40.27 24.61L493-266.69q-8.69 8.69-13.92 20.5t-5.23 24.73v.69q0 8.54-6.12 14.65-6.11 6.12-14.65 6.12H184.62Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M381.54-350.77q-95.92 0-162.58-66.65-66.65-66.66-66.65-162.58 0-95.92 66.65-162.58 66.66-66.65 162.58-66.65 95.92 0 162.58 66.65 66.65 66.66 66.65 162.58 0 41.69-14.77 80.69t-38.77 66.69l236.31 236.31q5.61 5.62 6 13.77.38 8.16-6 14.54-6.39 6.38-14.16 6.38-7.76 0-14.15-6.38L528.92-404.31q-30 25.54-69 39.54t-78.38 14Zm0-40q79.61 0 134.42-54.81 54.81-54.8 54.81-134.42 0-79.62-54.81-134.42-54.81-54.81-134.42-54.81-79.62 0-134.42 54.81-54.81 54.8-54.81 134.42 0 79.62 54.81 134.42 54.8 54.81 134.42 54.81Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M672.31-200q-13.73 0-23.02-9.29T640-232.31V-360q0-13.73 9.29-23.02t23.02-9.29h55.38q13.73 0 23.02 9.29T760-360v127.69q0 13.73-9.29 23.02T727.69-200h-55.38Zm-220 0q-13.73 0-23.02-9.29T420-232.31v-495.38q0-13.73 9.29-23.02t23.02-9.29h55.38q13.73 0 23.02 9.29t9.29 23.02v495.38q0 13.73-9.29 23.02T507.69-200h-55.38Zm-220 0q-13.73 0-23.02-9.29T200-232.31v-302.7q0-14.3 9.29-23.49 9.29-9.19 23.02-9.19h55.38q13.73 0 23.02 9.29 9.29 9.28 9.29 23.02v302.7q0 14.3-9.29 23.49-9.29 9.19-23.02 9.19h-55.38Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-320q-66.85 0-113.42-46.58Q320-413.15 320-480t46.58-113.42Q413.15-640 480-640t113.42 46.58Q640-546.85 640-480t-46.58 113.42Q546.85-320 480-320ZM80-460q-8.5 0-14.25-5.76T60-480.03q0-8.51 5.75-14.24T80-500h100q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T180-460H80Zm700 0q-8.5 0-14.25-5.76T760-480.03q0-8.51 5.75-14.24T780-500h100q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T880-460H780ZM479.97-760q-8.51 0-14.24-5.75T460-780v-100q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-880v100q0 8.5-5.76 14.25T479.97-760Zm0 700q-8.51 0-14.24-5.75T460-80v-100q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-180v100q0 8.5-5.76 14.25T479.97-60ZM254.46-678.77l-57.61-55.85q-5.85-5.61-5.73-13.76.11-8.16 5.96-14.77 6.38-6.62 14.15-6.62 7.77 0 14.15 6.62L282-706.31q6.38 6.62 6.38 14.16 0 7.53-6 14.15t-13.65 6.12q-7.65-.5-14.27-6.89Zm480.16 481.92L678-253.69q-6.38-6.62-6.38-14.27 0-7.66 6.38-14.04 5.23-6.62 13.08-6.12 7.84.5 14.46 6.89l57.61 55.85q5.85 5.61 5.73 13.76-.11 8.16-5.96 14.77-6.38 6.62-14.15 6.62-7.77 0-14.15-6.62ZM678-677.62q-6.62-6-6.12-13.65t6.89-14.27l55.85-57.61q5.61-5.85 13.76-5.73 8.16.11 14.77 5.96 6.62 6.38 6.62 14.15 0 7.77-6.62 14.15L706.31-678q-6.62 6.38-14.16 6.38-7.53 0-14.15-6ZM196.85-196.68q-6.62-6.78-6.62-14.55 0-7.77 6.62-14.15L253.69-282q6.62-6.38 14.27-6.38 7.66 0 14.04 6.38 5.85 5.23 5.35 13.08-.5 7.84-6.12 14.46l-55.85 57.61q-6.38 6.62-14.15 6.5-7.77-.11-14.38-6.33Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M482.31-160Q349-160 255.65-253.35 162.31-346.69 162.31-480q0-98.77 56.54-181.42 56.53-82.66 160.38-118.89 12.23-4.31 21.46-2.27 9.23 2.04 15.23 7.96 6 5.93 7.66 15.24 1.65 9.3-2.5 19.53-7.77 19.08-11.27 38.85-3.5 19.77-3.5 41 0 106.92 74.54 181.46Q555.38-404 662.31-404q27.92 0 51.11-5.92 23.2-5.93 39.5-9.62 8.7-1.61 15.96.42 7.27 2.04 11.66 7.04 4.61 5 6.27 12.31 1.65 7.31-1.89 16.69-28.61 98-112.11 160.54Q589.31-160 482.31-160Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480.13-120q-74.67 0-140.41-28.34-65.73-28.34-114.36-76.92-48.63-48.58-76.99-114.26Q120-405.19 120-479.87q0-74.67 28.34-140.41 28.34-65.73 76.92-114.36 48.58-48.63 114.26-76.99Q405.19-840 479.87-840q74.67 0 140.41 28.34 65.73 28.34 114.36 76.92 48.63 48.58 76.99 114.26Q840-554.81 840-480.13q0 74.67-28.34 140.41-28.34 65.73-76.92 114.36-48.58 48.63-114.26 76.99Q554.81-120 480.13-120ZM500-160.69q123.62-8.08 211.81-98.35T800-480q0-130.69-87.42-220.19-87.43-89.5-212.58-99.12v638.62Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M460-460H260q-8.5 0-14.25-5.76T240-480.03q0-8.51 5.75-14.24T260-500h200v-200q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-700v200h200q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T700-460H500v200q0 8.5-5.76 14.25T479.97-240q-8.51 0-14.24-5.75T460-260v-200Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="m420-203.08-149.54 64.31q-32.31 13.92-61.38-5.35Q180-163.38 180-197.92v-457.46q0-27.62 18.5-46.12Q217-720 244.62-720h350.76q27.62 0 46.12 18.5Q660-683 660-655.38v457.46q0 34.54-29.08 53.8-29.07 19.27-61.38 5.35L420-203.08ZM760-220q-8.54 0-14.27-5.73T740-240v-535.39q0-9.23-7.69-16.92-7.69-7.69-16.93-7.69H320q-8.54 0-14.27-5.73T300-820q0-8.54 5.73-14.27T320-840h395.38q27.62 0 46.12 18.5Q780-803 780-775.39V-240q0 8.54-5.73 14.27T760-220Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M180-200q-25.31 0-42.65-17.35Q120-234.69 120-260v-435.38q0-25.31 19.65-44.97Q159.31-760 184.62-760H357q12.92 0 25.12 5.23 12.19 5.23 20.88 13.92L463.85-680h349.23q8.54 0 14.27 5.73t5.73 14.27q0 8.54-5.73 14.27T813.08-640H297.85Q242-640 201-604.08q-41 35.93-41 90.54v248.92q0 8.47 4.23 13.85 4.23 5.39 11.15 9.23l76.7-256.84q6.46-20.62 23.73-33.43 17.27-12.81 38.65-12.81h512.92q32.54 0 52.2 25.97 19.65 25.96 10.19 57.03l-65.85 219.24q-5.69 19.07-21.8 30.73Q786-200 766.15-200H180Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M166.78-246.78v-466.44 466.44Zm0 106q-44.3 0-75.15-30.85-30.85-30.85-30.85-75.15v-466.44q0-44.3 30.85-75.15 30.85-30.85 75.15-30.85h181q21.23 0 40.46 7.98 19.24 7.98 34.19 22.94L480-730.74h313.22q44.3 0 75.15 30.85 30.85 30.85 30.85 75.15v51.17q0 22.09-15.46 37.55-15.46 15.45-37.54 15.45-22.09 0-37.55-15.45-15.45-15.46-15.45-37.55v-51.17H436.26l-88.48-88.48h-181v466.44h256.83q22.09 0 37.54 15.45 15.46 15.46 15.46 37.55 0 22.08-15.46 37.54-15.45 15.46-37.54 15.46H166.78Zm389.83 27v-63.74q0-10.83 4.13-20.31 4.13-9.47 11.83-17.17L781-423q10.7-10.8 23.77-15.59 13.07-4.8 26.14-4.8 14.26 0 27.27 5.35 13.01 5.34 23.65 16.04l37 37q9.59 10.7 14.99 23.77t5.4 26.14q0 13.83-4.85 27.03-4.85 13.19-15.54 23.89l-208 208q-7.62 7.69-17.14 11.54-9.52 3.85-20.34 3.85h-63.74q-22.09 0-37.54-15.46-15.46-15.46-15.46-37.54Zm311.3-221.31-37-37 37 37Zm-240 203h38l118.74-119.74-18-19-19-18-119.74 118.74v38Zm138.74-138.74-19-18 37 37-18-19Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M375.48-307q-114.09 0-193.55-79.46-79.45-79.45-79.45-193.54 0-114.09 79.45-193.54Q261.39-853 375.48-853q114.09 0 193.54 79.46 79.46 79.45 79.46 193.54 0 45.13-12.87 83.28T601-429.7l219.48 220.05q14.96 15.52 14.96 37.32 0 21.81-15.53 36.77-14.95 14.95-37.04 14.95t-37.04-14.95L526.91-354.48q-29.43 21.74-68.15 34.61Q420.04-307 375.48-307Zm0-106q69.91 0 118.45-48.54 48.55-48.55 48.55-118.46t-48.55-118.46Q445.39-747 375.48-747t-118.46 48.54Q208.48-649.91 208.48-580t48.54 118.46Q305.57-413 375.48-413Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M694.7-140.78q-22.09 0-37.55-15.46-15.45-15.46-15.45-37.54v-201.13q0-22.09 15.45-37.55 15.46-15.45 37.55-15.45h71.52q22.08 0 37.54 15.45 15.46 15.46 15.46 37.55v201.13q0 22.08-15.46 37.54t-37.54 15.46H694.7Zm-250.18 0q-22.09 0-37.54-15.46-15.46-15.46-15.46-37.54v-572.44q0-22.08 15.46-37.54 15.45-15.46 37.54-15.46h70.96q22.09 0 37.54 15.46 15.46 15.46 15.46 37.54v572.44q0 22.08-15.46 37.54-15.45 15.46-37.54 15.46h-70.96Zm-250.74 0q-22.08 0-37.54-15.46t-15.46-37.54v-372.44q0-22.08 15.46-37.54t37.54-15.46h71.52q22.09 0 37.55 15.46 15.45 15.46 15.45 37.54v372.44q0 22.08-15.45 37.54-15.46 15.46-37.55 15.46h-71.52Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-386q39.26 0 66.63-27.37Q574-440.74 574-480q0-39.26-27.37-66.63Q519.26-574 480-574q-39.26 0-66.63 27.37Q386-519.26 386-480q0 39.26 27.37 66.63Q440.74-386 480-386Zm0 106q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-427q-22.09 0-37.54-15.46Q27-457.91 27-480t15.46-37.54Q57.91-533 80-533h80q22.09 0 37.54 15.46Q213-502.09 213-480t-15.46 37.54Q182.09-427 160-427H80Zm720 0q-22.09 0-37.54-15.46Q747-457.91 747-480t15.46-37.54Q777.91-533 800-533h80q22.09 0 37.54 15.46Q933-502.09 933-480t-15.46 37.54Q902.09-427 880-427h-80ZM480-747q-22.09 0-37.54-15.46Q427-777.91 427-800v-80q0-22.09 15.46-37.54Q457.91-933 480-933t37.54 15.46Q533-902.09 533-880v80q0 22.09-15.46 37.54Q502.09-747 480-747Zm0 720q-22.09 0-37.54-15.46Q427-57.91 427-80v-80q0-22.09 15.46-37.54Q457.91-213 480-213t37.54 15.46Q533-182.09 533-160v80q0 22.09-15.46 37.54Q502.09-27 480-27ZM216.96-668.39l-43-42Q158-725.35 158.5-747.43q.5-22.09 15.46-38.61Q189.35-802 211.43-802q22.09 0 37.61 15.96l42.57 43q14.96 15.39 14.67 36.76-.28 21.37-14.67 37.32-14.96 15.96-36.83 16.03-21.87.06-37.82-15.46Zm494 494.43-42.57-43q-14.96-15.39-14.96-36.97 0-21.59 14.96-37.11 14.96-15.96 36.83-15.46 21.87.5 37.82 15.46l43 41.43q15.96 14.96 15.46 37.04-.5 22.09-15.46 38.61Q770.65-158 748.57-158q-22.09 0-37.61-15.96Zm-42-494.43Q653-683.35 653.5-705.22q.5-21.87 15.46-37.82l41.43-43q14.96-15.96 37.04-15.46 22.09.5 38.61 15.46Q802-770.65 802-748.57q0 22.09-15.96 37.61l-43 42.57q-15.39 14.96-36.76 14.67-21.37-.28-37.32-14.67Zm-495 494.43Q158-189.35 158-211.43q0-22.09 15.96-37.61l43-42.57q15.39-14.96 36.97-14.96 21.59 0 37.11 14.96 15.96 14.96 15.46 36.83-.5 21.87-15.46 37.82l-41.43 43Q234.65-158 212.57-158.5q-22.09-.5-38.61-15.46ZM480-480Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480.57-111.52q-157.22 0-263.14-105.63Q111.52-322.78 111.52-480q0-128.39 77.57-229.89 77.56-101.5 214.17-129.24 18.65-5.39 33.74-1.59 15.09 3.81 25.33 13.37 10.23 9.57 13.84 23.83 3.61 14.26-1 30.35-9.65 23.74-15.6 47.08-5.96 23.35-5.96 48 0 94.01 66.13 159.81t160.61 65.8q24.78 0 49.63-5.32 24.85-5.33 46.02-14.55 15.52-4.17 28.72-.85 13.19 3.33 21.93 11.72 9.7 8.39 13.5 22.63 3.81 14.24-1.02 33.33Q814.96-276 713.72-193.76q-101.24 82.24-233.15 82.24Zm0-106q73.3 0 133.97-37.2 60.68-37.19 93.24-98.8-14.35 2.74-28.41 4.04-14.07 1.31-27.85.18-120.74-9.61-205.82-93.29-85.09-83.67-95.83-208.93-.57-13.78.46-28.13 1.02-14.35 4.32-28.13-61.04 33.13-98.8 94.09-37.76 60.95-37.76 133.69 0 108.74 76.87 185.61 76.86 76.87 185.61 76.87Zm-17.35-245.13Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M479.95-60.78q-86.91 0-163.3-32.91-76.39-32.92-133.22-89.74-56.82-56.83-89.74-133.27-32.91-76.44-32.91-163.35t32.91-163.3q32.92-76.39 89.74-133.22 56.83-56.82 133.27-89.74 76.44-32.91 163.35-32.91t163.3 32.91q76.39 32.92 133.22 89.74 56.82 56.83 89.74 133.27 32.91 76.44 32.91 163.35t-32.91 163.3q-32.92 76.39-89.74 133.22-56.83 56.82-133.27 89.74-76.44 32.91-163.35 32.91Zm46.83-110.13Q641.26-188.17 717.24-274t75.98-206q0-118.63-75.98-204.94-75.98-86.32-190.46-103.58v617.61Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M427-427H233.78q-22.08 0-37.54-15.46-15.46-15.45-15.46-37.54t15.46-37.54Q211.7-533 233.78-533H427v-193.22q0-22.08 15.46-37.54 15.45-15.46 37.54-15.46t37.54 15.46Q533-748.3 533-726.22V-533h193.22q22.08 0 37.54 15.46 15.46 15.45 15.46 37.54t-15.46 37.54Q748.3-427 726.22-427H533v193.22q0 22.08-15.46 37.54-15.45 15.46-37.54 15.46t-37.54-15.46Q427-211.7 427-233.78V-427Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M387-150.39 241.04-86.87q-53 22.65-100.87-8.48-47.87-31.13-47.87-88.83v-461.34q0-44.3 30.85-75.15 30.85-30.85 75.15-30.85h377.39q44.31 0 75.16 30.85 30.85 30.85 30.85 75.15v461.34q0 57.7-47.87 88.83-47.87 31.13-100.88 8.48L387-150.39Zm0-115.7 188.69 82.61v-462.04H198.3v462.04L387-266.09Zm427.7 88.57q-22.09 0-37.55-15.46-15.45-15.46-15.45-37.54v-601h-441q-22.09 0-37.55-15.46-15.45-15.45-15.45-37.54t15.45-37.55q15.46-15.45 37.55-15.45h441q44.3 0 75.15 30.85 30.85 30.84 30.85 75.15v601q0 22.08-15.46 37.54t-37.54 15.46Zm-427.7-468H198.3h377.39H387Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M166.78-140.78q-44.3 0-75.15-30.85-30.85-30.85-30.85-75.15v-466.44q0-44.87 30.85-75.43 30.85-30.57 75.15-30.57h181q21.23 0 40.46 7.98 19.24 7.98 34.19 22.94L480-730.74h366.22q22.08 0 37.54 15.46 15.46 15.45 15.46 37.54t-15.46 37.54q-15.46 15.46-37.54 15.46H436.26l-88.48-88.48h-181v469.26l70.52-226.82q10.83-33.35 38.55-53.65 27.72-20.31 62.76-20.31h471.91q54 0 85.7 43.52 31.69 43.53 15.61 94.53l-53.92 174.43q-14.78 45.78-46.17 68.63-31.39 22.85-78.31 22.85H166.78Zm112.83-106h471.35l59-191.96H338.61l-59 191.96ZM166.78-470.91v-242.31 242.31Zm112.83 224.13 59-191.96-59 191.96Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M160-240v-480 480Zm0 80q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h320q33 0 56.5 23.5T880-640v80q0 17-11.5 28.5T840-520q-17 0-28.5-11.5T800-560v-80H447l-80-80H160v480h280q17 0 28.5 11.5T480-200q0 17-11.5 28.5T440-160H160Zm400 40v-66q0-8 3-15.5t9-13.5l209-208q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q8 9 12.5 20t4.5 22q0 11-4 22.5T903-300L695-92q-6 6-13.5 9T666-80h-66q-17 0-28.5-11.5T560-120Zm300-223-37-37 37 37ZM620-140h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M380-320q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l224 224q11 11 11 28t-11 28q-11 11-28 11t-28-11L532-372q-30 24-69 38t-83 14Zm0-80q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M680-160q-17 0-28.5-11.5T640-200v-200q0-17 11.5-28.5T680-440h80q17 0 28.5 11.5T800-400v200q0 17-11.5 28.5T760-160h-80Zm-240 0q-17 0-28.5-11.5T400-200v-560q0-17 11.5-28.5T440-800h80q17 0 28.5 11.5T560-760v560q0 17-11.5 28.5T520-160h-80Zm-240 0q-17 0-28.5-11.5T160-200v-360q0-17 11.5-28.5T200-600h80q17 0 28.5 11.5T320-560v360q0 17-11.5 28.5T280-160h-80Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM80-440q-17 0-28.5-11.5T40-480q0-17 11.5-28.5T80-520h80q17 0 28.5 11.5T200-480q0 17-11.5 28.5T160-440H80Zm720 0q-17 0-28.5-11.5T760-480q0-17 11.5-28.5T800-520h80q17 0 28.5 11.5T920-480q0 17-11.5 28.5T880-440h-80ZM480-760q-17 0-28.5-11.5T440-800v-80q0-17 11.5-28.5T480-920q17 0 28.5 11.5T520-880v80q0 17-11.5 28.5T480-760Zm0 720q-17 0-28.5-11.5T440-80v-80q0-17 11.5-28.5T480-200q17 0 28.5 11.5T520-160v80q0 17-11.5 28.5T480-40ZM226-678l-43-42q-12-11-11.5-28t11.5-29q12-12 29-12t28 12l42 43q11 12 11 28t-11 28q-11 12-27.5 11.5T226-678Zm494 495-42-43q-11-12-11-28.5t11-27.5q11-12 27.5-11.5T734-282l43 42q12 11 11.5 28T777-183q-12 12-29 12t-28-12Zm-42-495q-12-11-11.5-27.5T678-734l42-43q11-12 28-11.5t29 11.5q12 12 12 29t-12 28l-43 42q-12 11-28 11t-28-11ZM183-183q-12-12-12-29t12-28l43-42q12-11 28.5-11t27.5 11q12 11 11.5 27.5T282-226l-42 43q-11 12-28 11.5T183-183Zm297-297Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-120q-151 0-255.5-104.5T120-480q0-138 90-239.5T440-838q13-2 23 3.5t16 14.5q6 9 6.5 21t-7.5 23q-17 26-25.5 55t-8.5 61q0 90 63 153t153 63q31 0 61.5-9t54.5-25q11-7 22.5-6.5T819-479q10 5 15.5 15t3.5 24q-14 138-117.5 229T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm40-83q119-15 199.5-104.5T800-480q0-123-80.5-212.5T520-797v634Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M440-440H240q-17 0-28.5-11.5T200-480q0-17 11.5-28.5T240-520h200v-200q0-17 11.5-28.5T480-760q17 0 28.5 11.5T520-720v200h200q17 0 28.5 11.5T760-480q0 17-11.5 28.5T720-440H520v200q0 17-11.5 28.5T480-200q-17 0-28.5-11.5T440-240v-200Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M400-160 232-88q-40 17-76-6.5T120-161v-519q0-33 23.5-56.5T200-760h400q33 0 56.5 23.5T680-680v519q0 43-36 66.5T568-88l-168-72Zm0-88 200 86v-518H200v518l200-86Zm400 88q-17 0-28.5-11.5T760-200v-640H280q-17 0-28.5-11.5T240-880q0-17 11.5-28.5T280-920h480q33 0 56.5 23.5T840-840v640q0 17-11.5 28.5T800-160ZM400-680H200h400-200Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H447l-80-80H160v480l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm-84-262v-218 218Zm84 262 72-240-72 240Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" height="128" view
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M160-240v-480 480Zm24.62 40q-27.62 0-46.12-18.5Q120-237 120-264.62v-430.76q0-27.62 18.5-46.12Q157-760 184.62-760H357q12.92 0 25.12 5.23 12.19 5.23 20.88 13.92L463.85-680h311.53q27.62 0 46.12 18.5Q840-643 840-615.38v67.69q0 8.54-5.73 14.27T820-527.69q-8.54 0-14.27-5.73T800-547.69v-67.69q0-9.24-7.69-16.93-7.69-7.69-16.93-7.69H447.77l-80-80H184.62q-10.77 0-17.7 6.92-6.92 6.93-6.92 17.7v430.76q0 9.24 7.69 16.93 7.69 7.69 16.93 7.69h269.23q8.53 0 14.27 5.73 5.73 5.73 5.73 14.27t-5.73 14.27q-5.74 5.73-14.27 5.73H184.62Zm384.61 47.69v-42.92q0-6.46 2.23-12.04 2.23-5.58 7.46-10.81l203.62-202.61q5.92-5.93 12.31-8 6.38-2.08 12.77-2.08 6.61 0 13.38 2.58 6.77 2.57 11.92 7.73l37 37.77q4.93 5.92 7.5 12.31Q880-364 880-357.62q0 6.39-2.46 12.89-2.46 6.5-7.62 12.42L667.31-129.69q-5.23 5.23-10.81 7.46-5.58 2.23-12.04 2.23h-42.92q-13.92 0-23.12-9.19-9.19-9.19-9.19-23.12Zm275.39-205.31-37-37.76 37 37.76Zm-240 202.24h38l138.69-138.93-18.77-19-18.23-19.54-139.69 139.47v38Zm157.92-157.93-18.23-19.54 37 38.54-18.77-19Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M381.54-350.77q-95.92 0-162.58-66.65-66.65-66.66-66.65-162.58 0-95.92 66.65-162.58 66.66-66.65 162.58-66.65 95.92 0 162.58 66.65 66.65 66.66 66.65 162.58 0 41.69-14.77 80.69t-38.77 66.69l236.31 236.31q5.61 5.62 6 13.77.38 8.16-6 14.54-6.39 6.38-14.16 6.38-7.76 0-14.15-6.38L528.92-404.31q-30 25.54-69 39.54t-78.38 14Zm0-40q79.61 0 134.42-54.81 54.81-54.8 54.81-134.42 0-79.62-54.81-134.42-54.81-54.81-134.42-54.81-79.62 0-134.42 54.81-54.81 54.8-54.81 134.42 0 79.62 54.81 134.42 54.8 54.81 134.42 54.81Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M672.31-200q-13.73 0-23.02-9.29T640-232.31V-360q0-13.73 9.29-23.02t23.02-9.29h55.38q13.73 0 23.02 9.29T760-360v127.69q0 13.73-9.29 23.02T727.69-200h-55.38Zm-220 0q-13.73 0-23.02-9.29T420-232.31v-495.38q0-13.73 9.29-23.02t23.02-9.29h55.38q13.73 0 23.02 9.29t9.29 23.02v495.38q0 13.73-9.29 23.02T507.69-200h-55.38Zm-220 0q-13.73 0-23.02-9.29T200-232.31v-302.7q0-14.3 9.29-23.49 9.29-9.19 23.02-9.19h55.38q13.73 0 23.02 9.29 9.29 9.28 9.29 23.02v302.7q0 14.3-9.29 23.49-9.29 9.19-23.02 9.19h-55.38Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 40q-66.85 0-113.42-46.58Q320-413.15 320-480t46.58-113.42Q413.15-640 480-640t113.42 46.58Q640-546.85 640-480t-46.58 113.42Q546.85-320 480-320ZM80-460q-8.5 0-14.25-5.76T60-480.03q0-8.51 5.75-14.24T80-500h100q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T180-460H80Zm700 0q-8.5 0-14.25-5.76T760-480.03q0-8.51 5.75-14.24T780-500h100q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T880-460H780ZM479.97-760q-8.51 0-14.24-5.75T460-780v-100q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-880v100q0 8.5-5.76 14.25T479.97-760Zm0 700q-8.51 0-14.24-5.75T460-80v-100q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-180v100q0 8.5-5.76 14.25T479.97-60ZM254.46-678.77l-57.61-55.85q-5.85-5.61-5.73-13.76.11-8.16 5.96-14.77 6.38-6.62 14.15-6.62 7.77 0 14.15 6.62L282-706.31q6.38 6.62 6.38 14.16 0 7.53-6 14.15t-13.65 6.12q-7.65-.5-14.27-6.89Zm480.16 481.92L678-253.69q-6.38-6.62-6.38-14.27 0-7.66 6.38-14.04 5.23-6.62 13.08-6.12 7.84.5 14.46 6.89l57.61 55.85q5.85 5.61 5.73 13.76-.11 8.16-5.96 14.77-6.38 6.62-14.15 6.62-7.77 0-14.15-6.62ZM678-677.62q-6.62-6-6.12-13.65t6.89-14.27l55.85-57.61q5.61-5.85 13.76-5.73 8.16.11 14.77 5.96 6.62 6.38 6.62 14.15 0 7.77-6.62 14.15L706.31-678q-6.62 6.38-14.16 6.38-7.53 0-14.15-6ZM196.85-196.68q-6.62-6.78-6.62-14.55 0-7.77 6.62-14.15L253.69-282q6.62-6.38 14.27-6.38 7.66 0 14.04 6.38 5.85 5.23 5.35 13.08-.5 7.84-6.12 14.46l-55.85 57.61q-6.38 6.62-14.15 6.5-7.77-.11-14.38-6.33ZM480-480Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M482.31-160Q349-160 255.65-253.35 162.31-346.69 162.31-480q0-98.77 56.54-181.42 56.53-82.66 160.38-118.89 12.23-4.31 21.46-2.27 9.23 2.04 15.23 7.96 6 5.93 7.66 15.24 1.65 9.3-2.5 19.53-7.77 19.08-11.27 38.66t-3.5 41.19q0 106.67 74.66 181.33Q555.64-404 662.31-404q27.92 0 51.11-5.92 23.2-5.93 39.5-9.62 8.7-1.61 15.96.42 7.27 2.04 11.54 7.04 4.73 5 6.39 12.31 1.65 7.31-1.89 16.69-28.61 98-112.11 160.54Q589.31-160 482.31-160Zm0-40q88 0 158-48.5t102-126.5q-20 5-40 8t-40 3q-123 0-209.5-86.5T366.31-660q0-20 3-40t8-40q-78 32-126.5 102t-48.5 158q0 116 82 198t198 82Zm-10-270Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M480.13-120q-74.67 0-140.41-28.34-65.73-28.34-114.36-76.92-48.63-48.58-76.99-114.26Q120-405.19 120-479.87q0-74.67 28.34-140.41 28.34-65.73 76.92-114.36 48.58-48.63 114.26-76.99Q405.19-840 479.87-840q74.67 0 140.41 28.34 65.73 28.34 114.36 76.92 48.63 48.58 76.99 114.26Q840-554.81 840-480.13q0 74.67-28.34 140.41-28.34 65.73-76.92 114.36-48.58 48.63-114.26 76.99Q554.81-120 480.13-120ZM500-160.69q123.62-8.08 211.81-98.35T800-480q0-130.69-87.42-220.19-87.43-89.5-212.58-99.12v638.62Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M460-460H260q-8.5 0-14.25-5.76T240-480.03q0-8.51 5.75-14.24T260-500h200v-200q0-8.5 5.76-14.25t14.27-5.75q8.51 0 14.24 5.75T500-700v200h200q8.5 0 14.25 5.76t5.75 14.27q0 8.51-5.75 14.24T700-460H500v200q0 8.5-5.76 14.25T479.97-240q-8.51 0-14.24-5.75T460-260v-200Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="m420-203.08-149.54 64.31q-32.31 13.92-61.38-5.35Q180-163.38 180-197.92v-457.46q0-27.62 18.5-46.12Q217-720 244.62-720h350.76q27.62 0 46.12 18.5Q660-683 660-655.38v457.46q0 34.54-29.08 53.8-29.07 19.27-61.38 5.35L420-203.08Zm0-44.92 165.38 71.38q12.31 5.39 23.47-2.3 11.15-7.7 11.15-20.77v-455.69q0-9.24-7.69-16.93-7.69-7.69-16.93-7.69H244.62q-9.24 0-16.93 7.69-7.69 7.69-7.69 16.93v455.69q0 13.07 11.15 20.77 11.16 7.69 23.47 2.3L420-248Zm340 28q-8.54 0-14.27-5.73T740-240v-535.39q0-9.23-7.69-16.92-7.69-7.69-16.93-7.69H320q-8.54 0-14.27-5.73T300-820q0-8.54 5.73-14.27T320-840h395.38q27.62 0 46.12 18.5Q780-803 780-775.39V-240q0 8.54-5.73 14.27T760-220ZM420-680H220h400-200Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="0 -960 960 960" width="128" fill="#000000"><path d="M180-200q-25.31 0-42.65-17.35Q120-234.69 120-260v-435.38q0-25.31 19.65-44.97Q159.31-760 184.62-760H357q12.92 0 25.12 5.23 12.19 5.23 20.88 13.92L463.85-680h349.23q8.54 0 14.27 5.73t5.73 14.27q0 8.54-5.73 14.27T813.08-640H447.77l-80-80H184.62q-10.77 0-17.7 6.92-6.92 6.93-6.92 17.7V-240q0-10.77 4.23-8.08 4.23 2.7 11.15 6.54l76.7-256.84q6.46-20.62 23.73-33.43 17.27-12.81 38.65-12.81h512.92q32.54 0 52.2 25.97 19.65 25.96 10.19 57.03l-65.85 219.24q-5.69 19.07-21.8 30.73Q786-200 766.15-200H180Zm37.08-40h546q8.46 0 15-4.62 6.54-4.61 8.84-13.07l64.31-215.39q3.85-12.3-3.85-21.92-7.69-9.62-20-9.62H314.46q-8.46 0-15 4.62-6.54 4.62-8.84 13.08L217.08-240ZM160-498.15V-720v221.85ZM217.08-240l73.54-246.92q2.3-8.46 3.84-13.08l1.54-4.62-2.69 9.62q-2.69 9.62-6.54 21.92l-64.31 215.39q-2.31 8.46-3.84 13.07l-1.54 4.62Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 2
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M21 15.2426V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5511 3 20.9925V9H9C9.55228 9 10 8.55228 10 8V2H20.0017C20.5531 2 21 2.45531 21 2.9918V6.75736L12.0012 15.7562L11.995 19.995L16.2414 20.0012L21 15.2426ZM21.7782 8.80761L23.1924 10.2218L15.4142 18L13.9979 17.9979L14 16.5858L21.7782 8.80761ZM3 7L8 2.00318V7H3Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M16 2L21 7V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5447 3 21.0082V2.9918C3 2.44405 3.44495 2 3.9934 2H16ZM13.529 14.4464L15.7395 16.6569L17.1537 15.2426L14.9432 13.0322C15.8492 11.4983 15.6432 9.48951 14.3252 8.17157C12.7631 6.60948 10.2305 6.60948 8.66839 8.17157C7.1063 9.73367 7.1063 12.2663 8.66839 13.8284C9.98633 15.1464 11.9951 15.3524 13.529 14.4464ZM12.911 12.4142C12.13 13.1953 10.8637 13.1953 10.0826 12.4142C9.30156 11.6332 9.30156 10.3668 10.0826 9.58579C10.8637 8.80474 12.13 8.80474 12.911 9.58579C13.6921 10.3668 13.6921 11.6332 12.911 12.4142Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M3 12H7V21H3V12ZM17 8H21V21H17V8ZM10 2H14V21H10V2Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M12 18C8.68629 18 6 15.3137 6 12C6 8.68629 8.68629 6 12 6C15.3137 6 18 8.68629 18 12C18 15.3137 15.3137 18 12 18ZM11 1H13V4H11V1ZM11 20H13V23H11V20ZM3.51472 4.92893L4.92893 3.51472L7.05025 5.63604L5.63604 7.05025L3.51472 4.92893ZM16.9497 18.364L18.364 16.9497L20.4853 19.0711L19.0711 20.4853L16.9497 18.364ZM19.0711 3.51472L20.4853 4.92893L18.364 7.05025L16.9497 5.63604L19.0711 3.51472ZM5.63604 16.9497L7.05025 18.364L4.92893 20.4853L3.51472 19.0711L5.63604 16.9497ZM23 11V13H20V11H23ZM4 11V13H1V11H4Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M11.3807 2.01886C9.91573 3.38768 9 5.3369 9 7.49999C9 11.6421 12.3579 15 16.5 15C18.6631 15 20.6123 14.0843 21.9811 12.6193C21.6613 17.8537 17.3149 22 12 22C6.47715 22 2 17.5228 2 12C2 6.68514 6.14629 2.33869 11.3807 2.01886Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M12 21.9967C6.47715 21.9967 2 17.5196 2 11.9967C2 6.47386 6.47715 1.9967 12 1.9967C17.5228 1.9967 22 6.47386 22 11.9967C22 17.5196 17.5228 21.9967 12 21.9967ZM12 19.9967V3.9967C7.58172 3.9967 4 7.57843 4 11.9967C4 16.415 7.58172 19.9967 12 19.9967Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M5 2H19C19.5523 2 20 2.44772 20 3V22.1433C20 22.4194 19.7761 22.6434 19.5 22.6434C19.4061 22.6434 19.314 22.6168 19.2344 22.5669L12 18.0313L4.76559 22.5669C4.53163 22.7136 4.22306 22.6429 4.07637 22.4089C4.02647 22.3293 4 22.2373 4 22.1433V3C4 2.44772 4.44772 2 5 2Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M22 11V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V11H22ZM22 9H2V4C2 3.44772 2.44772 3 3 3H10.4142L12.4142 5H21C21.5523 5 22 5.44772 22 6V9Z" /></svg>
|
||||
|
||||
@@ -56,6 +56,9 @@ icon:sb_outline = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 2
|
||||
icon:sb_project = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M21 6.75736L19 8.75736V4H10V9H5V20H19V17.2426L21 15.2426V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5501 3 20.9932V8L9.00319 2H19.9978C20.5513 2 21 2.45531 21 2.9918V6.75736ZM21.7782 8.80761L23.1924 10.2218L15.4142 18L13.9979 17.9979L14 16.5858L21.7782 8.80761Z" /></svg>
|
||||
icon:sb_search = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M15 4H5V20H19V8H15V4ZM3 2.9918C3 2.44405 3.44749 2 3.9985 2H16L20.9997 7L21 20.9925C21 21.5489 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5447 3 21.0082V2.9918ZM13.529 14.4464C11.9951 15.3524 9.98633 15.1464 8.66839 13.8284C7.1063 12.2663 7.1063 9.73367 8.66839 8.17157C10.2305 6.60948 12.7631 6.60948 14.3252 8.17157C15.6432 9.48951 15.8492 11.4983 14.9432 13.0322L17.1537 15.2426L15.7395 16.6569L13.529 14.4464ZM12.911 12.4142C13.6921 11.6332 13.6921 10.3668 12.911 9.58579C12.13 8.80474 10.8637 8.80474 10.0826 9.58579C9.30156 10.3668 9.30156 11.6332 10.0826 12.4142C10.8637 13.1953 12.13 13.1953 12.911 12.4142Z" /></svg>
|
||||
icon:sb_stats = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M3 12H7V21H3V12ZM17 8H21V21H17V8ZM10 2H14V21H10V2Z" /></svg>
|
||||
icon:theme_light = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M12 18C8.68629 18 6 15.3137 6 12C6 8.68629 8.68629 6 12 6C15.3137 6 18 8.68629 18 12C18 15.3137 15.3137 18 12 18ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16ZM11 1H13V4H11V1ZM11 20H13V23H11V20ZM3.51472 4.92893L4.92893 3.51472L7.05025 5.63604L5.63604 7.05025L3.51472 4.92893ZM16.9497 18.364L18.364 16.9497L20.4853 19.0711L19.0711 20.4853L16.9497 18.364ZM19.0711 3.51472L20.4853 4.92893L18.364 7.05025L16.9497 5.63604L19.0711 3.51472ZM5.63604 16.9497L7.05025 18.364L4.92893 20.4853L3.51472 19.0711L5.63604 16.9497ZM23 11V13H20V11H23ZM4 11V13H1V11H4Z" /></svg>
|
||||
icon:theme_dark = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M10 7C10 10.866 13.134 14 17 14C18.9584 14 20.729 13.1957 21.9995 11.8995C22 11.933 22 11.9665 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C12.0335 2 12.067 2 12.1005 2.00049C10.8043 3.27098 10 5.04157 10 7ZM4 12C4 16.4183 7.58172 20 12 20C15.0583 20 17.7158 18.2839 19.062 15.7621C18.3945 15.9187 17.7035 16 17 16C12.0294 16 8 11.9706 8 7C8 6.29648 8.08133 5.60547 8.2379 4.938C5.71611 6.28423 4 8.9417 4 12Z" /></svg>
|
||||
icon:theme_auto = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M12 21.9967C6.47715 21.9967 2 17.5196 2 11.9967C2 6.47386 6.47715 1.9967 12 1.9967C17.5228 1.9967 22 6.47386 22 11.9967C22 17.5196 17.5228 21.9967 12 21.9967ZM12 19.9967C16.4183 19.9967 20 16.415 20 11.9967C20 7.57843 16.4183 3.9967 12 3.9967C7.58172 3.9967 4 7.57843 4 11.9967C4 16.415 7.58172 19.9967 12 19.9967ZM12 17.9967V5.9967C15.3137 5.9967 18 8.683 18 11.9967C18 15.3104 15.3137 17.9967 12 17.9967Z" /></svg>
|
||||
icon:add = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z" /></svg>
|
||||
icon:bookmarks = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M5 2H19C19.5523 2 20 2.44772 20 3V22.1433C20 22.4194 19.7761 22.6434 19.5 22.6434C19.4061 22.6434 19.314 22.6168 19.2344 22.5669L12 18.0313L4.76559 22.5669C4.53163 22.7136 4.22306 22.6429 4.07637 22.4089C4.02647 22.3293 4 22.2373 4 22.1433V3C4 2.44772 4.44772 2 5 2ZM18 4H6V19.4324L12 15.6707L18 19.4324V4Z" /></svg>
|
||||
icon:browse = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#000000" height="128" width="128"><path d="M12.4142 5H21C21.5523 5 22 5.44772 22 6V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H10.4142L12.4142 5ZM20 11H4V19H20V11ZM20 9V7H11.5858L9.58579 5H4V9H20Z" /></svg>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 292 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 273 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 344 KiB |
@@ -1,28 +0,0 @@
|
||||
[Main]
|
||||
name = Cyberpunk Night
|
||||
author = Anders Lemvigh
|
||||
url = https://github.com/alemvigh
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Syntax]
|
||||
background = 0, 0, 0
|
||||
text = 150, 150, 150
|
||||
link = 77, 77, 255
|
||||
headertext = 255, 255, 255
|
||||
headertag = 50, 0, 180
|
||||
emphasis = 0, 255, 255
|
||||
dialog = 0, 255, 0
|
||||
altdialog = 0, 140, 255
|
||||
note = 150, 150, 150
|
||||
hidden = 77, 77, 100
|
||||
shortcode = 255, 255, 0
|
||||
keyword = 255, 100, 255
|
||||
tag = 255, 150, 10
|
||||
value = 255, 150, 10
|
||||
spellcheckline = 242, 72, 23
|
||||
errorline = 186, 218, 4
|
||||
replacetag = 0, 0, 180
|
||||
modifier = 144, 142, 176
|
||||
optional = 180, 180, 180
|
||||
texthighlight = 255, 255, 132, 96
|
||||
@@ -1,42 +0,0 @@
|
||||
[Main]
|
||||
name = Default Dark
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = 2a2a2a : 42, 42, 42
|
||||
# Foreground = cccccc : 204, 204, 204
|
||||
# Comment = 969696 : 150, 150, 150
|
||||
# Red = e64250 : 230, 66, 80
|
||||
# Orange = f99157 : 249, 145, 87
|
||||
# Yellow = ffff84 : 255, 255, 132
|
||||
# Green = 99cc99 : 153, 204, 153
|
||||
# Blue = 288ed7 : 102, 153, 204
|
||||
# Purple = 8c56d7 : 140, 86, 215
|
||||
##
|
||||
|
||||
[Syntax]
|
||||
background = 42, 42, 42
|
||||
text = 204, 204, 204
|
||||
link = 102, 153, 204
|
||||
headertext = 153, 204, 153
|
||||
headertag = 153, 204, 153, 160
|
||||
emphasis = 249, 145, 87
|
||||
dialog = 102, 153, 204
|
||||
altdialog = 102, 153, 204
|
||||
note = 255, 255, 216
|
||||
hidden = 150, 150, 150
|
||||
shortcode = 153, 204, 153
|
||||
keyword = 230, 66, 80
|
||||
tag = 153, 204, 153
|
||||
value = 102, 153, 204
|
||||
optional = 153, 204, 153
|
||||
spellcheckline = 230, 66, 80
|
||||
errorline = 153, 204, 153
|
||||
replacetag = 153, 204, 153
|
||||
modifier = 153, 204, 153
|
||||
texthighlight = 255, 255, 132, 96
|
||||
@@ -1,42 +0,0 @@
|
||||
[Main]
|
||||
name = Default Light
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = ffffff : 255, 255, 255
|
||||
# Foreground = 000000 : 0, 0, 0
|
||||
# Comment = 646464 : 100, 100, 100
|
||||
# Red = c83232 : 200, 50, 50
|
||||
# Orange = ae6e1e : 174, 110, 30
|
||||
# Yellow = 969600 : 150, 150, 0
|
||||
# Green = 006400 : 0, 100, 0
|
||||
# Blue = 0000c8 : 0, 0, 200
|
||||
# Purple = 6400ae : 100, 0, 174
|
||||
##
|
||||
|
||||
[Syntax]
|
||||
background = 255, 255, 255
|
||||
text = 0, 0, 0
|
||||
link = 0, 0, 200
|
||||
headertext = 0, 100, 0
|
||||
headertag = 0, 100, 0, 160
|
||||
emphasis = 174, 110, 30
|
||||
dialog = 0, 0, 200
|
||||
altdialog = 0, 0, 200
|
||||
note = 100, 100, 0
|
||||
hidden = 100, 100, 100
|
||||
shortcode = 0, 100, 0
|
||||
keyword = 200, 50, 50
|
||||
tag = 0, 100, 0
|
||||
value = 0, 0, 200
|
||||
optional = 0, 100, 0
|
||||
spellcheckline = 200, 50, 50
|
||||
errorline = 0, 100, 0
|
||||
replacetag = 0, 100, 0
|
||||
modifier = 0, 100, 0
|
||||
texthighlight = 150, 150, 0, 96
|
||||
@@ -1,44 +0,0 @@
|
||||
[Main]
|
||||
name = Dracula
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Zeno Rocha
|
||||
url = https://draculatheme.com
|
||||
license = MIT
|
||||
licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = 282a36 : 40, 42, 54
|
||||
# Foreground = f8f8f2 : 248, 248, 242
|
||||
# Comment = 6272a4 : 98, 114, 164
|
||||
# Cyan = 8be9fd : 139, 233, 253
|
||||
# Green = 50fa7b : 80, 250, 123
|
||||
# Orange = ffb86c : 255, 184, 108
|
||||
# Pink = ff79c6 : 255, 121, 198
|
||||
# Purple = bd93f9 : 189, 147, 249
|
||||
# Red = ff5555 : 255, 85, 85
|
||||
# Yellow = f1fa8c : 241, 250, 140
|
||||
##
|
||||
|
||||
[Syntax]
|
||||
# See: https://spec.draculatheme.com/
|
||||
background = 40, 42, 54
|
||||
text = 248, 248, 242
|
||||
link = 255, 121, 198
|
||||
headertext = 189, 147, 249
|
||||
headertag = 189, 147, 249, 160
|
||||
emphasis = 255, 184, 108
|
||||
dialog = 80, 250, 123
|
||||
altdialog = 241, 250, 140
|
||||
note = 255, 204, 233
|
||||
hidden = 98, 114, 164
|
||||
shortcode = 139, 233, 253
|
||||
keyword = 255, 121, 198
|
||||
tag = 255, 184, 108
|
||||
value = 255, 184, 108
|
||||
optional = 80, 250, 123
|
||||
spellcheckline = 255, 85, 85
|
||||
errorline = 80, 250, 123
|
||||
replacetag = 241, 250, 140
|
||||
modifier = 139, 233, 253
|
||||
texthighlight = 241, 250, 140, 96
|
||||
@@ -1,29 +0,0 @@
|
||||
[Main]
|
||||
name = Grey Dark
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Syntax]
|
||||
background = 54, 54, 54
|
||||
text = 200, 200, 200
|
||||
link = 200, 200, 200
|
||||
headertext = 225, 225, 225
|
||||
headertag = 225, 225, 225, 160
|
||||
emphasis = 200, 200, 200
|
||||
dialog = 200, 200, 200
|
||||
altdialog = 200, 200, 200
|
||||
note = 200, 200, 200
|
||||
hidden = 150, 150, 150
|
||||
shortcode = 225, 225, 225
|
||||
keyword = 225, 225, 225
|
||||
tag = 200, 200, 200
|
||||
value = 200, 200, 200
|
||||
optional = 225, 225, 225
|
||||
spellcheckline = 200, 46, 0
|
||||
errorline = 46, 200, 0
|
||||
replacetag = 225, 225, 225
|
||||
modifier = 225, 225, 225
|
||||
texthighlight = 255, 255, 255, 64
|
||||
@@ -1,29 +0,0 @@
|
||||
[Main]
|
||||
name = Grey Light
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Syntax]
|
||||
background = 255, 255, 255
|
||||
text = 20, 20, 20
|
||||
link = 20, 20, 20
|
||||
headertext = 0, 0, 0
|
||||
headertag = 0, 0, 0, 160
|
||||
emphasis = 20, 20, 20
|
||||
dialog = 20, 20, 20
|
||||
altdialog = 20, 20, 20
|
||||
note = 20, 20, 20
|
||||
hidden = 100, 100, 100
|
||||
shortcode = 0, 0, 0
|
||||
keyword = 0, 0, 0
|
||||
tag = 20, 20, 20
|
||||
value = 20, 20, 20
|
||||
optional = 0, 0, 0
|
||||
spellcheckline = 200, 0, 0
|
||||
errorline = 0, 150, 0
|
||||
replacetag = 0, 0, 0
|
||||
modifier = 0, 0, 0
|
||||
texthighlight = 0, 0, 0, 64
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Light Owl
|
||||
# Source: https://github.com/sdras/night-owl-vscode-theme
|
||||
# Credit: Sarah Drasner
|
||||
##
|
||||
# Colours:
|
||||
# Background = fbfbfb : 251, 251, 251
|
||||
# Current Line = e0e0e0 : 224, 224, 224
|
||||
# Selection = e0e0e0 : 224, 224, 224
|
||||
# Foreground = 403f52 : 64, 63, 82
|
||||
# Comment = 989fb1 : 152, 159, 177
|
||||
# Red = de3d3a : 222, 61, 58
|
||||
# Orange = e0af05 : 224, 175, 5
|
||||
# Yellow = daaa01 : 218, 170, 1
|
||||
# Green = 08916a : 8, 145, 106
|
||||
# Aqua = 2aa298 : 42, 162, 152
|
||||
# Blue = 288ed7 : 40, 142, 215
|
||||
# Purple = 964ac1 : 150, 74, 193
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Light Owl
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Sarah Drasner (color theme)
|
||||
url = https://github.com/sdras/night-owl-vscode-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE
|
||||
|
||||
[Syntax]
|
||||
background = 251, 251, 251
|
||||
text = 64, 63, 82
|
||||
link = 40, 142, 215
|
||||
headertext = 40, 142, 215
|
||||
headertag = 40, 142, 215, 160
|
||||
emphasis = 224, 175, 5
|
||||
dialog = 8, 145, 106
|
||||
altdialog = 218, 170, 1
|
||||
note = 128, 118, 75
|
||||
hidden = 152, 159, 177
|
||||
shortcode = 40, 142, 215
|
||||
keyword = 222, 61, 58
|
||||
tag = 150, 74, 193
|
||||
value = 224, 175, 5
|
||||
optional = 40, 142, 215
|
||||
spellcheckline = 222, 61, 58
|
||||
errorline = 8, 145, 106
|
||||
replacetag = 42, 162, 152
|
||||
modifier = 8, 145, 106
|
||||
texthighlight = 218, 170, 1, 96
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Night Owl
|
||||
# Source: https://github.com/sdras/night-owl-vscode-theme
|
||||
# Credit: Sarah Drasner
|
||||
##
|
||||
# Colours:
|
||||
# Background = 011627 : 1, 22, 39
|
||||
# Current Line = 32374d : 50, 55, 77
|
||||
# Selection = 32374d : 50, 55, 77
|
||||
# Foreground = d6deeb : 214, 222, 235
|
||||
# Comment = 637777 : 99, 119, 119
|
||||
# Red = f78c6c : 247, 140, 108
|
||||
# Orange = ecc48d : 236, 196, 141
|
||||
# Yellow = ffeb95 : 255, 235, 149
|
||||
# Green = addb67 : 173, 219, 103
|
||||
# Aqua = 7fdbca : 127, 219, 202
|
||||
# Blue = 82aaff : 130, 170, 255
|
||||
# Purple = c792ea : 199, 146, 234
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Night Owl
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Sarah Drasner (color theme)
|
||||
url = https://github.com/sdras/night-owl-vscode-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE
|
||||
|
||||
[Syntax]
|
||||
background = 1, 22, 39
|
||||
text = 214, 222, 235
|
||||
link = 130, 170, 255
|
||||
headertext = 130, 170, 255
|
||||
headertag = 130, 170, 255, 160
|
||||
emphasis = 236, 196, 141
|
||||
dialog = 173, 219, 103
|
||||
altdialog = 255, 235, 149
|
||||
note = 255, 249, 202
|
||||
hidden = 99, 119, 119
|
||||
shortcode = 130, 170, 255
|
||||
keyword = 247, 140, 108
|
||||
tag = 199, 146, 234
|
||||
value = 255, 235, 149
|
||||
optional = 130, 170, 255
|
||||
spellcheckline = 247, 140, 108
|
||||
errorline = 173, 219, 103
|
||||
replacetag = 127, 219, 202
|
||||
modifier = 173, 219, 103
|
||||
texthighlight = 255, 235, 149, 96
|
||||
@@ -1,42 +0,0 @@
|
||||
[Main]
|
||||
name = Snazzy Light
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Florian Reuschel (color theme)
|
||||
url = https://github.com/loilo/vscode-snazzy-light
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/loilo/vscode-snazzy-light/blob/master/LICENSE
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = fafbfc : 250, 251, 252
|
||||
# Foreground = 565869 : 86, 88, 105
|
||||
# Comment = 9194a2 : 145, 148, 162
|
||||
# Yellow = cf9c00 : 207, 156, 0
|
||||
# Red = ff5c57 : 255, 92, 87
|
||||
# Pink = f767bb : 247, 103, 187
|
||||
# Blue = 09a1ed : 9, 161, 237
|
||||
# Cyan = 13bbb7 : 19, 187, 183
|
||||
# Green = 2dae58 : 45, 174, 88
|
||||
##
|
||||
|
||||
[Syntax]
|
||||
background = 250, 251, 252
|
||||
text = 86, 88, 105
|
||||
link = 9, 161, 237
|
||||
headertext = 45, 174, 88
|
||||
headertag = 45, 174, 88, 160
|
||||
emphasis = 247, 103, 187
|
||||
dialog = 9, 161, 237
|
||||
altdialog = 207, 156, 0
|
||||
note = 120, 187, 185
|
||||
hidden = 145, 148, 162
|
||||
shortcode = 247, 103, 187
|
||||
keyword = 9, 161, 237
|
||||
tag = 45, 174, 88
|
||||
value = 207, 156, 0
|
||||
optional = 207, 156, 0
|
||||
spellcheckline = 255, 92, 87
|
||||
errorline = 45, 174, 88
|
||||
replacetag = 19, 187, 183
|
||||
modifier = 247, 103, 187
|
||||
texthighlight = 207, 156, 0, 96
|
||||
@@ -1,29 +0,0 @@
|
||||
[Main]
|
||||
name = Solarized Dark
|
||||
author = nullbasis
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
license = MIT
|
||||
licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE
|
||||
|
||||
[Syntax]
|
||||
background = 7, 54, 66
|
||||
text = 253, 246, 227
|
||||
link = 38, 139, 210
|
||||
headertext = 147, 161, 161
|
||||
headertag = 42, 161, 152
|
||||
emphasis = 38, 139, 210
|
||||
dialog = 42, 161, 152
|
||||
altdialog = 42, 161, 152
|
||||
note = 101, 161, 156
|
||||
hidden = 147, 161, 161
|
||||
shortcode = 147, 161, 161
|
||||
keyword = 133, 153, 0
|
||||
tag = 203, 75, 22
|
||||
value = 203, 75, 22
|
||||
optional = 147, 161, 161
|
||||
spellcheckline = 203, 75, 22
|
||||
errorline = 220, 50, 47
|
||||
replacetag = 133, 153, 0
|
||||
modifier = 181, 137, 0
|
||||
texthighlight = 181, 137, 0, 96
|
||||
@@ -1,29 +0,0 @@
|
||||
[Main]
|
||||
name = Solarized Light
|
||||
author = nullbasis
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
license = MIT
|
||||
licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE
|
||||
|
||||
[Syntax]
|
||||
background = 253, 246, 227
|
||||
text = 0, 43, 54
|
||||
link = 38, 139, 210
|
||||
headertext = 88, 110, 117
|
||||
headertag = 42, 161, 152
|
||||
emphasis = 38, 139, 210
|
||||
dialog = 42, 161, 152
|
||||
altdialog = 42, 161, 152
|
||||
note = 27, 102, 96
|
||||
hidden = 88, 110, 117
|
||||
shortcode = 88, 110, 117
|
||||
keyword = 133, 153, 0
|
||||
tag = 203, 75, 22
|
||||
value = 203, 75, 22
|
||||
optional = 88, 110, 117
|
||||
spellcheckline = 203, 75, 22
|
||||
errorline = 220, 50, 47
|
||||
replacetag = 133, 153, 0
|
||||
modifier = 181, 137, 0
|
||||
texthighlight = 181, 137, 0, 96
|
||||
@@ -1,39 +0,0 @@
|
||||
[Main]
|
||||
name = Tango
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = 30302f : 48, 48, 47
|
||||
# Foreground = eeeeec : 238, 238, 236
|
||||
# Comment = 8f8f8d : 143, 143, 141
|
||||
# Red = ef2929 : 239, 41, 41
|
||||
# Orange = c4a000 : 196, 160, 0
|
||||
# Yellow = fce94f : 252, 233, 79
|
||||
# Green = 8ae234 : 138, 226, 52
|
||||
# Cyan = 34e2e2 : 52, 226, 226
|
||||
# Blue = 3465a4 : 114, 159, 207
|
||||
# Purple = ad7fa8 : 173, 127, 168
|
||||
##
|
||||
|
||||
[Syntax]
|
||||
background = 48, 48, 47
|
||||
text = 238, 238, 236
|
||||
link = 114, 159, 207
|
||||
headertext = 114, 159, 207
|
||||
headertag = 114, 159, 207, 160
|
||||
emphasis = 196, 160, 0
|
||||
dialog = 138, 226, 52
|
||||
altdialog = 252, 233, 79
|
||||
note = 252, 242, 164
|
||||
hidden = 143, 143, 141
|
||||
shortcode = 114, 159, 207
|
||||
keyword = 239, 41, 41
|
||||
tag = 173, 127, 168
|
||||
value = 239, 41, 41
|
||||
optional = 114, 159, 207
|
||||
spellcheckline = 239, 41, 41
|
||||
errorline = 138, 226, 52
|
||||
replacetag = 52, 226, 226
|
||||
modifier = 114, 159, 207
|
||||
texthighlight = 252, 233, 79, 96
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Tomorrow
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = ffffff : 255, 255, 255
|
||||
# Current Line = efefef : 239, 239, 239
|
||||
# Selection = d6d6d6 : 214, 214, 214
|
||||
# Foreground = 4d4d4c : 77, 77, 76
|
||||
# Comment = 8e908c : 142, 144, 140
|
||||
# Red = c82829 : 240, 40, 41
|
||||
# Orange = f5871f : 245, 135, 31
|
||||
# Yellow = eab700 : 234, 183, 0
|
||||
# Green = 718c00 : 113, 140, 0
|
||||
# Aqua = 3e999f : 62, 153, 159
|
||||
# Blue = 4271ae : 66, 113, 174
|
||||
# Purple = 8959a8 : 137, 89, 168
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Tomorrow
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Chris Kempson (color theme)
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md
|
||||
|
||||
[Syntax]
|
||||
background = 255, 255, 255
|
||||
text = 77, 77, 76
|
||||
link = 66, 113, 174
|
||||
headertext = 66, 113, 174
|
||||
headertag = 66, 113, 174, 160
|
||||
emphasis = 245, 135, 31
|
||||
dialog = 113, 140, 0
|
||||
altdialog = 234, 183, 0
|
||||
note = 115, 90, 0
|
||||
hidden = 142, 144, 140
|
||||
shortcode = 66, 113, 174
|
||||
keyword = 240, 40, 41
|
||||
tag = 137, 89, 168
|
||||
value = 234, 183, 0
|
||||
optional = 66, 113, 174
|
||||
spellcheckline = 240, 40, 41
|
||||
errorline = 113, 140, 0
|
||||
replacetag = 62, 153, 159
|
||||
modifier = 245, 135, 31
|
||||
texthighlight = 234, 183, 0, 96
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Tomorrow Night
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = 1d1f21 : 29, 31, 33
|
||||
# Current Line = 282a2e : 40, 42, 46
|
||||
# Selection = 373b41 : 55, 59. 65
|
||||
# Foreground = c5c8c6 : 197, 200, 198
|
||||
# Comment = 969896 : 150, 152, 150
|
||||
# Red = cc6666 : 204, 102, 102
|
||||
# Orange = de935f : 222, 147, 95
|
||||
# Yellow = f0c674 : 240, 198, 116
|
||||
# Green = b5bd68 : 181, 189, 104
|
||||
# Aqua = 8abeb7 : 138, 190, 183
|
||||
# Blue = 81a2be : 129, 162, 190
|
||||
# Purple = b294bb : 178, 148, 187
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Tomorrow Night
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Chris Kempson (color theme)
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md
|
||||
|
||||
[Syntax]
|
||||
background = 29, 31, 33
|
||||
text = 197, 200, 198
|
||||
link = 197, 200, 198, 160
|
||||
headertext = 129, 162, 190
|
||||
headertag = 94, 119, 139
|
||||
emphasis = 222, 147, 95
|
||||
dialog = 181, 189, 104
|
||||
altdialog = 240, 198, 116
|
||||
note = 240, 219, 178
|
||||
hidden = 150, 152, 150
|
||||
shortcode = 129, 162, 190
|
||||
keyword = 204, 102, 102
|
||||
tag = 178, 148, 187
|
||||
value = 240, 198, 116
|
||||
optional = 129, 162, 190
|
||||
spellcheckline = 204, 102, 102
|
||||
errorline = 181, 189, 104
|
||||
replacetag = 138, 190, 183
|
||||
modifier = 222, 147, 95
|
||||
texthighlight = 240, 198, 116, 96
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Tomorrow Night Blue
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = 002451 : 0, 36, 81
|
||||
# Current Line = 00346e : 0, 52, 110
|
||||
# Selection = 003f8e : 0, 63, 142
|
||||
# Foreground = ffffff : 255, 255, 255
|
||||
# Comment = 7285b7 : 114, 133, 183
|
||||
# Red = ff9da4 : 255, 157, 164
|
||||
# Orange = ffc58f : 255, 197, 143
|
||||
# Yellow = ffeead : 255, 238, 173
|
||||
# Green = d1f1a9 : 209, 241, 169
|
||||
# Aqua = 99ffff : 153, 255, 255
|
||||
# Blue = bbdaff : 187, 218, 255
|
||||
# Purple = ebbbff : 235, 187, 255
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Tomorrow Night Blue
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Chris Kempson (color theme)
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md
|
||||
|
||||
[Syntax]
|
||||
background = 0, 36, 81
|
||||
text = 255, 255, 255
|
||||
link = 187, 218, 255
|
||||
headertext = 187, 218, 255
|
||||
headertag = 187, 218, 255, 160
|
||||
emphasis = 255, 197, 143
|
||||
dialog = 209, 241, 169
|
||||
altdialog = 255, 238, 173
|
||||
note = 255, 247, 214
|
||||
hidden = 114, 133, 183
|
||||
shortcode = 187, 218, 255
|
||||
keyword = 255, 157, 164
|
||||
tag = 235, 187, 255
|
||||
value = 255, 238, 173
|
||||
optional = 187, 218, 255
|
||||
spellcheckline = 255, 157, 164
|
||||
errorline = 209, 241, 169
|
||||
replacetag = 153, 255, 255
|
||||
modifier = 255, 197, 143
|
||||
texthighlight = 255, 238, 173, 96
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Tomorrow Night Bright
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = 000000 : 0, 0, 0
|
||||
# Current Line = 2a2a2a : 42, 42, 42
|
||||
# Selection = 424242 : 66, 66, 66
|
||||
# Foreground = eaeaea : 234, 234, 234
|
||||
# Comment = 969896 : 150, 152, 150
|
||||
# Red = d54e53 : 213, 78, 83
|
||||
# Orange = e78c45 : 231, 140, 69
|
||||
# Yellow = e7c547 : 231, 197, 71
|
||||
# Green = b9ca4a : 185, 202, 74
|
||||
# Aqua = 70c0b1 : 112, 192, 177
|
||||
# Blue = 7aa6da : 122, 166, 218
|
||||
# Purple = c397d8 : 195, 151, 216
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Tomorrow Night Bright
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Chris Kempson (color theme)
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md
|
||||
|
||||
[Syntax]
|
||||
background = 0, 0, 0
|
||||
text = 234, 234, 234
|
||||
link = 122, 166, 218
|
||||
headertext = 122, 166, 218
|
||||
headertag = 122, 166, 218, 160
|
||||
emphasis = 231, 140, 69
|
||||
dialog = 185, 202, 74
|
||||
altdialog = 231, 197, 71
|
||||
note = 231, 214, 150
|
||||
hidden = 150, 152, 150
|
||||
shortcode = 122, 166, 218
|
||||
keyword = 213, 78, 83
|
||||
tag = 195, 151, 216
|
||||
value = 231, 197, 71
|
||||
optional = 122, 166, 218
|
||||
spellcheckline = 213, 78, 83
|
||||
errorline = 185, 202, 74
|
||||
replacetag = 112, 192, 177
|
||||
modifier = 231, 140, 69
|
||||
texthighlight = 231, 197, 71, 128
|
||||
@@ -1,49 +0,0 @@
|
||||
##
|
||||
# Theme: Tomorrow Night Eighties
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = 2d2d2d : 45, 45, 45
|
||||
# Current Line = 393939 : 57, 57, 57
|
||||
# Selection = 515151 : 81, 81, 81
|
||||
# Foreground = cccccc : 204, 204, 204
|
||||
# Comment = 999999 : 153, 153, 153
|
||||
# Red = f2777a : 242, 119, 122
|
||||
# Orange = f99157 : 249, 145, 57
|
||||
# Yellow = ffcc66 : 255, 204, 102
|
||||
# Green = 99cc99 : 153, 204, 153
|
||||
# Aqua = 66cccc : 102, 204, 204
|
||||
# Blue = 6699cc : 102, 153, 204
|
||||
# Purple = cc99cc : 204, 153, 204
|
||||
##
|
||||
|
||||
[Main]
|
||||
name = Tomorrow Night Eighties
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Chris Kempson (color theme)
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md
|
||||
|
||||
[Syntax]
|
||||
background = 45, 45, 45
|
||||
text = 204, 204, 204
|
||||
link = 102, 153, 204
|
||||
headertext = 102, 153, 204
|
||||
headertag = 102, 153, 204, 160
|
||||
emphasis = 249, 145, 57
|
||||
dialog = 153, 204, 153
|
||||
altdialog = 255, 204, 102
|
||||
note = 255, 230, 179
|
||||
hidden = 153, 153, 153
|
||||
shortcode = 102, 153, 204
|
||||
keyword = 242, 119, 122
|
||||
tag = 204, 153, 204
|
||||
value = 255, 204, 102
|
||||
optional = 102, 153, 204
|
||||
spellcheckline = 242, 119, 122
|
||||
errorline = 153, 204, 153
|
||||
replacetag = 102, 204, 204
|
||||
modifier = 249, 145, 57
|
||||
texthighlight = 255, 204, 102, 96
|
||||
@@ -67,20 +67,38 @@ more contributions are listed on the project's Members page.</p>
|
||||
<li><b>PyEnchant</b> by Dimitri Merejkowsky</li>
|
||||
</ul>
|
||||
|
||||
<h3>Assets</h3>
|
||||
<h3>Icon Themes</h3>
|
||||
|
||||
<p>Some of the assets bundled with novelWriter were adapted from the following sources:</p>
|
||||
<p>The following icon themes are bundles with novelWriter:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Material Symbols</b> icons by Google Inc (Apache 2.0)</li>
|
||||
<li><b>Remix</b> icons by RemixIcon (Apache 2.0)</li>
|
||||
<li><b>Font Awesome</b> icons by Fonticons Inc (CC BY 4.0)</li>
|
||||
<li><b>Tomorrow</b> syntax themes by Chris Kempson (MIT License)</li>
|
||||
<li><b>Owl</b> syntax themes by Sarah Drasner (MIT License)</li>
|
||||
<li><b>Solarized</b> themes by Ethan Schoonover (MIT License)</li>
|
||||
<li><b>Cyberpunk Night</b> theme by Anders Lemvigh (CC BY-SA 4.0)</li>
|
||||
<li><b>Dracula</b> theme by Zeno Rocha (MIT License)</li>
|
||||
<li><b>Snazzy Light</b> theme by Florian Reuschel (MIT License)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Colour Themes</h3>
|
||||
|
||||
<p>Some colour themes included with novelWriter were adapted from the following sources:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Dracula</b> theme by Zeno Rocha</li>
|
||||
<li><b>Espresso</b> theme by Sainnhe Park and Antoine Cotten</li>
|
||||
<li><b>Noctis</b> themes by Liviu Schera, and contributors</li>
|
||||
<li><b>Owl</b> themes by Sarah Drasner</li>
|
||||
<li><b>Primer</b> themes by GitHub Inc and Myian</li>
|
||||
<li><b>Snazzy Light</b> theme by Florian Reuschel</li>
|
||||
<li><b>Solarized</b> themes by Ethan Schoonover</li>
|
||||
<li><b>Tango</b> themes by the Tango Desktop Project</li>
|
||||
<li><b>Tomorrow</b> themes by Chris Kempson</li>
|
||||
</ul>
|
||||
|
||||
<p>Other themes were created for novelWriter:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Blue Streak</b> themes by Veronica Berglyd Olsen</li>
|
||||
<li><b>Cyberpunk Night</b> theme by Anders Lemvigh</li>
|
||||
<li><b>LCARS</b> theme by Veronica Berglyd Olsen</li>
|
||||
</ul>
|
||||
|
||||
<h3>Fonts</h3>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Blue Streak Dark
|
||||
mode = dark
|
||||
description = A theme mainly using shades of blue
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Base]
|
||||
base = #2d2d2d
|
||||
default = #cccccc
|
||||
faded = #999999
|
||||
red = #ff6666
|
||||
orange = #ff9966
|
||||
yellow = #ffcc66
|
||||
green = #99cc99
|
||||
cyan = #66cccc
|
||||
blue = #6699cc
|
||||
purple = #cc99cc
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = default
|
||||
file = default
|
||||
title = blue:D150
|
||||
chapter = blue
|
||||
scene = blue:L150
|
||||
note = yellow
|
||||
active = blue:L150
|
||||
inactive = blue:D150
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L125
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = base:L150
|
||||
text = default
|
||||
tooltipbase = yellow:L140
|
||||
tooltiptext = base:D150
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = blue
|
||||
highlightedtext = default:L120
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = blue:L125
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = blue:48
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = blue:L150
|
||||
dialog = blue
|
||||
altdialog = blue:L150
|
||||
note = blue:L150
|
||||
hidden = faded
|
||||
shortcode = blue:D125
|
||||
keyword = blue:D125
|
||||
tag = blue
|
||||
value = blue
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = blue:L150
|
||||
modifier = blue:D125
|
||||
texthighlight = blue:96
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Blue Streak Light
|
||||
mode = light
|
||||
description = A theme mainly using shades of blue
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Base]
|
||||
base = #fcfcfc
|
||||
default = #303030
|
||||
faded = #6c6c6c
|
||||
red = #cc3939
|
||||
orange = #cc7239
|
||||
yellow = #cca339
|
||||
green = #72a372
|
||||
cyan = #39a3a3
|
||||
blue = #3972a3
|
||||
purple = #a372a3
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = faded
|
||||
file = faded
|
||||
title = blue:D150
|
||||
chapter = blue
|
||||
scene = blue:L125
|
||||
note = yellow
|
||||
active = blue:L115
|
||||
inactive = blue:D150
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:D105
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = base:D110
|
||||
text = default
|
||||
tooltipbase = yellow:L150
|
||||
tooltiptext = default:D150
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = blue:L110
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = blue:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = blue:L125
|
||||
dialog = blue
|
||||
altdialog = blue:L125
|
||||
note = blue:L125
|
||||
hidden = faded
|
||||
shortcode = blue:D125
|
||||
keyword = blue:D125
|
||||
tag = blue
|
||||
value = blue
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = blue:L125
|
||||
modifier = blue:D125
|
||||
texthighlight = blue:96
|
||||
@@ -1,48 +1,75 @@
|
||||
[Main]
|
||||
name = Cyberpunk Night
|
||||
mode = dark
|
||||
description = A taste of the future 80s
|
||||
author = Anders Lemvigh
|
||||
url = https://github.com/alemvigh
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Icons]
|
||||
default = 136, 136, 136
|
||||
faded = 97, 97, 97
|
||||
red = 242, 72, 23
|
||||
orange = 255, 150, 10
|
||||
yellow = 255, 255, 0
|
||||
green = 0, 255, 0
|
||||
aqua = 0, 255, 255
|
||||
blue = 77, 77, 255
|
||||
purple = 50, 0, 180
|
||||
[Base]
|
||||
base = #000000
|
||||
default = #888888
|
||||
faded = #616161
|
||||
red = #f24817
|
||||
orange = #ff960a
|
||||
yellow = #ffff00
|
||||
green = #00ff00
|
||||
cyan = #00ffff
|
||||
blue = #4d4dff
|
||||
purple = #320064
|
||||
|
||||
[Project]
|
||||
root = 77, 77, 255
|
||||
folder = 255, 255, 0
|
||||
file = 136, 136, 136
|
||||
title = 0, 255, 0
|
||||
chapter = 242, 72, 23
|
||||
scene = 77, 77, 255
|
||||
note = 255, 255, 0
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 0, 0, 0
|
||||
windowtext = 150, 150, 150
|
||||
base = 0, 0, 0
|
||||
alternatebase = 40, 40, 40
|
||||
text = 150, 150, 150
|
||||
tooltipbase = 40, 20, 70
|
||||
tooltiptext = 255, 255, 255
|
||||
button = 5, 0, 10
|
||||
buttontext = 150, 150, 150
|
||||
brighttext = 255, 255, 255
|
||||
highlight = 50, 30, 80
|
||||
highlightedtext = 255, 255, 255
|
||||
link = 77, 77, 255
|
||||
linkvisited = 50, 0, 80
|
||||
window = base
|
||||
windowtext = #969696
|
||||
base = base
|
||||
alternatebase = #282828
|
||||
text = #969696
|
||||
tooltipbase = #281446
|
||||
tooltiptext = #ffffff
|
||||
button = #05000a
|
||||
buttontext = #969696
|
||||
brighttext = #ffffff
|
||||
highlight = #321e50
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = #320050
|
||||
accent = #321e50
|
||||
|
||||
[GUI]
|
||||
helptext = 97, 97, 97
|
||||
fadedtext = 97, 97, 97
|
||||
errortext = 242, 72, 23
|
||||
helptext = faded
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #969696
|
||||
line = #282828
|
||||
link = blue
|
||||
headertext = #ffffff
|
||||
headertag = purple
|
||||
emphasis = cyan
|
||||
dialog = green
|
||||
altdialog = #008cff
|
||||
note = #969696
|
||||
hidden = #4d4d64
|
||||
shortcode = yellow
|
||||
keyword = #ff64ff
|
||||
tag = orange
|
||||
value = orange
|
||||
spellcheckline = red
|
||||
errorline = #bada04
|
||||
replacetag = #0000b4
|
||||
modifier = #908eb0
|
||||
optional = #b4b4b4
|
||||
texthighlight = #ffff8460
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[Main]
|
||||
name = Qt Default Theme
|
||||
description = Qt standard colours
|
||||
@@ -1,49 +1,76 @@
|
||||
[Main]
|
||||
name = Default Dark Theme
|
||||
mode = dark
|
||||
description = The novelWriter standard dark theme
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Icons]
|
||||
default = 184, 184, 184
|
||||
faded = 148, 148, 148
|
||||
red = 242, 119, 122
|
||||
orange = 249, 145, 57
|
||||
yellow = 255, 204, 102
|
||||
green = 153, 204, 153
|
||||
aqua = 102, 204, 204
|
||||
blue = 102, 153, 204
|
||||
purple = 204, 153, 204
|
||||
[Base]
|
||||
base = #373737
|
||||
default = #cccccc
|
||||
faded = #949494
|
||||
red = #ff6666
|
||||
orange = #ff9966
|
||||
yellow = #ffcc66
|
||||
green = #99cc99
|
||||
cyan = #66cccc
|
||||
blue = #6699cc
|
||||
purple = #cc99cc
|
||||
|
||||
[Project]
|
||||
root = 102, 153, 204
|
||||
folder = 255, 204, 102
|
||||
file = 184, 184, 184
|
||||
title = 153, 204, 153
|
||||
chapter = 242, 119, 122
|
||||
scene = 102, 153, 204
|
||||
note = 255, 204, 102
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 54, 54, 54
|
||||
windowtext = 204, 204, 204
|
||||
base = 62, 62, 62
|
||||
alternatebase = 78, 78, 78
|
||||
text = 204, 204, 204
|
||||
tooltipbase = 255, 255, 192
|
||||
tooltiptext = 21, 21, 13
|
||||
button = 62, 62, 62
|
||||
buttontext = 204, 204, 204
|
||||
brighttext = 62, 62, 62
|
||||
highlight = 44, 152, 247
|
||||
highlightedtext = 255, 255, 255
|
||||
link = 102, 153, 204
|
||||
linkvisited = 102, 153, 204
|
||||
window = base:L125
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #4e4e4e
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = 164, 164, 164
|
||||
fadedtext = 148, 148, 148
|
||||
errortext = 255, 164, 164
|
||||
helptext = #a4a4a4
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = green
|
||||
headertag = green:D150
|
||||
emphasis = orange
|
||||
dialog = blue
|
||||
altdialog = red
|
||||
note = yellow
|
||||
hidden = faded
|
||||
shortcode = green
|
||||
keyword = red
|
||||
tag = green
|
||||
value = green
|
||||
optional = green
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = green
|
||||
modifier = blue
|
||||
texthighlight = yellow:72
|
||||
|
||||
@@ -1,49 +1,76 @@
|
||||
[Main]
|
||||
name = Default Light Theme
|
||||
mode = light
|
||||
description = The novelWriter standard light theme
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
license = CC BY-SA 4.0
|
||||
licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Icons]
|
||||
default = 72, 72, 72
|
||||
faded = 108, 108, 108
|
||||
red = 240, 40, 41
|
||||
orange = 245, 135, 31
|
||||
yellow = 234, 183, 0
|
||||
green = 113, 140, 0
|
||||
aqua = 62, 153, 159
|
||||
blue = 66, 113, 174
|
||||
purple = 137, 89, 168
|
||||
[Base]
|
||||
base = #fcfcfc
|
||||
default = #303030
|
||||
faded = #6c6c6c
|
||||
red = #a62a2d
|
||||
orange = #b36829
|
||||
yellow = #a39c34
|
||||
green = #296629
|
||||
cyan = #269999
|
||||
blue = #3a70a6
|
||||
purple = #b35ab3
|
||||
|
||||
[Project]
|
||||
root = 66, 113, 174
|
||||
folder = 234, 183, 0
|
||||
file = 72, 72, 72
|
||||
title = 113, 140, 0
|
||||
chapter = 240, 40, 41
|
||||
scene = 66, 113, 174
|
||||
note = 234, 183, 0
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 239, 239, 239
|
||||
windowtext = 0, 0, 0
|
||||
base = 255, 255, 255
|
||||
alternatebase = 224, 224, 224
|
||||
text = 0, 0, 0
|
||||
tooltipbase = 255, 255, 220
|
||||
tooltiptext = 0, 0, 0
|
||||
button = 239, 239, 239
|
||||
buttontext = 0, 0, 0
|
||||
brighttext = 255, 255, 255
|
||||
highlight = 48, 135, 198
|
||||
highlightedtext = 255, 255, 255
|
||||
link = 66, 113, 174
|
||||
linkvisited = 66, 113, 174
|
||||
window = base:D105
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #e0e0e0
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #efefef
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #3087c6
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #3087c6
|
||||
|
||||
[GUI]
|
||||
helptext = 92, 92, 92
|
||||
fadedtext = 108, 108, 108
|
||||
errortext = 255, 92, 92
|
||||
helptext = #5c5c5c
|
||||
fadedtext = #6c6c6c
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = green
|
||||
headertag = green:L135
|
||||
emphasis = orange
|
||||
dialog = blue
|
||||
altdialog = red
|
||||
note = yellow:D125
|
||||
hidden = faded
|
||||
shortcode = green
|
||||
keyword = red
|
||||
tag = green
|
||||
value = green
|
||||
optional = green
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = green
|
||||
modifier = blue
|
||||
texthighlight = yellow:72
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
[Main]
|
||||
name = Dracula
|
||||
mode = dark
|
||||
description = A dark theme with bright colours
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Zeno Rocha
|
||||
url = https://draculatheme.com
|
||||
license = MIT
|
||||
licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# See: https://spec.draculatheme.com/
|
||||
# Background = 282a36 : 40, 42, 54
|
||||
# Foreground = f8f8f2 : 248, 248, 242
|
||||
# Current Line = 44475A : 68, 71, 90
|
||||
# Current Line = 44475a : 68, 71, 90
|
||||
# Comment = 6272a4 : 98, 114, 164
|
||||
# Cyan = 8be9fd : 139, 233, 253
|
||||
# Green = 50fa7b : 80, 250, 123
|
||||
@@ -22,43 +22,71 @@ licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE
|
||||
# Yellow = f1fa8c : 241, 250, 140
|
||||
##
|
||||
|
||||
[Icons]
|
||||
default = 230, 230, 224
|
||||
faded = 98, 114, 164
|
||||
red = 255, 85, 85
|
||||
orange = 255, 184, 108
|
||||
yellow = 241, 250, 140
|
||||
green = 80, 250, 123
|
||||
aqua = 139, 233, 253
|
||||
blue = 147, 207, 249
|
||||
purple = 189, 147, 249
|
||||
[Base]
|
||||
base = #282a36
|
||||
default = #e6e6e0
|
||||
faded = #6272a4
|
||||
red = #ff5555
|
||||
orange = #ffb86c
|
||||
yellow = #f1fa8c
|
||||
green = #50fa7b
|
||||
cyan = #8be9fd
|
||||
blue = #93cff9
|
||||
purple = #bd93f9
|
||||
|
||||
[Project]
|
||||
root = 189, 147, 249
|
||||
folder = 241, 250, 140
|
||||
file = 230, 230, 224
|
||||
title = 80, 250, 123
|
||||
chapter = 255, 85, 85
|
||||
scene = 139, 233, 253
|
||||
note = 241, 250, 140
|
||||
root = purple
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = cyan
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 68, 71, 90
|
||||
windowtext = 248, 248, 242
|
||||
base = 40, 42, 54
|
||||
alternatebase = 51, 54, 69
|
||||
text = 248, 248, 242
|
||||
tooltipbase = 241, 250, 140
|
||||
tooltiptext = 40, 42, 54
|
||||
button = 80, 83, 105
|
||||
buttontext = 248, 248, 242
|
||||
brighttext = 68, 71, 90
|
||||
highlight = 166, 129, 218
|
||||
highlightedtext = 248, 248, 242
|
||||
link = 139, 233, 253
|
||||
linkvisited = 139, 233, 253
|
||||
window = #44475a
|
||||
windowtext = #f8f8f2
|
||||
base = base
|
||||
alternatebase = #333645
|
||||
text = #f8f8f2
|
||||
tooltipbase = yellow
|
||||
tooltiptext = base
|
||||
button = #505369
|
||||
buttontext = #f8f8f2
|
||||
brighttext = base
|
||||
highlight = #a681da
|
||||
highlightedtext = #f8f8f2
|
||||
link = cyan
|
||||
linkvisited = cyan
|
||||
accent = #a681da
|
||||
|
||||
[GUI]
|
||||
helptext = 204, 172, 249
|
||||
fadedtext = 98, 114, 164
|
||||
errortext = 255, 85, 85
|
||||
helptext = #ccacf9
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #f8f8f2
|
||||
line = base:L150
|
||||
link = #ff79c6
|
||||
headertext = purple
|
||||
headertag = purple:D150
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #ffcce9
|
||||
hidden = faded
|
||||
shortcode = cyan
|
||||
keyword = #ff79c6
|
||||
tag = orange
|
||||
value = orange
|
||||
optional = green
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = yellow
|
||||
modifier = cyan
|
||||
texthighlight = yellow:96
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Espresso
|
||||
mode = dark
|
||||
description = High contrast & vivid color scheme based on Monokai Pro
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Sainnhe Park and Antoine Cotten
|
||||
url = https://github.com/sainnhe/sonokai
|
||||
|
||||
[Base]
|
||||
base = #2f2726
|
||||
default = #e5e4e2
|
||||
faded = #96817b
|
||||
red = #f86882
|
||||
orange = #f08d71
|
||||
yellow = #f0c66f
|
||||
green = #a6cd77
|
||||
cyan = #81d0c9
|
||||
blue = #89a8e0
|
||||
purple = #9fa0e1
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L125
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #51403c
|
||||
text = default
|
||||
tooltipbase = yellow:L125
|
||||
tooltiptext = base
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #4e5f80
|
||||
highlightedtext = default
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = #392e2c
|
||||
link = blue
|
||||
headertext = yellow:L125
|
||||
headertag = faded
|
||||
emphasis = orange
|
||||
dialog = yellow
|
||||
altdialog = orange
|
||||
note = yellow:L125
|
||||
hidden = faded
|
||||
shortcode = green
|
||||
keyword = red
|
||||
tag = green
|
||||
value = orange
|
||||
optional = yellow
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = blue
|
||||
texthighlight = yellow:108
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Grey Dark
|
||||
mode = dark
|
||||
description = A theme with minimal colours
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Base]
|
||||
base = #3e3e3e
|
||||
default = #c8c8c8
|
||||
faded = #949494
|
||||
red = #f2777a
|
||||
orange = #f99139
|
||||
yellow = #ffcc66
|
||||
green = #99cc99
|
||||
cyan = #66cccc
|
||||
blue = #6699cc
|
||||
purple = #cc99cc
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #363636
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #4e4e4e
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = default:D120
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = #363636
|
||||
text = default
|
||||
line = default:32
|
||||
link = default
|
||||
headertext = default:L115
|
||||
headertag = default:D125
|
||||
emphasis = default
|
||||
dialog = default
|
||||
altdialog = default
|
||||
note = default
|
||||
hidden = faded
|
||||
shortcode = default:L115
|
||||
keyword = default:L115
|
||||
tag = default
|
||||
value = default
|
||||
optional = default:L115
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = default:L115
|
||||
modifier = default:L115
|
||||
texthighlight = #ffffff40
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Grey Light
|
||||
mode = light
|
||||
description = A theme with minimal colours
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Veronica Berglyd Olsen
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Base]
|
||||
base = #ffffff
|
||||
default = #282828
|
||||
faded = #6c6c6c
|
||||
red = #a62a2d
|
||||
orange = #b36829
|
||||
yellow = #a68542
|
||||
green = #296629
|
||||
cyan = #269999
|
||||
blue = #3a70a6
|
||||
purple = #b35ab3
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #efefef
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #e0e0e0
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #efefef
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #3087c6
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #3087c6
|
||||
|
||||
[GUI]
|
||||
helptext = default:L225
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = default
|
||||
headertext = default:D200
|
||||
headertag = default:L400
|
||||
emphasis = default
|
||||
dialog = default
|
||||
altdialog = default
|
||||
note = default
|
||||
hidden = faded
|
||||
shortcode = default:D200
|
||||
keyword = default:D200
|
||||
tag = default
|
||||
value = default
|
||||
optional = default:D200
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = default:D200
|
||||
modifier = default:D200
|
||||
texthighlight = #00000040
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = LCARS
|
||||
mode = dark
|
||||
description = The Next Generation of Star Trek colours
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Star Trek TNG
|
||||
url = https://github.com/vkbo/novelWriter
|
||||
|
||||
[Base]
|
||||
base = #101010
|
||||
default = #c7c7c7
|
||||
faded = #757575
|
||||
red = #e24d5f
|
||||
orange = #ff9902
|
||||
yellow = #ffdc59
|
||||
green = #54e985
|
||||
cyan = #7ffff2
|
||||
blue = #009cff
|
||||
purple = #8aa5ff
|
||||
|
||||
[Project]
|
||||
root = orange
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = blue
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L180
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = base:L300
|
||||
text = default
|
||||
tooltipbase = yellow:L140
|
||||
tooltiptext = base
|
||||
button = base:L140
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = purple
|
||||
highlightedtext = base
|
||||
link = purple
|
||||
linkvisited = purple
|
||||
accent = orange
|
||||
|
||||
[GUI]
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = yellow:48
|
||||
link = purple
|
||||
headertext = orange
|
||||
headertag = red
|
||||
emphasis = orange
|
||||
dialog = yellow
|
||||
altdialog = green
|
||||
note = purple
|
||||
hidden = faded
|
||||
shortcode = purple
|
||||
keyword = red
|
||||
tag = orange
|
||||
value = orange
|
||||
optional = purple
|
||||
spellcheckline = red
|
||||
errorline = red
|
||||
replacetag = purple
|
||||
modifier = red
|
||||
texthighlight = orange:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Light Owl
|
||||
mode = light
|
||||
description = A theme for the night owls out there, but for daylight
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Sarah Drasner
|
||||
url = https://github.com/sdras/night-owl-vscode-theme
|
||||
|
||||
##
|
||||
# Theme: Light Owl
|
||||
# Source: https://github.com/sdras/night-owl-vscode-theme
|
||||
# Credit: Sarah Drasner
|
||||
##
|
||||
# Colours:
|
||||
# Background = #fbfbfb
|
||||
# Current Line = #eaeaea
|
||||
# Selection = #e0e0e0
|
||||
# Foreground = #403f52
|
||||
# Comment = #989fb1
|
||||
# Red = #de3d3a
|
||||
# Orange = #e0af05
|
||||
# Yellow = #daaa01
|
||||
# Green = #08916a
|
||||
# Aqua = #2aa298
|
||||
# Blue = #288ed7
|
||||
# Purple = #964ac1
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #fbfbfb
|
||||
default = #403f52
|
||||
faded = #989fb1
|
||||
red = #de3d3a
|
||||
orange = #e0af05
|
||||
yellow = #daaa01
|
||||
green = #08916a
|
||||
cyan = #2aa298
|
||||
blue = #288ed7
|
||||
purple = #964ac1
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #eaeaea
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #e0e0e0
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #3087c6
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #3087c6
|
||||
|
||||
[GUI]
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:160
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = yellow:D175
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = orange
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = green
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Night Owl
|
||||
mode = dark
|
||||
description = A theme for the night owls out there
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Sarah Drasner
|
||||
url = https://github.com/sdras/night-owl-vscode-theme
|
||||
|
||||
##
|
||||
# Theme: Night Owl
|
||||
# Source: https://github.com/sdras/night-owl-vscode-theme
|
||||
# Credit: Sarah Drasner
|
||||
##
|
||||
# Colours:
|
||||
# Background = #011627
|
||||
# Current Line = #434652
|
||||
# Selection = #32374d
|
||||
# Foreground = #d6deeb
|
||||
# Comment = #637777
|
||||
# Red = #f78c6c
|
||||
# Orange = #ecc48d
|
||||
# Yellow = #ffeb95
|
||||
# Green = #addb67
|
||||
# Aqua = #7fdbca
|
||||
# Blue = #82aaff
|
||||
# Purple = #c792ea
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #011627
|
||||
default = #d6deeb
|
||||
faded = #637777
|
||||
red = #f78c6c
|
||||
orange = #ecc48d
|
||||
yellow = #ffeb95
|
||||
green = #addb67
|
||||
cyan = #7fdbca
|
||||
blue = #82aaff
|
||||
purple = #c792ea
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L140
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #32374d
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:48
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:160
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = yellow:L115
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = orange
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = green
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,108 @@
|
||||
[Main]
|
||||
name = Noctis
|
||||
mode = dark
|
||||
description = A dark theme with a well balanced blend of warm and cold medium contrast colors
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Liviu Schera, and contributors
|
||||
url = https://github.com/liviuschera/noctis
|
||||
|
||||
##
|
||||
# Noctis Lux : themes/noctis.json
|
||||
##
|
||||
# colors
|
||||
# selection.background : #107684 -> Palette.highlight
|
||||
# sideBar.background : #041d20 -> Palette.window
|
||||
# editor.background : #052529 -> Base.base
|
||||
# editor.foreground : #b2cacd -> Base.default
|
||||
# editor.selectionBackground : #169fb144 -> Syntax.line, Syntax.texthighlight
|
||||
# textLink.foreground : #40d4e7 -> Palette.link, Syntax.link
|
||||
# input.background : #052529 -> Palette.button
|
||||
# input.foreground : #cdd3de -> Palette.buttontext
|
||||
# notifications.foreground : #cdd3de -> Palette.tooltiptext
|
||||
# notifications.background : #073940 -> Palette.tooltipbase
|
||||
##
|
||||
# tokenColors
|
||||
# COMMENT : #5b858b -> Base.faded
|
||||
# TEXT : #b2cacd -> Syntax.text, Syntax.optional
|
||||
# KEYWORD : #df769b -> Base.red
|
||||
# VARIABLE : #e4b781 -> Palette.accent
|
||||
# ANNOTATION : #d67e5c -> Syntax.note, Syntax.emphasis
|
||||
# CONSTANT : #d5971a -> Base.yellow
|
||||
# TAG : #e66533 -> Base.orange
|
||||
# STRING : #49e9a6 -> Syntax.headertext, Palette.accent
|
||||
# STRINGINTERPOLATED : #16b673 -> Base.green
|
||||
# NUMBER : #7060eb -> Base.purple
|
||||
# FUNCTION : #16a3b6 -> Base.cyan
|
||||
# SUPPORT : #49d6e9 -> Syntax.replacetag
|
||||
# MISC : #49ace9 -> Base.blue
|
||||
# INVALID : #e3541c -> GUI.errortext
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #052529
|
||||
default = #b2cacd
|
||||
faded = #5b858b
|
||||
red = #df769b
|
||||
orange = #e66533
|
||||
yellow = #d5971a
|
||||
green = #16b673
|
||||
cyan = #16a3b6
|
||||
blue = #49ace9
|
||||
purple = #7060eb
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #041d20
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = base:L175
|
||||
text = default
|
||||
tooltipbase = #073940
|
||||
tooltiptext = #cdd3de
|
||||
button = base
|
||||
buttontext = #cdd3de
|
||||
brighttext = base
|
||||
highlight = #107684
|
||||
highlightedtext = default
|
||||
link = #40d4e7
|
||||
linkvisited = blue
|
||||
accent = #49e9a6
|
||||
|
||||
[GUI]
|
||||
helptext = #e4b781
|
||||
fadedtext = faded
|
||||
errortext = #e3541c
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #b2cacd
|
||||
line = #169fb132
|
||||
link = #40d4e7
|
||||
headertext = #49e9a6
|
||||
headertag = green:D125
|
||||
emphasis = #d67e5c
|
||||
dialog = green
|
||||
altdialog = blue
|
||||
note = #d67e5c
|
||||
hidden = faded
|
||||
shortcode = red
|
||||
keyword = yellow
|
||||
tag = blue
|
||||
value = red:D125
|
||||
optional = #b2cacd
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = #49d6e9
|
||||
modifier = red
|
||||
texthighlight = #169fb144
|
||||
@@ -0,0 +1,108 @@
|
||||
[Main]
|
||||
name = Noctis Lux
|
||||
mode = light
|
||||
description = A light theme with a well balanced blend of warm and cold medium contrast colors
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Liviu Schera, and contributors
|
||||
url = https://github.com/liviuschera/noctis
|
||||
|
||||
##
|
||||
# Noctis Lux : themes/lux.json
|
||||
##
|
||||
# colors
|
||||
# selection.background : #169fb155 -> Palette.highlight
|
||||
# sideBar.background : #f9f1e1 -> Palette.window
|
||||
# editor.background : #fef8ec -> Base.base
|
||||
# editor.foreground : #005661 -> Base.default
|
||||
# editor.selectionBackground : #ade2eb77 -> Syntax.line, Syntax.texthighlight
|
||||
# textLink.foreground : #00c6e0 -> Palette.link, Syntax.link
|
||||
# input.background : #fef8ec -> Palette.button
|
||||
# input.foreground : #6a7a7c -> Palette.buttontext
|
||||
# notifications.foreground : #005661 -> Palette.tooltiptext
|
||||
# notifications.background : #f2edde -> Palette.tooltipbase
|
||||
##
|
||||
# tokenColors
|
||||
# COMMENT : #8ca6a6 -> Base.faded
|
||||
# TEXT : #004d57 -> Syntax.text, Syntax.optional
|
||||
# KEYWORD : #ff5792 -> Base.red
|
||||
# VARIABLE : #fa8900 -> Palette.accent
|
||||
# ANNOTATION : #b3694d -> Syntax.note, Syntax.emphasis
|
||||
# CONSTANT : #a88c00 -> Base.yellow
|
||||
# TAG : #e64100 -> Base.orange
|
||||
# STRING : #00b368 -> Syntax.headertext, Palette.accent
|
||||
# STRINGINTERPOLATED : #009456 -> Base.green
|
||||
# NUMBER : #5842ff -> Base.purple
|
||||
# FUNCTION : #0095a8 -> Base.cyan
|
||||
# SUPPORT : #00bdd6 -> Syntax.replacetag
|
||||
# MISC : #0094f0 -> Base.blue
|
||||
# INVALID : #ff530f -> GUI.errortext
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #fef8ec
|
||||
default = #005661
|
||||
faded = #8ca6a6
|
||||
red = #ff5792
|
||||
orange = #e64100
|
||||
yellow = #a88c00
|
||||
green = #009456
|
||||
cyan = #0095a8
|
||||
blue = #0094f0
|
||||
purple = #5842ff
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #f9f1e1
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = base:D115
|
||||
text = default
|
||||
tooltipbase = #f2edde
|
||||
tooltiptext = #005661
|
||||
button = base
|
||||
buttontext = #6a7a7c
|
||||
brighttext = base
|
||||
highlight = #169fb155
|
||||
highlightedtext = default
|
||||
link = #00c6e0
|
||||
linkvisited = blue
|
||||
accent = #00b368
|
||||
|
||||
[GUI]
|
||||
helptext = #fa8900
|
||||
fadedtext = faded
|
||||
errortext = #ff530f
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #004d57
|
||||
line = #ade2eb56
|
||||
link = #00c6e0
|
||||
headertext = #00b368
|
||||
headertag = green:D125
|
||||
emphasis = #b3694d
|
||||
dialog = green
|
||||
altdialog = blue
|
||||
note = #b3694d
|
||||
hidden = faded
|
||||
shortcode = red
|
||||
keyword = yellow
|
||||
tag = blue
|
||||
value = red:D125
|
||||
optional = #004d57
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = #00bdd6
|
||||
modifier = red
|
||||
texthighlight = #ade2eb77
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Primer Light
|
||||
mode = light
|
||||
description = Primer
|
||||
author = Myian
|
||||
credit = GitHub Inc.
|
||||
url = https://github.com/primer
|
||||
|
||||
[Base]
|
||||
base = #ffffff
|
||||
default = #1f2328
|
||||
faded = #8c959f
|
||||
red = #cf222e
|
||||
orange = #e16f24
|
||||
yellow = #d4a72c
|
||||
green = #2da44e
|
||||
cyan = #339d9b
|
||||
blue = #0969da
|
||||
purple = #8557db
|
||||
|
||||
[Project]
|
||||
root = #32383f
|
||||
folder = orange
|
||||
file = #49bcb7
|
||||
title = #116329
|
||||
chapter = #2e934a
|
||||
scene = #4ac26b
|
||||
note = yellow
|
||||
active = #24292f
|
||||
inactive = faded
|
||||
disabled = #afb8c1
|
||||
|
||||
[Palette]
|
||||
window = #eaeef2
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #dde3e8
|
||||
text = default
|
||||
tooltipbase = #fff8c5
|
||||
tooltiptext = default
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = green
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = green
|
||||
|
||||
[GUI]
|
||||
helptext = #424a53
|
||||
fadedtext = #8c959f
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #424a53
|
||||
line = #dde3e8
|
||||
link = blue
|
||||
headertext = default
|
||||
headertag = #8c959f
|
||||
emphasis = #2e934a
|
||||
dialog = #000000
|
||||
altdialog = cyan
|
||||
note = #bf8700
|
||||
hidden = #8c959f
|
||||
shortcode = #e85aad
|
||||
keyword = blue
|
||||
tag = #218bff
|
||||
value = orange
|
||||
optional = #54aeff
|
||||
spellcheckline = #fa4549
|
||||
errorline = cyan
|
||||
replacetag = purple
|
||||
modifier = #bc4c00
|
||||
texthighlight = #a7fbbe
|
||||
@@ -0,0 +1,76 @@
|
||||
[Main]
|
||||
name = Primer Night
|
||||
mode = dark
|
||||
description = Primer
|
||||
author = Myian
|
||||
credit = GitHub Inc.
|
||||
url = https://github.com/primer
|
||||
|
||||
[Base]
|
||||
base = #0d1117
|
||||
default = #f0f6fc
|
||||
faded = #6e7681
|
||||
red = #ff7b72
|
||||
orange = #ffa657
|
||||
yellow = #f8e3a1
|
||||
green = #56d364
|
||||
cyan = #57CCC5
|
||||
blue = #79c0ff
|
||||
purple = #c398ff
|
||||
|
||||
[Project]
|
||||
root = default
|
||||
folder = orange
|
||||
file = #8adfd7
|
||||
title = #238636
|
||||
chapter = #56d364
|
||||
scene = #aff5b4
|
||||
note = yellow
|
||||
active = default
|
||||
inactive = faded
|
||||
disabled = #484f58
|
||||
|
||||
[Palette]
|
||||
window = #161b22
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #30363d
|
||||
text = default
|
||||
tooltipbase = yellow
|
||||
tooltiptext = base
|
||||
button = #21262d
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #207c59
|
||||
highlightedtext = default
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #207c59
|
||||
|
||||
[GUI]
|
||||
helptext = #8b949e
|
||||
fadedtext = #6e7681
|
||||
errortext = #f85149
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #b1bac4
|
||||
line = #30363d
|
||||
link = blue
|
||||
headertext = default
|
||||
headertag = #b1bac4
|
||||
emphasis = #97ee9e
|
||||
dialog = #ffffff
|
||||
altdialog = #8adfd7
|
||||
note = #f8e3a1
|
||||
hidden = faded
|
||||
shortcode = #ff9bce
|
||||
keyword = #4493f8
|
||||
tag = blue
|
||||
value = #ffc680
|
||||
optional = #a5d6ff
|
||||
spellcheckline = #f85149
|
||||
errorline = cyan
|
||||
replacetag = purple
|
||||
modifier = orange
|
||||
texthighlight = #104C35
|
||||
@@ -1,48 +1,89 @@
|
||||
[Main]
|
||||
name = Snazzy Light
|
||||
author = Veronica Berglyd Olsen (adaptation)
|
||||
credit = Florian Reuschel (color theme)
|
||||
url = https://github.com/loilo/vscode-snazzy-light
|
||||
license = MIT License
|
||||
licenseurl = https://github.com/loilo/vscode-snazzy-light/blob/master/LICENSE
|
||||
name = Snazzy Light
|
||||
mode = light
|
||||
description = A vivid light color theme
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Florian Reuschel, Sindre Sorhus
|
||||
url = https://github.com/loilo/vscode-snazzy-light
|
||||
|
||||
[Icons]
|
||||
default = 86, 88, 105
|
||||
faded = 84, 85, 84
|
||||
red = 255, 92, 87
|
||||
orange = 245, 185, 0
|
||||
yellow = 207, 156, 0
|
||||
green = 45, 174, 88
|
||||
aqua = 19, 187, 183
|
||||
blue = 9, 161, 237
|
||||
purple = 247, 103, 187
|
||||
##
|
||||
# Colours:
|
||||
# Background = fafbfc : 250, 251, 252
|
||||
# Foreground = 565869 : 86, 88, 105
|
||||
# Comment = 9194a2 : 145, 148, 162
|
||||
# Yellow = cf9c00 : 207, 156, 0
|
||||
# Red = ff5c57 : 255, 92, 87
|
||||
# Pink = f767bb : 247, 103, 187
|
||||
# Blue = 09a1ed : 9, 161, 237
|
||||
# Cyan = 13bbb7 : 19, 187, 183
|
||||
# Green = 2dae58 : 45, 174, 88
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #fafbfc
|
||||
default = #565869
|
||||
faded = #545554
|
||||
red = #ff5c57
|
||||
orange = #f5b900
|
||||
yellow = #cf9c00
|
||||
green = #2dae58
|
||||
cyan = #13bbb7
|
||||
blue = #09a1ed
|
||||
purple = #f767bb
|
||||
|
||||
[Project]
|
||||
root = 9, 161, 237
|
||||
folder = 207, 156, 0
|
||||
file = 84, 85, 84
|
||||
title = 45, 174, 88
|
||||
chapter = 255, 92, 87
|
||||
scene = 9, 161, 237
|
||||
note = 207, 156, 0
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = faded
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 243, 244, 245
|
||||
windowtext = 86, 88, 105
|
||||
base = 250, 251, 252
|
||||
alternatebase = 234, 234, 235
|
||||
text = 86, 88, 105
|
||||
tooltipbase = 245, 233, 194
|
||||
tooltiptext = 86, 88, 105
|
||||
button = 250, 251, 252
|
||||
buttontext = 86, 88, 105
|
||||
brighttext = 255, 255, 255
|
||||
highlight = 9, 161, 237
|
||||
highlightedtext = 255, 255, 255
|
||||
link = 9, 161, 237
|
||||
linkvisited = 9, 161, 237
|
||||
window = #f3f4f5
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #eaeaeb
|
||||
text = default
|
||||
tooltipbase = #f5e9c2
|
||||
tooltiptext = default
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = blue
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = 9, 161, 237
|
||||
fadedtext = 84, 85, 84
|
||||
errortext = 255, 92, 87
|
||||
helptext = blue
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = green
|
||||
headertag = green:D125
|
||||
emphasis = purple
|
||||
dialog = blue
|
||||
altdialog = yellow
|
||||
note = cyan
|
||||
hidden = purple:D150
|
||||
shortcode = purple
|
||||
keyword = blue
|
||||
tag = green
|
||||
value = yellow
|
||||
optional = yellow
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = purple
|
||||
texthighlight = yellow:96
|
||||
|
||||
@@ -1,48 +1,95 @@
|
||||
[Main]
|
||||
name = Solarized Dark
|
||||
author = nullbasis
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
license = MIT
|
||||
licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE
|
||||
name = Solarized Dark
|
||||
mode = dark
|
||||
description = Precision colors for machines and people
|
||||
author = nullbasis, Veronica Berglyd Olsen
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
|
||||
[Icons]
|
||||
default = 230, 223, 206
|
||||
faded = 166, 161, 149
|
||||
red = 220, 50, 47
|
||||
orange = 203, 75, 22
|
||||
yellow = 181, 137, 0
|
||||
green = 133, 153, 0
|
||||
aqua = 42, 161, 152
|
||||
blue = 38, 139, 210
|
||||
purple = 211, 54, 130
|
||||
##
|
||||
# base03: #002b36
|
||||
# base02: #073642
|
||||
# base01: #586e75
|
||||
# base00: #657b83
|
||||
# base0: #839496
|
||||
# base1: #93a1a1
|
||||
# base2: #eee8d5
|
||||
# base3: #fdf6e3
|
||||
# yellow: #b58900
|
||||
# orange: #cb4b16
|
||||
# red: #dc322f
|
||||
# magenta: #d33682
|
||||
# violet: #6c71c4
|
||||
# blue: #268bd2
|
||||
# cyan: #2aa198
|
||||
# green: #859900
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #002b36
|
||||
default = #fdf6e3
|
||||
faded = #eee8d5
|
||||
red = #dc322f
|
||||
orange = #cb4b16
|
||||
yellow = #b58900
|
||||
green = #859900
|
||||
cyan = #2aa198
|
||||
blue = #268bd2
|
||||
purple = #6c71c4
|
||||
|
||||
[Project]
|
||||
root = 42, 161, 152
|
||||
folder = 42, 161, 152
|
||||
file = 230, 223, 206
|
||||
title = 133, 153, 0
|
||||
chapter = 220, 50, 47
|
||||
scene = 38, 139, 210
|
||||
note = 181, 137, 0
|
||||
root = cyan
|
||||
folder = cyan
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 0, 43, 54
|
||||
windowtext = 253, 246, 227
|
||||
base = 7, 54, 66
|
||||
alternatebase = 88, 110, 117
|
||||
text = 253, 246, 227
|
||||
tooltipbase = 133, 153, 0
|
||||
tooltiptext = 0, 43, 54
|
||||
button = 7, 54, 66
|
||||
buttontext = 253, 246, 227
|
||||
brighttext = 7, 54, 66
|
||||
highlight = 42, 161, 152
|
||||
highlightedtext = 0, 43, 54
|
||||
link = 38, 139, 210
|
||||
linkvisited = 38, 139, 210
|
||||
window = #073642
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #586e75
|
||||
text = default
|
||||
tooltipbase = yellow:L150
|
||||
tooltiptext = #002b36
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = cyan
|
||||
highlightedtext = default
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = cyan
|
||||
|
||||
[GUI]
|
||||
helptext = 101, 123, 131
|
||||
fadedtext = 101, 123, 131
|
||||
errortext = 220, 50, 47
|
||||
helptext = cyan
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = #073642
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = #657b83
|
||||
emphasis = blue
|
||||
dialog = cyan
|
||||
altdialog = red
|
||||
note = cyan:D125
|
||||
hidden = default:L200
|
||||
shortcode = blue
|
||||
keyword = green
|
||||
tag = yellow
|
||||
value = orange
|
||||
optional = cyan:D125
|
||||
spellcheckline = red
|
||||
errorline = red
|
||||
replacetag = green
|
||||
modifier = yellow
|
||||
texthighlight = yellow:128
|
||||
|
||||
@@ -1,48 +1,95 @@
|
||||
[Main]
|
||||
name = Solarized Light
|
||||
author = nullbasis
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
license = MIT
|
||||
licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE
|
||||
name = Solarized Light
|
||||
mode = light
|
||||
description = Precision colors for machines and people
|
||||
author = nullbasis, Veronica Berglyd Olsen
|
||||
credit = Ethan Schoonover
|
||||
url = https://ethanschoonover.com/solarized/
|
||||
|
||||
[Icons]
|
||||
default = 59, 68, 71
|
||||
faded = 78, 91, 95
|
||||
red = 220, 50, 47
|
||||
orange = 203, 75, 22
|
||||
yellow = 181, 137, 0
|
||||
green = 133, 153, 0
|
||||
aqua = 42, 161, 152
|
||||
blue = 38, 139, 210
|
||||
purple = 211, 54, 130
|
||||
##
|
||||
# base03: #002b36
|
||||
# base02: #073642
|
||||
# base01: #586e75
|
||||
# base00: #657b83
|
||||
# base0: #839496
|
||||
# base1: #93a1a1
|
||||
# base2: #eee8d5
|
||||
# base3: #fdf6e3
|
||||
# yellow: #b58900
|
||||
# orange: #cb4b16
|
||||
# red: #dc322f
|
||||
# magenta: #d33682
|
||||
# violet: #6c71c4
|
||||
# blue: #268bd2
|
||||
# cyan: #2aa198
|
||||
# green: #859900
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #fdf6e3
|
||||
default = #002b36
|
||||
faded = #073642
|
||||
red = #dc322f
|
||||
orange = #cb4b16
|
||||
yellow = #b58900
|
||||
green = #859900
|
||||
cyan = #2aa198
|
||||
blue = #268bd2
|
||||
purple = #6c71c4
|
||||
|
||||
[Project]
|
||||
root = 42, 161, 152
|
||||
folder = 42, 161, 152
|
||||
file = 59, 68, 71
|
||||
title = 133, 153, 0
|
||||
chapter = 220, 50, 47
|
||||
scene = 38, 139, 210
|
||||
note = 181, 137, 0
|
||||
root = cyan
|
||||
folder = cyan
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = 238, 232, 213
|
||||
windowtext = 0, 43, 54
|
||||
base = 253, 246, 227
|
||||
alternatebase = 147, 161, 161
|
||||
text = 0, 43, 54
|
||||
tooltipbase = 133, 153, 0
|
||||
tooltiptext = 0, 43, 54
|
||||
button = 238, 232, 213
|
||||
buttontext = 0, 43, 54
|
||||
brighttext = 253, 246, 227
|
||||
highlight = 42, 161, 152
|
||||
highlightedtext = 253, 246, 227
|
||||
link = 38, 139, 210
|
||||
linkvisited = 38, 139, 210
|
||||
window = #eee8d5
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #93a1a1
|
||||
text = default
|
||||
tooltipbase = yellow:L150
|
||||
tooltiptext = #002b36
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = cyan
|
||||
highlightedtext = default
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = cyan
|
||||
|
||||
[GUI]
|
||||
helptext = 78, 91, 95
|
||||
fadedtext = 78, 91, 95
|
||||
errortext = 220, 50, 47
|
||||
helptext = cyan
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = #eee8d5
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = #657b83
|
||||
emphasis = blue
|
||||
dialog = cyan
|
||||
altdialog = red
|
||||
note = cyan:D125
|
||||
hidden = default:L200
|
||||
shortcode = blue
|
||||
keyword = green
|
||||
tag = yellow
|
||||
value = orange
|
||||
optional = cyan:D125
|
||||
spellcheckline = red
|
||||
errorline = red
|
||||
replacetag = green
|
||||
modifier = yellow
|
||||
texthighlight = yellow:128
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
[Main]
|
||||
name = Tango Dark
|
||||
mode = dark
|
||||
description = Colors for everyone
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Tango Desktop Project
|
||||
url = https://en.wikipedia.org/wiki/Tango_Desktop_Project
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = #30302f
|
||||
# Foreground = #eeeeec
|
||||
# Comment = #8f8f8d
|
||||
# Red = #ef2929
|
||||
# Orange = #c4a000
|
||||
# Yellow = #fce94f
|
||||
# Green = #8ae234
|
||||
# Cyan = #34e2e2
|
||||
# Blue = #3465a4
|
||||
# Purple = #ad7fa8
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #2e3436
|
||||
default = #eeeeec
|
||||
faded = #babdb6
|
||||
red = #ef2929
|
||||
orange = #fcaf3e
|
||||
yellow = #fce94f
|
||||
green = #8ae234
|
||||
cyan = #34e2e2
|
||||
blue = #729fcf
|
||||
purple = #ad7fa8
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L140
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #454e51
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #555753
|
||||
buttontext = default
|
||||
brighttext = #555753
|
||||
highlight = blue
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = orange
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:160
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = yellow:L115
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = red
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = blue
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,90 @@
|
||||
[Main]
|
||||
name = Tango Light
|
||||
mode = light
|
||||
description = Colors for everyone
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Tango Desktop Project
|
||||
url = https://en.wikipedia.org/wiki/Tango_Desktop_Project
|
||||
|
||||
##
|
||||
# Colours:
|
||||
# Background = #eeeeec
|
||||
# Foreground = #2e3436
|
||||
# Comment = #8f8f8d
|
||||
# Red = #a40000
|
||||
# Orange = #c4a000
|
||||
# Yellow = #fce94f
|
||||
# Green = #8ae234
|
||||
# Cyan = #34e2e2
|
||||
# Blue = #3465a4
|
||||
# Purple = #ad7fa8
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #eeeeec
|
||||
default = #2e3436
|
||||
faded = #888a85
|
||||
red = #a40000
|
||||
orange = #ce5c00
|
||||
yellow = #c4a000
|
||||
green = #4e9a06
|
||||
cyan = #069a9a
|
||||
blue = #204a87
|
||||
purple = #5c3566
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:D110
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #e0e0e0
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #d3d7cf
|
||||
buttontext = default
|
||||
brighttext = #d3d7cf
|
||||
highlight = blue:L200
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue:L150
|
||||
|
||||
[GUI]
|
||||
helptext = orange
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:160
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = yellow:D125
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = red
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = blue
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Tomorrow
|
||||
mode = light
|
||||
description = A colourful theme with muted colours and sensible highlighting
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Chris Kempson
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
|
||||
##
|
||||
# Theme: Tomorrow
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = #ffffff
|
||||
# Current Line = #efefef
|
||||
# Selection = #d6d6d6
|
||||
# Foreground = #4d4d4c
|
||||
# Comment = #8e908c
|
||||
# Red = #c82829
|
||||
# Orange = #f5871f
|
||||
# Yellow = #eab700
|
||||
# Green = #718c00
|
||||
# Aqua = #3e999f
|
||||
# Blue = #4271ae
|
||||
# Purple = #8959a8
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #ffffff
|
||||
default = #484848
|
||||
faded = #6c6c6c
|
||||
red = #c82829
|
||||
orange = #f5871f
|
||||
yellow = #eab700
|
||||
green = #718c00
|
||||
cyan = #3e999f
|
||||
blue = #4271ae
|
||||
purple = #8959a8
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #efefef
|
||||
windowtext = #000000
|
||||
base = base
|
||||
alternatebase = #d6d6d6
|
||||
text = #000000
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = #efefef
|
||||
buttontext = #000000
|
||||
brighttext = #efefef
|
||||
highlight = blue
|
||||
highlightedtext = base
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = blue
|
||||
|
||||
[GUI]
|
||||
helptext = #5c5c5c
|
||||
fadedtext = faded
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = #4d4d4c
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:L135
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #b38c00
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = yellow
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = orange
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Tomorrow Night
|
||||
mode = dark
|
||||
description = A colourful theme with muted colours and sensible highlighting
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Chris Kempson
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
|
||||
##
|
||||
# Theme: Tomorrow Night
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = #1d1f21
|
||||
# Current Line = #282a2e
|
||||
# Selection = #373b41
|
||||
# Foreground = #c5c8c6
|
||||
# Comment = #969896
|
||||
# Red = #cc6666
|
||||
# Orange = #de935f
|
||||
# Yellow = #f0c674
|
||||
# Green = #b5bd68
|
||||
# Aqua = #8abeb7
|
||||
# Blue = #81a2be
|
||||
# Purple = #b294bb
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #1d1f21
|
||||
default = #c5c8c6
|
||||
faded = #969896
|
||||
red = #cc6666
|
||||
orange = #de935f
|
||||
yellow = #f0c674
|
||||
green = #b5bd68
|
||||
cyan = #8abeb7
|
||||
blue = #81a2be
|
||||
purple = #b294bb
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #282a2e
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #373b41
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = #a4a4a4
|
||||
fadedtext = #949494
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:48
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #f0dbb2
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = yellow
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = orange
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Tomorrow Night Blue
|
||||
mode = dark
|
||||
description = A colourful theme with muted colours and sensible highlighting
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Chris Kempson
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
|
||||
##
|
||||
# Theme: Tomorrow Night Blue
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = #002451
|
||||
# Current Line = #00346e
|
||||
# Selection = #003f8e
|
||||
# Foreground = #ffffff
|
||||
# Comment = #7285b7
|
||||
# Red = #ff9da4
|
||||
# Orange = #ffc58f
|
||||
# Yellow = #ffeead
|
||||
# Green = #d1f1a9
|
||||
# Aqua = #99ffff
|
||||
# Blue = #bbdaff
|
||||
# Purple = #ebbbff
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #002451
|
||||
default = #ffffff
|
||||
faded = #7285b7
|
||||
red = #ff9da4
|
||||
orange = #ffc58f
|
||||
yellow = #ffeead
|
||||
green = #d1f1a9
|
||||
cyan = #99ffff
|
||||
blue = #bbdaff
|
||||
purple = #ebbbff
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = base:L125
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #003f8e
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = #a4a4a4
|
||||
fadedtext = #949494
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #fff4cc
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = yellow
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = orange
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Tomorrow Night Bright
|
||||
mode = dark
|
||||
description = A colourful theme with muted colours and sensible highlighting
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Chris Kempson
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
|
||||
##
|
||||
# Theme: Tomorrow Night Bright
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = #000000
|
||||
# Current Line = #2a2a2a
|
||||
# Selection = #424242
|
||||
# Foreground = #eaeaea
|
||||
# Comment = #969896
|
||||
# Red = #d54e53
|
||||
# Orange = #e78c45
|
||||
# Yellow = #e7c547
|
||||
# Green = #b9ca4a
|
||||
# Aqua = #70c0b1
|
||||
# Blue = #7aa6da
|
||||
# Purple = #c397d8
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #000000
|
||||
default = #eaeaea
|
||||
faded = #969896
|
||||
red = #d54e53
|
||||
orange = #e78c45
|
||||
yellow = #e7c547
|
||||
green = #b9ca4a
|
||||
cyan = #70c0b1
|
||||
blue = #7aa6da
|
||||
purple = #c397d8
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #181818
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #424242
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = #a4a4a4
|
||||
fadedtext = #949494
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:48
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #e7d696
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = yellow
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = orange
|
||||
texthighlight = yellow:96
|
||||
@@ -0,0 +1,96 @@
|
||||
[Main]
|
||||
name = Tomorrow Night Eighties
|
||||
mode = dark
|
||||
description = A colourful theme with muted colours and sensible highlighting
|
||||
author = Veronica Berglyd Olsen
|
||||
credit = Chris Kempson
|
||||
url = https://github.com/chriskempson/tomorrow-theme
|
||||
|
||||
##
|
||||
# Theme: Tomorrow Night Eighties
|
||||
# Source: https://github.com/chriskempson/tomorrow-theme
|
||||
# Credit: Chris Kempson
|
||||
##
|
||||
# Colours:
|
||||
# Background = #2d2d2d
|
||||
# Current Line = #393939
|
||||
# Selection = #515151
|
||||
# Foreground = #cccccc
|
||||
# Comment = #999999
|
||||
# Red = #f2777a
|
||||
# Orange = #f99157
|
||||
# Yellow = #ffcc66
|
||||
# Green = #99cc99
|
||||
# Aqua = #66cccc
|
||||
# Blue = #6699cc
|
||||
# Purple = #cc99cc
|
||||
##
|
||||
|
||||
[Base]
|
||||
base = #2d2d2d
|
||||
default = #cccccc
|
||||
faded = #999999
|
||||
red = #f2777a
|
||||
orange = #f99157
|
||||
yellow = #ffcc66
|
||||
green = #99cc99
|
||||
cyan = #66cccc
|
||||
blue = #6699cc
|
||||
purple = #cc99cc
|
||||
|
||||
[Project]
|
||||
root = blue
|
||||
folder = yellow
|
||||
file = default
|
||||
title = green
|
||||
chapter = red
|
||||
scene = blue
|
||||
note = yellow
|
||||
active = green
|
||||
inactive = red
|
||||
disabled = faded
|
||||
|
||||
[Palette]
|
||||
window = #393939
|
||||
windowtext = default
|
||||
base = base
|
||||
alternatebase = #515151
|
||||
text = default
|
||||
tooltipbase = #ffffc0
|
||||
tooltiptext = #15150d
|
||||
button = base
|
||||
buttontext = default
|
||||
brighttext = base
|
||||
highlight = #2c98f7
|
||||
highlightedtext = #ffffff
|
||||
link = blue
|
||||
linkvisited = blue
|
||||
accent = #2c98f7
|
||||
|
||||
[GUI]
|
||||
helptext = #a4a4a4
|
||||
fadedtext = #949494
|
||||
errortext = red
|
||||
|
||||
[Syntax]
|
||||
background = base
|
||||
text = default
|
||||
line = default:32
|
||||
link = blue
|
||||
headertext = blue
|
||||
headertag = blue:D150
|
||||
emphasis = orange
|
||||
dialog = green
|
||||
altdialog = yellow
|
||||
note = #ffe6b3
|
||||
hidden = faded
|
||||
shortcode = blue
|
||||
keyword = red
|
||||
tag = purple
|
||||
value = yellow
|
||||
optional = blue
|
||||
spellcheckline = red
|
||||
errorline = green
|
||||
replacetag = cyan
|
||||
modifier = orange
|
||||
texthighlight = yellow:96
|
||||
@@ -31,6 +31,7 @@ import xml.etree.ElementTree as ET
|
||||
|
||||
from configparser import ConfigParser
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeGuard, TypeVar
|
||||
from urllib.parse import urljoin
|
||||
@@ -691,6 +692,9 @@ def openExternalPath(path: Path) -> bool:
|
||||
# Classes
|
||||
##
|
||||
|
||||
_T_Enum = TypeVar("_T_Enum", bound=Enum)
|
||||
|
||||
|
||||
class NWConfigParser(ConfigParser):
|
||||
"""Common: Adapted Config Parser
|
||||
|
||||
@@ -751,3 +755,10 @@ class NWConfigParser(ConfigParser):
|
||||
for i in range(min(len(data), len(result))):
|
||||
result[i] = checkInt(data[i].strip(), result[i])
|
||||
return result
|
||||
|
||||
def rdEnum(self, section: str, option: str, default: _T_Enum) -> _T_Enum:
|
||||
"""Read enum value."""
|
||||
if self.has_option(section, option):
|
||||
data = self.get(section, option, fallback="")
|
||||
return type(default).__members__.get(data.upper(), default)
|
||||
return default
|
||||
|
||||
+45
-35
@@ -45,6 +45,7 @@ from novelwriter.common import (
|
||||
formatTimeStamp, processDialogSymbols, simplified
|
||||
)
|
||||
from novelwriter.constants import nwFiles, nwQuotes, nwUnicode
|
||||
from novelwriter.enum import nwTheme
|
||||
from novelwriter.error import formatException, logException
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -55,8 +56,8 @@ if TYPE_CHECKING:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DEF_GUI = "default"
|
||||
DEF_SYNTAX = "default_light"
|
||||
DEF_GUI_DARK = "default_dark"
|
||||
DEF_GUI_LIGHT = "default_light"
|
||||
DEF_ICONS = "material_rounded_normal"
|
||||
DEF_TREECOL = "theme"
|
||||
|
||||
@@ -69,22 +70,23 @@ class Config:
|
||||
"_manuals", "_nwLangPath", "_qLocale", "_qtLangPath", "_qtTrans", "_recentPaths",
|
||||
"_recentProjects", "_splash", "allowOpenDial", "altDialogClose", "altDialogOpen",
|
||||
"appHandle", "appName", "askBeforeBackup", "askBeforeExit", "autoSaveDoc", "autoSaveProj",
|
||||
"autoScroll", "autoScrollPos", "autoSelect", "backupOnClose", "cursorWidth", "dialogLine",
|
||||
"dialogStyle", "doJustify", "doReplace", "doReplaceDQuote", "doReplaceDash",
|
||||
"autoScroll", "autoScrollPos", "autoSelect", "backupOnClose", "cursorWidth", "darkTheme",
|
||||
"dialogLine", "dialogStyle", "doJustify", "doReplace", "doReplaceDQuote", "doReplaceDash",
|
||||
"doReplaceDots", "doReplaceSQuote", "emphLabels", "fmtApostrophe", "fmtDQuoteClose",
|
||||
"fmtDQuoteOpen", "fmtPadAfter", "fmtPadBefore", "fmtPadThin", "fmtSQuoteClose",
|
||||
"fmtSQuoteOpen", "focusWidth", "guiFont", "guiLocale", "guiSyntax", "guiTheme",
|
||||
"hasEnchant", "hideFocusFooter", "hideHScroll", "hideVScroll", "highlightEmph", "hostName",
|
||||
"iconColDocs", "iconColTree", "iconTheme", "incNotesWCount", "isDebug", "kernelVer",
|
||||
"lastNotes", "mainPanePos", "mainWinSize", "memInfo", "narratorBreak", "narratorDialog",
|
||||
"nativeFont", "osDarwin", "osLinux", "osType", "osUnknown", "osWindows", "outlinePanePos",
|
||||
"prefsWinSize", "scrollPastEnd", "searchCase", "searchLoop", "searchMatchCap",
|
||||
"searchNextFile", "searchProjCase", "searchProjRegEx", "searchProjWord", "searchRegEx",
|
||||
"searchWord", "showEditToolBar", "showFullPath", "showLineEndings", "showMultiSpaces",
|
||||
"showSessionTime", "showTabsNSpaces", "showViewerPanel", "spellLanguage", "stopWhenIdle",
|
||||
"tabWidth", "textFont", "textMargin", "textWidth", "useCharCount", "userIdleTime",
|
||||
"verPyQtString", "verPyQtValue", "verPyString", "verQtString", "verQtValue",
|
||||
"viewComments", "viewPanePos", "viewSynopsis", "welcomeWinSize",
|
||||
"fmtSQuoteOpen", "focusWidth", "guiFont", "guiLocale", "hasEnchant", "hideFocusFooter",
|
||||
"hideHScroll", "hideVScroll", "highlightEmph", "hostName", "iconColDocs", "iconColTree",
|
||||
"iconTheme", "incNotesWCount", "isDebug", "kernelVer", "lastNotes", "lightTheme",
|
||||
"lineHighlight", "mainPanePos", "mainWinSize", "memInfo", "narratorBreak",
|
||||
"narratorDialog", "nativeFont", "osDarwin", "osLinux", "osType", "osUnknown", "osWindows",
|
||||
"outlinePanePos", "prefsWinSize", "scrollPastEnd", "searchCase", "searchLoop",
|
||||
"searchMatchCap", "searchNextFile", "searchProjCase", "searchProjRegEx", "searchProjWord",
|
||||
"searchRegEx", "searchWord", "showEditToolBar", "showFullPath", "showLineEndings",
|
||||
"showMultiSpaces", "showSessionTime", "showTabsNSpaces", "showViewerPanel",
|
||||
"spellLanguage", "stopWhenIdle", "tabWidth", "textFont", "textMargin", "textWidth",
|
||||
"themeMode", "useCharCount", "userIdleTime", "verPyQtString", "verPyQtValue",
|
||||
"verPyString", "verQtString", "verQtValue", "viewComments", "viewNotes", "viewPanePos",
|
||||
"viewSynopsis", "welcomeWinSize",
|
||||
)
|
||||
|
||||
LANG_NW = 1
|
||||
@@ -153,14 +155,15 @@ class Config:
|
||||
|
||||
# General GUI Settings
|
||||
self.guiLocale = self._qLocale.name()
|
||||
self.guiTheme = DEF_GUI # GUI theme
|
||||
self.guiSyntax = DEF_SYNTAX # Syntax theme
|
||||
self.guiFont = QFont() # Main GUI font
|
||||
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
||||
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
||||
self.lastNotes = "0x0" # The latest release notes that have been shown
|
||||
self.nativeFont = True # Use native font dialog
|
||||
self.useCharCount = False # Use character count as primary count
|
||||
self.lightTheme = DEF_GUI_LIGHT # Light GUI theme
|
||||
self.darkTheme = DEF_GUI_DARK # Dark GUI theme
|
||||
self.themeMode = nwTheme.AUTO # Colour theme mode
|
||||
self.guiFont = QFont() # Main GUI font
|
||||
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
||||
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
||||
self.lastNotes = "0x0" # The latest release notes that have been shown
|
||||
self.nativeFont = True # Use native font dialog
|
||||
self.useCharCount = False # Use character count as primary count
|
||||
|
||||
# Icons
|
||||
self.iconTheme = DEF_ICONS # Icons theme
|
||||
@@ -178,8 +181,8 @@ class Config:
|
||||
# Project Settings
|
||||
self.autoSaveProj = 60 # Interval for auto-saving project, in seconds
|
||||
self.autoSaveDoc = 30 # Interval for auto-saving document, in seconds
|
||||
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
||||
self.backupOnClose = False # Flag for running automatic backups
|
||||
self.emphLabels = False # Add emphasis to H1 and H2 item labels
|
||||
self.backupOnClose = True # Flag for running automatic backups
|
||||
self.askBeforeBackup = True # Flag for asking before running automatic backup
|
||||
self.askBeforeExit = True # Flag for asking before exiting the app
|
||||
|
||||
@@ -189,6 +192,7 @@ class Config:
|
||||
self.textMargin = 40 # Editor/viewer text margin
|
||||
self.tabWidth = 40 # Editor tabulator width
|
||||
self.cursorWidth = 1 # Editor cursor width
|
||||
self.lineHighlight = False # Highlight current line in editor
|
||||
|
||||
self.focusWidth = 800 # Focus Mode text width
|
||||
self.hideFocusFooter = False # Hide document footer in Focus Mode
|
||||
@@ -206,7 +210,7 @@ class Config:
|
||||
self.doReplaceDash = True # Replace multiple hyphens with dashes
|
||||
self.doReplaceDots = True # Replace three dots with ellipsis
|
||||
|
||||
self.autoScroll = False # Typewriter-like scrolling
|
||||
self.autoScroll = True # Typewriter-like scrolling
|
||||
self.autoScrollPos = 30 # Start point for typewriter-like scrolling
|
||||
self.scrollPastEnd = True # Scroll past end of document, and centre cursor
|
||||
|
||||
@@ -245,6 +249,7 @@ class Config:
|
||||
self.showSessionTime = True # Show the session time in the status bar
|
||||
self.viewComments = True # Comments are shown in the viewer
|
||||
self.viewSynopsis = True # Synopsis is shown in the viewer
|
||||
self.viewNotes = True # Notes are shown in the viewer
|
||||
|
||||
# Search Box States
|
||||
self.searchCase = False
|
||||
@@ -403,7 +408,7 @@ class Config:
|
||||
else:
|
||||
font = QFontDatabase.systemFont(QFontDatabase.SystemFont.GeneralFont)
|
||||
self.guiFont = fontMatcher(font)
|
||||
logger.debug("GUI font set to: %s", describeFont(font))
|
||||
logger.debug("Main font set to: %s", describeFont(font))
|
||||
QApplication.setFont(self.guiFont)
|
||||
return
|
||||
|
||||
@@ -551,11 +556,10 @@ class Config:
|
||||
self._confPath.mkdir(exist_ok=True)
|
||||
self._dataPath.mkdir(exist_ok=True)
|
||||
|
||||
# Also create the syntax, themes and icons folders if possible
|
||||
# Also create the themes and icons folders if possible
|
||||
if self._dataPath.is_dir():
|
||||
(self._dataPath / "cache").mkdir(exist_ok=True)
|
||||
(self._dataPath / "icons").mkdir(exist_ok=True)
|
||||
(self._dataPath / "syntax").mkdir(exist_ok=True)
|
||||
(self._dataPath / "themes").mkdir(exist_ok=True)
|
||||
|
||||
self._recentPaths.loadCache()
|
||||
@@ -626,8 +630,9 @@ class Config:
|
||||
# Main
|
||||
sec = "Main"
|
||||
self.setGuiFont(conf.rdStr(sec, "font", ""))
|
||||
self.guiTheme = conf.rdStr(sec, "theme", self.guiTheme)
|
||||
self.guiSyntax = conf.rdStr(sec, "syntax", self.guiSyntax)
|
||||
self.lightTheme = conf.rdStr(sec, "lighttheme", self.lightTheme)
|
||||
self.darkTheme = conf.rdStr(sec, "darktheme", self.darkTheme)
|
||||
self.themeMode = conf.rdEnum(sec, "thememode", self.themeMode)
|
||||
self.iconTheme = conf.rdStr(sec, "icons", self.iconTheme)
|
||||
self.iconColTree = conf.rdStr(sec, "iconcoltree", self.iconColTree)
|
||||
self.iconColDocs = conf.rdBool(sec, "iconcoldocs", self.iconColDocs)
|
||||
@@ -665,6 +670,7 @@ class Config:
|
||||
self.textMargin = conf.rdInt(sec, "margin", self.textMargin)
|
||||
self.tabWidth = conf.rdInt(sec, "tabwidth", self.tabWidth)
|
||||
self.cursorWidth = conf.rdInt(sec, "cursorwidth", self.cursorWidth)
|
||||
self.lineHighlight = conf.rdBool(sec, "linehighlight", self.lineHighlight)
|
||||
self.focusWidth = conf.rdInt(sec, "focuswidth", self.focusWidth)
|
||||
self.hideFocusFooter = conf.rdBool(sec, "hidefocusfooter", self.hideFocusFooter)
|
||||
self.doJustify = conf.rdBool(sec, "justify", self.doJustify)
|
||||
@@ -708,6 +714,7 @@ class Config:
|
||||
self.showSessionTime = conf.rdBool(sec, "showsessiontime", self.showSessionTime)
|
||||
self.viewComments = conf.rdBool(sec, "viewcomments", self.viewComments)
|
||||
self.viewSynopsis = conf.rdBool(sec, "viewsynopsis", self.viewSynopsis)
|
||||
self.viewNotes = conf.rdBool(sec, "viewnotes", self.viewNotes)
|
||||
self.searchCase = conf.rdBool(sec, "searchcase", self.searchCase)
|
||||
self.searchWord = conf.rdBool(sec, "searchword", self.searchWord)
|
||||
self.searchRegEx = conf.rdBool(sec, "searchregex", self.searchRegEx)
|
||||
@@ -721,7 +728,7 @@ class Config:
|
||||
# Check Values
|
||||
# ============
|
||||
|
||||
self._prepareFont(self.guiFont, "GUI")
|
||||
self._prepareFont(self.guiFont, "main")
|
||||
self._prepareFont(self.textFont, "document")
|
||||
|
||||
# If we're using straight quotes, disable auto-replace
|
||||
@@ -751,8 +758,9 @@ class Config:
|
||||
|
||||
conf["Main"] = {
|
||||
"font": self.guiFont.toString(),
|
||||
"theme": str(self.guiTheme),
|
||||
"syntax": str(self.guiSyntax),
|
||||
"lighttheme": str(self.lightTheme),
|
||||
"darktheme": str(self.darkTheme),
|
||||
"thememode": self.themeMode.name,
|
||||
"icons": str(self.iconTheme),
|
||||
"iconcoltree": str(self.iconColTree),
|
||||
"iconcoldocs": str(self.iconColDocs),
|
||||
@@ -790,6 +798,7 @@ class Config:
|
||||
"margin": str(self.textMargin),
|
||||
"tabwidth": str(self.tabWidth),
|
||||
"cursorwidth": str(self.cursorWidth),
|
||||
"lineHighlight": str(self.lineHighlight),
|
||||
"focuswidth": str(self.focusWidth),
|
||||
"hidefocusfooter": str(self.hideFocusFooter),
|
||||
"justify": str(self.doJustify),
|
||||
@@ -833,6 +842,7 @@ class Config:
|
||||
"showsessiontime": str(self.showSessionTime),
|
||||
"viewcomments": str(self.viewComments),
|
||||
"viewsynopsis": str(self.viewSynopsis),
|
||||
"viewnotes": str(self.viewNotes),
|
||||
"searchcase": str(self.searchCase),
|
||||
"searchword": str(self.searchWord),
|
||||
"searchregex": str(self.searchRegEx),
|
||||
|
||||
@@ -28,7 +28,8 @@ from typing import Final
|
||||
from PyQt6.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
|
||||
|
||||
from novelwriter.enum import (
|
||||
nwBuildFmt, nwComment, nwItemClass, nwItemLayout, nwOutline, nwStatusShape
|
||||
nwBuildFmt, nwComment, nwItemClass, nwItemLayout, nwOutline, nwStatusShape,
|
||||
nwTheme
|
||||
)
|
||||
|
||||
|
||||
@@ -76,6 +77,7 @@ class nwRegEx:
|
||||
FMT_EI = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_EB = r"(?<![\w\\])(\*{2})(?![\s\*])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_ST = r"(?<![\w\\])(~{2})(?![\s~])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_HL = r"(?<![\w\\])(={2})(?![\s=])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_SC = r"(?i)(?<!\\)(\[(?:b|/b|i|/i|s|/s|u|/u|m|/m|sup|/sup|sub|/sub|br)\])"
|
||||
FMT_SV = r"(?i)(?<!\\)(\[(?:footnote|field):)(.+?)(?<!\\)(\])"
|
||||
|
||||
@@ -446,17 +448,27 @@ class nwLabels:
|
||||
"Custom": (-1.0, -1.0),
|
||||
}
|
||||
THEME_COLORS: Final[dict[str, str]] = {
|
||||
"theme": QT_TRANSLATE_NOOP("Constant", "Theme Colours"),
|
||||
"default": QT_TRANSLATE_NOOP("Constant", "Foreground Colour"),
|
||||
"base": QT_TRANSLATE_NOOP("Constant", "Background Colour"),
|
||||
"faded": QT_TRANSLATE_NOOP("Constant", "Faded Colour"),
|
||||
"red": QT_TRANSLATE_NOOP("Constant", "Red"),
|
||||
"orange": QT_TRANSLATE_NOOP("Constant", "Orange"),
|
||||
"yellow": QT_TRANSLATE_NOOP("Constant", "Yellow"),
|
||||
"green": QT_TRANSLATE_NOOP("Constant", "Green"),
|
||||
"aqua": QT_TRANSLATE_NOOP("Constant", "Aqua"),
|
||||
"cyan": QT_TRANSLATE_NOOP("Constant", "Cyan"),
|
||||
"blue": QT_TRANSLATE_NOOP("Constant", "Blue"),
|
||||
"purple": QT_TRANSLATE_NOOP("Constant", "Purple"),
|
||||
}
|
||||
THEME_MODE_ICON: Final[dict[nwTheme, str]] = {
|
||||
nwTheme.AUTO: "theme_auto",
|
||||
nwTheme.LIGHT: "theme_light",
|
||||
nwTheme.DARK: "theme_dark",
|
||||
}
|
||||
THEME_MODE_LABEL: Final[dict[nwTheme, str]] = {
|
||||
nwTheme.AUTO: QT_TRANSLATE_NOOP("Constant", "System Theme"),
|
||||
nwTheme.LIGHT: QT_TRANSLATE_NOOP("Constant", "Light Theme"),
|
||||
nwTheme.DARK: QT_TRANSLATE_NOOP("Constant", "Dark Theme"),
|
||||
}
|
||||
|
||||
|
||||
class nwHeadFmt:
|
||||
|
||||
@@ -607,6 +607,7 @@ class ProjectBuilder:
|
||||
project.data.setSaveCount(0)
|
||||
project.data.setAutoCount(0)
|
||||
project.data.setEditTime(0)
|
||||
project.index.rebuild()
|
||||
project.saveProject()
|
||||
project.closeProject()
|
||||
return
|
||||
|
||||
@@ -363,13 +363,13 @@ class NWItem:
|
||||
"""
|
||||
if self.isFileType():
|
||||
key = "checked" if self._active else "unchecked"
|
||||
color = "green" if self._active else "red"
|
||||
color = "active" if self._active else "inactive"
|
||||
text = trConst(nwLabels.ACTIVE_NAME[key])
|
||||
icon = SHARED.theme.getIcon(key, color)
|
||||
else:
|
||||
key = "noncheckable"
|
||||
color = "disabled"
|
||||
text = ""
|
||||
icon = SHARED.theme.getIcon("noncheckable", "faded")
|
||||
return text, icon
|
||||
return text, SHARED.theme.getIcon(key, color)
|
||||
|
||||
##
|
||||
# Checker Methods
|
||||
|
||||
@@ -483,14 +483,14 @@ class NWProject:
|
||||
|
||||
def setDefaultStatusImport(self) -> None:
|
||||
"""Set the default status and importance values."""
|
||||
self._data.itemStatus.add(None, self.tr("New"), (120, 120, 120), "STAR", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Note"), (205, 171, 143), "TRIANGLE", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Draft"), (143, 240, 164), "CIRCLE_T", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Finished"), (249, 240, 107), "STAR", 0)
|
||||
self._data.itemImport.add(None, self.tr("New"), (120, 120, 120), "SQUARE", 0)
|
||||
self._data.itemImport.add(None, self.tr("Minor"), (220, 138, 221), "BLOCK_2", 0)
|
||||
self._data.itemImport.add(None, self.tr("Major"), (220, 138, 221), "BLOCK_3", 0)
|
||||
self._data.itemImport.add(None, self.tr("Main"), (220, 138, 221), "BLOCK_4", 0)
|
||||
self._data.itemStatus.add(None, self.tr("New"), "faded", "STAR", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Note"), "red", "TRIANGLE", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Draft"), "yellow", "CIRCLE_T", 0)
|
||||
self._data.itemStatus.add(None, self.tr("Finished"), "green", "STAR", 0)
|
||||
self._data.itemImport.add(None, self.tr("New"), "purple", "SQUARE", 0)
|
||||
self._data.itemImport.add(None, self.tr("Minor"), "purple", "BLOCK_2", 0)
|
||||
self._data.itemImport.add(None, self.tr("Major"), "purple", "BLOCK_3", 0)
|
||||
self._data.itemImport.add(None, self.tr("Main"), "purple", "BLOCK_4", 0)
|
||||
return
|
||||
|
||||
def setProjectLang(self, language: str | None) -> None:
|
||||
@@ -547,6 +547,12 @@ class NWProject:
|
||||
self._tree.refreshAllItems()
|
||||
return
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
"""Update theme elements."""
|
||||
self._data.itemStatus.refreshIcons()
|
||||
self._data.itemImport.refreshIcons()
|
||||
return
|
||||
|
||||
def localLookup(self, word: str | int) -> str:
|
||||
"""Look up a word or number in the translation map for the
|
||||
project and return it. The variable is cast to a string before
|
||||
|
||||
@@ -46,7 +46,7 @@ if TYPE_CHECKING:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
FILE_VERSION = "1.5" # The current project file format version
|
||||
FILE_REVISION = "5" # The current project file format revision
|
||||
FILE_REVISION = "6" # The current project file format revision
|
||||
HEX_VERSION = 0x0105
|
||||
|
||||
NUM_VERSION = {
|
||||
@@ -111,6 +111,8 @@ class ProjectXMLReader:
|
||||
nodes. 2.5.
|
||||
Rev 5: Added novelChars and notesChars attributes to content
|
||||
node. 2.7 RC 1.
|
||||
Rev 6: Replaced red, green and blue attributes with a single
|
||||
color attribute. 2.8 Beta 1.
|
||||
"""
|
||||
|
||||
def __init__(self, path: str | Path) -> None:
|
||||
@@ -439,12 +441,15 @@ class ProjectXMLReader:
|
||||
for xEntry in xItem:
|
||||
if xEntry.tag == "entry":
|
||||
key = xEntry.attrib.get("key", None)
|
||||
red = checkInt(xEntry.attrib.get("red", 0), 0)
|
||||
green = checkInt(xEntry.attrib.get("green", 0), 0)
|
||||
blue = checkInt(xEntry.attrib.get("blue", 0), 0)
|
||||
red = checkInt(xEntry.attrib.get("red", 0), 0) # Deprecated in 1.5 R6
|
||||
green = checkInt(xEntry.attrib.get("green", 0), 0) # Deprecated in 1.5 R6
|
||||
blue = checkInt(xEntry.attrib.get("blue", 0), 0) # Deprecated in 1.5 R6
|
||||
color = xEntry.attrib.get("color") # Added in 1.5 R6
|
||||
count = checkInt(xEntry.attrib.get("count", 0), 0)
|
||||
shape = xEntry.attrib.get("shape", "")
|
||||
sObject.add(key, xEntry.text or "", (red, green, blue), shape, count)
|
||||
if color is None:
|
||||
color = f"{red}, {green}, {blue}"
|
||||
sObject.add(key, xEntry.text or "", color, shape, count)
|
||||
return
|
||||
|
||||
def _parseDictKeyText(self, xItem: ET.Element) -> dict:
|
||||
|
||||
+23
-12
@@ -35,6 +35,7 @@ from PyQt6.QtGui import QColor, QIcon, QPainter, QPainterPath, QPixmap, QPolygon
|
||||
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.common import simplified
|
||||
from novelwriter.constants import nwLabels
|
||||
from novelwriter.enum import nwStatusShape
|
||||
from novelwriter.types import QtPaintAntiAlias, QtTransparent
|
||||
|
||||
@@ -43,12 +44,15 @@ if TYPE_CHECKING:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CUSTOM_COL = "custom"
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class StatusEntry:
|
||||
|
||||
name: str
|
||||
color: QColor
|
||||
theme: str
|
||||
shape: nwStatusShape
|
||||
icon: QIcon
|
||||
count: int = 0
|
||||
@@ -62,7 +66,7 @@ class StatusEntry:
|
||||
return status
|
||||
|
||||
|
||||
NO_ENTRY = StatusEntry("", QColor(0, 0, 0), nwStatusShape.SQUARE, QIcon(), 0)
|
||||
NO_ENTRY = StatusEntry("", QColor(0, 0, 0), CUSTOM_COL, nwStatusShape.SQUARE, QIcon(), 0)
|
||||
|
||||
T_UpdateEntry = list[tuple[str | None, StatusEntry]]
|
||||
T_StatusKind = Literal["s", "i"]
|
||||
@@ -97,15 +101,12 @@ class NWStatus:
|
||||
# Methods
|
||||
##
|
||||
|
||||
def add(self, key: str | None, name: str, color: tuple[int, int, int],
|
||||
shape: str, count: int) -> str:
|
||||
def add(self, key: str | None, name: str, color: str, shape: str, count: int) -> str:
|
||||
"""Add or update a status entry. If the key is invalid, a new
|
||||
key is generated.
|
||||
"""
|
||||
if isinstance(color, tuple) and len(color) == 3:
|
||||
qColor = QColor(*color)
|
||||
else:
|
||||
qColor = QColor(100, 100, 100)
|
||||
qColor = SHARED.theme.parseColor(color)
|
||||
theme = color if color in nwLabels.THEME_COLORS else CUSTOM_COL
|
||||
|
||||
try:
|
||||
iShape = nwStatusShape[shape]
|
||||
@@ -115,7 +116,7 @@ class NWStatus:
|
||||
key = self._checkKey(key)
|
||||
name = simplified(name)
|
||||
icon = self.createIcon(self._height, qColor, iShape)
|
||||
self._store[key] = StatusEntry(name, qColor, iShape, icon, count)
|
||||
self._store[key] = StatusEntry(name, qColor, theme, iShape, icon, count)
|
||||
|
||||
if self._default is None:
|
||||
self._default = key
|
||||
@@ -157,12 +158,14 @@ class NWStatus:
|
||||
def pack(self) -> Iterable[tuple[str, dict]]:
|
||||
"""Pack the status entries into a dictionary."""
|
||||
for key, entry in self._store.items():
|
||||
if entry.theme == CUSTOM_COL:
|
||||
color = entry.color.name(QColor.NameFormat.HexRgb)
|
||||
else:
|
||||
color = entry.theme
|
||||
yield (entry.name, {
|
||||
"key": key,
|
||||
"count": str(entry.count),
|
||||
"red": str(entry.color.red()),
|
||||
"green": str(entry.color.green()),
|
||||
"blue": str(entry.color.blue()),
|
||||
"color": color,
|
||||
"shape": entry.shape.name,
|
||||
})
|
||||
return
|
||||
@@ -179,12 +182,20 @@ class NWStatus:
|
||||
try:
|
||||
shape = nwStatusShape[str(data[0])]
|
||||
color = QColor(str(data[1]))
|
||||
theme = CUSTOM_COL if data[1].startswith("#") else data[1]
|
||||
icon = NWStatus.createIcon(self._height, color, shape)
|
||||
return StatusEntry(simplified(data[2]), color, shape, icon)
|
||||
return StatusEntry(simplified(data[2]), color, theme, shape, icon)
|
||||
except Exception:
|
||||
logger.error("Could not parse entry %s", str(data))
|
||||
return None
|
||||
|
||||
def refreshIcons(self) -> None:
|
||||
"""Refresh all icons."""
|
||||
for entry in self._store.values():
|
||||
entry.color = SHARED.theme.parseColor(entry.theme)
|
||||
entry.icon = NWStatus.createIcon(self._height, entry.color, entry.shape)
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def createIcon(height: int, color: QColor, shape: nwStatusShape) -> QIcon:
|
||||
"""Generate an icon for a status label."""
|
||||
|
||||
@@ -28,13 +28,13 @@ import logging
|
||||
|
||||
from PyQt6.QtCore import pyqtSlot
|
||||
from PyQt6.QtWidgets import (
|
||||
QAbstractItemView, QComboBox, QDialogButtonBox, QGridLayout, QLabel,
|
||||
QListWidget, QListWidgetItem, QVBoxLayout, QWidget
|
||||
QAbstractItemView, QDialogButtonBox, QGridLayout, QLabel, QListWidget,
|
||||
QListWidgetItem, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.extensions.configlayout import NColorLabel
|
||||
from novelwriter.extensions.modified import NDialog
|
||||
from novelwriter.extensions.modified import NComboBox, NDialog
|
||||
from novelwriter.extensions.switch import NSwitch
|
||||
from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtUserRole
|
||||
|
||||
@@ -79,7 +79,7 @@ class GuiDocSplit(NDialog):
|
||||
self.listBox.setMinimumWidth(400)
|
||||
self.listBox.setMinimumHeight(180)
|
||||
|
||||
self.splitLevel = QComboBox(self)
|
||||
self.splitLevel = NComboBox(self)
|
||||
self.splitLevel.addItem(self.tr("Split on Heading Level 1 (Partition)"), 1)
|
||||
self.splitLevel.addItem(self.tr("Split up to Heading Level 2 (Chapter)"), 2)
|
||||
self.splitLevel.addItem(self.tr("Split up to Heading Level 3 (Scene)"), 3)
|
||||
|
||||
@@ -35,7 +35,7 @@ from PyQt6.QtWidgets import (
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact
|
||||
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL
|
||||
from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS, DEF_TREECOL
|
||||
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
|
||||
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
||||
from novelwriter.extensions.configlayout import NColorLabel, NScrollableForm
|
||||
@@ -165,22 +165,34 @@ class GuiPreferences(NDialog):
|
||||
)
|
||||
|
||||
# Colour Theme
|
||||
self.guiTheme = NComboBox(self)
|
||||
self.guiTheme.setMinimumWidth(200)
|
||||
for theme, name in SHARED.theme.listThemes():
|
||||
self.guiTheme.addItem(name, theme)
|
||||
self.guiTheme.setCurrentData(CONFIG.guiTheme, DEF_GUI)
|
||||
self.lightTheme = NComboBox(self)
|
||||
self.lightTheme.setMinimumWidth(200)
|
||||
self.darkTheme = NComboBox(self)
|
||||
self.darkTheme.setMinimumWidth(200)
|
||||
for key, theme in SHARED.theme.colourThemes.items():
|
||||
if theme.dark:
|
||||
self.darkTheme.addItem(theme.name, key)
|
||||
else:
|
||||
self.lightTheme.addItem(theme.name, key)
|
||||
|
||||
self.lightTheme.setCurrentData(CONFIG.lightTheme, DEF_GUI_LIGHT)
|
||||
self.darkTheme.setCurrentData(CONFIG.darkTheme, DEF_GUI_DARK)
|
||||
|
||||
self.mainForm.addRow(
|
||||
self.tr("Colour theme"), self.guiTheme,
|
||||
self.tr("User interface colour theme."), stretch=(3, 2)
|
||||
self.tr("Light colour theme"), self.lightTheme,
|
||||
self.tr("You can change theme mode from the sidebar."), stretch=(3, 2)
|
||||
)
|
||||
self.mainForm.addRow(
|
||||
self.tr("Dark colour theme"), self.darkTheme,
|
||||
self.tr("You can change theme mode from the sidebar."), stretch=(3, 2)
|
||||
)
|
||||
|
||||
# Icon Theme
|
||||
self.iconTheme = NComboBox(self)
|
||||
self.iconTheme.setMinimumWidth(200)
|
||||
for theme, name in SHARED.theme.iconCache.listThemes():
|
||||
self.iconTheme.addItem(name, theme)
|
||||
for key, theme in SHARED.theme.iconCache.iconThemes.items():
|
||||
self.iconTheme.addItem(theme.name, key)
|
||||
|
||||
self.iconTheme.setCurrentData(CONFIG.iconTheme, DEF_ICONS)
|
||||
|
||||
self.mainForm.addRow(
|
||||
@@ -242,18 +254,6 @@ class GuiPreferences(NDialog):
|
||||
self.sidebar.addButton(title, section)
|
||||
self.mainForm.addGroupLabel(title, section)
|
||||
|
||||
# Document Colour Theme
|
||||
self.guiSyntax = NComboBox(self)
|
||||
self.guiSyntax.setMinimumWidth(200)
|
||||
for syntax, name in SHARED.theme.listSyntax():
|
||||
self.guiSyntax.addItem(name, syntax)
|
||||
self.guiSyntax.setCurrentData(CONFIG.guiSyntax, DEF_SYNTAX)
|
||||
|
||||
self.mainForm.addRow(
|
||||
self.tr("Document colour theme"), self.guiSyntax,
|
||||
self.tr("Colour theme for the editor and viewer."), stretch=(3, 2)
|
||||
)
|
||||
|
||||
# Document Font Family
|
||||
self.textFont = QLineEdit(self)
|
||||
self.textFont.setReadOnly(True)
|
||||
@@ -294,6 +294,7 @@ class GuiPreferences(NDialog):
|
||||
# Tree Icon Colours
|
||||
self.iconColTree = NComboBox(self)
|
||||
self.iconColTree.setMinimumWidth(200)
|
||||
self.iconColTree.addItem(self.tr("Theme Colours"), DEF_TREECOL)
|
||||
for key, label in nwLabels.THEME_COLORS.items():
|
||||
self.iconColTree.addItem(trConst(label), key)
|
||||
self.iconColTree.setCurrentData(CONFIG.iconColTree, DEF_TREECOL)
|
||||
@@ -543,6 +544,13 @@ class GuiPreferences(NDialog):
|
||||
unit=self.tr("px")
|
||||
)
|
||||
|
||||
# Highlight Current Line
|
||||
self.lineHighlight = NSwitch(self)
|
||||
self.lineHighlight.setChecked(CONFIG.lineHighlight)
|
||||
self.mainForm.addRow(
|
||||
self.tr("Highlight current line"), self.lineHighlight
|
||||
)
|
||||
|
||||
# Show Tabs and Spaces
|
||||
self.showTabsNSpaces = NSwitch(self)
|
||||
self.showTabsNSpaces.setChecked(CONFIG.showTabsNSpaces)
|
||||
@@ -966,18 +974,23 @@ class GuiPreferences(NDialog):
|
||||
|
||||
# Appearance
|
||||
guiLocale = self.guiLocale.currentData()
|
||||
guiTheme = self.guiTheme.currentData()
|
||||
lightTheme = self.lightTheme.currentData()
|
||||
darkTheme = self.darkTheme.currentData()
|
||||
iconTheme = self.iconTheme.currentData()
|
||||
useCharCount = self.useCharCount.isChecked()
|
||||
|
||||
updateTheme |= CONFIG.guiTheme != guiTheme
|
||||
updateTheme |= CONFIG.lightTheme != lightTheme
|
||||
updateTheme |= CONFIG.darkTheme != darkTheme
|
||||
updateTheme |= CONFIG.iconTheme != iconTheme
|
||||
needsRestart |= CONFIG.guiLocale != guiLocale
|
||||
needsRestart |= CONFIG.guiFont != self._guiFont
|
||||
refreshTree |= CONFIG.useCharCount != useCharCount
|
||||
updateSyntax |= CONFIG.lightTheme != lightTheme
|
||||
updateSyntax |= CONFIG.darkTheme != darkTheme
|
||||
|
||||
CONFIG.guiLocale = guiLocale
|
||||
CONFIG.guiTheme = guiTheme
|
||||
CONFIG.lightTheme = lightTheme
|
||||
CONFIG.darkTheme = darkTheme
|
||||
CONFIG.iconTheme = iconTheme
|
||||
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
||||
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
||||
@@ -986,11 +999,6 @@ class GuiPreferences(NDialog):
|
||||
CONFIG.setGuiFont(self._guiFont)
|
||||
|
||||
# Document Style
|
||||
guiSyntax = self.guiSyntax.currentData()
|
||||
|
||||
updateSyntax |= CONFIG.guiSyntax != guiSyntax
|
||||
|
||||
CONFIG.guiSyntax = guiSyntax
|
||||
CONFIG.showFullPath = self.showFullPath.isChecked()
|
||||
CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
|
||||
CONFIG.setTextFont(self._textFont)
|
||||
@@ -1031,9 +1039,14 @@ class GuiPreferences(NDialog):
|
||||
CONFIG.tabWidth = self.tabWidth.value()
|
||||
|
||||
# Text Editing
|
||||
lineHighlight = self.lineHighlight.isChecked()
|
||||
|
||||
updateSyntax |= CONFIG.lineHighlight != lineHighlight
|
||||
|
||||
CONFIG.spellLanguage = self.spellLanguage.currentData()
|
||||
CONFIG.autoSelect = self.autoSelect.isChecked()
|
||||
CONFIG.cursorWidth = self.cursorWidth.value()
|
||||
CONFIG.lineHighlight = lineHighlight
|
||||
CONFIG.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
||||
CONFIG.showLineEndings = self.showLineEndings.isChecked()
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtGui import QCloseEvent, QColor
|
||||
from PyQt6.QtWidgets import (
|
||||
QAbstractItemView, QApplication, QColorDialog, QDialogButtonBox,
|
||||
QFileDialog, QGridLayout, QHBoxLayout, QLineEdit, QMenu, QStackedWidget,
|
||||
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
||||
QFileDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
|
||||
QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import formatFileFilter, qtAddAction, qtLambda, simplified
|
||||
from novelwriter.constants import nwLabels, trConst
|
||||
from novelwriter.core.status import NWStatus, StatusEntry
|
||||
from novelwriter.core.status import CUSTOM_COL, NWStatus, StatusEntry
|
||||
from novelwriter.enum import nwStatusShape
|
||||
from novelwriter.extensions.configlayout import NColorLabel, NFixedPage, NScrollableForm
|
||||
from novelwriter.extensions.modified import NComboBox, NDialog, NIconToolButton
|
||||
@@ -326,6 +326,7 @@ class _StatusPage(NFixedPage):
|
||||
self._changed = False
|
||||
self._color = QColor(100, 100, 100)
|
||||
self._shape = nwStatusShape.SQUARE
|
||||
self._theme = CUSTOM_COL
|
||||
self._icons = {}
|
||||
|
||||
self._iPx = SHARED.theme.baseIconHeight
|
||||
@@ -384,11 +385,26 @@ class _StatusPage(NFixedPage):
|
||||
self.exportButton.clicked.connect(self._exportLabels)
|
||||
|
||||
# Edit Form
|
||||
self.labelText = QLineEdit(self)
|
||||
self.labelText.setMaxLength(40)
|
||||
self.labelText.setPlaceholderText(self.tr("Select item to edit"))
|
||||
self.labelText.setEnabled(False)
|
||||
self.labelText.textEdited.connect(self._onNameEdit)
|
||||
self.editName = QLineEdit(self)
|
||||
self.editName.setMaxLength(40)
|
||||
self.editName.setPlaceholderText(self.tr("Select item to edit"))
|
||||
self.editName.setEnabled(False)
|
||||
self.editName.textEdited.connect(self._onNameEdit)
|
||||
|
||||
self.labelName = QLabel(self.tr("Label"), self)
|
||||
self.labelName.setBuddy(self.editName)
|
||||
|
||||
# Icon Colours
|
||||
self.iconColor = NComboBox(self)
|
||||
self.iconColor.setMinimumWidth(200)
|
||||
self.iconColor.setEnabled(False)
|
||||
self.iconColor.addItem(self.tr("Custom"), CUSTOM_COL)
|
||||
for key, label in nwLabels.THEME_COLORS.items():
|
||||
self.iconColor.addItem(trConst(label), key)
|
||||
self.iconColor.currentIndexChanged.connect(self._onThemeSelect)
|
||||
|
||||
self.labelColor = QLabel(self.tr("Colour"), self)
|
||||
self.labelColor.setBuddy(self.iconColor)
|
||||
|
||||
buttonStyle = (
|
||||
"QToolButton {padding: 0 4px;} "
|
||||
@@ -425,6 +441,9 @@ class _StatusPage(NFixedPage):
|
||||
self.shapeButton.setStyleSheet(buttonStyle)
|
||||
self.shapeButton.setEnabled(False)
|
||||
|
||||
self.labelShape = QLabel(self.tr("Shape"), self)
|
||||
self.labelShape.setBuddy(self.iconColor)
|
||||
|
||||
# Assemble
|
||||
self.listControls = QVBoxLayout()
|
||||
self.listControls.addWidget(self.addButton)
|
||||
@@ -435,10 +454,15 @@ class _StatusPage(NFixedPage):
|
||||
self.listControls.addWidget(self.importButton)
|
||||
self.listControls.addWidget(self.exportButton)
|
||||
|
||||
self.editBox = QHBoxLayout()
|
||||
self.editBox.addWidget(self.labelText, 1)
|
||||
self.editBox.addWidget(self.colorButton, 0)
|
||||
self.editBox.addWidget(self.shapeButton, 0)
|
||||
self.editBox = QGridLayout()
|
||||
self.editBox.addWidget(self.labelName, 0, 0)
|
||||
self.editBox.addWidget(self.editName, 0, 1, 1, 5)
|
||||
self.editBox.addWidget(self.labelColor, 1, 0)
|
||||
self.editBox.addWidget(self.iconColor, 1, 1)
|
||||
self.editBox.addWidget(self.colorButton, 1, 2)
|
||||
self.editBox.addWidget(self.labelShape, 1, 3)
|
||||
self.editBox.addWidget(self.shapeButton, 1, 4)
|
||||
self.editBox.setColumnStretch(5, 1)
|
||||
|
||||
self.innerBox = QGridLayout()
|
||||
self.innerBox.addWidget(self.listBox, 0, 0)
|
||||
@@ -496,11 +520,20 @@ class _StatusPage(NFixedPage):
|
||||
self._changed = True
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
def _onThemeSelect(self, index: int) -> None:
|
||||
"""Update the colour handling on theme selection change."""
|
||||
self._theme = str(self.iconColor.currentData())
|
||||
self._setButtonIcons()
|
||||
self._updateIcon()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _onColorSelect(self) -> None:
|
||||
"""Open a dialog to select the status icon colour."""
|
||||
if (color := QColorDialog.getColor(self._color, self, self.trSelColor)).isValid():
|
||||
self._color = color
|
||||
self._theme = CUSTOM_COL
|
||||
self._setButtonIcons()
|
||||
self._updateIcon()
|
||||
return
|
||||
@@ -511,7 +544,8 @@ class _StatusPage(NFixedPage):
|
||||
color = QColor(100, 100, 100)
|
||||
shape = nwStatusShape.SQUARE
|
||||
icon = NWStatus.createIcon(self._iPx, color, shape)
|
||||
self._addItem(None, StatusEntry(self.tr("New Item"), color, shape, icon, 0))
|
||||
theme = str(self.iconColor.currentData())
|
||||
self._addItem(None, StatusEntry(self.tr("New Item"), color, theme, shape, icon, 0))
|
||||
self._changed = True
|
||||
return
|
||||
|
||||
@@ -537,22 +571,26 @@ class _StatusPage(NFixedPage):
|
||||
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
|
||||
self._color = entry.color
|
||||
self._shape = entry.shape
|
||||
self._theme = entry.theme
|
||||
self._setButtonIcons()
|
||||
|
||||
self.labelText.setText(entry.name)
|
||||
self.labelText.selectAll()
|
||||
self.labelText.setFocus()
|
||||
self.editName.setText(entry.name)
|
||||
self.editName.selectAll()
|
||||
self.editName.setFocus()
|
||||
|
||||
self.labelText.setEnabled(True)
|
||||
self.editName.setEnabled(True)
|
||||
self.iconColor.setEnabled(True)
|
||||
self.colorButton.setEnabled(True)
|
||||
self.shapeButton.setEnabled(True)
|
||||
else:
|
||||
self._color = QColor(100, 100, 100)
|
||||
self._shape = nwStatusShape.SQUARE
|
||||
self._theme = CUSTOM_COL
|
||||
self._setButtonIcons()
|
||||
self.labelText.setText("")
|
||||
self.editName.setText("")
|
||||
|
||||
self.labelText.setEnabled(False)
|
||||
self.editName.setEnabled(False)
|
||||
self.iconColor.setEnabled(False)
|
||||
self.colorButton.setEnabled(False)
|
||||
self.shapeButton.setEnabled(False)
|
||||
return
|
||||
@@ -608,10 +646,11 @@ class _StatusPage(NFixedPage):
|
||||
def _updateIcon(self) -> None:
|
||||
"""Apply changes made to a status icon."""
|
||||
if item := self._getSelectedItem():
|
||||
icon = NWStatus.createIcon(self._iPx, self._color, self._shape)
|
||||
icon = NWStatus.createIcon(self._iPx, self._pickColor(), self._shape)
|
||||
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
|
||||
entry.color = self._color
|
||||
entry.shape = self._shape
|
||||
entry.theme = self._theme
|
||||
entry.icon = icon
|
||||
item.setIcon(self.C_LABEL, icon)
|
||||
self._changed = True
|
||||
@@ -658,11 +697,18 @@ class _StatusPage(NFixedPage):
|
||||
|
||||
def _setButtonIcons(self) -> None:
|
||||
"""Set the colour of the colour button."""
|
||||
icon = NWStatus.createIcon(self._iPx, self._color, nwStatusShape.SQUARE)
|
||||
icon = NWStatus.createIcon(self._iPx, self._pickColor(), nwStatusShape.SQUARE)
|
||||
self.iconColor.setCurrentData(self._theme, CUSTOM_COL)
|
||||
self.colorButton.setIcon(icon)
|
||||
self.shapeButton.setIcon(self._icons[self._shape])
|
||||
return
|
||||
|
||||
def _pickColor(self) -> QColor:
|
||||
"""Get the correct colour value based on selections."""
|
||||
if self._theme == CUSTOM_COL:
|
||||
return self._color
|
||||
return SHARED.theme.getBaseColor(self._theme)
|
||||
|
||||
|
||||
class _ReplacePage(NFixedPage):
|
||||
|
||||
|
||||
+37
-29
@@ -92,35 +92,36 @@ class nwDocAction(Enum):
|
||||
MD_ITALIC = 6
|
||||
MD_BOLD = 7
|
||||
MD_STRIKE = 8
|
||||
S_QUOTE = 9
|
||||
D_QUOTE = 10
|
||||
SEL_ALL = 11
|
||||
SEL_PARA = 12
|
||||
BLOCK_H1 = 13
|
||||
BLOCK_H2 = 14
|
||||
BLOCK_H3 = 15
|
||||
BLOCK_H4 = 16
|
||||
BLOCK_COM = 17
|
||||
BLOCK_IGN = 18
|
||||
BLOCK_TXT = 19
|
||||
BLOCK_TTL = 20
|
||||
BLOCK_UNN = 21
|
||||
BLOCK_HSC = 22
|
||||
REPL_SNG = 23
|
||||
REPL_DBL = 24
|
||||
RM_BREAKS = 25
|
||||
ALIGN_L = 26
|
||||
ALIGN_C = 27
|
||||
ALIGN_R = 28
|
||||
INDENT_L = 29
|
||||
INDENT_R = 30
|
||||
SC_ITALIC = 31
|
||||
SC_BOLD = 32
|
||||
SC_STRIKE = 33
|
||||
SC_ULINE = 34
|
||||
SC_MARK = 35
|
||||
SC_SUP = 36
|
||||
SC_SUB = 37
|
||||
MD_MARK = 9
|
||||
S_QUOTE = 10
|
||||
D_QUOTE = 11
|
||||
SEL_ALL = 12
|
||||
SEL_PARA = 13
|
||||
BLOCK_H1 = 14
|
||||
BLOCK_H2 = 15
|
||||
BLOCK_H3 = 16
|
||||
BLOCK_H4 = 17
|
||||
BLOCK_COM = 18
|
||||
BLOCK_IGN = 19
|
||||
BLOCK_TXT = 20
|
||||
BLOCK_TTL = 21
|
||||
BLOCK_UNN = 22
|
||||
BLOCK_HSC = 23
|
||||
REPL_SNG = 24
|
||||
REPL_DBL = 25
|
||||
RM_BREAKS = 26
|
||||
ALIGN_L = 27
|
||||
ALIGN_C = 28
|
||||
ALIGN_R = 29
|
||||
INDENT_L = 30
|
||||
INDENT_R = 31
|
||||
SC_ITALIC = 32
|
||||
SC_BOLD = 33
|
||||
SC_STRIKE = 34
|
||||
SC_ULINE = 35
|
||||
SC_MARK = 36
|
||||
SC_SUP = 37
|
||||
SC_SUB = 38
|
||||
|
||||
|
||||
class nwDocInsert(Enum):
|
||||
@@ -156,6 +157,13 @@ class nwFocus(Enum):
|
||||
OUTLINE = 3
|
||||
|
||||
|
||||
class nwTheme(Enum):
|
||||
|
||||
AUTO = 0
|
||||
LIGHT = 1
|
||||
DARK = 2
|
||||
|
||||
|
||||
class nwOutline(Enum):
|
||||
|
||||
TITLE = 0
|
||||
|
||||
@@ -117,12 +117,19 @@ class NTreeView(QTreeView):
|
||||
|
||||
class NComboBox(QComboBox):
|
||||
|
||||
def __init__(self, parent: QWidget | None = None) -> None:
|
||||
def __init__(self, parent: QWidget | None = None, maxItems: int = 15) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
self.setMaxVisibleItems(maxItems)
|
||||
|
||||
# The style sheet disables Fusion style pop-up mode on some platforms
|
||||
# and allows for scrolling of long lists of items
|
||||
self.setStyleSheet("QComboBox {combobox-popup: 0;}")
|
||||
|
||||
return
|
||||
|
||||
def wheelEvent(self, event: QWheelEvent) -> None:
|
||||
"""Only capture the mouse wheel if the widget has focus."""
|
||||
if self.hasFocus():
|
||||
super().wheelEvent(event)
|
||||
else:
|
||||
|
||||
@@ -25,14 +25,19 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtGui import QPalette
|
||||
from PyQt6.QtWidgets import QComboBox, QWidget
|
||||
from PyQt6.QtWidgets import QComboBox
|
||||
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.constants import nwLabels
|
||||
from novelwriter.enum import nwItemClass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ class _PagedToolButton(QToolButton):
|
||||
|
||||
if self.isChecked():
|
||||
painter.setBrush(palette.highlight())
|
||||
painter.setOpacity(0.35)
|
||||
painter.setOpacity(0.8)
|
||||
painter.drawRoundedRect(0, 0, width, height, 4, 4)
|
||||
textCol = palette.highlightedText().color()
|
||||
else:
|
||||
|
||||
@@ -33,7 +33,7 @@ from novelwriter.types import QtNoPen, QtPaintAntiAlias, QtSizeFixed
|
||||
|
||||
class NSwitch(QAbstractButton):
|
||||
|
||||
__slots__ = ("_offset", "_rH", "_rR", "_xH", "_xR", "_xW")
|
||||
__slots__ = ("_cOff", "_cOn", "_offset", "_rH", "_rR", "_xH", "_xR", "_xW")
|
||||
|
||||
def __init__(self, parent: QWidget, height: int = 0) -> None:
|
||||
super().__init__(parent=parent)
|
||||
@@ -44,6 +44,9 @@ class NSwitch(QAbstractButton):
|
||||
self._rH = self._xH - 4
|
||||
self._rR = self._xR - 2
|
||||
|
||||
self._cOn = SHARED.theme.accentCol
|
||||
self._cOff = self.palette().alternateBase()
|
||||
|
||||
self.setCheckable(True)
|
||||
self.setSizePolicy(QtSizeFixed, QtSizeFixed)
|
||||
self.setFixedWidth(self._xW)
|
||||
@@ -97,7 +100,7 @@ class NSwitch(QAbstractButton):
|
||||
painter.setOpacity(1.0 if self.isEnabled() else 0.5)
|
||||
|
||||
painter.setPen(palette.highlight().color() if self.hasFocus() else palette.mid().color())
|
||||
painter.setBrush(palette.highlight() if self.isChecked() else palette.alternateBase())
|
||||
painter.setBrush(self._cOn if self.isChecked() else self._cOff)
|
||||
painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
|
||||
|
||||
painter.setPen(QtNoPen)
|
||||
|
||||
@@ -29,7 +29,15 @@ from enum import Flag, IntEnum
|
||||
|
||||
from PyQt6.QtGui import QColor
|
||||
|
||||
ESCAPES = {r"\*": "*", r"\~": "~", r"\_": "_", r"\[": "[", r"\]": "]", r"\ ": ""}
|
||||
ESCAPES = {
|
||||
r"\*": "*",
|
||||
r"\~": "~",
|
||||
r"\=": "=",
|
||||
r"\_": "_",
|
||||
r"\[": "[",
|
||||
r"\]": "]",
|
||||
r"\ ": "",
|
||||
}
|
||||
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ from novelwriter import __version__
|
||||
from novelwriter.common import firstFloat, xmlElement, xmlSubElem
|
||||
from novelwriter.constants import nwHeadFmt, nwStyles
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.formats.tokenizer import COMMENT_BLOCKS, Tokenizer
|
||||
from novelwriter.types import QtHexRgb
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -296,7 +296,7 @@ class ToDocX(Tokenizer):
|
||||
elif tType == BlockTyp.SKIP:
|
||||
self._processFragments(par, S_NORM, "")
|
||||
|
||||
elif tType == BlockTyp.COMMENT:
|
||||
elif tType in COMMENT_BLOCKS:
|
||||
self._processFragments(par, S_META, tText, tFormat)
|
||||
|
||||
elif tType == BlockTyp.KEYWORD:
|
||||
|
||||
@@ -32,7 +32,7 @@ from typing import TYPE_CHECKING
|
||||
from novelwriter.common import formatTimeStamp
|
||||
from novelwriter.constants import nwHtmlUnicode, nwStyles
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.formats.tokenizer import COMMENT_BLOCKS, Tokenizer
|
||||
from novelwriter.types import FONT_STYLE, FONT_WEIGHTS, QtHexRgb
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -159,34 +159,33 @@ class ToHtml(Tokenizer):
|
||||
# If we don't have formatting, we can do a plain replace
|
||||
tText = tText.replace("<", "<").replace(">", ">")
|
||||
|
||||
# Styles
|
||||
# Inline Styles
|
||||
aStyle = []
|
||||
if self._cssStyles:
|
||||
if tStyle & BlockFmt.LEFT:
|
||||
aStyle.append("text-align: left;")
|
||||
elif tStyle & BlockFmt.RIGHT:
|
||||
aStyle.append("text-align: right;")
|
||||
elif tStyle & BlockFmt.CENTRE:
|
||||
aStyle.append("text-align: center;")
|
||||
elif tStyle & BlockFmt.JUSTIFY:
|
||||
aStyle.append("text-align: justify;")
|
||||
if tStyle & BlockFmt.LEFT:
|
||||
aStyle.append("text-align: left;")
|
||||
elif tStyle & BlockFmt.RIGHT:
|
||||
aStyle.append("text-align: right;")
|
||||
elif tStyle & BlockFmt.CENTRE:
|
||||
aStyle.append("text-align: center;")
|
||||
elif tStyle & BlockFmt.JUSTIFY:
|
||||
aStyle.append("text-align: justify;")
|
||||
|
||||
if tStyle & BlockFmt.PBB:
|
||||
aStyle.append("page-break-before: always;")
|
||||
if tStyle & BlockFmt.PBA:
|
||||
aStyle.append("page-break-after: always;")
|
||||
if tStyle & BlockFmt.PBB:
|
||||
aStyle.append("page-break-before: always;")
|
||||
if tStyle & BlockFmt.PBA:
|
||||
aStyle.append("page-break-after: always;")
|
||||
|
||||
if tStyle & BlockFmt.Z_BTM:
|
||||
aStyle.append("margin-bottom: 0;")
|
||||
if tStyle & BlockFmt.Z_TOP:
|
||||
aStyle.append("margin-top: 0;")
|
||||
if tStyle & BlockFmt.Z_BTM:
|
||||
aStyle.append("margin-bottom: 0;")
|
||||
if tStyle & BlockFmt.Z_TOP:
|
||||
aStyle.append("margin-top: 0;")
|
||||
|
||||
if tStyle & BlockFmt.IND_L:
|
||||
aStyle.append(f"margin-left: {self._blockIndent:.2f}em;")
|
||||
if tStyle & BlockFmt.IND_R:
|
||||
aStyle.append(f"margin-right: {self._blockIndent:.2f}em;")
|
||||
if tStyle & BlockFmt.IND_T:
|
||||
aStyle.append(f"text-indent: {self._firstWidth:.2f}em;")
|
||||
if tStyle & BlockFmt.IND_L:
|
||||
aStyle.append(f"margin-left: {self._blockIndent:.2f}em;")
|
||||
if tStyle & BlockFmt.IND_R:
|
||||
aStyle.append(f"margin-right: {self._blockIndent:.2f}em;")
|
||||
if tStyle & BlockFmt.IND_T:
|
||||
aStyle.append(f"text-indent: {self._firstWidth:.2f}em;")
|
||||
|
||||
if aStyle:
|
||||
stVals = " ".join(aStyle)
|
||||
@@ -229,7 +228,7 @@ class ToHtml(Tokenizer):
|
||||
elif tType == BlockTyp.SKIP:
|
||||
lines.append(f"<p{hStyle}> </p>\n")
|
||||
|
||||
elif tType == BlockTyp.COMMENT:
|
||||
elif tType in COMMENT_BLOCKS:
|
||||
lines.append(f"<p class='comment'{hStyle}>{self._formatText(tText, tFmt)}</p>\n")
|
||||
|
||||
elif tType == BlockTyp.KEYWORD:
|
||||
@@ -288,26 +287,25 @@ class ToHtml(Tokenizer):
|
||||
json.dump(data, fObj, indent=2)
|
||||
|
||||
else:
|
||||
html = []
|
||||
html.append("<!DOCTYPE html>")
|
||||
html.append("<html>")
|
||||
html.append("<head>")
|
||||
html.append(f"<title>{self._project.data.name:s}</title>")
|
||||
html.append("<meta charset='utf-8'>")
|
||||
if self._cssStyles:
|
||||
html.append("<meta name='viewport' content='width=device-width, initial-scale=1'>")
|
||||
html.append("<style>")
|
||||
html.extend(self.getStyleSheet())
|
||||
html.append("</style>")
|
||||
html.append("</head>")
|
||||
html.append("<body>")
|
||||
html.append(("".join(self._pages)).replace("\t", "	").rstrip())
|
||||
html.append("</body>")
|
||||
html.append("</html>\n")
|
||||
|
||||
with open(path, mode="w", encoding="utf-8") as fObj:
|
||||
fObj.write((
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<meta charset='utf-8'>\n"
|
||||
"<title>{title:s}</title>\n"
|
||||
"<style>\n"
|
||||
"{style:s}\n"
|
||||
"</style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"{body:s}\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
).format(
|
||||
title=self._project.data.name,
|
||||
style="\n".join(self.getStyleSheet()),
|
||||
body=("".join(self._pages)).replace("\t", "	").rstrip(),
|
||||
))
|
||||
fObj.write("\n".join(html))
|
||||
|
||||
logger.info("Wrote file: %s", path)
|
||||
|
||||
@@ -410,7 +408,11 @@ class ToHtml(Tokenizer):
|
||||
# isn't already open, and only closed if it has previously been opened.
|
||||
tags: list[tuple[int, str]] = []
|
||||
state = dict.fromkeys(HTML_OPENER, False)
|
||||
plain = not self._cssStyles
|
||||
for pos, fmt, data in tFmt:
|
||||
if plain and fmt in (TextFmt.COL_B, TextFmt.COL_E):
|
||||
# We ignore colour tags if CSS is off
|
||||
continue
|
||||
if m := HTML_OPENER.get(fmt):
|
||||
if not state.get(fmt, True):
|
||||
if fmt == TextFmt.COL_B and (color := self._classes.get(data)):
|
||||
|
||||
@@ -71,11 +71,23 @@ COMMENT_STYLE = {
|
||||
nwComment.COMMENT: ComStyle(),
|
||||
nwComment.STORY: ComStyle("Story Structure", "modifier", "note"),
|
||||
}
|
||||
HEADINGS = [
|
||||
COMMENT_TYPE = {
|
||||
nwComment.PLAIN: BlockTyp.COMMENT,
|
||||
nwComment.IGNORE: BlockTyp.COMMENT,
|
||||
nwComment.SYNOPSIS: BlockTyp.SUMMARY,
|
||||
nwComment.SHORT: BlockTyp.SUMMARY,
|
||||
nwComment.NOTE: BlockTyp.NOTE,
|
||||
nwComment.FOOTNOTE: BlockTyp.COMMENT,
|
||||
nwComment.COMMENT: BlockTyp.COMMENT,
|
||||
nwComment.STORY: BlockTyp.NOTE,
|
||||
}
|
||||
HEADING_BLOCKS = [
|
||||
BlockTyp.TITLE, BlockTyp.PART, BlockTyp.HEAD1,
|
||||
BlockTyp.HEAD2, BlockTyp.HEAD3, BlockTyp.HEAD4,
|
||||
]
|
||||
SKIP_INDENT = [*HEADINGS, BlockTyp.SEP, BlockTyp.SKIP]
|
||||
COMMENT_BLOCKS = (BlockTyp.COMMENT, BlockTyp.SUMMARY, BlockTyp.NOTE)
|
||||
META_BLOCKS = (BlockTyp.COMMENT, BlockTyp.SUMMARY, BlockTyp.NOTE, BlockTyp.KEYWORD)
|
||||
SKIP_INDENT = [*HEADING_BLOCKS, BlockTyp.SEP, BlockTyp.SKIP]
|
||||
B_EMPTY: T_Block = (BlockTyp.EMPTY, "", "", [], BlockFmt.NONE)
|
||||
|
||||
|
||||
@@ -189,6 +201,7 @@ class Tokenizer(ABC):
|
||||
(REGEX_PATTERNS.markdownItalic, [0, TextFmt.I_B, 0, TextFmt.I_E]),
|
||||
(REGEX_PATTERNS.markdownBold, [0, TextFmt.B_B, 0, TextFmt.B_E]),
|
||||
(REGEX_PATTERNS.markdownStrike, [0, TextFmt.D_B, 0, TextFmt.D_E]),
|
||||
(REGEX_PATTERNS.markdownMark, [0, TextFmt.M_B, 0, TextFmt.M_E]),
|
||||
]
|
||||
|
||||
self._shortCodeFmt = {
|
||||
@@ -618,7 +631,7 @@ class Tokenizer(ABC):
|
||||
bStyle = COMMENT_STYLE[cStyle]
|
||||
tLine, tFmt = self._formatComment(bStyle, cKey, cText)
|
||||
tBlocks.append((
|
||||
BlockTyp.COMMENT, "", tLine, tFmt, tStyle
|
||||
COMMENT_TYPE[cStyle], "", tLine, tFmt, tStyle
|
||||
))
|
||||
|
||||
elif cStyle == nwComment.FOOTNOTE:
|
||||
@@ -862,12 +875,12 @@ class Tokenizer(ABC):
|
||||
# We don't need to keep the empty lines after this pass
|
||||
pass
|
||||
|
||||
elif cBlock[0] == BlockTyp.KEYWORD:
|
||||
# Adjust margins for lines in a list of keyword lines
|
||||
elif cBlock[0] in (BlockTyp.KEYWORD, BlockTyp.NOTE):
|
||||
# Adjust margins for lines in repeated meta blocks
|
||||
aStyle = cBlock[4]
|
||||
if pBlock[0] == BlockTyp.KEYWORD:
|
||||
if pBlock[0] == cBlock[0]:
|
||||
aStyle |= BlockFmt.Z_TOP
|
||||
if nBlock[0] == BlockTyp.KEYWORD:
|
||||
if nBlock[0] == cBlock[0]:
|
||||
aStyle |= BlockFmt.Z_BTM
|
||||
sBlocks.append((
|
||||
cBlock[0], cBlock[1], cBlock[2], cBlock[3], aStyle
|
||||
@@ -991,7 +1004,7 @@ class Tokenizer(ABC):
|
||||
allWordChars += nPWChars
|
||||
textWordChars += nPWChars
|
||||
|
||||
elif tType in HEADINGS:
|
||||
elif tType in HEADING_BLOCKS:
|
||||
titleCount += 1
|
||||
allWords += nWords
|
||||
titleWords += nWords
|
||||
@@ -1005,7 +1018,7 @@ class Tokenizer(ABC):
|
||||
allChars += nChars
|
||||
allWordChars += nWChars
|
||||
|
||||
elif tType in (BlockTyp.COMMENT, BlockTyp.KEYWORD):
|
||||
elif tType in META_BLOCKS:
|
||||
words = tText.split()
|
||||
allWords += len(words)
|
||||
allChars += len(tText)
|
||||
|
||||
@@ -29,7 +29,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from novelwriter.constants import nwUnicode
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.formats.tokenizer import COMMENT_BLOCKS, Tokenizer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
@@ -144,7 +144,7 @@ class ToMarkdown(Tokenizer):
|
||||
elif tType == BlockTyp.SKIP:
|
||||
lines.append(f"{cSkip}\n\n")
|
||||
|
||||
elif tType == BlockTyp.COMMENT:
|
||||
elif tType in COMMENT_BLOCKS:
|
||||
lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n")
|
||||
|
||||
elif tType == BlockTyp.KEYWORD:
|
||||
|
||||
@@ -40,7 +40,7 @@ from novelwriter import __version__
|
||||
from novelwriter.common import xmlElement, xmlIndent, xmlSubElem
|
||||
from novelwriter.constants import nwHeadFmt, nwStyles
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, TextFmt, stripEscape
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.formats.tokenizer import COMMENT_BLOCKS, Tokenizer
|
||||
from novelwriter.types import FONT_STYLE, QtHexRgb
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -389,7 +389,7 @@ class ToOdt(Tokenizer):
|
||||
elif tType == BlockTyp.SKIP:
|
||||
self._addTextPar(xText, S_TEXT, oStyle, "")
|
||||
|
||||
elif tType == BlockTyp.COMMENT:
|
||||
elif tType in COMMENT_BLOCKS:
|
||||
self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat)
|
||||
|
||||
elif tType == BlockTyp.KEYWORD:
|
||||
|
||||
@@ -37,7 +37,7 @@ from PyQt6.QtPrintSupport import QPrinter
|
||||
from novelwriter import __version__
|
||||
from novelwriter.constants import nwStyles, nwUnicode
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
||||
from novelwriter.formats.tokenizer import HEADINGS, Tokenizer
|
||||
from novelwriter.formats.tokenizer import HEADING_BLOCKS, META_BLOCKS, Tokenizer
|
||||
from novelwriter.types import (
|
||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||
QtKeepAnchor, QtMoveAnchor, QtPageBreakAfter, QtPageBreakAuto,
|
||||
@@ -214,7 +214,7 @@ class ToQTextDocument(Tokenizer):
|
||||
for tType, tMeta, tText, tFormat, tStyle in self._blocks:
|
||||
|
||||
bFmt = QTextBlockFormat(self._blockFmt)
|
||||
if tType in (BlockTyp.COMMENT, BlockTyp.KEYWORD):
|
||||
if tType in META_BLOCKS:
|
||||
bFmt.setTopMargin(self._mMeta[0])
|
||||
bFmt.setBottomMargin(self._mMeta[1])
|
||||
elif tType == BlockTyp.SEP:
|
||||
@@ -248,17 +248,21 @@ class ToQTextDocument(Tokenizer):
|
||||
if tStyle & BlockFmt.IND_T:
|
||||
bFmt.setTextIndent(self._tIndent)
|
||||
|
||||
if tType in (BlockTyp.TEXT, BlockTyp.COMMENT, BlockTyp.KEYWORD):
|
||||
if tType == BlockTyp.TEXT:
|
||||
newBlock(cursor, bFmt)
|
||||
self._insertFragments(tText, tFormat, cursor, self._charFmt)
|
||||
|
||||
elif tType in HEADINGS:
|
||||
elif tType in HEADING_BLOCKS:
|
||||
bFmt, cFmt = self._genHeadStyle(tType, tMeta, bFmt)
|
||||
for tPart in tText.split("\n"):
|
||||
newBlock(cursor, bFmt)
|
||||
cursor.insertText(tPart, cFmt)
|
||||
bFmt.setPageBreakPolicy(QtPageBreakAuto)
|
||||
|
||||
elif tType in META_BLOCKS:
|
||||
newBlock(cursor, bFmt)
|
||||
self._insertFragments(tText, tFormat, cursor, self._charFmt)
|
||||
|
||||
elif tType == BlockTyp.SEP:
|
||||
newBlock(cursor, bFmt)
|
||||
cursor.insertText(tText, self._charFmt)
|
||||
|
||||
@@ -45,11 +45,11 @@ from PyQt6.QtCore import (
|
||||
from PyQt6.QtGui import (
|
||||
QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent,
|
||||
QKeySequence, QMouseEvent, QPalette, QPixmap, QResizeEvent, QShortcut,
|
||||
QTextBlock, QTextCursor, QTextDocument, QTextOption
|
||||
QTextBlock, QTextCursor, QTextDocument, QTextFormat, QTextOption
|
||||
)
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
|
||||
QPlainTextEdit, QToolBar, QVBoxLayout, QWidget
|
||||
QPlainTextEdit, QTextEdit, QToolBar, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -75,7 +75,8 @@ from novelwriter.tools.lipsum import GuiLipsum
|
||||
from novelwriter.types import (
|
||||
QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop,
|
||||
QtAlignRight, QtKeepAnchor, QtModCtrl, QtModNone, QtModShift, QtMouseLeft,
|
||||
QtMoveAnchor, QtMoveLeft, QtMoveRight, QtScrollAlwaysOff, QtScrollAsNeeded
|
||||
QtMoveAnchor, QtMoveLeft, QtMoveRight, QtScrollAlwaysOff, QtScrollAsNeeded,
|
||||
QtTransparent
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -145,6 +146,8 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self._lastActive = 0.0 # Timestamp of last activity
|
||||
self._lastFind = None # Position of the last found search word
|
||||
self._doReplace = False # Switch to temporarily disable auto-replace
|
||||
self._lineColor = QtTransparent
|
||||
self._selection = QTextEdit.ExtraSelection()
|
||||
|
||||
# Auto-Replace
|
||||
self._autoReplace = TextAutoReplace()
|
||||
@@ -283,6 +286,7 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self.docHeader.clearHeader()
|
||||
self.docFooter.setHandle(self._docHandle)
|
||||
self.docToolBar.setVisible(False)
|
||||
self.setExtraSelections([])
|
||||
|
||||
self.itemHandleChanged.emit("")
|
||||
|
||||
@@ -315,6 +319,10 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self.docHeader.matchColors()
|
||||
self.docFooter.matchColors()
|
||||
|
||||
self._lineColor = syntax.line
|
||||
self._selection.format.setBackground(self._lineColor)
|
||||
self._selection.format.setProperty(QTextFormat.Property.FullWidthSelection, True)
|
||||
|
||||
return
|
||||
|
||||
def initEditor(self) -> None:
|
||||
@@ -372,6 +380,8 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
# Refresh sizes
|
||||
self.setTabStopDistance(CONFIG.tabWidth)
|
||||
self.setCursorWidth(CONFIG.cursorWidth)
|
||||
self.setExtraSelections([])
|
||||
self._cursorMoved()
|
||||
|
||||
# If we have a document open, we should refresh it in case the
|
||||
# font changed, otherwise we just clear the editor entirely,
|
||||
@@ -733,6 +743,8 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self._toggleFormat(2, "*")
|
||||
elif action == nwDocAction.MD_STRIKE:
|
||||
self._toggleFormat(2, "~")
|
||||
elif action == nwDocAction.MD_MARK:
|
||||
self._toggleFormat(2, "=")
|
||||
elif action == nwDocAction.S_QUOTE:
|
||||
self._wrapSelection(CONFIG.fmtSQuoteOpen, CONFIG.fmtSQuoteClose)
|
||||
elif action == nwDocAction.D_QUOTE:
|
||||
@@ -1110,6 +1122,10 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
def _cursorMoved(self) -> None:
|
||||
"""Triggered when the cursor moved in the editor."""
|
||||
self.docFooter.updateLineCount(self.textCursor())
|
||||
if CONFIG.lineHighlight:
|
||||
self._selection.cursor = self.textCursor()
|
||||
self._selection.cursor.clearSelection()
|
||||
self.setExtraSelections([self._selection])
|
||||
return
|
||||
|
||||
@pyqtSlot(int, int, str)
|
||||
@@ -2410,6 +2426,12 @@ class GuiDocToolBar(QWidget):
|
||||
qtLambda(self.requestDocAction.emit, nwDocAction.MD_STRIKE)
|
||||
)
|
||||
|
||||
self.tbMarkMD = NIconToolButton(self, iSz)
|
||||
self.tbMarkMD.setToolTip(self.tr("Markdown Highlight"))
|
||||
self.tbMarkMD.clicked.connect(
|
||||
qtLambda(self.requestDocAction.emit, nwDocAction.MD_MARK)
|
||||
)
|
||||
|
||||
self.tbBold = NIconToolButton(self, iSz)
|
||||
self.tbBold.setToolTip(self.tr("Shortcode Bold"))
|
||||
self.tbBold.clicked.connect(
|
||||
@@ -2459,6 +2481,7 @@ class GuiDocToolBar(QWidget):
|
||||
self.outerBox.addWidget(self.tbBoldMD)
|
||||
self.outerBox.addWidget(self.tbItalicMD)
|
||||
self.outerBox.addWidget(self.tbStrikeMD)
|
||||
self.outerBox.addWidget(self.tbMarkMD)
|
||||
self.outerBox.addSpacing(4)
|
||||
self.outerBox.addWidget(self.tbBold)
|
||||
self.outerBox.addWidget(self.tbItalic)
|
||||
@@ -2493,6 +2516,7 @@ class GuiDocToolBar(QWidget):
|
||||
self.tbBoldMD.setThemeIcon("fmt_bold", "orange")
|
||||
self.tbItalicMD.setThemeIcon("fmt_italic", "orange")
|
||||
self.tbStrikeMD.setThemeIcon("fmt_strike", "orange")
|
||||
self.tbMarkMD.setThemeIcon("fmt_mark", "orange")
|
||||
self.tbBold.setThemeIcon("fmt_bold")
|
||||
self.tbItalic.setThemeIcon("fmt_italic")
|
||||
self.tbStrike.setThemeIcon("fmt_strike")
|
||||
|
||||
@@ -113,6 +113,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
self._addCharFormat("bold", colEmph, "b")
|
||||
self._addCharFormat("italic", colEmph, "i")
|
||||
self._addCharFormat("strike", syntax.hidden, "s")
|
||||
self._addCharFormat("mark", syntax.mark, "bg")
|
||||
self._addCharFormat("mspaces", syntax.error, "err")
|
||||
self._addCharFormat("nobreak", colBreak, "bg")
|
||||
self._addCharFormat("altdialog", syntax.dialA)
|
||||
@@ -200,6 +201,17 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
self._txtRules.append((rxRule, hlRule))
|
||||
self._cmnRules.append((rxRule, hlRule))
|
||||
|
||||
# Markdown Highlight
|
||||
rxRule = REGEX_PATTERNS.markdownMark
|
||||
hlRule = {
|
||||
1: self._hStyles["markup"],
|
||||
2: self._hStyles["mark"],
|
||||
3: self._hStyles["markup"],
|
||||
}
|
||||
self._minRules.append((rxRule, hlRule))
|
||||
self._txtRules.append((rxRule, hlRule))
|
||||
self._cmnRules.append((rxRule, hlRule))
|
||||
|
||||
# Shortcodes
|
||||
rxRule = QRegularExpression(REGEX_PATTERNS.shortcodePlain.pattern, RX_UNICODE)
|
||||
hlRule = {
|
||||
@@ -460,9 +472,6 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
blockMerge = name == "markup"
|
||||
charFormat.setProperty(QtTextUserProperty, blockMerge)
|
||||
|
||||
if color:
|
||||
charFormat.setForeground(color)
|
||||
|
||||
if style:
|
||||
styles = style.split(",")
|
||||
if "b" in styles:
|
||||
@@ -478,6 +487,10 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
charFormat.setUnderlineStyle(QTextCharFormat.UnderlineStyle.SpellCheckUnderline)
|
||||
if "bg" in styles and color is not None:
|
||||
charFormat.setBackground(QBrush(color, Qt.BrushStyle.SolidPattern))
|
||||
color = None
|
||||
|
||||
if color:
|
||||
charFormat.setForeground(color)
|
||||
|
||||
if size:
|
||||
charFormat.setFontPointSize(round(size*CONFIG.textFont.pointSize()))
|
||||
|
||||
@@ -228,11 +228,11 @@ class GuiDocViewer(QTextBrowser):
|
||||
qDoc.setTheme(self._docTheme)
|
||||
qDoc.initDocument()
|
||||
qDoc.setKeywords(True)
|
||||
qDoc.setCommentType(nwComment.NOTE, CONFIG.viewComments)
|
||||
qDoc.setCommentType(nwComment.STORY, CONFIG.viewComments)
|
||||
qDoc.setCommentType(nwComment.PLAIN, CONFIG.viewComments)
|
||||
qDoc.setCommentType(nwComment.SYNOPSIS, CONFIG.viewSynopsis)
|
||||
qDoc.setCommentType(nwComment.SHORT, CONFIG.viewSynopsis)
|
||||
qDoc.setCommentType(nwComment.STORY, CONFIG.viewNotes)
|
||||
qDoc.setCommentType(nwComment.NOTE, CONFIG.viewNotes)
|
||||
|
||||
# Be extra careful here to prevent crashes when first opening a
|
||||
# project as a crash here leaves no way of recovering.
|
||||
@@ -913,12 +913,23 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
||||
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
||||
|
||||
# Show Notes
|
||||
self.showNotes = QToolButton(self)
|
||||
self.showNotes.setText(self.tr("Notes"))
|
||||
self.showNotes.setCheckable(True)
|
||||
self.showNotes.setChecked(CONFIG.viewNotes)
|
||||
self.showNotes.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
||||
self.showNotes.setIconSize(iSz)
|
||||
self.showNotes.toggled.connect(self._doToggleNotes)
|
||||
self.showNotes.setToolTip(self.tr("Show Notes"))
|
||||
|
||||
# Assemble Layout
|
||||
self.outerBox = QHBoxLayout()
|
||||
self.outerBox.addWidget(self.showHide, 0)
|
||||
self.outerBox.addStretch(1)
|
||||
self.outerBox.addWidget(self.showComments, 0)
|
||||
self.outerBox.addWidget(self.showSynopsis, 0)
|
||||
self.outerBox.addWidget(self.showNotes, 0)
|
||||
self.outerBox.setSpacing(4)
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
@@ -944,6 +955,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.setFont(SHARED.theme.guiFont)
|
||||
self.showComments.setFont(SHARED.theme.guiFontSmall)
|
||||
self.showSynopsis.setFont(SHARED.theme.guiFontSmall)
|
||||
self.showNotes.setFont(SHARED.theme.guiFontSmall)
|
||||
return
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
@@ -955,11 +967,13 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showHide.setThemeIcon("panel")
|
||||
self.showComments.setIcon(bulletIcon)
|
||||
self.showSynopsis.setIcon(bulletIcon)
|
||||
self.showNotes.setIcon(bulletIcon)
|
||||
|
||||
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
|
||||
self.showHide.setStyleSheet(buttonStyle)
|
||||
self.showComments.setStyleSheet(buttonStyle)
|
||||
self.showSynopsis.setStyleSheet(buttonStyle)
|
||||
self.showNotes.setStyleSheet(buttonStyle)
|
||||
|
||||
self.matchColors()
|
||||
|
||||
@@ -994,3 +1008,10 @@ class GuiDocViewFooter(QWidget):
|
||||
CONFIG.viewSynopsis = state
|
||||
self.docViewer.reloadText()
|
||||
return
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def _doToggleNotes(self, state: bool) -> None:
|
||||
"""Toggle the view notes button and reload the document."""
|
||||
CONFIG.viewNotes = state
|
||||
self.docViewer.reloadText()
|
||||
return
|
||||
|
||||
@@ -233,14 +233,8 @@ class GuiItemDetails(QWidget):
|
||||
# Label
|
||||
# =====
|
||||
|
||||
if nwItem.isFileType():
|
||||
if nwItem.isActive:
|
||||
self.labelIcon.setPixmap(SHARED.theme.getPixmap("checked", (iPx, iPx), "green"))
|
||||
else:
|
||||
self.labelIcon.setPixmap(SHARED.theme.getPixmap("unchecked", (iPx, iPx), "red"))
|
||||
else:
|
||||
self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx), "faded"))
|
||||
|
||||
_, icon = nwItem.getActiveStatus()
|
||||
self.labelIcon.setPixmap(icon.pixmap(iPx, iPx))
|
||||
self.labelData.setText(elide(nwItem.itemName, 100))
|
||||
|
||||
# Status
|
||||
|
||||
@@ -675,6 +675,14 @@ class GuiMainMenu(QMenuBar):
|
||||
)
|
||||
self.mainGui.addAction(self.aFmtStrike)
|
||||
|
||||
# Format > Highlight
|
||||
self.aFmtMark = qtAddAction(self.fmtMenu, self.tr("Highlight"))
|
||||
self.aFmtMark.setShortcut("Ctrl+M")
|
||||
self.aFmtMark.triggered.connect(
|
||||
lambda: self.requestDocAction.emit(nwDocAction.MD_MARK)
|
||||
)
|
||||
self.mainGui.addAction(self.aFmtStrike)
|
||||
|
||||
# Edit > Separator
|
||||
self.fmtMenu.addSeparator()
|
||||
|
||||
|
||||
@@ -27,12 +27,13 @@ import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import QEvent, QPoint, QSize, pyqtSignal
|
||||
from PyQt6.QtCore import QEvent, QPoint, QSize, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtWidgets import QMenu, QVBoxLayout, QWidget
|
||||
|
||||
from novelwriter import SHARED
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import qtLambda
|
||||
from novelwriter.enum import nwView
|
||||
from novelwriter.constants import nwLabels, trConst
|
||||
from novelwriter.enum import nwTheme, nwView
|
||||
from novelwriter.extensions.eventfilters import StatusTipFilter
|
||||
from novelwriter.extensions.modified import NIconToolButton
|
||||
from novelwriter.gui.theme import STYLES_BIG_TOOLBUTTON
|
||||
@@ -77,9 +78,9 @@ class GuiSideBar(QWidget):
|
||||
self.tbOutline.setToolTip("{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
|
||||
self.tbOutline.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.OUTLINE))
|
||||
|
||||
self.tbBuild = NIconToolButton(self, iSz)
|
||||
self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
|
||||
self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
|
||||
self.tbTheme = NIconToolButton(self, iSz)
|
||||
self.tbTheme.setToolTip(self.tr("Switch Colour Theme"))
|
||||
self.tbTheme.clicked.connect(self._cycleColurTheme)
|
||||
|
||||
self.tbDetails = NIconToolButton(self, iSz)
|
||||
self.tbDetails.setToolTip("{0} [Shift+F6]".format(self.tr("Novel Details")))
|
||||
@@ -89,6 +90,10 @@ class GuiSideBar(QWidget):
|
||||
self.tbStats.setToolTip("{0} [F6]".format(self.tr("Writing Statistics")))
|
||||
self.tbStats.clicked.connect(self.mainGui.showWritingStatsDialog)
|
||||
|
||||
self.tbBuild = NIconToolButton(self, iSz)
|
||||
self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
|
||||
self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
|
||||
|
||||
# Settings Menu
|
||||
self.tbSettings = NIconToolButton(self, iSz)
|
||||
self.tbSettings.setToolTip(self.tr("Settings"))
|
||||
@@ -111,6 +116,7 @@ class GuiSideBar(QWidget):
|
||||
self.outerBox.addStretch(1)
|
||||
self.outerBox.addWidget(self.tbDetails)
|
||||
self.outerBox.addWidget(self.tbStats)
|
||||
self.outerBox.addWidget(self.tbTheme)
|
||||
self.outerBox.addWidget(self.tbSettings)
|
||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
||||
self.outerBox.setSpacing(6)
|
||||
@@ -133,6 +139,7 @@ class GuiSideBar(QWidget):
|
||||
self.tbBuild.setStyleSheet(buttonStyle)
|
||||
self.tbDetails.setStyleSheet(buttonStyle)
|
||||
self.tbStats.setStyleSheet(buttonStyle)
|
||||
self.tbTheme.setStyleSheet(buttonStyle)
|
||||
self.tbSettings.setStyleSheet(buttonStyle)
|
||||
|
||||
self.tbProject.setThemeIcon("sb_project")
|
||||
@@ -144,6 +151,36 @@ class GuiSideBar(QWidget):
|
||||
self.tbStats.setThemeIcon("sb_stats")
|
||||
self.tbSettings.setThemeIcon("settings")
|
||||
|
||||
self._setThemeModeIcon()
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
|
||||
@pyqtSlot()
|
||||
def _cycleColurTheme(self) -> None:
|
||||
"""Go to nex colour theme."""
|
||||
match CONFIG.themeMode:
|
||||
case nwTheme.AUTO:
|
||||
CONFIG.themeMode = nwTheme.LIGHT
|
||||
case nwTheme.LIGHT:
|
||||
CONFIG.themeMode = nwTheme.DARK
|
||||
case nwTheme.DARK:
|
||||
CONFIG.themeMode = nwTheme.AUTO
|
||||
self.mainGui.checkThemeUpdate()
|
||||
self._setThemeModeIcon()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _setThemeModeIcon(self) -> None:
|
||||
"""Set the theme button icon."""
|
||||
self.tbTheme.setThemeIcon(nwLabels.THEME_MODE_ICON[CONFIG.themeMode])
|
||||
self.tbTheme.setToolTip(trConst(nwLabels.THEME_MODE_LABEL[CONFIG.themeMode]))
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -143,9 +143,9 @@ class GuiMainStatus(QStatusBar):
|
||||
self.idlePixmap = SHARED.theme.getPixmap("timer_off", (iPx, iPx))
|
||||
self.timeIcon.setPixmap(self.timePixmap)
|
||||
|
||||
colNone = SHARED.theme.getIconColor("default").darker(150)
|
||||
colSaved = SHARED.theme.getIconColor("green").darker(150)
|
||||
colUnsaved = SHARED.theme.getIconColor("red").darker(150)
|
||||
colNone = SHARED.theme.getBaseColor("default").darker(150)
|
||||
colSaved = SHARED.theme.getBaseColor("green").darker(150)
|
||||
colUnsaved = SHARED.theme.getBaseColor("red").darker(150)
|
||||
self.docIcon.setColors(colNone, colSaved, colUnsaved)
|
||||
self.projIcon.setColors(colNone, colSaved, colUnsaved)
|
||||
|
||||
|
||||
+362
-326
@@ -26,21 +26,23 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from configparser import ConfigParser
|
||||
from dataclasses import dataclass
|
||||
from math import ceil
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
from PyQt6.QtCore import QSize, Qt
|
||||
from PyQt6.QtGui import (
|
||||
QColor, QFont, QFontDatabase, QFontMetrics, QIcon, QPainter, QPainterPath,
|
||||
QPalette, QPixmap
|
||||
QColor, QFont, QFontDatabase, QFontMetrics, QGuiApplication, QIcon,
|
||||
QPainter, QPainterPath, QPalette, QPixmap
|
||||
)
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.common import NWConfigParser, minmax
|
||||
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX
|
||||
from novelwriter.common import checkInt, minmax
|
||||
from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS, DEF_TREECOL
|
||||
from novelwriter.constants import nwLabels
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType, nwTheme
|
||||
from novelwriter.error import logException
|
||||
from novelwriter.types import QtBlack, QtHexArgb, QtPaintAntiAlias, QtTransparent
|
||||
|
||||
@@ -54,21 +56,36 @@ STYLES_MIN_TOOLBUTTON = "minimalToolButton"
|
||||
STYLES_BIG_TOOLBUTTON = "bigToolButton"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ThemeEntry:
|
||||
|
||||
name: str
|
||||
dark: bool
|
||||
path: Path
|
||||
|
||||
|
||||
class ThemeMeta:
|
||||
|
||||
name: str = ""
|
||||
mode: str = ""
|
||||
description: str = ""
|
||||
author: str = ""
|
||||
credit: str = ""
|
||||
url: str = ""
|
||||
license: str = ""
|
||||
licenseUrl: str = ""
|
||||
|
||||
|
||||
class IconsMeta:
|
||||
|
||||
name: str = ""
|
||||
author: str = ""
|
||||
license: str = ""
|
||||
|
||||
|
||||
class SyntaxColors:
|
||||
|
||||
back: QColor = QColor(255, 255, 255)
|
||||
text: QColor = QColor(0, 0, 0)
|
||||
line: QColor = QColor(0, 0, 0)
|
||||
link: QColor = QColor(0, 0, 0)
|
||||
head: QColor = QColor(0, 0, 0)
|
||||
headH: QColor = QColor(0, 0, 0)
|
||||
@@ -96,45 +113,41 @@ class GuiTheme:
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"_availSyntax", "_availThemes", "_guiPalette", "_styleSheets", "_syntaxList", "_themeList",
|
||||
"baseButtonHeight", "baseIconHeight", "baseIconSize", "buttonIconSize", "errorText",
|
||||
"fadedText", "fontPixelSize", "fontPointSize", "getDecoration", "getHeaderDecoration",
|
||||
"getHeaderDecorationNarrow", "getIcon", "getIconColor", "getItemIcon", "getPixmap",
|
||||
"getToggleIcon", "guiFont", "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall",
|
||||
"helpText", "iconCache", "isDarkTheme", "syntaxMeta", "syntaxTheme", "textNHeight",
|
||||
"textNWidth", "themeMeta",
|
||||
"_allThemes", "_currentTheme", "_darkThemes", "_guiPalette", "_lightThemes", "_meta",
|
||||
"_qColors", "_styleSheets", "_svgColors", "_syntaxList", "accentCol", "baseButtonHeight",
|
||||
"baseIconHeight", "baseIconSize", "buttonIconSize", "errorText", "fadedText",
|
||||
"fontPixelSize", "fontPointSize", "getDecoration", "getHeaderDecoration",
|
||||
"getHeaderDecorationNarrow", "getIcon", "getItemIcon", "getPixmap", "getToggleIcon",
|
||||
"guiFont", "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall", "helpText",
|
||||
"iconCache", "isDarkTheme", "syntaxTheme", "textNHeight", "textNWidth",
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
self.iconCache = GuiIcons(self)
|
||||
|
||||
# GUI Theme
|
||||
self.themeMeta = ThemeMeta()
|
||||
# Theme Objects
|
||||
self.iconCache = GuiIcons(self)
|
||||
self.syntaxTheme = SyntaxColors()
|
||||
self.isDarkTheme = False
|
||||
|
||||
# Special Text Colours
|
||||
# Special Colours
|
||||
self.helpText = QColor(0, 0, 0)
|
||||
self.fadedText = QColor(0, 0, 0)
|
||||
self.errorText = QColor(255, 0, 0)
|
||||
self.accentCol = QColor(255, 0, 255) # Needed until we move to Qt 6.6
|
||||
|
||||
# Syntax Theme
|
||||
self.syntaxMeta = ThemeMeta()
|
||||
self.syntaxTheme = SyntaxColors()
|
||||
|
||||
# Load Themes
|
||||
# Theme Data
|
||||
self._meta = ThemeMeta()
|
||||
self._currentTheme = ""
|
||||
self._guiPalette = QPalette()
|
||||
self._themeList: list[tuple[str, str]] = []
|
||||
self._syntaxList: list[tuple[str, str]] = []
|
||||
self._availThemes: dict[str, Path] = {}
|
||||
self._availSyntax: dict[str, Path] = {}
|
||||
self._allThemes: dict[str, ThemeEntry] = {}
|
||||
self._styleSheets: dict[str, str] = {}
|
||||
self._svgColors: dict[str, bytes] = {}
|
||||
self._qColors: dict[str, QColor] = {}
|
||||
|
||||
# Icon Functions
|
||||
self.getIcon = self.iconCache.getIcon
|
||||
self.getPixmap = self.iconCache.getPixmap
|
||||
self.getItemIcon = self.iconCache.getItemIcon
|
||||
self.getIconColor = self.iconCache.getIconColor
|
||||
self.getToggleIcon = self.iconCache.getToggleIcon
|
||||
self.getDecoration = self.iconCache.getDecoration
|
||||
self.getHeaderDecoration = self.iconCache.getHeaderDecoration
|
||||
@@ -178,19 +191,19 @@ class GuiTheme:
|
||||
logger.debug("Text 'N' Height: %d", self.textNHeight)
|
||||
logger.debug("Text 'N' Width: %d", self.textNWidth)
|
||||
|
||||
# Process Themes
|
||||
_listConf(self._availSyntax, CONFIG.assetPath("syntax"), ".conf")
|
||||
_listConf(self._availThemes, CONFIG.assetPath("themes"), ".conf")
|
||||
_listConf(self._availSyntax, CONFIG.dataPath("syntax"), ".conf")
|
||||
_listConf(self._availThemes, CONFIG.dataPath("themes"), ".conf")
|
||||
|
||||
self.loadTheme()
|
||||
self.loadSyntax()
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Methods
|
||||
# Properties
|
||||
##
|
||||
|
||||
@property
|
||||
def colourThemes(self) -> dict[str, ThemeEntry]:
|
||||
"""Return a dictionary of all themes."""
|
||||
return self._allThemes
|
||||
|
||||
##
|
||||
# Getters
|
||||
##
|
||||
|
||||
def getTextWidth(self, text: str, font: QFont | None = None) -> int:
|
||||
@@ -203,30 +216,79 @@ class GuiTheme:
|
||||
qMetrics = QFontMetrics(self.guiFont)
|
||||
return ceil(qMetrics.boundingRect(text).width())
|
||||
|
||||
def getBaseColor(self, name: str) -> QColor:
|
||||
"""Return a base color."""
|
||||
return QColor(self._qColors.get(name) or QtBlack)
|
||||
|
||||
def getRawBaseColor(self, name: str) -> bytes:
|
||||
"""Return a base color."""
|
||||
return self._svgColors.get(name, self._svgColors.get("default", b"#000000"))
|
||||
|
||||
##
|
||||
# Theme Methods
|
||||
##
|
||||
|
||||
def loadTheme(self) -> bool:
|
||||
"""Load the currently specified GUI theme."""
|
||||
theme = CONFIG.guiTheme
|
||||
if theme not in self._availThemes:
|
||||
logger.error("Could not find GUI theme '%s'", theme)
|
||||
theme = DEF_GUI
|
||||
CONFIG.guiTheme = theme
|
||||
def initThemes(self) -> None:
|
||||
"""Initialise themes."""
|
||||
CONFIG.splashMessage("Scanning for colour themes ...")
|
||||
themes: list[Path] = []
|
||||
_listContent(themes, CONFIG.assetPath("themes"), ".conf")
|
||||
_listContent(themes, CONFIG.dataPath("themes"), ".conf")
|
||||
self._scanThemes(themes)
|
||||
|
||||
if not (file := self._availThemes.get(theme)):
|
||||
self.iconCache.initIcons()
|
||||
self.loadTheme()
|
||||
|
||||
return
|
||||
|
||||
def isDesktopDarkMode(self) -> bool:
|
||||
"""Check if the desktop is in dark mode."""
|
||||
if CONFIG.verQtValue >= 0x060500 and (hint := QGuiApplication.styleHints()):
|
||||
return hint.colorScheme() == Qt.ColorScheme.Dark
|
||||
|
||||
palette = QPalette()
|
||||
text = palette.windowText().color()
|
||||
window = palette.window().color()
|
||||
return text.lightnessF() > window.lightnessF()
|
||||
|
||||
def loadTheme(self, force: bool = False) -> bool:
|
||||
"""Load the currently specified GUI theme. The boolean return
|
||||
can be used to determine if the GUI needs refreshing.
|
||||
"""
|
||||
match CONFIG.themeMode:
|
||||
case nwTheme.LIGHT:
|
||||
darkMode = False
|
||||
case nwTheme.DARK:
|
||||
darkMode = True
|
||||
case _:
|
||||
darkMode = self.isDesktopDarkMode()
|
||||
|
||||
theme = CONFIG.darkTheme if darkMode else CONFIG.lightTheme
|
||||
if theme not in self._allThemes:
|
||||
logger.error("Could not find theme '%s'", theme)
|
||||
if darkMode:
|
||||
theme = DEF_GUI_DARK
|
||||
CONFIG.darkTheme = DEF_GUI_DARK
|
||||
else:
|
||||
theme = DEF_GUI_LIGHT
|
||||
CONFIG.lightTheme = DEF_GUI_LIGHT
|
||||
|
||||
if theme == self._currentTheme and not force:
|
||||
logger.info("Theme '%s' is already loaded", theme)
|
||||
return False
|
||||
|
||||
entry = self._allThemes.get(theme)
|
||||
if not entry:
|
||||
logger.error("Could not load GUI theme")
|
||||
return False
|
||||
|
||||
CONFIG.splashMessage("Loading GUI theme ...")
|
||||
CONFIG.splashMessage(f"Loading colour theme: {entry.name}")
|
||||
logger.info("Loading GUI theme '%s'", theme)
|
||||
parser = NWConfigParser()
|
||||
parser = ConfigParser()
|
||||
try:
|
||||
with open(file, mode="r", encoding="utf-8") as fo:
|
||||
parser.read_file(fo)
|
||||
parser.read(entry.path, encoding="utf-8")
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", file)
|
||||
logger.error("Could not read file: %s", entry.path)
|
||||
logException()
|
||||
return False
|
||||
|
||||
@@ -237,39 +299,42 @@ class GuiTheme:
|
||||
sec = "Main"
|
||||
meta = ThemeMeta()
|
||||
if parser.has_section(sec):
|
||||
meta.name = parser.rdStr(sec, "name", "")
|
||||
meta.description = parser.rdStr(sec, "description", "N/A")
|
||||
meta.author = parser.rdStr(sec, "author", "N/A")
|
||||
meta.credit = parser.rdStr(sec, "credit", "N/A")
|
||||
meta.url = parser.rdStr(sec, "url", "")
|
||||
meta.license = parser.rdStr(sec, "license", "N/A")
|
||||
meta.licenseUrl = parser.rdStr(sec, "licenseurl", "")
|
||||
meta.name = parser.get(sec, "name", fallback="")
|
||||
meta.mode = parser.get(sec, "mode", fallback="light")
|
||||
meta.description = parser.get(sec, "description", fallback="")
|
||||
meta.author = parser.get(sec, "author", fallback="")
|
||||
meta.credit = parser.get(sec, "credit", fallback="")
|
||||
meta.url = parser.get(sec, "url", fallback="")
|
||||
|
||||
self.themeMeta = meta
|
||||
self._meta = meta
|
||||
|
||||
# Icons
|
||||
sec = "Icons"
|
||||
# Base
|
||||
sec = "Base"
|
||||
if parser.has_section(sec):
|
||||
self.iconCache.setIconColor("default", self._parseColor(parser, sec, "default"))
|
||||
self.iconCache.setIconColor("faded", self._parseColor(parser, sec, "faded"))
|
||||
self.iconCache.setIconColor("red", self._parseColor(parser, sec, "red"))
|
||||
self.iconCache.setIconColor("orange", self._parseColor(parser, sec, "orange"))
|
||||
self.iconCache.setIconColor("yellow", self._parseColor(parser, sec, "yellow"))
|
||||
self.iconCache.setIconColor("green", self._parseColor(parser, sec, "green"))
|
||||
self.iconCache.setIconColor("aqua", self._parseColor(parser, sec, "aqua"))
|
||||
self.iconCache.setIconColor("blue", self._parseColor(parser, sec, "blue"))
|
||||
self.iconCache.setIconColor("purple", self._parseColor(parser, sec, "purple"))
|
||||
self._setBaseColor("base", self._readColor(parser, sec, "base"))
|
||||
self._setBaseColor("default", self._readColor(parser, sec, "default"))
|
||||
self._setBaseColor("faded", self._readColor(parser, sec, "faded"))
|
||||
self._setBaseColor("red", self._readColor(parser, sec, "red"))
|
||||
self._setBaseColor("orange", self._readColor(parser, sec, "orange"))
|
||||
self._setBaseColor("yellow", self._readColor(parser, sec, "yellow"))
|
||||
self._setBaseColor("green", self._readColor(parser, sec, "green"))
|
||||
self._setBaseColor("cyan", self._readColor(parser, sec, "cyan"))
|
||||
self._setBaseColor("blue", self._readColor(parser, sec, "blue"))
|
||||
self._setBaseColor("purple", self._readColor(parser, sec, "purple"))
|
||||
|
||||
# Project
|
||||
sec = "Project"
|
||||
if parser.has_section(sec):
|
||||
self.iconCache.setIconColor("root", self._parseColor(parser, sec, "root"))
|
||||
self.iconCache.setIconColor("folder", self._parseColor(parser, sec, "folder"))
|
||||
self.iconCache.setIconColor("file", self._parseColor(parser, sec, "file"))
|
||||
self.iconCache.setIconColor("title", self._parseColor(parser, sec, "title"))
|
||||
self.iconCache.setIconColor("chapter", self._parseColor(parser, sec, "chapter"))
|
||||
self.iconCache.setIconColor("scene", self._parseColor(parser, sec, "scene"))
|
||||
self.iconCache.setIconColor("note", self._parseColor(parser, sec, "note"))
|
||||
self._setBaseColor("root", self._readColor(parser, sec, "root"))
|
||||
self._setBaseColor("folder", self._readColor(parser, sec, "folder"))
|
||||
self._setBaseColor("file", self._readColor(parser, sec, "file"))
|
||||
self._setBaseColor("title", self._readColor(parser, sec, "title"))
|
||||
self._setBaseColor("chapter", self._readColor(parser, sec, "chapter"))
|
||||
self._setBaseColor("scene", self._readColor(parser, sec, "scene"))
|
||||
self._setBaseColor("note", self._readColor(parser, sec, "note"))
|
||||
self._setBaseColor("active", self._readColor(parser, sec, "active"))
|
||||
self._setBaseColor("inactive", self._readColor(parser, sec, "inactive"))
|
||||
self._setBaseColor("disabled", self._readColor(parser, sec, "disabled"))
|
||||
|
||||
# Palette
|
||||
sec = "Palette"
|
||||
@@ -288,20 +353,46 @@ class GuiTheme:
|
||||
self._setPalette(parser, sec, "highlightedtext", QPalette.ColorRole.HighlightedText)
|
||||
self._setPalette(parser, sec, "link", QPalette.ColorRole.Link)
|
||||
self._setPalette(parser, sec, "linkvisited", QPalette.ColorRole.LinkVisited)
|
||||
self.accentCol = self._readColor(parser, sec, "accent") # Special handling 'til Qt 6.6
|
||||
|
||||
# GUI
|
||||
sec = "GUI"
|
||||
if parser.has_section(sec):
|
||||
self.helpText = self._parseColor(parser, sec, "helptext")
|
||||
self.fadedText = self._parseColor(parser, sec, "fadedtext")
|
||||
self.errorText = self._parseColor(parser, sec, "errortext")
|
||||
self.helpText = self._readColor(parser, sec, "helptext")
|
||||
self.fadedText = self._readColor(parser, sec, "fadedtext")
|
||||
self.errorText = self._readColor(parser, sec, "errortext")
|
||||
|
||||
# Syntax
|
||||
sec = "Syntax"
|
||||
self.syntaxTheme = SyntaxColors()
|
||||
if parser.has_section(sec):
|
||||
self.syntaxTheme.back = self._readColor(parser, sec, "background")
|
||||
self.syntaxTheme.text = self._readColor(parser, sec, "text")
|
||||
self.syntaxTheme.line = self._readColor(parser, sec, "line")
|
||||
self.syntaxTheme.link = self._readColor(parser, sec, "link")
|
||||
self.syntaxTheme.head = self._readColor(parser, sec, "headertext")
|
||||
self.syntaxTheme.headH = self._readColor(parser, sec, "headertag")
|
||||
self.syntaxTheme.emph = self._readColor(parser, sec, "emphasis")
|
||||
self.syntaxTheme.dialN = self._readColor(parser, sec, "dialog")
|
||||
self.syntaxTheme.dialA = self._readColor(parser, sec, "altdialog")
|
||||
self.syntaxTheme.hidden = self._readColor(parser, sec, "hidden")
|
||||
self.syntaxTheme.note = self._readColor(parser, sec, "note")
|
||||
self.syntaxTheme.code = self._readColor(parser, sec, "shortcode")
|
||||
self.syntaxTheme.key = self._readColor(parser, sec, "keyword")
|
||||
self.syntaxTheme.tag = self._readColor(parser, sec, "tag")
|
||||
self.syntaxTheme.val = self._readColor(parser, sec, "value")
|
||||
self.syntaxTheme.opt = self._readColor(parser, sec, "optional")
|
||||
self.syntaxTheme.spell = self._readColor(parser, sec, "spellcheckline")
|
||||
self.syntaxTheme.error = self._readColor(parser, sec, "errorline")
|
||||
self.syntaxTheme.repTag = self._readColor(parser, sec, "replacetag")
|
||||
self.syntaxTheme.mod = self._readColor(parser, sec, "modifier")
|
||||
self.syntaxTheme.mark = self._readColor(parser, sec, "texthighlight")
|
||||
|
||||
# Update Dependant Colours
|
||||
# Based on: https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qplatformtheme.cpp
|
||||
text = self._guiPalette.text().color()
|
||||
window = self._guiPalette.window().color()
|
||||
highlight = self._guiPalette.highlight().color()
|
||||
isDark = text.lightnessF() > window.lightnessF()
|
||||
|
||||
QtColActive = QPalette.ColorGroup.Active
|
||||
QtColInactive = QPalette.ColorGroup.Inactive
|
||||
@@ -321,8 +412,8 @@ class GuiTheme:
|
||||
darkOff = dark.darker(150)
|
||||
shadowOff = ref.darker(150)
|
||||
|
||||
grey = QColor(120, 120, 120) if isDark else QColor(140, 140, 140)
|
||||
dimmed = QColor(130, 130, 130) if isDark else QColor(190, 190, 190)
|
||||
grey = QColor(120, 120, 120) if darkMode else QColor(140, 140, 140)
|
||||
dimmed = QColor(130, 130, 130) if darkMode else QColor(190, 190, 190)
|
||||
|
||||
placeholder = QColor(text)
|
||||
placeholder.setAlpha(128)
|
||||
@@ -347,145 +438,94 @@ class GuiTheme:
|
||||
self._guiPalette.setBrush(QtColDisabled, QPalette.ColorRole.Highlight, grey)
|
||||
|
||||
if CONFIG.verQtValue >= 0x060600:
|
||||
self._guiPalette.setBrush(QtColActive, QPalette.ColorRole.Accent, highlight)
|
||||
self._guiPalette.setBrush(QtColInactive, QPalette.ColorRole.Accent, highlight)
|
||||
self._guiPalette.setBrush(QtColActive, QPalette.ColorRole.Accent, self.accentCol)
|
||||
self._guiPalette.setBrush(QtColInactive, QPalette.ColorRole.Accent, self.accentCol)
|
||||
self._guiPalette.setBrush(QtColDisabled, QPalette.ColorRole.Accent, grey)
|
||||
|
||||
# Set project override colours
|
||||
if (override := CONFIG.iconColTree) != DEF_TREECOL:
|
||||
color = self._qColors.get(override, QtBlack)
|
||||
self._setBaseColor("root", color)
|
||||
self._setBaseColor("folder", color)
|
||||
if not CONFIG.iconColDocs:
|
||||
self._setBaseColor("file", color)
|
||||
self._setBaseColor("title", color)
|
||||
self._setBaseColor("chapter", color)
|
||||
self._setBaseColor("scene", color)
|
||||
self._setBaseColor("note", color)
|
||||
|
||||
self.isDarkTheme = darkMode
|
||||
self._currentTheme = theme
|
||||
|
||||
# Load icons after the theme is parsed
|
||||
self.iconCache.loadTheme(CONFIG.iconTheme)
|
||||
|
||||
# Finalise
|
||||
self.isDarkTheme = isDark
|
||||
QApplication.setPalette(self._guiPalette)
|
||||
self._buildStyleSheets(self._guiPalette)
|
||||
|
||||
CONFIG.splashMessage(f"Loaded GUI theme: {meta.name}")
|
||||
|
||||
return True
|
||||
|
||||
def loadSyntax(self) -> bool:
|
||||
"""Load the currently specified syntax highlighter theme."""
|
||||
theme = CONFIG.guiSyntax
|
||||
if theme not in self._availSyntax:
|
||||
logger.error("Could not find syntax theme '%s'", theme)
|
||||
theme = DEF_SYNTAX
|
||||
CONFIG.guiSyntax = theme
|
||||
|
||||
if not (file := self._availSyntax.get(theme)):
|
||||
logger.error("Could not load syntax theme")
|
||||
return False
|
||||
|
||||
CONFIG.splashMessage("Loading syntax theme ...")
|
||||
logger.info("Loading syntax theme '%s'", theme)
|
||||
parser = NWConfigParser()
|
||||
try:
|
||||
with open(file, mode="r", encoding="utf-8") as fo:
|
||||
parser.read_file(fo)
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", file)
|
||||
logException()
|
||||
return False
|
||||
|
||||
# Main
|
||||
sec = "Main"
|
||||
meta = ThemeMeta()
|
||||
if parser.has_section(sec):
|
||||
meta.name = parser.rdStr(sec, "name", "")
|
||||
meta.description = parser.rdStr(sec, "description", "N/A")
|
||||
meta.author = parser.rdStr(sec, "author", "N/A")
|
||||
meta.credit = parser.rdStr(sec, "credit", "N/A")
|
||||
meta.url = parser.rdStr(sec, "url", "")
|
||||
meta.license = parser.rdStr(sec, "license", "N/A")
|
||||
meta.licenseUrl = parser.rdStr(sec, "licenseurl", "")
|
||||
|
||||
# Syntax
|
||||
sec = "Syntax"
|
||||
syntax = SyntaxColors()
|
||||
if parser.has_section(sec):
|
||||
syntax.back = self._parseColor(parser, sec, "background")
|
||||
syntax.text = self._parseColor(parser, sec, "text")
|
||||
syntax.link = self._parseColor(parser, sec, "link")
|
||||
syntax.head = self._parseColor(parser, sec, "headertext")
|
||||
syntax.headH = self._parseColor(parser, sec, "headertag")
|
||||
syntax.emph = self._parseColor(parser, sec, "emphasis")
|
||||
syntax.dialN = self._parseColor(parser, sec, "dialog")
|
||||
syntax.dialA = self._parseColor(parser, sec, "altdialog")
|
||||
syntax.hidden = self._parseColor(parser, sec, "hidden")
|
||||
syntax.note = self._parseColor(parser, sec, "note")
|
||||
syntax.code = self._parseColor(parser, sec, "shortcode")
|
||||
syntax.key = self._parseColor(parser, sec, "keyword")
|
||||
syntax.tag = self._parseColor(parser, sec, "tag")
|
||||
syntax.val = self._parseColor(parser, sec, "value")
|
||||
syntax.opt = self._parseColor(parser, sec, "optional")
|
||||
syntax.spell = self._parseColor(parser, sec, "spellcheckline")
|
||||
syntax.error = self._parseColor(parser, sec, "errorline")
|
||||
syntax.repTag = self._parseColor(parser, sec, "replacetag")
|
||||
syntax.mod = self._parseColor(parser, sec, "modifier")
|
||||
syntax.mark = self._parseColor(parser, sec, "texthighlight")
|
||||
|
||||
CONFIG.splashMessage(f"Loaded syntax theme: {meta.name}")
|
||||
|
||||
self.syntaxMeta = meta
|
||||
self.syntaxTheme = syntax
|
||||
|
||||
return True
|
||||
|
||||
def listThemes(self) -> list[tuple[str, str]]:
|
||||
"""Scan the GUI themes folder and list all themes."""
|
||||
if self._themeList:
|
||||
return self._themeList
|
||||
|
||||
themes = []
|
||||
parser = NWConfigParser()
|
||||
for key, path in self._availThemes.items():
|
||||
logger.debug("Checking theme config '%s'", key)
|
||||
if name := _loadInternalName(parser, path):
|
||||
themes.append((key, name))
|
||||
|
||||
self._themeList = sorted(themes, key=_sortTheme)
|
||||
|
||||
return self._themeList
|
||||
|
||||
def listSyntax(self) -> list[tuple[str, str]]:
|
||||
"""Scan the syntax themes folder and list all themes."""
|
||||
if self._syntaxList:
|
||||
return self._syntaxList
|
||||
|
||||
themes = []
|
||||
parser = NWConfigParser()
|
||||
for key, path in self._availSyntax.items():
|
||||
logger.debug("Checking theme syntax '%s'", key)
|
||||
if name := _loadInternalName(parser, path):
|
||||
themes.append((key, name))
|
||||
|
||||
self._syntaxList = sorted(themes, key=_sortTheme)
|
||||
|
||||
return self._syntaxList
|
||||
|
||||
def getStyleSheet(self, name: str) -> str:
|
||||
"""Load a standard style sheet."""
|
||||
return self._styleSheets.get(name, "")
|
||||
|
||||
def parseColor(self, value: str, default: QColor = QtBlack) -> QColor:
|
||||
"""Parse a string as a colour value."""
|
||||
if value in self._qColors:
|
||||
# Named colour
|
||||
return self._qColors[value]
|
||||
elif value.startswith("#") and len(value) == 7:
|
||||
# Assume #RRGGBB
|
||||
return QColor.fromString(value)
|
||||
elif value.startswith("#") and len(value) == 9:
|
||||
# Assume #RRGGBBAA and convert to #AARRGGBB
|
||||
return QColor.fromString(f"#{value[7:9]}{value[1:7]}")
|
||||
elif ":" in value:
|
||||
# Colour name and lighter, darker or alpha
|
||||
name, _, adjust = value.partition(":")
|
||||
color = QColor(self._qColors.get(name.strip(), default))
|
||||
if adjust.startswith("L"):
|
||||
color = color.lighter(checkInt(adjust[1:], 100))
|
||||
elif adjust.startswith("D"):
|
||||
color = color.darker(checkInt(adjust[1:], 100))
|
||||
else:
|
||||
color.setAlpha(checkInt(adjust, 255))
|
||||
return color
|
||||
elif "," in value:
|
||||
# Integer red, green, blue, alpha
|
||||
data = value.split(",")
|
||||
result = [0, 0, 0, 255]
|
||||
for i in range(min(len(data), 4)):
|
||||
result[i] = checkInt(data[i].strip(), result[i])
|
||||
return QColor(*result)
|
||||
return default
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _setBaseColor(self, key: str, color: QColor) -> None:
|
||||
"""Set the colour for a named colour."""
|
||||
self._qColors[key] = QColor(color)
|
||||
self._svgColors[key] = color.name(QColor.NameFormat.HexRgb).encode("utf-8")
|
||||
return
|
||||
|
||||
def _resetTheme(self) -> None:
|
||||
"""Reset GUI colours to default values."""
|
||||
palette = QPalette()
|
||||
|
||||
text = palette.color(QPalette.ColorRole.Text)
|
||||
window = palette.color(QPalette.ColorRole.Window)
|
||||
isDark = text.lightnessF() > window.lightnessF()
|
||||
isDark = self.isDesktopDarkMode()
|
||||
|
||||
# Reset GUI Palette
|
||||
base = palette.color(QPalette.ColorRole.Base)
|
||||
default = palette.color(QPalette.ColorRole.Text)
|
||||
faded = QColor(128, 128, 128)
|
||||
dimmed = QColor(130, 130, 130) if isDark else QColor(190, 190, 190)
|
||||
red = QColor(242, 119, 122) if isDark else QColor(240, 40, 41)
|
||||
orange = QColor(249, 145, 57) if isDark else QColor(245, 135, 31)
|
||||
yellow = QColor(255, 204, 102) if isDark else QColor(234, 183, 0)
|
||||
green = QColor(153, 204, 153) if isDark else QColor(113, 140, 0)
|
||||
aqua = QColor(102, 204, 204) if isDark else QColor(62, 153, 159)
|
||||
cyan = QColor(102, 204, 204) if isDark else QColor(62, 153, 159)
|
||||
blue = QColor(102, 153, 204) if isDark else QColor(66, 113, 174)
|
||||
purple = QColor(204, 153, 204) if isDark else QColor(137, 89, 168)
|
||||
|
||||
@@ -496,37 +536,42 @@ class GuiTheme:
|
||||
|
||||
self._guiPalette = palette
|
||||
|
||||
# Reset Icons
|
||||
icons = self.iconCache
|
||||
icons.clear()
|
||||
icons.setIconColor("default", text)
|
||||
icons.setIconColor("faded", faded)
|
||||
icons.setIconColor("red", red)
|
||||
icons.setIconColor("orange", orange)
|
||||
icons.setIconColor("yellow", yellow)
|
||||
icons.setIconColor("green", green)
|
||||
icons.setIconColor("aqua", aqua)
|
||||
icons.setIconColor("blue", blue)
|
||||
icons.setIconColor("purple", purple)
|
||||
icons.setIconColor("root", blue)
|
||||
icons.setIconColor("folder", yellow)
|
||||
icons.setIconColor("file", text)
|
||||
icons.setIconColor("title", green)
|
||||
icons.setIconColor("chapter", red)
|
||||
icons.setIconColor("scene", blue)
|
||||
icons.setIconColor("note", yellow)
|
||||
# Reset Base Colours and Icons
|
||||
self.iconCache.clear()
|
||||
self._svgColors = {}
|
||||
self._qColors = {}
|
||||
self._setBaseColor("base", base)
|
||||
self._setBaseColor("default", default)
|
||||
self._setBaseColor("faded", faded)
|
||||
self._setBaseColor("red", red)
|
||||
self._setBaseColor("orange", orange)
|
||||
self._setBaseColor("yellow", yellow)
|
||||
self._setBaseColor("green", green)
|
||||
self._setBaseColor("cyan", cyan)
|
||||
self._setBaseColor("blue", blue)
|
||||
self._setBaseColor("purple", purple)
|
||||
self._setBaseColor("root", blue)
|
||||
self._setBaseColor("folder", yellow)
|
||||
self._setBaseColor("file", default)
|
||||
self._setBaseColor("title", green)
|
||||
self._setBaseColor("chapter", red)
|
||||
self._setBaseColor("scene", blue)
|
||||
self._setBaseColor("note", yellow)
|
||||
self._setBaseColor("active", green)
|
||||
self._setBaseColor("inactive", red)
|
||||
self._setBaseColor("disabled", faded)
|
||||
|
||||
return
|
||||
|
||||
def _parseColor(self, parser: NWConfigParser, section: str, name: str) -> QColor:
|
||||
def _readColor(self, parser: ConfigParser, section: str, name: str) -> QColor:
|
||||
"""Parse a colour value from a config string."""
|
||||
return QColor(*parser.rdIntList(section, name, [0, 0, 0, 255]))
|
||||
return self.parseColor(parser.get(section, name, fallback="default"))
|
||||
|
||||
def _setPalette(
|
||||
self, parser: NWConfigParser, section: str, name: str, value: QPalette.ColorRole
|
||||
self, parser: ConfigParser, section: str, name: str, value: QPalette.ColorRole
|
||||
) -> None:
|
||||
"""Set a palette colour value from a config string."""
|
||||
self._guiPalette.setBrush(value, self._parseColor(parser, section, name))
|
||||
self._guiPalette.setBrush(value, self._readColor(parser, section, name))
|
||||
return
|
||||
|
||||
def _buildStyleSheets(self, palette: QPalette) -> None:
|
||||
@@ -561,6 +606,35 @@ class GuiTheme:
|
||||
|
||||
return
|
||||
|
||||
def _scanThemes(self, files: list[Path]) -> None:
|
||||
"""Scan the GUI themes folder and list all themes."""
|
||||
parser = ConfigParser()
|
||||
data: dict[str, tuple[str, str, bool, Path]] = {}
|
||||
keys = []
|
||||
for file in files:
|
||||
try:
|
||||
parser.clear()
|
||||
parser.read(file, encoding="utf-8")
|
||||
name = parser.get("Main", "name", fallback="")
|
||||
mode = parser.get("Main", "mode", fallback="").lower()
|
||||
if name and mode in ("light", "dark"):
|
||||
key = file.stem
|
||||
prefix = "*" if key.startswith("default") else ""
|
||||
lookup = f"{prefix}{name} {key}"
|
||||
keys.append(lookup)
|
||||
data[lookup] = (file.stem, name, mode == "dark", file)
|
||||
except Exception: # noqa: PERF203
|
||||
logger.error("Could not read file: %s", file)
|
||||
logException()
|
||||
|
||||
self._allThemes = {}
|
||||
for lookup in sorted(keys):
|
||||
key, name, dark, item = data[lookup]
|
||||
logger.debug("Checking theme config '%s'", key)
|
||||
self._allThemes[key] = ThemeEntry(name, dark, item)
|
||||
|
||||
return
|
||||
|
||||
|
||||
class GuiIcons:
|
||||
"""The icon class manages the content of the assets/icons folder,
|
||||
@@ -572,9 +646,8 @@ class GuiIcons:
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"_availThemes", "_headerDec", "_headerDecNarrow", "_noIcon",
|
||||
"_qColors", "_qIcons", "_svgColors", "_svgData", "_themeList",
|
||||
"mainTheme", "themeMeta",
|
||||
"_allThemes", "_headerDec", "_headerDecNarrow", "_meta",
|
||||
"_noIcon", "_qIcons", "_svgData", "_theme",
|
||||
)
|
||||
|
||||
TOGGLE_ICON_KEYS: Final[dict[str, tuple[str, str]]] = {
|
||||
@@ -582,69 +655,78 @@ class GuiIcons:
|
||||
"unfold": ("unfold-show", "unfold-hide"),
|
||||
}
|
||||
IMAGE_MAP: Final[dict[str, tuple[str, str]]] = {
|
||||
"welcome": ("welcome-light.jpg", "welcome-dark.jpg"),
|
||||
"welcome": ("welcome.webp", "welcome.webp"),
|
||||
"nw-text": ("novelwriter-text-light.svg", "novelwriter-text-dark.svg"),
|
||||
}
|
||||
|
||||
def __init__(self, mainTheme: GuiTheme) -> None:
|
||||
|
||||
self.mainTheme = mainTheme
|
||||
self.themeMeta = ThemeMeta()
|
||||
self._theme = mainTheme
|
||||
self._meta = IconsMeta()
|
||||
|
||||
# Storage
|
||||
self._allThemes: dict[str, ThemeEntry] = {}
|
||||
self._svgData: dict[str, bytes] = {}
|
||||
self._svgColors: dict[str, bytes] = {}
|
||||
self._qColors: dict[str, QColor] = {}
|
||||
self._qIcons: dict[str, QIcon] = {}
|
||||
self._headerDec: list[QPixmap] = []
|
||||
self._headerDecNarrow: list[QPixmap] = []
|
||||
|
||||
# Icon Theme Path
|
||||
self._availThemes: dict[str, Path] = {}
|
||||
self._themeList: list[tuple[str, str]] = []
|
||||
|
||||
# None Icon
|
||||
self._noIcon = QIcon(str(CONFIG.assetPath("icons") / "none.svg"))
|
||||
|
||||
_listConf(self._availThemes, CONFIG.assetPath("icons"), ".icons")
|
||||
_listConf(self._availThemes, CONFIG.dataPath("icons"), ".icons")
|
||||
|
||||
return
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear the icon cache."""
|
||||
self._svgData = {}
|
||||
self._svgColors = {}
|
||||
self._qColors = {}
|
||||
self._qIcons = {}
|
||||
self._headerDec = []
|
||||
self._headerDecNarrow = []
|
||||
self.themeMeta = ThemeMeta()
|
||||
self._meta = ThemeMeta()
|
||||
return
|
||||
|
||||
##
|
||||
# Properties
|
||||
##
|
||||
|
||||
@property
|
||||
def iconThemes(self) -> dict[str, ThemeEntry]:
|
||||
"""Return a dictionary of all icon themes."""
|
||||
return self._allThemes
|
||||
|
||||
##
|
||||
# Actions
|
||||
##
|
||||
|
||||
def loadTheme(self, theme: str) -> bool:
|
||||
def initIcons(self) -> None:
|
||||
"""Initialise icons."""
|
||||
CONFIG.splashMessage("Scanning for icon themes ...")
|
||||
icons: list[Path] = []
|
||||
_listContent(icons, CONFIG.assetPath("icons"), ".icons")
|
||||
_listContent(icons, CONFIG.dataPath("icons"), ".icons")
|
||||
self._scanThemes(icons)
|
||||
return
|
||||
|
||||
def loadTheme(self, theme: str) -> None:
|
||||
"""Update the theme map. This is more of an init, since many of
|
||||
the GUI icons cannot really be replaced without writing specific
|
||||
update functions for the classes where they're used.
|
||||
"""
|
||||
if theme not in self._availThemes:
|
||||
if theme not in self._allThemes:
|
||||
logger.error("Could not find icon theme '%s'", theme)
|
||||
theme = DEF_ICONS
|
||||
CONFIG.iconTheme = theme
|
||||
|
||||
if not (file := self._availThemes.get(theme)):
|
||||
entry = self._allThemes.get(theme)
|
||||
if not entry:
|
||||
logger.error("Could not load icon theme")
|
||||
return False
|
||||
return
|
||||
|
||||
CONFIG.splashMessage("Loading icon theme ...")
|
||||
CONFIG.splashMessage(f"Loading icon theme: {entry.name}")
|
||||
logger.info("Loading icon theme '%s'", theme)
|
||||
try:
|
||||
meta = ThemeMeta()
|
||||
with open(file, mode="r", encoding="utf-8") as icons:
|
||||
meta = IconsMeta()
|
||||
with open(entry.path, mode="r", encoding="utf-8") as icons:
|
||||
for icon in icons:
|
||||
bits = icon.partition("=")
|
||||
key = bits[0].strip()
|
||||
@@ -658,47 +740,23 @@ class GuiIcons:
|
||||
meta.author = value
|
||||
elif key == "meta:license":
|
||||
meta.license = value
|
||||
self.themeMeta = meta
|
||||
self._meta = meta
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", file)
|
||||
logger.error("Could not read file: %s", entry.path)
|
||||
logException()
|
||||
return False
|
||||
|
||||
CONFIG.splashMessage(f"Loaded icon theme: {meta.name}")
|
||||
CONFIG.splashMessage("Generating additional icons ...")
|
||||
|
||||
# Set colour overrides for project item icons
|
||||
if (override := CONFIG.iconColTree) != "theme":
|
||||
color = self._svgColors.get(override, b"#000000")
|
||||
self._svgColors["root"] = color
|
||||
self._svgColors["folder"] = color
|
||||
if not CONFIG.iconColDocs:
|
||||
self._svgColors["file"] = color
|
||||
self._svgColors["title"] = color
|
||||
self._svgColors["chapter"] = color
|
||||
self._svgColors["scene"] = color
|
||||
self._svgColors["note"] = color
|
||||
return
|
||||
|
||||
# Populate generated icons cache
|
||||
CONFIG.splashMessage("Generating additional icons ...")
|
||||
self.getHeaderDecoration(0)
|
||||
self.getHeaderDecorationNarrow(0)
|
||||
|
||||
return True
|
||||
|
||||
def setIconColor(self, key: str, color: QColor) -> None:
|
||||
"""Set an icon colour for a named colour."""
|
||||
self._qColors[key] = QColor(color)
|
||||
self._svgColors[key] = color.name(QColor.NameFormat.HexRgb).encode("utf-8")
|
||||
return
|
||||
|
||||
##
|
||||
# Access Functions
|
||||
##
|
||||
|
||||
def getIconColor(self, name: str) -> QColor:
|
||||
"""Return an icon color."""
|
||||
return QColor(self._qColors.get(name) or QtBlack)
|
||||
|
||||
def getIcon(self, name: str, color: str | None = None, w: int = 24, h: int = 24) -> QIcon:
|
||||
"""Return an icon from the icon buffer, or load it."""
|
||||
variant = f"{name}-{color}" if color else name
|
||||
@@ -769,7 +827,7 @@ class GuiIcons:
|
||||
map or the icon map. This function always returns a QPixmap.
|
||||
"""
|
||||
if name in self.IMAGE_MAP:
|
||||
idx = int(self.mainTheme.isDarkTheme)
|
||||
idx = int(self._theme.isDarkTheme)
|
||||
imgPath = CONFIG.assetPath("images") / self.IMAGE_MAP[name][idx]
|
||||
else:
|
||||
logger.error("Decoration with name '%s' does not exist", name)
|
||||
@@ -793,7 +851,7 @@ class GuiIcons:
|
||||
def getHeaderDecoration(self, hLevel: int) -> QPixmap:
|
||||
"""Get the decoration for a specific heading level."""
|
||||
if not self._headerDec:
|
||||
iPx = self.mainTheme.baseIconHeight
|
||||
iPx = self._theme.baseIconHeight
|
||||
self._headerDec = [
|
||||
self._generateDecoration("file", iPx, 0),
|
||||
self._generateDecoration("title", iPx, 0),
|
||||
@@ -806,7 +864,7 @@ class GuiIcons:
|
||||
def getHeaderDecorationNarrow(self, hLevel: int) -> QPixmap:
|
||||
"""Get the narrow decoration for a specific heading level."""
|
||||
if not self._headerDecNarrow:
|
||||
iPx = self.mainTheme.baseIconHeight
|
||||
iPx = self._theme.baseIconHeight
|
||||
self._headerDecNarrow = [
|
||||
self._generateDecoration("file", iPx, 0),
|
||||
self._generateDecoration("title", iPx, 0),
|
||||
@@ -817,21 +875,6 @@ class GuiIcons:
|
||||
]
|
||||
return self._headerDecNarrow[minmax(hLevel, 0, 5)]
|
||||
|
||||
def listThemes(self) -> list[tuple[str, str]]:
|
||||
"""Scan the GUI icons folder and list all themes."""
|
||||
if self._themeList:
|
||||
return self._themeList
|
||||
|
||||
themes = []
|
||||
for key, path in self._availThemes.items():
|
||||
logger.debug("Checking icon theme '%s'", key)
|
||||
if name := _loadIconName(path):
|
||||
themes.append((key, name))
|
||||
|
||||
self._themeList = sorted(themes, key=_sortTheme)
|
||||
|
||||
return self._themeList
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
@@ -847,7 +890,7 @@ class GuiIcons:
|
||||
return QIcon(str(CONFIG.assetPath("icons") / "x-novelwriter-project.svg"))
|
||||
|
||||
if svg := self._svgData.get(name, b""):
|
||||
if fill := self._svgColors.get(color or "default"):
|
||||
if fill := self._theme.getRawBaseColor(color or "default"):
|
||||
svg = svg.replace(b"#000000", fill)
|
||||
pixmap = QPixmap(w, h)
|
||||
pixmap.fill(QtTransparent)
|
||||
@@ -869,53 +912,46 @@ class GuiIcons:
|
||||
|
||||
painter = QPainter(pixmap)
|
||||
painter.setRenderHint(QtPaintAntiAlias)
|
||||
if fill := self._svgColors.get(color or "default"):
|
||||
if fill := self._theme.getRawBaseColor(color or "default"):
|
||||
painter.fillPath(path, QColor(fill.decode(encoding="utf-8")))
|
||||
painter.end()
|
||||
|
||||
tMode = Qt.TransformationMode.SmoothTransformation
|
||||
return pixmap.scaledToHeight(height, tMode)
|
||||
|
||||
def _scanThemes(self, entries: list[Path]) -> None:
|
||||
"""Scan the GUI themes folder and list all themes."""
|
||||
data: dict[str, tuple[str, str, Path]] = {}
|
||||
keys = []
|
||||
for entry in entries:
|
||||
try:
|
||||
with open(entry, mode="r", encoding="utf-8") as fo:
|
||||
for line in fo:
|
||||
key, _, value = line.partition("=")
|
||||
if key.strip() == "meta:name":
|
||||
if name := value.strip():
|
||||
lookup = entry.stem
|
||||
keys.append(lookup)
|
||||
data[lookup] = (lookup, name, entry)
|
||||
break
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", entry)
|
||||
logException()
|
||||
|
||||
self._allThemes = {}
|
||||
for lookup in sorted(keys):
|
||||
key, name, item = data[lookup]
|
||||
logger.debug("Checking icon theme '%s'", key)
|
||||
self._allThemes[key] = ThemeEntry(name, False, item)
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Module Functions
|
||||
# ================
|
||||
|
||||
def _listConf(target: dict, path: Path, extension: str) -> None:
|
||||
"""Scan for theme files and populate the dictionary."""
|
||||
def _listContent(data: list[Path], path: Path, extension: str) -> None:
|
||||
"""List files of a specific type and extend the list."""
|
||||
if path.is_dir():
|
||||
for item in path.iterdir():
|
||||
if item.is_file() and item.name.endswith(extension):
|
||||
target[item.stem] = item
|
||||
data.extend(n for n in path.iterdir() if n.is_file() and n.suffix == extension)
|
||||
return
|
||||
|
||||
|
||||
def _sortTheme(data: tuple[str, str]) -> str:
|
||||
"""Key function for theme sorting."""
|
||||
key, name = data
|
||||
return f"*{name}" if key.startswith("default_") else name
|
||||
|
||||
|
||||
def _loadInternalName(parser: NWConfigParser, path: str | Path) -> str:
|
||||
"""Open a conf file and read the 'name' setting."""
|
||||
try:
|
||||
with open(path, mode="r", encoding="utf-8") as inFile:
|
||||
parser.read_file(inFile)
|
||||
return parser.rdStr("Main", "name", "")
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", path)
|
||||
logException()
|
||||
return ""
|
||||
|
||||
|
||||
def _loadIconName(path: Path) -> str:
|
||||
"""Open an icons file and read the name setting."""
|
||||
try:
|
||||
with open(path, mode="r", encoding="utf-8") as icons:
|
||||
for icon in icons:
|
||||
key, _, value = icon.partition("=")
|
||||
if key.strip() == "meta:name":
|
||||
return value.strip()
|
||||
except Exception:
|
||||
logger.error("Could not read file: %s", path)
|
||||
logException()
|
||||
return ""
|
||||
|
||||
+49
-20
@@ -30,7 +30,7 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
from time import time
|
||||
|
||||
from PyQt6.QtCore import Qt, QTimer, pyqtSlot
|
||||
from PyQt6.QtCore import QEvent, Qt, QTimer, pyqtSlot
|
||||
from PyQt6.QtGui import QCloseEvent, QCursor, QIcon, QShortcut
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox,
|
||||
@@ -38,7 +38,7 @@ from PyQt6.QtWidgets import (
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED, __hexversion__, __version__
|
||||
from novelwriter.common import formatFileFilter, formatVersion, hexToInt
|
||||
from novelwriter.common import formatFileFilter, formatVersion, hexToInt, minmax
|
||||
from novelwriter.constants import nwConst
|
||||
from novelwriter.dialogs.about import GuiAbout
|
||||
from novelwriter.dialogs.preferences import GuiPreferences
|
||||
@@ -103,7 +103,7 @@ class GuiMain(QMainWindow):
|
||||
SHARED.initSharedData(self)
|
||||
|
||||
# Prepare Main Window
|
||||
self.resize(*CONFIG.mainWinSize)
|
||||
self._setWindowSize(CONFIG.mainWinSize)
|
||||
self._updateWindowTitle()
|
||||
|
||||
nwIcon = CONFIG.assetPath("icons") / "novelwriter.svg"
|
||||
@@ -902,10 +902,46 @@ class GuiMain(QMainWindow):
|
||||
|
||||
return not self.splitView.isVisible()
|
||||
|
||||
def checkThemeUpdate(self) -> None:
|
||||
"""Load theme if mode changed."""
|
||||
if SHARED.theme.loadTheme():
|
||||
self.refreshThemeColors(syntax=True)
|
||||
self.docEditor.initEditor()
|
||||
self.docViewer.initViewer()
|
||||
return
|
||||
|
||||
def refreshThemeColors(self, syntax: bool = False, force: bool = False) -> None:
|
||||
"""Refresh the GUI theme."""
|
||||
SHARED.theme.loadTheme(force=force)
|
||||
SHARED.project.updateTheme()
|
||||
self.setPalette(QApplication.palette())
|
||||
self.docEditor.updateTheme()
|
||||
self.docViewer.updateTheme()
|
||||
self.docViewerPanel.updateTheme()
|
||||
self.sideBar.updateTheme()
|
||||
self.projView.updateTheme()
|
||||
self.novelView.updateTheme()
|
||||
self.projSearch.updateTheme()
|
||||
self.outlineView.updateTheme()
|
||||
self.itemDetails.updateTheme()
|
||||
self.mainStatus.updateTheme()
|
||||
SHARED.project.tree.refreshAllItems()
|
||||
|
||||
if syntax:
|
||||
self.docEditor.updateSyntaxColors()
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Events
|
||||
##
|
||||
|
||||
def changeEvent(self, event: QEvent) -> None:
|
||||
"""Capture application change events."""
|
||||
if int(event.type()) == 210: # ThemeChange
|
||||
self.checkThemeUpdate()
|
||||
return
|
||||
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""Capture the closing event of the GUI and call the close
|
||||
function to handle all the close process steps.
|
||||
@@ -1054,23 +1090,7 @@ class GuiMain(QMainWindow):
|
||||
self.novelView.refreshCurrentTree()
|
||||
|
||||
if theme:
|
||||
SHARED.theme.loadTheme()
|
||||
self.setPalette(QApplication.palette())
|
||||
self.docEditor.updateTheme()
|
||||
self.docViewer.updateTheme()
|
||||
self.docViewerPanel.updateTheme()
|
||||
self.sideBar.updateTheme()
|
||||
self.projView.updateTheme()
|
||||
self.novelView.updateTheme()
|
||||
self.projSearch.updateTheme()
|
||||
self.outlineView.updateTheme()
|
||||
self.itemDetails.updateTheme()
|
||||
self.mainStatus.updateTheme()
|
||||
SHARED.project.tree.refreshAllItems()
|
||||
|
||||
if syntax:
|
||||
SHARED.theme.loadSyntax()
|
||||
self.docEditor.updateSyntaxColors()
|
||||
self.refreshThemeColors(syntax=syntax, force=True)
|
||||
|
||||
self.docEditor.initEditor()
|
||||
self.docViewer.initViewer()
|
||||
@@ -1326,6 +1346,15 @@ class GuiMain(QMainWindow):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _setWindowSize(self, size: list[int]) -> None:
|
||||
"""Set the main window size."""
|
||||
if len(size) == 2 and (screen := SHARED.mainScreen):
|
||||
availSize = screen.availableSize()
|
||||
width = minmax(size[0], 900, availSize.width())
|
||||
height = minmax(size[1], 500, availSize.height())
|
||||
self.resize(width, height)
|
||||
return
|
||||
|
||||
def _updateWindowTitle(self, projName: str | None = None) -> None:
|
||||
"""Set the window title and add the project's name."""
|
||||
self.setWindowTitle(" - ".join(filter(None, [projName, CONFIG.appName])))
|
||||
|
||||
+22
-5
@@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
@@ -32,8 +33,8 @@ from time import time
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
from PyQt6.QtCore import QObject, QRunnable, QThreadPool, QTimer, QUrl, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtGui import QDesktopServices, QFont
|
||||
from PyQt6.QtWidgets import QFileDialog, QFontDialog, QMessageBox, QWidget
|
||||
from PyQt6.QtGui import QDesktopServices, QFont, QScreen
|
||||
from PyQt6.QtWidgets import QApplication, QFileDialog, QFontDialog, QMessageBox, QWidget
|
||||
|
||||
from novelwriter.common import formatFileFilter
|
||||
from novelwriter.constants import nwFiles
|
||||
@@ -41,6 +42,8 @@ from novelwriter.core.spellcheck import NWSpellEnchant
|
||||
from novelwriter.enum import nwChange, nwItemClass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.status import T_StatusKind
|
||||
from novelwriter.gui.theme import GuiTheme
|
||||
@@ -50,6 +53,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
NWWidget = TypeVar("NWWidget", bound=QWidget)
|
||||
|
||||
RX_HTML = re.compile(r"<.*?>")
|
||||
|
||||
|
||||
class SharedData(QObject):
|
||||
|
||||
@@ -150,6 +155,11 @@ class SharedData(QObject):
|
||||
"""Return the last alert message."""
|
||||
return self._lastAlert
|
||||
|
||||
@property
|
||||
def mainScreen(self) -> QScreen | None:
|
||||
"""Return the screen of the main window."""
|
||||
return QApplication.screenAt(self.mainGui.rect().center())
|
||||
|
||||
##
|
||||
# Setters
|
||||
##
|
||||
@@ -170,6 +180,7 @@ class SharedData(QObject):
|
||||
is created.
|
||||
"""
|
||||
self._theme = theme
|
||||
self._theme.initThemes()
|
||||
return
|
||||
|
||||
def initSharedData(self, gui: GuiMain) -> None:
|
||||
@@ -376,7 +387,7 @@ class SharedData(QObject):
|
||||
alert.setAlertType(_GuiAlert.INFO, False)
|
||||
self._lastAlert = alert.logMessage
|
||||
if log:
|
||||
logger.info(self._lastAlert, stacklevel=2)
|
||||
self._logMessage(self._lastAlert, logger.info)
|
||||
alert.exec()
|
||||
return
|
||||
|
||||
@@ -387,7 +398,7 @@ class SharedData(QObject):
|
||||
alert.setAlertType(_GuiAlert.WARN, False)
|
||||
self._lastAlert = alert.logMessage
|
||||
if log:
|
||||
logger.warning(self._lastAlert, stacklevel=2)
|
||||
self._logMessage(self._lastAlert, logger.warning)
|
||||
alert.exec()
|
||||
return
|
||||
|
||||
@@ -401,7 +412,7 @@ class SharedData(QObject):
|
||||
alert.setException(exc)
|
||||
self._lastAlert = alert.logMessage
|
||||
if log:
|
||||
logger.error(self._lastAlert, stacklevel=2)
|
||||
self._logMessage(self._lastAlert, logger.error)
|
||||
alert.exec()
|
||||
return
|
||||
|
||||
@@ -419,6 +430,12 @@ class SharedData(QObject):
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _logMessage(self, message: str, log: Callable) -> None:
|
||||
"""Print message to log."""
|
||||
for text in message.split("<br>"):
|
||||
log(RX_HTML.sub("", text), stacklevel=3)
|
||||
return
|
||||
|
||||
def _resetProject(self) -> None:
|
||||
"""Create a new project and spell checking instance."""
|
||||
from novelwriter.core.project import NWProject
|
||||
|
||||
@@ -42,6 +42,7 @@ class RegExPatterns:
|
||||
_rxItalic = re.compile(nwRegEx.FMT_EI)
|
||||
_rxBold = re.compile(nwRegEx.FMT_EB)
|
||||
_rxStrike = re.compile(nwRegEx.FMT_ST)
|
||||
_rxMark = re.compile(nwRegEx.FMT_HL)
|
||||
_rxSCPlain = re.compile(nwRegEx.FMT_SC)
|
||||
_rxSCValue = re.compile(nwRegEx.FMT_SV)
|
||||
|
||||
@@ -75,6 +76,11 @@ class RegExPatterns:
|
||||
"""Markdown strikethrough style."""
|
||||
return self._rxStrike
|
||||
|
||||
@property
|
||||
def markdownMark(self) -> re.Pattern:
|
||||
"""Markdown highlight style."""
|
||||
return self._rxMark
|
||||
|
||||
@property
|
||||
def shortcodePlain(self) -> re.Pattern:
|
||||
"""Plain shortcode style."""
|
||||
|
||||
@@ -32,7 +32,7 @@ from PyQt6.QtCore import (
|
||||
QAbstractListModel, QModelIndex, QObject, QPoint, QSize, Qt, pyqtSignal,
|
||||
pyqtSlot
|
||||
)
|
||||
from PyQt6.QtGui import QAction, QCloseEvent, QColor, QFont, QPainter, QPaintEvent, QPen, QShortcut
|
||||
from PyQt6.QtGui import QAction, QCloseEvent, QFont, QPainter, QPaintEvent, QPen, QShortcut
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication, QFileDialog, QFormLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||
QListView, QMenu, QPushButton, QScrollArea, QStackedWidget,
|
||||
@@ -77,7 +77,6 @@ class GuiWelcome(NDialog):
|
||||
|
||||
self.bgImage = SHARED.theme.getDecoration("welcome")
|
||||
self.nwImage = SHARED.theme.getDecoration("nw-text", h=36)
|
||||
self.bgColor = QColor(54, 54, 54) if SHARED.theme.isDarkTheme else QColor(255, 255, 255)
|
||||
|
||||
self.nwLogo = QLabel(self)
|
||||
self.nwLogo.setPixmap(SHARED.theme.getPixmap("novelwriter", (128, 128)))
|
||||
@@ -178,8 +177,8 @@ class GuiWelcome(NDialog):
|
||||
hPix = min(hWin, 600)
|
||||
tMode = Qt.TransformationMode.SmoothTransformation
|
||||
painter = QPainter(self)
|
||||
painter.fillRect(self.rect(), self.bgColor)
|
||||
painter.drawPixmap(0, hWin - hPix, self.bgImage.scaledToHeight(hPix, tMode))
|
||||
painter.end()
|
||||
super().paintEvent(event)
|
||||
return
|
||||
|
||||
@@ -420,7 +419,7 @@ class _ProjectListItem(QStyledItemDelegate):
|
||||
painter.save()
|
||||
if opt.state & QtSelected == QtSelected:
|
||||
painter.setOpacity(0.25)
|
||||
painter.fillRect(rect, QApplication.palette().highlight())
|
||||
painter.fillRect(rect, QApplication.palette().text())
|
||||
painter.setOpacity(1.0)
|
||||
|
||||
painter.drawPixmap(2, rect.top() + 6, self._icon)
|
||||
|
||||
@@ -128,6 +128,7 @@ QtHeaderFixed = QHeaderView.ResizeMode.Fixed
|
||||
|
||||
# Scroll Bar Policy
|
||||
|
||||
QtScrollAlwaysOn = Qt.ScrollBarPolicy.ScrollBarAlwaysOn
|
||||
QtScrollAlwaysOff = Qt.ScrollBarPolicy.ScrollBarAlwaysOff
|
||||
QtScrollAsNeeded = Qt.ScrollBarPolicy.ScrollBarAsNeeded
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user