diff --git a/CREDITS.md b/CREDITS.md index dc6b4c53..66d2f64b 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -31,7 +31,6 @@ The following libraries are dependencies of novelWriter: Some of the assets bundled with novelWriter were adapted from the following sources: * Typicons icons by Stephen Hutchings (CC BY-SA 4.0) -* Cantarell font by Dave Crossland (OPEN FONT LICENSE Version 1.1) * Tomorrow syntax themes by Chris Kempson (MIT License) * Owl syntax themes by Sarah Drasner (MIT License) * Solarized themes by Ethan Schoonover, added by @nullbasis (MIT License) diff --git a/novelWriter.pro b/novelWriter.pro index d1bc3e7b..2d948874 100644 --- a/novelWriter.pro +++ b/novelWriter.pro @@ -22,7 +22,6 @@ SOURCES += \ novelwriter/gui/projdetails.py \ novelwriter/gui/projtree.py \ novelwriter/gui/statusbar.py \ - novelwriter/gui/theme.py \ novelwriter/tools/build.py \ novelwriter/tools/projwizard.py \ novelwriter/tools/writingstats.py \ diff --git a/novelwriter/assets/fonts/Cantarell/Cantarell-Bold.ttf b/novelwriter/assets/fonts/Cantarell/Cantarell-Bold.ttf deleted file mode 100644 index ca364663..00000000 Binary files a/novelwriter/assets/fonts/Cantarell/Cantarell-Bold.ttf and /dev/null differ diff --git a/novelwriter/assets/fonts/Cantarell/Cantarell-BoldItalic.ttf b/novelwriter/assets/fonts/Cantarell/Cantarell-BoldItalic.ttf deleted file mode 100644 index a54eab4c..00000000 Binary files a/novelwriter/assets/fonts/Cantarell/Cantarell-BoldItalic.ttf and /dev/null differ diff --git a/novelwriter/assets/fonts/Cantarell/Cantarell-Italic.ttf b/novelwriter/assets/fonts/Cantarell/Cantarell-Italic.ttf deleted file mode 100644 index 725b1986..00000000 Binary files a/novelwriter/assets/fonts/Cantarell/Cantarell-Italic.ttf and /dev/null differ diff --git a/novelwriter/assets/fonts/Cantarell/Cantarell-Regular.ttf b/novelwriter/assets/fonts/Cantarell/Cantarell-Regular.ttf deleted file mode 100644 index ceb92751..00000000 Binary files a/novelwriter/assets/fonts/Cantarell/Cantarell-Regular.ttf and /dev/null differ diff --git a/novelwriter/assets/fonts/Cantarell/OFL.txt b/novelwriter/assets/fonts/Cantarell/OFL.txt deleted file mode 100644 index 4e495019..00000000 --- a/novelwriter/assets/fonts/Cantarell/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright (c) 2009-2010, Understanding Limited (dave@understandinglimited.com) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/novelwriter/assets/icons/fallback/README.md b/novelwriter/assets/icons/fallback/README.md deleted file mode 100644 index 45a06454..00000000 --- a/novelwriter/assets/icons/fallback/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## License - -All icons in the fallback folder are modified from the Typicons theme by -Stephen Hutchings, released under CC BY-SA 4.0. - -See: https://github.com/stephenhutchings/typicons.font diff --git a/novelwriter/assets/icons/fallback/add-dark.svg b/novelwriter/assets/icons/fallback/add-dark.svg deleted file mode 100644 index 0846263d..00000000 --- a/novelwriter/assets/icons/fallback/add-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/add.svg b/novelwriter/assets/icons/fallback/add.svg deleted file mode 100644 index e7399157..00000000 --- a/novelwriter/assets/icons/fallback/add.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/backward-dark.svg b/novelwriter/assets/icons/fallback/backward-dark.svg deleted file mode 100644 index bc1c987f..00000000 --- a/novelwriter/assets/icons/fallback/backward-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/backward.svg b/novelwriter/assets/icons/fallback/backward.svg deleted file mode 100644 index 2e7af570..00000000 --- a/novelwriter/assets/icons/fallback/backward.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/bullet-off-dark.svg b/novelwriter/assets/icons/fallback/bullet-off-dark.svg deleted file mode 100644 index 46e56070..00000000 --- a/novelwriter/assets/icons/fallback/bullet-off-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/bullet-off.svg b/novelwriter/assets/icons/fallback/bullet-off.svg deleted file mode 100644 index 2e2712be..00000000 --- a/novelwriter/assets/icons/fallback/bullet-off.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/bullet-on-dark.svg b/novelwriter/assets/icons/fallback/bullet-on-dark.svg deleted file mode 100644 index ba3d9739..00000000 --- a/novelwriter/assets/icons/fallback/bullet-on-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/bullet-on.svg b/novelwriter/assets/icons/fallback/bullet-on.svg deleted file mode 100644 index 7a077ddd..00000000 --- a/novelwriter/assets/icons/fallback/bullet-on.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/check-dark.svg b/novelwriter/assets/icons/fallback/check-dark.svg deleted file mode 100644 index 0c1bea67..00000000 --- a/novelwriter/assets/icons/fallback/check-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/check.svg b/novelwriter/assets/icons/fallback/check.svg deleted file mode 100644 index 894c6186..00000000 --- a/novelwriter/assets/icons/fallback/check.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/cross-dark.svg b/novelwriter/assets/icons/fallback/cross-dark.svg deleted file mode 100644 index f863c42b..00000000 --- a/novelwriter/assets/icons/fallback/cross-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/cross.svg b/novelwriter/assets/icons/fallback/cross.svg deleted file mode 100644 index bc451278..00000000 --- a/novelwriter/assets/icons/fallback/cross.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/edit-dark.svg b/novelwriter/assets/icons/fallback/edit-dark.svg deleted file mode 100644 index f7665c6b..00000000 --- a/novelwriter/assets/icons/fallback/edit-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/edit.svg b/novelwriter/assets/icons/fallback/edit.svg deleted file mode 100644 index ddd96f64..00000000 --- a/novelwriter/assets/icons/fallback/edit.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/forward-dark.svg b/novelwriter/assets/icons/fallback/forward-dark.svg deleted file mode 100644 index 18eafe98..00000000 --- a/novelwriter/assets/icons/fallback/forward-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/forward.svg b/novelwriter/assets/icons/fallback/forward.svg deleted file mode 100644 index 8da983ca..00000000 --- a/novelwriter/assets/icons/fallback/forward.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/hash-dark.svg b/novelwriter/assets/icons/fallback/hash-dark.svg deleted file mode 100644 index 9f3db253..00000000 --- a/novelwriter/assets/icons/fallback/hash-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/hash.svg b/novelwriter/assets/icons/fallback/hash.svg deleted file mode 100644 index 99fddb80..00000000 --- a/novelwriter/assets/icons/fallback/hash.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/maximise-dark.svg b/novelwriter/assets/icons/fallback/maximise-dark.svg deleted file mode 100644 index 1ce767a3..00000000 --- a/novelwriter/assets/icons/fallback/maximise-dark.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/maximise.svg b/novelwriter/assets/icons/fallback/maximise.svg deleted file mode 100644 index 0e1d4a86..00000000 --- a/novelwriter/assets/icons/fallback/maximise.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/minimise-dark.svg b/novelwriter/assets/icons/fallback/minimise-dark.svg deleted file mode 100644 index 4bc48ce2..00000000 --- a/novelwriter/assets/icons/fallback/minimise-dark.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/minimise.svg b/novelwriter/assets/icons/fallback/minimise.svg deleted file mode 100644 index b0a1972f..00000000 --- a/novelwriter/assets/icons/fallback/minimise.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/proj_nwx.svg b/novelwriter/assets/icons/fallback/proj_nwx.svg deleted file mode 100644 index 08546d15..00000000 --- a/novelwriter/assets/icons/fallback/proj_nwx.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/reference-dark.svg b/novelwriter/assets/icons/fallback/reference-dark.svg deleted file mode 100644 index 4d98eb91..00000000 --- a/novelwriter/assets/icons/fallback/reference-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/reference.svg b/novelwriter/assets/icons/fallback/reference.svg deleted file mode 100644 index b39357c9..00000000 --- a/novelwriter/assets/icons/fallback/reference.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/refresh-dark.svg b/novelwriter/assets/icons/fallback/refresh-dark.svg deleted file mode 100644 index 31367a18..00000000 --- a/novelwriter/assets/icons/fallback/refresh-dark.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/refresh.svg b/novelwriter/assets/icons/fallback/refresh.svg deleted file mode 100644 index c87d3257..00000000 --- a/novelwriter/assets/icons/fallback/refresh.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/remove-dark.svg b/novelwriter/assets/icons/fallback/remove-dark.svg deleted file mode 100644 index 799e4ff3..00000000 --- a/novelwriter/assets/icons/fallback/remove-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/remove.svg b/novelwriter/assets/icons/fallback/remove.svg deleted file mode 100644 index eb40a0e2..00000000 --- a/novelwriter/assets/icons/fallback/remove.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/search-dark.svg b/novelwriter/assets/icons/fallback/search-dark.svg deleted file mode 100644 index ecf47350..00000000 --- a/novelwriter/assets/icons/fallback/search-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/search-replace.svg b/novelwriter/assets/icons/fallback/search-replace.svg deleted file mode 100644 index cbf10912..00000000 --- a/novelwriter/assets/icons/fallback/search-replace.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/search.svg b/novelwriter/assets/icons/fallback/search.svg deleted file mode 100644 index d541d53b..00000000 --- a/novelwriter/assets/icons/fallback/search.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/sticky-off-dark.svg b/novelwriter/assets/icons/fallback/sticky-off-dark.svg deleted file mode 100644 index f571d5c9..00000000 --- a/novelwriter/assets/icons/fallback/sticky-off-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/sticky-off.svg b/novelwriter/assets/icons/fallback/sticky-off.svg deleted file mode 100644 index 57b2b498..00000000 --- a/novelwriter/assets/icons/fallback/sticky-off.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/sticky-on-dark.svg b/novelwriter/assets/icons/fallback/sticky-on-dark.svg deleted file mode 100644 index 62c6a66b..00000000 --- a/novelwriter/assets/icons/fallback/sticky-on-dark.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/fallback/sticky-on.svg b/novelwriter/assets/icons/fallback/sticky-on.svg deleted file mode 100644 index 3473b82f..00000000 --- a/novelwriter/assets/icons/fallback/sticky-on.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/novelwriter/assets/icons/system/icons.conf b/novelwriter/assets/icons/system/icons.conf deleted file mode 100644 index 9f94d37b..00000000 --- a/novelwriter/assets/icons/system/icons.conf +++ /dev/null @@ -1,8 +0,0 @@ -## -# System Theme -# Dummy theme that relies on Qt and novelWriter fallback icons -## - -[Main] -name = System Theme -description = Dummy theme that relies on Qt and novelWriter fallback icons diff --git a/novelwriter/assets/icons/typicons_dark/README.md b/novelwriter/assets/icons/typicons_dark/README.md index cfa5ea08..48c3f4ef 100644 --- a/novelwriter/assets/icons/typicons_dark/README.md +++ b/novelwriter/assets/icons/typicons_dark/README.md @@ -1,5 +1,29 @@ -## Typicons +# Typicons for Dark Backgrounds + +This theme is based on Typicons. All files are prefixed, depending on whether they are based +directly on original Typicons, redesigned, or designed from scratch. + +## Typicons Icons + +The files have a `typ_` prefix. These are colourised and rescaled Typicons, but with no other +modifications. Copyright: Stephen Hutchings Source: https://github.com/stephenhutchings/typicons.font License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) + +## Original Icons + +The files have a `nw_` prefix. These are made completely from scratch for novelWriter and are not +using any design elements from Typicons. + +Copyright: Veronica Berglyd Olsen +License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) + +## Mixed Icons + +The files have a `mixed_` prefix. These are redesigned from Typicons components, modified from +Typicons, or consist of a mix of Typicons and new elements. + +Copyright: Stephen Hutchings, Veronica Berglyd Olsen +License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) diff --git a/novelwriter/assets/icons/typicons_dark/icons.conf b/novelwriter/assets/icons/typicons_dark/icons.conf index 99bee3fe..e06aba68 100644 --- a/novelwriter/assets/icons/typicons_dark/icons.conf +++ b/novelwriter/assets/icons/typicons_dark/icons.conf @@ -7,57 +7,70 @@ ## [Main] -name = Typicons Dark -description = Colourised icons for dark GUI theme based on Typicons. -author = Veronica Berglyd Olsen (adaptation) -credit = Stephen Hutchings (icon design) -url = https://github.com/stephenhutchings/typicons.font -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ +name = Typicons Dark +description = Colourised icons for dark GUI theme based on Typicons. +author = Veronica Berglyd Olsen (adaptation) +credit = Stephen Hutchings (icon design) +url = https://github.com/stephenhutchings/typicons.font +license = CC BY-SA 4.0 +licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ [Map] -cls_none = cancel.svg -cls_novel = book.svg -cls_plot = puzzle.svg -cls_character = user.svg -cls_world = location.svg -cls_timeline = calendar.svg -cls_object = key.svg -cls_entity = flag.svg -cls_custom = star.svg -cls_archive = delete.svg -cls_trash = trash.svg -proj_document = document-text.svg -proj_title = document-title.svg -proj_chapter = document-chapter.svg -proj_scene = document-scene.svg -proj_note = document-note.svg -proj_folder = folder.svg -doc_h0 = heading0.svg -doc_h1 = heading1.svg -doc_h2 = heading2.svg -doc_h3 = heading3.svg -doc_h4 = heading4.svg -delete = delete.svg -add = plus.svg -remove = minus.svg -close = times.svg -refresh = refresh.svg -maximise = arrow-maximise.svg -minimise = arrow-minimise.svg -done = input-checked.svg -search = search.svg -search-replace = search-replace.svg -clear = backspace.svg -save = download.svg -edit = pencil.svg -check = tick.svg -cross = times.svg -hash = hash.svg -reference = at.svg -backward = chevron-left.svg -forward = chevron-right.svg -sticky-on = pin.svg -sticky-off = pin-outline.svg -bullet-on = media-record.svg -bullet-off = media-record-outline.svg +add = typ_plus.svg +backward = typ_chevron-left.svg +bullet-off = typ_media-record-outline.svg +bullet-on = typ_media-record.svg +check = typ_tick.svg +clear = typ_backspace.svg +close = typ_times.svg +cls_archive = typ_delete.svg +cls_character = typ_user.svg +cls_custom = typ_star.svg +cls_entity = typ_flag.svg +cls_none = typ_cancel.svg +cls_novel = typ_book.svg +cls_object = typ_key.svg +cls_plot = typ_puzzle.svg +cls_timeline = typ_calendar.svg +cls_trash = typ_trash.svg +cls_world = typ_location.svg +cross = typ_times.svg +delete = typ_delete.svg +doc_h0 = mixed_heading0.svg +doc_h1 = mixed_heading1.svg +doc_h2 = mixed_heading2.svg +doc_h3 = mixed_heading3.svg +doc_h4 = mixed_heading4.svg +done = typ_input-checked.svg +edit = typ_pencil.svg +forward = typ_chevron-right.svg +hash = typ_hash.svg +maximise = typ_arrow-maximise.svg +minimise = typ_arrow-minimise.svg +proj_chapter = mixed_document-chapter.svg +proj_document = typ_document-text.svg +proj_folder = typ_folder.svg +proj_note = mixed_document-note.svg +proj_scene = mixed_document-scene.svg +proj_title = mixed_document-title.svg +reference = typ_at.svg +refresh = typ_refresh.svg +remove = typ_minus.svg +save = typ_download.svg +search = typ_search.svg +search_cancel = typ_cancel-grey.svg +search_case = nw_search-case.svg +search_loop = typ_arrow-repeat-grey.svg +search_preserve = nw_search-preserve.svg +search_project = typ_arrow-down-thick-grey.svg +search_regex = nw_search-regex.svg +search_replace = mixed_search-replace.svg +search_word = nw_search-word.svg +settings = typ_cog.svg +status_idle = typ_media-pause-grey.svg +status_lang = typ_globe-grey.svg +status_lines = typ_th-list-grey.svg +status_stats = typ_chart-bar-grey.svg +status_time = typ_stopwatch-grey.svg +sticky-off = typ_pin-outline.svg +sticky-on = typ_pin.svg diff --git a/novelwriter/assets/icons/typicons_dark/document-chapter.svg b/novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/document-chapter.svg rename to novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg diff --git a/novelwriter/assets/icons/typicons_dark/document-note.svg b/novelwriter/assets/icons/typicons_dark/mixed_document-note.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/document-note.svg rename to novelwriter/assets/icons/typicons_dark/mixed_document-note.svg diff --git a/novelwriter/assets/icons/typicons_dark/document-scene.svg b/novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/document-scene.svg rename to novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg diff --git a/novelwriter/assets/icons/typicons_dark/document-title.svg b/novelwriter/assets/icons/typicons_dark/mixed_document-title.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/document-title.svg rename to novelwriter/assets/icons/typicons_dark/mixed_document-title.svg diff --git a/novelwriter/assets/icons/typicons_dark/heading0.svg b/novelwriter/assets/icons/typicons_dark/mixed_heading0.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/heading0.svg rename to novelwriter/assets/icons/typicons_dark/mixed_heading0.svg diff --git a/novelwriter/assets/icons/typicons_dark/heading1.svg b/novelwriter/assets/icons/typicons_dark/mixed_heading1.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/heading1.svg rename to novelwriter/assets/icons/typicons_dark/mixed_heading1.svg diff --git a/novelwriter/assets/icons/typicons_dark/heading2.svg b/novelwriter/assets/icons/typicons_dark/mixed_heading2.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/heading2.svg rename to novelwriter/assets/icons/typicons_dark/mixed_heading2.svg diff --git a/novelwriter/assets/icons/typicons_dark/heading3.svg b/novelwriter/assets/icons/typicons_dark/mixed_heading3.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/heading3.svg rename to novelwriter/assets/icons/typicons_dark/mixed_heading3.svg diff --git a/novelwriter/assets/icons/typicons_dark/heading4.svg b/novelwriter/assets/icons/typicons_dark/mixed_heading4.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/heading4.svg rename to novelwriter/assets/icons/typicons_dark/mixed_heading4.svg diff --git a/novelwriter/assets/icons/fallback/search-replace-dark.svg b/novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search-replace-dark.svg rename to novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg diff --git a/novelwriter/assets/icons/fallback/search_case-dark.svg b/novelwriter/assets/icons/typicons_dark/nw_search-case.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_case-dark.svg rename to novelwriter/assets/icons/typicons_dark/nw_search-case.svg diff --git a/novelwriter/assets/icons/fallback/search_preserve-dark.svg b/novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_preserve-dark.svg rename to novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg diff --git a/novelwriter/assets/icons/fallback/search_regex-dark.svg b/novelwriter/assets/icons/typicons_dark/nw_search-regex.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_regex-dark.svg rename to novelwriter/assets/icons/typicons_dark/nw_search-regex.svg diff --git a/novelwriter/assets/icons/fallback/search_word-dark.svg b/novelwriter/assets/icons/typicons_dark/nw_search-word.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_word-dark.svg rename to novelwriter/assets/icons/typicons_dark/nw_search-word.svg diff --git a/novelwriter/assets/icons/fallback/search_project-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_project-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/arrow-maximise.svg b/novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/arrow-maximise.svg rename to novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg diff --git a/novelwriter/assets/icons/typicons_dark/arrow-minimise.svg b/novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/arrow-minimise.svg rename to novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg diff --git a/novelwriter/assets/icons/fallback/search_loop-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_loop-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/at.svg b/novelwriter/assets/icons/typicons_dark/typ_at.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/at.svg rename to novelwriter/assets/icons/typicons_dark/typ_at.svg diff --git a/novelwriter/assets/icons/typicons_dark/backspace.svg b/novelwriter/assets/icons/typicons_dark/typ_backspace.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/backspace.svg rename to novelwriter/assets/icons/typicons_dark/typ_backspace.svg diff --git a/novelwriter/assets/icons/typicons_dark/book.svg b/novelwriter/assets/icons/typicons_dark/typ_book.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/book.svg rename to novelwriter/assets/icons/typicons_dark/typ_book.svg diff --git a/novelwriter/assets/icons/typicons_dark/bookmark.svg b/novelwriter/assets/icons/typicons_dark/typ_bookmark.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/bookmark.svg rename to novelwriter/assets/icons/typicons_dark/typ_bookmark.svg diff --git a/novelwriter/assets/icons/typicons_dark/calendar.svg b/novelwriter/assets/icons/typicons_dark/typ_calendar.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/calendar.svg rename to novelwriter/assets/icons/typicons_dark/typ_calendar.svg diff --git a/novelwriter/assets/icons/fallback/search_cancel-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_cancel-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/cancel.svg b/novelwriter/assets/icons/typicons_dark/typ_cancel.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/cancel.svg rename to novelwriter/assets/icons/typicons_dark/typ_cancel.svg diff --git a/novelwriter/assets/icons/fallback/status_stats-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_stats-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/chevron-left.svg b/novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/chevron-left.svg rename to novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg diff --git a/novelwriter/assets/icons/typicons_dark/chevron-right.svg b/novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/chevron-right.svg rename to novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg diff --git a/novelwriter/assets/icons/fallback/settings-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_cog.svg similarity index 100% rename from novelwriter/assets/icons/fallback/settings-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_cog.svg diff --git a/novelwriter/assets/icons/typicons_dark/delete.svg b/novelwriter/assets/icons/typicons_dark/typ_delete.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/delete.svg rename to novelwriter/assets/icons/typicons_dark/typ_delete.svg diff --git a/novelwriter/assets/icons/typicons_dark/document-text.svg b/novelwriter/assets/icons/typicons_dark/typ_document-text.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/document-text.svg rename to novelwriter/assets/icons/typicons_dark/typ_document-text.svg diff --git a/novelwriter/assets/icons/typicons_dark/download.svg b/novelwriter/assets/icons/typicons_dark/typ_download.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/download.svg rename to novelwriter/assets/icons/typicons_dark/typ_download.svg diff --git a/novelwriter/assets/icons/typicons_dark/flag.svg b/novelwriter/assets/icons/typicons_dark/typ_flag.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/flag.svg rename to novelwriter/assets/icons/typicons_dark/typ_flag.svg diff --git a/novelwriter/assets/icons/typicons_dark/folder.svg b/novelwriter/assets/icons/typicons_dark/typ_folder.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/folder.svg rename to novelwriter/assets/icons/typicons_dark/typ_folder.svg diff --git a/novelwriter/assets/icons/fallback/status_lang-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_lang-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/globe.svg b/novelwriter/assets/icons/typicons_dark/typ_globe.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/globe.svg rename to novelwriter/assets/icons/typicons_dark/typ_globe.svg diff --git a/novelwriter/assets/icons/typicons_dark/hash.svg b/novelwriter/assets/icons/typicons_dark/typ_hash.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/hash.svg rename to novelwriter/assets/icons/typicons_dark/typ_hash.svg diff --git a/novelwriter/assets/icons/typicons_dark/input-checked.svg b/novelwriter/assets/icons/typicons_dark/typ_input-checked.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/input-checked.svg rename to novelwriter/assets/icons/typicons_dark/typ_input-checked.svg diff --git a/novelwriter/assets/icons/typicons_dark/key.svg b/novelwriter/assets/icons/typicons_dark/typ_key.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/key.svg rename to novelwriter/assets/icons/typicons_dark/typ_key.svg diff --git a/novelwriter/assets/icons/typicons_dark/location.svg b/novelwriter/assets/icons/typicons_dark/typ_location.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/location.svg rename to novelwriter/assets/icons/typicons_dark/typ_location.svg diff --git a/novelwriter/assets/icons/fallback/status_idle-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_idle-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/media-record-outline.svg b/novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/media-record-outline.svg rename to novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg diff --git a/novelwriter/assets/icons/typicons_dark/media-record.svg b/novelwriter/assets/icons/typicons_dark/typ_media-record.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/media-record.svg rename to novelwriter/assets/icons/typicons_dark/typ_media-record.svg diff --git a/novelwriter/assets/icons/typicons_dark/minus.svg b/novelwriter/assets/icons/typicons_dark/typ_minus.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/minus.svg rename to novelwriter/assets/icons/typicons_dark/typ_minus.svg diff --git a/novelwriter/assets/icons/typicons_dark/search-replace.svg b/novelwriter/assets/icons/typicons_dark/typ_mod_search-replace.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/search-replace.svg rename to novelwriter/assets/icons/typicons_dark/typ_mod_search-replace.svg diff --git a/novelwriter/assets/icons/typicons_dark/pencil.svg b/novelwriter/assets/icons/typicons_dark/typ_pencil.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/pencil.svg rename to novelwriter/assets/icons/typicons_dark/typ_pencil.svg diff --git a/novelwriter/assets/icons/typicons_dark/pin-outline.svg b/novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/pin-outline.svg rename to novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg diff --git a/novelwriter/assets/icons/typicons_dark/pin.svg b/novelwriter/assets/icons/typicons_dark/typ_pin.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/pin.svg rename to novelwriter/assets/icons/typicons_dark/typ_pin.svg diff --git a/novelwriter/assets/icons/typicons_dark/plus.svg b/novelwriter/assets/icons/typicons_dark/typ_plus.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/plus.svg rename to novelwriter/assets/icons/typicons_dark/typ_plus.svg diff --git a/novelwriter/assets/icons/typicons_dark/puzzle.svg b/novelwriter/assets/icons/typicons_dark/typ_puzzle.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/puzzle.svg rename to novelwriter/assets/icons/typicons_dark/typ_puzzle.svg diff --git a/novelwriter/assets/icons/typicons_dark/refresh.svg b/novelwriter/assets/icons/typicons_dark/typ_refresh.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/refresh.svg rename to novelwriter/assets/icons/typicons_dark/typ_refresh.svg diff --git a/novelwriter/assets/icons/typicons_dark/search.svg b/novelwriter/assets/icons/typicons_dark/typ_search.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/search.svg rename to novelwriter/assets/icons/typicons_dark/typ_search.svg diff --git a/novelwriter/assets/icons/typicons_dark/star.svg b/novelwriter/assets/icons/typicons_dark/typ_star.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/star.svg rename to novelwriter/assets/icons/typicons_dark/typ_star.svg diff --git a/novelwriter/assets/icons/fallback/status_time-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_time-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/stopwatch.svg b/novelwriter/assets/icons/typicons_dark/typ_stopwatch.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/stopwatch.svg rename to novelwriter/assets/icons/typicons_dark/typ_stopwatch.svg diff --git a/novelwriter/assets/icons/fallback/status_lines-dark.svg b/novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_lines-dark.svg rename to novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg diff --git a/novelwriter/assets/icons/typicons_dark/tick.svg b/novelwriter/assets/icons/typicons_dark/typ_tick.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/tick.svg rename to novelwriter/assets/icons/typicons_dark/typ_tick.svg diff --git a/novelwriter/assets/icons/typicons_dark/times.svg b/novelwriter/assets/icons/typicons_dark/typ_times.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/times.svg rename to novelwriter/assets/icons/typicons_dark/typ_times.svg diff --git a/novelwriter/assets/icons/typicons_dark/trash.svg b/novelwriter/assets/icons/typicons_dark/typ_trash.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/trash.svg rename to novelwriter/assets/icons/typicons_dark/typ_trash.svg diff --git a/novelwriter/assets/icons/typicons_dark/user.svg b/novelwriter/assets/icons/typicons_dark/typ_user.svg similarity index 100% rename from novelwriter/assets/icons/typicons_dark/user.svg rename to novelwriter/assets/icons/typicons_dark/typ_user.svg diff --git a/novelwriter/assets/icons/typicons_light/README.md b/novelwriter/assets/icons/typicons_light/README.md index cfa5ea08..eb6f78a5 100644 --- a/novelwriter/assets/icons/typicons_light/README.md +++ b/novelwriter/assets/icons/typicons_light/README.md @@ -1,5 +1,29 @@ -## Typicons +# Typicons for Light Backgrounds + +This theme is based on Typicons. All files are prefixed, depending on whether they are based +directly on original Typicons, redesigned, or designed from scratch. + +## Typicons Icons + +The files have a `typ_` prefix. These are colourised and rescaled Typicons, but with no other +modifications. Copyright: Stephen Hutchings Source: https://github.com/stephenhutchings/typicons.font License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) + +## Original Icons + +The files have a `nw_` prefix. These are made completely from scratch for novelWriter and are not +using any design elements from Typicons. + +Copyright: Veronica Berglyd Olsen +License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) + +## Mixed Icons + +The files have a `mixed_` prefix. These are redesigned from Typicons components, modified from +Typicons, or consist of a mix of Typicons and new elements. + +Copyright: Stephen Hutchings, Veronica Berglyd Olsen +License: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) diff --git a/novelwriter/assets/icons/typicons_light/icons.conf b/novelwriter/assets/icons/typicons_light/icons.conf index 64d6ec29..56e18b2a 100644 --- a/novelwriter/assets/icons/typicons_light/icons.conf +++ b/novelwriter/assets/icons/typicons_light/icons.conf @@ -7,57 +7,70 @@ ## [Main] -name = Typicons Light -description = Colourised icons for light GUI theme based on Typicons. -author = Veronica Berglyd Olsen (adaptation) -credit = Stephen Hutchings (icon design) -url = https://github.com/stephenhutchings/typicons.font -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ +name = Typicons Light +description = Colourised icons for light GUI theme based on Typicons. +author = Veronica Berglyd Olsen (adaptation) +credit = Stephen Hutchings (icon design) +url = https://github.com/stephenhutchings/typicons.font +license = CC BY-SA 4.0 +licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ [Map] -cls_none = cancel.svg -cls_novel = book.svg -cls_plot = puzzle.svg -cls_character = user.svg -cls_world = location.svg -cls_timeline = calendar.svg -cls_object = key.svg -cls_entity = flag.svg -cls_custom = star.svg -cls_archive = delete.svg -cls_trash = trash.svg -proj_document = document-text.svg -proj_title = document-title.svg -proj_chapter = document-chapter.svg -proj_scene = document-scene.svg -proj_note = document-note.svg -proj_folder = folder.svg -doc_h0 = heading0.svg -doc_h1 = heading1.svg -doc_h2 = heading2.svg -doc_h3 = heading3.svg -doc_h4 = heading4.svg -delete = delete.svg -add = plus.svg -remove = minus.svg -close = times.svg -refresh = refresh.svg -maximise = arrow-maximise.svg -minimise = arrow-minimise.svg -done = input-checked.svg -search = search.svg -search-replace = search-replace.svg -clear = backspace.svg -save = download.svg -edit = pencil.svg -check = tick.svg -cross = times.svg -hash = hash.svg -reference = at.svg -backward = chevron-left.svg -forward = chevron-right.svg -sticky-on = pin.svg -sticky-off = pin-outline.svg -bullet-on = media-record.svg -bullet-off = media-record-outline.svg +add = typ_plus.svg +backward = typ_chevron-left.svg +bullet-off = typ_media-record-outline.svg +bullet-on = typ_media-record.svg +check = typ_tick.svg +clear = typ_backspace.svg +close = typ_times.svg +cls_archive = typ_delete.svg +cls_character = typ_user.svg +cls_custom = typ_star.svg +cls_entity = typ_flag.svg +cls_none = typ_cancel.svg +cls_novel = typ_book.svg +cls_object = typ_key.svg +cls_plot = typ_puzzle.svg +cls_timeline = typ_calendar.svg +cls_trash = typ_trash.svg +cls_world = typ_location.svg +cross = typ_times.svg +delete = typ_delete.svg +doc_h0 = mixed_heading0.svg +doc_h1 = mixed_heading1.svg +doc_h2 = mixed_heading2.svg +doc_h3 = mixed_heading3.svg +doc_h4 = mixed_heading4.svg +done = typ_input-checked.svg +edit = typ_pencil.svg +forward = typ_chevron-right.svg +hash = typ_hash.svg +maximise = typ_arrow-maximise.svg +minimise = typ_arrow-minimise.svg +proj_chapter = mixed_document-chapter.svg +proj_document = typ_document-text.svg +proj_folder = typ_folder.svg +proj_note = mixed_document-note.svg +proj_scene = mixed_document-scene.svg +proj_title = mixed_document-title.svg +reference = typ_at.svg +refresh = typ_refresh.svg +remove = typ_minus.svg +save = typ_download.svg +search = typ_search.svg +search_cancel = typ_cancel-grey.svg +search_case = nw_search-case.svg +search_loop = typ_arrow-repeat-grey.svg +search_preserve = nw_search-preserve.svg +search_project = typ_arrow-down-thick-grey.svg +search_regex = nw_search-regex.svg +search_replace = mixed_search-replace.svg +search_word = nw_search-word.svg +settings = typ_cog.svg +status_idle = typ_media-pause-grey.svg +status_lang = typ_globe-grey.svg +status_lines = typ_th-list-grey.svg +status_stats = typ_chart-bar-grey.svg +status_time = typ_stopwatch-grey.svg +sticky-off = typ_pin-outline.svg +sticky-on = typ_pin.svg diff --git a/novelwriter/assets/icons/typicons_light/document-chapter.svg b/novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/document-chapter.svg rename to novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg diff --git a/novelwriter/assets/icons/typicons_light/document-note.svg b/novelwriter/assets/icons/typicons_light/mixed_document-note.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/document-note.svg rename to novelwriter/assets/icons/typicons_light/mixed_document-note.svg diff --git a/novelwriter/assets/icons/typicons_light/document-scene.svg b/novelwriter/assets/icons/typicons_light/mixed_document-scene.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/document-scene.svg rename to novelwriter/assets/icons/typicons_light/mixed_document-scene.svg diff --git a/novelwriter/assets/icons/typicons_light/document-title.svg b/novelwriter/assets/icons/typicons_light/mixed_document-title.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/document-title.svg rename to novelwriter/assets/icons/typicons_light/mixed_document-title.svg diff --git a/novelwriter/assets/icons/typicons_light/heading0.svg b/novelwriter/assets/icons/typicons_light/mixed_heading0.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/heading0.svg rename to novelwriter/assets/icons/typicons_light/mixed_heading0.svg diff --git a/novelwriter/assets/icons/typicons_light/heading1.svg b/novelwriter/assets/icons/typicons_light/mixed_heading1.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/heading1.svg rename to novelwriter/assets/icons/typicons_light/mixed_heading1.svg diff --git a/novelwriter/assets/icons/typicons_light/heading2.svg b/novelwriter/assets/icons/typicons_light/mixed_heading2.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/heading2.svg rename to novelwriter/assets/icons/typicons_light/mixed_heading2.svg diff --git a/novelwriter/assets/icons/typicons_light/heading3.svg b/novelwriter/assets/icons/typicons_light/mixed_heading3.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/heading3.svg rename to novelwriter/assets/icons/typicons_light/mixed_heading3.svg diff --git a/novelwriter/assets/icons/typicons_light/heading4.svg b/novelwriter/assets/icons/typicons_light/mixed_heading4.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/heading4.svg rename to novelwriter/assets/icons/typicons_light/mixed_heading4.svg diff --git a/novelwriter/assets/icons/typicons_light/search-replace.svg b/novelwriter/assets/icons/typicons_light/mixed_search-replace.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/search-replace.svg rename to novelwriter/assets/icons/typicons_light/mixed_search-replace.svg diff --git a/novelwriter/assets/icons/fallback/search_case.svg b/novelwriter/assets/icons/typicons_light/nw_search-case.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_case.svg rename to novelwriter/assets/icons/typicons_light/nw_search-case.svg diff --git a/novelwriter/assets/icons/fallback/search_preserve.svg b/novelwriter/assets/icons/typicons_light/nw_search-preserve.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_preserve.svg rename to novelwriter/assets/icons/typicons_light/nw_search-preserve.svg diff --git a/novelwriter/assets/icons/fallback/search_regex.svg b/novelwriter/assets/icons/typicons_light/nw_search-regex.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_regex.svg rename to novelwriter/assets/icons/typicons_light/nw_search-regex.svg diff --git a/novelwriter/assets/icons/fallback/search_word.svg b/novelwriter/assets/icons/typicons_light/nw_search-word.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_word.svg rename to novelwriter/assets/icons/typicons_light/nw_search-word.svg diff --git a/novelwriter/assets/icons/fallback/search_project.svg b/novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_project.svg rename to novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/arrow-maximise.svg b/novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/arrow-maximise.svg rename to novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg diff --git a/novelwriter/assets/icons/typicons_light/arrow-minimise.svg b/novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/arrow-minimise.svg rename to novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg diff --git a/novelwriter/assets/icons/fallback/search_loop.svg b/novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_loop.svg rename to novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/at.svg b/novelwriter/assets/icons/typicons_light/typ_at.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/at.svg rename to novelwriter/assets/icons/typicons_light/typ_at.svg diff --git a/novelwriter/assets/icons/typicons_light/backspace.svg b/novelwriter/assets/icons/typicons_light/typ_backspace.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/backspace.svg rename to novelwriter/assets/icons/typicons_light/typ_backspace.svg diff --git a/novelwriter/assets/icons/typicons_light/book.svg b/novelwriter/assets/icons/typicons_light/typ_book.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/book.svg rename to novelwriter/assets/icons/typicons_light/typ_book.svg diff --git a/novelwriter/assets/icons/typicons_light/bookmark.svg b/novelwriter/assets/icons/typicons_light/typ_bookmark.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/bookmark.svg rename to novelwriter/assets/icons/typicons_light/typ_bookmark.svg diff --git a/novelwriter/assets/icons/typicons_light/calendar.svg b/novelwriter/assets/icons/typicons_light/typ_calendar.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/calendar.svg rename to novelwriter/assets/icons/typicons_light/typ_calendar.svg diff --git a/novelwriter/assets/icons/fallback/search_cancel.svg b/novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/search_cancel.svg rename to novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/cancel.svg b/novelwriter/assets/icons/typicons_light/typ_cancel.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/cancel.svg rename to novelwriter/assets/icons/typicons_light/typ_cancel.svg diff --git a/novelwriter/assets/icons/fallback/status_stats.svg b/novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_stats.svg rename to novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/chevron-left.svg b/novelwriter/assets/icons/typicons_light/typ_chevron-left.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/chevron-left.svg rename to novelwriter/assets/icons/typicons_light/typ_chevron-left.svg diff --git a/novelwriter/assets/icons/typicons_light/chevron-right.svg b/novelwriter/assets/icons/typicons_light/typ_chevron-right.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/chevron-right.svg rename to novelwriter/assets/icons/typicons_light/typ_chevron-right.svg diff --git a/novelwriter/assets/icons/fallback/settings.svg b/novelwriter/assets/icons/typicons_light/typ_cog.svg similarity index 100% rename from novelwriter/assets/icons/fallback/settings.svg rename to novelwriter/assets/icons/typicons_light/typ_cog.svg diff --git a/novelwriter/assets/icons/typicons_light/delete.svg b/novelwriter/assets/icons/typicons_light/typ_delete.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/delete.svg rename to novelwriter/assets/icons/typicons_light/typ_delete.svg diff --git a/novelwriter/assets/icons/typicons_light/document-text.svg b/novelwriter/assets/icons/typicons_light/typ_document-text.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/document-text.svg rename to novelwriter/assets/icons/typicons_light/typ_document-text.svg diff --git a/novelwriter/assets/icons/typicons_light/download.svg b/novelwriter/assets/icons/typicons_light/typ_download.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/download.svg rename to novelwriter/assets/icons/typicons_light/typ_download.svg diff --git a/novelwriter/assets/icons/typicons_light/flag.svg b/novelwriter/assets/icons/typicons_light/typ_flag.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/flag.svg rename to novelwriter/assets/icons/typicons_light/typ_flag.svg diff --git a/novelwriter/assets/icons/typicons_light/folder.svg b/novelwriter/assets/icons/typicons_light/typ_folder.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/folder.svg rename to novelwriter/assets/icons/typicons_light/typ_folder.svg diff --git a/novelwriter/assets/icons/fallback/status_lang.svg b/novelwriter/assets/icons/typicons_light/typ_globe-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_lang.svg rename to novelwriter/assets/icons/typicons_light/typ_globe-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/globe.svg b/novelwriter/assets/icons/typicons_light/typ_globe.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/globe.svg rename to novelwriter/assets/icons/typicons_light/typ_globe.svg diff --git a/novelwriter/assets/icons/typicons_light/hash.svg b/novelwriter/assets/icons/typicons_light/typ_hash.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/hash.svg rename to novelwriter/assets/icons/typicons_light/typ_hash.svg diff --git a/novelwriter/assets/icons/typicons_light/input-checked.svg b/novelwriter/assets/icons/typicons_light/typ_input-checked.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/input-checked.svg rename to novelwriter/assets/icons/typicons_light/typ_input-checked.svg diff --git a/novelwriter/assets/icons/typicons_light/key.svg b/novelwriter/assets/icons/typicons_light/typ_key.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/key.svg rename to novelwriter/assets/icons/typicons_light/typ_key.svg diff --git a/novelwriter/assets/icons/typicons_light/location.svg b/novelwriter/assets/icons/typicons_light/typ_location.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/location.svg rename to novelwriter/assets/icons/typicons_light/typ_location.svg diff --git a/novelwriter/assets/icons/fallback/status_idle.svg b/novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_idle.svg rename to novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/media-record-outline.svg b/novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/media-record-outline.svg rename to novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg diff --git a/novelwriter/assets/icons/typicons_light/media-record.svg b/novelwriter/assets/icons/typicons_light/typ_media-record.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/media-record.svg rename to novelwriter/assets/icons/typicons_light/typ_media-record.svg diff --git a/novelwriter/assets/icons/typicons_light/minus.svg b/novelwriter/assets/icons/typicons_light/typ_minus.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/minus.svg rename to novelwriter/assets/icons/typicons_light/typ_minus.svg diff --git a/novelwriter/assets/icons/typicons_light/pencil.svg b/novelwriter/assets/icons/typicons_light/typ_pencil.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/pencil.svg rename to novelwriter/assets/icons/typicons_light/typ_pencil.svg diff --git a/novelwriter/assets/icons/typicons_light/pin-outline.svg b/novelwriter/assets/icons/typicons_light/typ_pin-outline.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/pin-outline.svg rename to novelwriter/assets/icons/typicons_light/typ_pin-outline.svg diff --git a/novelwriter/assets/icons/typicons_light/pin.svg b/novelwriter/assets/icons/typicons_light/typ_pin.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/pin.svg rename to novelwriter/assets/icons/typicons_light/typ_pin.svg diff --git a/novelwriter/assets/icons/typicons_light/plus.svg b/novelwriter/assets/icons/typicons_light/typ_plus.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/plus.svg rename to novelwriter/assets/icons/typicons_light/typ_plus.svg diff --git a/novelwriter/assets/icons/typicons_light/puzzle.svg b/novelwriter/assets/icons/typicons_light/typ_puzzle.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/puzzle.svg rename to novelwriter/assets/icons/typicons_light/typ_puzzle.svg diff --git a/novelwriter/assets/icons/typicons_light/refresh.svg b/novelwriter/assets/icons/typicons_light/typ_refresh.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/refresh.svg rename to novelwriter/assets/icons/typicons_light/typ_refresh.svg diff --git a/novelwriter/assets/icons/typicons_light/search.svg b/novelwriter/assets/icons/typicons_light/typ_search.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/search.svg rename to novelwriter/assets/icons/typicons_light/typ_search.svg diff --git a/novelwriter/assets/icons/typicons_light/star.svg b/novelwriter/assets/icons/typicons_light/typ_star.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/star.svg rename to novelwriter/assets/icons/typicons_light/typ_star.svg diff --git a/novelwriter/assets/icons/fallback/status_time.svg b/novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_time.svg rename to novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/stopwatch.svg b/novelwriter/assets/icons/typicons_light/typ_stopwatch.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/stopwatch.svg rename to novelwriter/assets/icons/typicons_light/typ_stopwatch.svg diff --git a/novelwriter/assets/icons/fallback/status_lines.svg b/novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg similarity index 100% rename from novelwriter/assets/icons/fallback/status_lines.svg rename to novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg diff --git a/novelwriter/assets/icons/typicons_light/tick.svg b/novelwriter/assets/icons/typicons_light/typ_tick.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/tick.svg rename to novelwriter/assets/icons/typicons_light/typ_tick.svg diff --git a/novelwriter/assets/icons/typicons_light/times.svg b/novelwriter/assets/icons/typicons_light/typ_times.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/times.svg rename to novelwriter/assets/icons/typicons_light/typ_times.svg diff --git a/novelwriter/assets/icons/typicons_light/trash.svg b/novelwriter/assets/icons/typicons_light/typ_trash.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/trash.svg rename to novelwriter/assets/icons/typicons_light/typ_trash.svg diff --git a/novelwriter/assets/icons/typicons_light/user.svg b/novelwriter/assets/icons/typicons_light/typ_user.svg similarity index 100% rename from novelwriter/assets/icons/typicons_light/user.svg rename to novelwriter/assets/icons/typicons_light/typ_user.svg diff --git a/novelwriter/assets/themes/syntax/default_dark.conf b/novelwriter/assets/syntax/default_dark.conf similarity index 100% rename from novelwriter/assets/themes/syntax/default_dark.conf rename to novelwriter/assets/syntax/default_dark.conf diff --git a/novelwriter/assets/themes/syntax/default_light.conf b/novelwriter/assets/syntax/default_light.conf similarity index 100% rename from novelwriter/assets/themes/syntax/default_light.conf rename to novelwriter/assets/syntax/default_light.conf diff --git a/novelwriter/assets/themes/syntax/grey_dark.conf b/novelwriter/assets/syntax/grey_dark.conf similarity index 100% rename from novelwriter/assets/themes/syntax/grey_dark.conf rename to novelwriter/assets/syntax/grey_dark.conf diff --git a/novelwriter/assets/themes/syntax/grey_light.conf b/novelwriter/assets/syntax/grey_light.conf similarity index 100% rename from novelwriter/assets/themes/syntax/grey_light.conf rename to novelwriter/assets/syntax/grey_light.conf diff --git a/novelwriter/assets/themes/syntax/light_owl.conf b/novelwriter/assets/syntax/light_owl.conf similarity index 100% rename from novelwriter/assets/themes/syntax/light_owl.conf rename to novelwriter/assets/syntax/light_owl.conf diff --git a/novelwriter/assets/themes/syntax/night_owl.conf b/novelwriter/assets/syntax/night_owl.conf similarity index 100% rename from novelwriter/assets/themes/syntax/night_owl.conf rename to novelwriter/assets/syntax/night_owl.conf diff --git a/novelwriter/assets/themes/syntax/solarized_dark.conf b/novelwriter/assets/syntax/solarized_dark.conf similarity index 100% rename from novelwriter/assets/themes/syntax/solarized_dark.conf rename to novelwriter/assets/syntax/solarized_dark.conf diff --git a/novelwriter/assets/themes/syntax/solarized_light.conf b/novelwriter/assets/syntax/solarized_light.conf similarity index 100% rename from novelwriter/assets/themes/syntax/solarized_light.conf rename to novelwriter/assets/syntax/solarized_light.conf diff --git a/novelwriter/assets/themes/syntax/tomorrow.conf b/novelwriter/assets/syntax/tomorrow.conf similarity index 100% rename from novelwriter/assets/themes/syntax/tomorrow.conf rename to novelwriter/assets/syntax/tomorrow.conf diff --git a/novelwriter/assets/themes/syntax/tomorrow_night.conf b/novelwriter/assets/syntax/tomorrow_night.conf similarity index 100% rename from novelwriter/assets/themes/syntax/tomorrow_night.conf rename to novelwriter/assets/syntax/tomorrow_night.conf diff --git a/novelwriter/assets/themes/syntax/tomorrow_night_blue.conf b/novelwriter/assets/syntax/tomorrow_night_blue.conf similarity index 100% rename from novelwriter/assets/themes/syntax/tomorrow_night_blue.conf rename to novelwriter/assets/syntax/tomorrow_night_blue.conf diff --git a/novelwriter/assets/themes/syntax/tomorrow_night_bright.conf b/novelwriter/assets/syntax/tomorrow_night_bright.conf similarity index 100% rename from novelwriter/assets/themes/syntax/tomorrow_night_bright.conf rename to novelwriter/assets/syntax/tomorrow_night_bright.conf diff --git a/novelwriter/assets/themes/syntax/tomorrow_night_eighties.conf b/novelwriter/assets/syntax/tomorrow_night_eighties.conf similarity index 100% rename from novelwriter/assets/themes/syntax/tomorrow_night_eighties.conf rename to novelwriter/assets/syntax/tomorrow_night_eighties.conf diff --git a/novelwriter/assets/themes/gui/default/theme.conf b/novelwriter/assets/themes/default.conf similarity index 100% rename from novelwriter/assets/themes/gui/default/theme.conf rename to novelwriter/assets/themes/default.conf diff --git a/novelwriter/assets/themes/gui/default_dark/theme.conf b/novelwriter/assets/themes/default_dark.conf similarity index 100% rename from novelwriter/assets/themes/gui/default_dark/theme.conf rename to novelwriter/assets/themes/default_dark.conf diff --git a/novelwriter/assets/themes/gui/default_dark/styles.qss b/novelwriter/assets/themes/default_dark.qss similarity index 100% rename from novelwriter/assets/themes/gui/default_dark/styles.qss rename to novelwriter/assets/themes/default_dark.qss diff --git a/novelwriter/assets/themes/gui/solarized_dark/theme.conf b/novelwriter/assets/themes/solarized_dark.conf similarity index 100% rename from novelwriter/assets/themes/gui/solarized_dark/theme.conf rename to novelwriter/assets/themes/solarized_dark.conf diff --git a/novelwriter/assets/themes/gui/solarized_light/theme.conf b/novelwriter/assets/themes/solarized_light.conf similarity index 100% rename from novelwriter/assets/themes/gui/solarized_light/theme.conf rename to novelwriter/assets/themes/solarized_light.conf diff --git a/novelwriter/common.py b/novelwriter/common.py index d4eb5a83..7e699e97 100644 --- a/novelwriter/common.py +++ b/novelwriter/common.py @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +import os import json import hashlib import logging @@ -415,6 +416,24 @@ def jsonEncode(data, n=0, nmax=0): # File and File System Functions # =============================================================================================== # +def readTextFile(filePath): + """Read the content of a text file in a robust manner. + """ + if not os.path.isfile(filePath): + return "" + + fileText = "" + try: + with open(filePath, mode="r", encoding="utf-8") as inFile: + fileText = inFile.read() + except Exception: + logger.error("Could not read file: %s", filePath) + logException() + return "" + + return fileText + + def makeFileNameSafe(theText): """Returns a filename safe version of the text. """ diff --git a/novelwriter/config.py b/novelwriter/config.py index 16f8e27d..8a7231f8 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -68,24 +68,24 @@ class Config: self.appRoot = None # The full path to the novelwriter root folder self.appIcon = None # The full path to the novelwriter icon file self.assetPath = None # The full path to the novelwriter/assets folder - self.themeRoot = None # The full path to the novelwriter/assets/themes folder - self.dictPath = None # The full path to the novelwriter/assets/dict folder - self.iconPath = None # The full path to the novelwriter/assets/icons folder self.pdfDocs = None # The location of the PDF manual, if it exists # Runtime Settings and Variables self.confChanged = False # True whenever the config has chenged, false after save # General - self.guiTheme = "default" - self.guiSyntax = "default_light" - self.guiIcons = "typicons_light" - self.guiDark = False # Load icons for dark backgrounds, if available + self.guiTheme = "" # GUI theme + self.guiSyntax = "" # Syntax theme + self.guiIcons = "" # Icon theme self.guiFont = "" # Defaults to system default font self.guiFontSize = 11 # Is overridden if system default is loaded self.guiScale = 1.0 # Set automatically by Theme class self.lastNotes = "0x0" # The latest release notes that have been shown + self.setDefaultGuiTheme() + self.setDefaultSyntaxTheme() + self.setDefaultIconTheme() + # Localisation self.qLocal = QLocale.system() self.guiLang = self.qLocal.name() @@ -293,10 +293,7 @@ class Config: # Assets self.assetPath = os.path.join(self.appPath, "assets") - self.themeRoot = os.path.join(self.assetPath, "themes") - self.dictPath = os.path.join(self.assetPath, "dict") - self.iconPath = os.path.join(self.assetPath, "icons") - self.appIcon = os.path.join(self.iconPath, "novelwriter.svg") + self.appIcon = os.path.join(self.assetPath, "icons", "novelwriter.svg") # Internationalisation self.nwLangPath = os.path.join(self.assetPath, "i18n") @@ -441,7 +438,6 @@ class Config: self.guiTheme = theConf.rdStr(cnfSec, "theme", self.guiTheme) self.guiSyntax = theConf.rdStr(cnfSec, "syntax", self.guiSyntax) self.guiIcons = theConf.rdStr(cnfSec, "icons", self.guiIcons) - self.guiDark = theConf.rdBool(cnfSec, "guidark", self.guiDark) self.guiFont = theConf.rdStr(cnfSec, "guifont", self.guiFont) self.guiFontSize = theConf.rdInt(cnfSec, "guifontsize", self.guiFontSize) self.lastNotes = theConf.rdStr(cnfSec, "lastnotes", self.lastNotes) @@ -564,7 +560,6 @@ class Config: "theme": str(self.guiTheme), "syntax": str(self.guiSyntax), "icons": str(self.guiIcons), - "guidark": str(self.guiDark), "guifont": str(self.guiFont), "guifontsize": str(self.guiFontSize), "lastnotes": str(self.lastNotes), @@ -852,6 +847,19 @@ class Config: self.confChanged = True return self.viewSynopsis + ## + # Default Setters + ## + + def setDefaultGuiTheme(self): + self.guiTheme = "default" + + def setDefaultSyntaxTheme(self): + self.guiSyntax = "default_light" + + def setDefaultIconTheme(self): + self.guiIcons = "typicons_light" + ## # Getters ## diff --git a/novelwriter/dialogs/about.py b/novelwriter/dialogs/about.py index 498a25df..2aefc3f6 100644 --- a/novelwriter/dialogs/about.py +++ b/novelwriter/dialogs/about.py @@ -36,6 +36,8 @@ from PyQt5.QtWidgets import ( QTextBrowser, QLabel ) +from novelwriter.common import readTextFile + logger = logging.getLogger(__name__) @@ -230,10 +232,9 @@ class GuiAbout(QDialog): """Load the content for the Release Notes page. """ docPath = os.path.join(self.mainConf.assetPath, "text", "release_notes.htm") - if os.path.isfile(docPath): - with open(docPath, mode="r", encoding="utf-8") as inFile: - helpText = inFile.read() - self.pageNotes.setHtml(helpText) + docText = readTextFile(docPath) + if docText: + self.pageNotes.setHtml(docText) else: self.pageNotes.setHtml("Error loading release notes text ...") return @@ -242,10 +243,9 @@ class GuiAbout(QDialog): """Load the content for the Licence page. """ docPath = os.path.join(self.mainConf.assetPath, "text", "gplv3_en.htm") - if os.path.isfile(docPath): - with open(docPath, mode="r", encoding="utf-8") as inFile: - helpText = inFile.read() - self.pageLicense.setHtml(helpText) + docText = readTextFile(docPath) + if docText: + self.pageLicense.setHtml(docText) else: self.pageLicense.setHtml("Error loading licence text ...") return diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index cd757f95..98f20993 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -203,15 +203,6 @@ class GuiPreferencesGeneral(QWidget): self.tr("Changing this requires restarting novelWriter.") ) - # Dark Icons - self.guiDark = QSwitch() - self.guiDark.setChecked(self.mainConf.guiDark) - self.mainForm.addRow( - self.tr("Prefer icons for dark backgrounds"), - self.guiDark, - self.tr("May improve the look of icons on dark themes.") - ) - # Font Family self.guiFont = QLineEdit() self.guiFont.setReadOnly(True) @@ -284,7 +275,6 @@ class GuiPreferencesGeneral(QWidget): guiLang = self.guiLang.currentData() guiTheme = self.guiTheme.currentData() guiIcons = self.guiIcons.currentData() - guiDark = self.guiDark.isChecked() guiFont = self.guiFont.text() guiFontSize = self.guiFontSize.value() emphLabels = self.emphLabels.isChecked() @@ -294,7 +284,6 @@ class GuiPreferencesGeneral(QWidget): needsRestart |= self.mainConf.guiLang != guiLang needsRestart |= self.mainConf.guiTheme != guiTheme needsRestart |= self.mainConf.guiIcons != guiIcons - needsRestart |= self.mainConf.guiDark != guiDark needsRestart |= self.mainConf.guiFont != guiFont needsRestart |= self.mainConf.guiFontSize != guiFontSize @@ -305,7 +294,6 @@ class GuiPreferencesGeneral(QWidget): self.mainConf.guiLang = guiLang self.mainConf.guiTheme = guiTheme self.mainConf.guiIcons = guiIcons - self.mainConf.guiDark = guiDark self.mainConf.guiFont = guiFont self.mainConf.guiFontSize = guiFontSize self.mainConf.emphLabels = emphLabels diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 941e83ee..b23a8aaf 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -2244,7 +2244,7 @@ class GuiDocEditSearch(QFrame): self.searchButton.setToolTip(self.tr("Find in current document")) self.searchButton.clicked.connect(self._doSearch) - self.replaceButton = QPushButton(self.theTheme.getIcon("search-replace"), "") + self.replaceButton = QPushButton(self.theTheme.getIcon("search_replace"), "") self.replaceButton.setFixedSize(QSize(bPx, bPx)) self.replaceButton.setToolTip(self.tr("Find and replace in current document")) self.replaceButton.clicked.connect(self._doReplace) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index fa2237a5..be1f6754 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -29,16 +29,15 @@ import logging import novelwriter from math import ceil -from functools import partial -from PyQt5.QtCore import QCoreApplication, Qt -from PyQt5.QtWidgets import QStyle, qApp +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import qApp from PyQt5.QtGui import ( QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap ) -from novelwriter.enum import nwAlert, nwItemLayout, nwItemType -from novelwriter.common import NWConfigParser +from novelwriter.enum import nwItemLayout, nwItemType +from novelwriter.common import NWConfigParser, readTextFile from novelwriter.constants import nwLabels logger = logging.getLogger(__name__) @@ -51,19 +50,10 @@ logger = logging.getLogger(__name__) class GuiTheme: - def __init__(self, theParent): + def __init__(self): - self.mainConf = novelwriter.CONFIG - self.theParent = theParent - self.theIcons = GuiIcons(self.theParent) - self.guiPalette = QPalette() - self.guiPath = "gui" - self.fontPath = "fonts" - self.syntaxPath = "syntax" - self.cssName = "style.qss" - self.confName = "theme.conf" - self.themeList = [] - self.syntaxList = [] + self.mainConf = novelwriter.CONFIG + self.theIcons = GuiIcons(self) # Loaded Theme Settings # ===================== @@ -84,6 +74,7 @@ class GuiTheme: self.helpText = [0, 0, 0] # Loaded Syntax Settings + # ====================== # Main self.syntaxName = "" @@ -115,14 +106,24 @@ class GuiTheme: # Changeable Settings self.guiTheme = None self.guiSyntax = None - self.themeRoot = None - self.themePath = None self.syntaxFile = None - self.confFile = None self.cssFile = None self.guiFontDB = QFontDatabase() - self.loadFonts() + # Class Setup + # =========== + + self._guiPalette = QPalette() + self._themeList = [] + self._syntaxList = [] + self._availThemes = {} + self._availSyntax = {} + + self._listConf(self._availSyntax, os.path.join(self.mainConf.dataPath, "syntax")) + self._listConf(self._availSyntax, os.path.join(self.mainConf.assetPath, "syntax")) + self._listConf(self._availThemes, os.path.join(self.mainConf.dataPath, "themes")) + self._listConf(self._availThemes, os.path.join(self.mainConf.assetPath, "themes")) + self.updateFont() self.updateTheme() self.theIcons.updateTheme() @@ -162,9 +163,6 @@ class GuiTheme: logger.verbose("Text 'N' Height: %d", self.textNHeight) logger.verbose("Text 'N' Width: %d", self.textNWidth) - # Internal Mapping - self.tr = partial(QCoreApplication.translate, "GuiTheme") - return ## @@ -184,43 +182,14 @@ class GuiTheme: # Actions ## - def loadFonts(self): - """Add the fonts in the assets fonts folder to the app. - """ - logger.debug("Loading additional fonts") - - ttfList = [] - fontAssets = os.path.join(self.mainConf.assetPath, self.fontPath) - for fontFam in os.listdir(fontAssets): - fontDir = os.path.join(fontAssets, fontFam) - if os.path.isdir(fontDir): - logger.verbose("Found font: %s", fontFam) - if fontFam not in self.guiFontDB.families(): - for fontFile in os.listdir(fontDir): - ttfFile = os.path.join(fontDir, fontFile) - if os.path.isfile(ttfFile) and fontFile.endswith(".ttf"): - ttfList.append(ttfFile) - - for ttfFile in ttfList: - relPath = os.path.relpath(ttfFile, fontAssets) - logger.verbose("Adding font: %s", relPath) - fontID = self.guiFontDB.addApplicationFont(ttfFile) - if fontID < 0: - logger.error("Failed to add font: %s", relPath) - - return - def updateFont(self): """Update the GUI's font style from settings. """ theFont = QFont() if self.mainConf.guiFont not in self.guiFontDB.families(): - if self.mainConf.osWindows: - if "Arial" in self.guiFontDB.families(): - theFont.setFamily("Arial") - else: - # On Windows, fall back to Cantarell provided by novelWriter - theFont.setFamily("Cantarell") + if self.mainConf.osWindows and "Arial" in self.guiFontDB.families(): + # On Windows we default to Arial if possible + theFont.setFamily("Arial") theFont.setPointSize(10) else: theFont = self.guiFontDB.systemFont(QFontDatabase.GeneralFont) @@ -237,16 +206,21 @@ class GuiTheme: def updateTheme(self): """Update the GUI theme from theme files. """ - self.guiTheme = self.mainConf.guiTheme - self.guiSyntax = self.mainConf.guiSyntax - self.themeRoot = self.mainConf.themeRoot - self.themePath = os.path.join(self.mainConf.themeRoot, self.guiPath, self.guiTheme) - self.syntaxFile = os.path.join(self.themeRoot, self.syntaxPath, self.guiSyntax+".conf") - self.confFile = os.path.join(self.themePath, self.confName) - self.cssFile = os.path.join(self.themePath, self.cssName) + self.guiTheme = self.mainConf.guiTheme + self.guiSyntax = self.mainConf.guiSyntax - self.loadTheme() - self.loadSyntax() + self.themeFile = self._availThemes.get(self.guiTheme, None) + if self.themeFile is None: + logger.error("Could not find GUI theme '%s'", self.guiTheme) + else: + self.cssFile = self.themeFile[:-5]+".css" + self.loadTheme() + + self.syntaxFile = self._availSyntax.get(self.guiSyntax, None) + if self.syntaxFile is None: + logger.error("Could not find syntax theme '%s'", self.guiSyntax) + else: + self.loadSyntax() # Update dependant colours backCol = qApp.palette().window().color() @@ -267,27 +241,15 @@ class GuiTheme: def loadTheme(self): """Load the currently specified GUI theme. """ - logger.debug("Loading theme files") - logger.debug("System icon theme is '%s'", str(QIcon.themeName())) - - # CSS File - cssData = "" - try: - if os.path.isfile(self.cssFile): - with open(self.cssFile, mode="r", encoding="utf-8") as inFile: - cssData = inFile.read() - except Exception: - logger.error("Could not load theme css file") - novelwriter.logException() - return False + logger.info("Loading GUI theme '%s'", self.guiTheme) # Config File confParser = NWConfigParser() try: - with open(self.confFile, mode="r", encoding="utf-8") as inFile: + with open(self.themeFile, mode="r", encoding="utf-8") as inFile: confParser.read_file(inFile) except Exception: - logger.error("Could not load theme settings from: %s", self.confFile) + logger.error("Could not load theme settings from: %s", self.themeFile) novelwriter.logException() return False @@ -327,18 +289,20 @@ class GuiTheme: self.statUnsaved = self._loadColour(confParser, cnfSec, "statusunsaved") self.statSaved = self._loadColour(confParser, cnfSec, "statussaved") - # Apply Styles - qApp.setStyleSheet(cssData) - qApp.setPalette(self.guiPalette) + # CSS File + cssData = readTextFile(self.cssFile) + if cssData: + qApp.setStyleSheet(cssData) - logger.info("Loaded theme '%s'", self.guiTheme) + # Apply Styles + qApp.setPalette(self._guiPalette) return True def loadSyntax(self): """Load the currently specified syntax highlighter theme. """ - logger.debug("Loading syntax theme files") + logger.info("Loading syntax theme '%s'", self.guiSyntax) confParser = NWConfigParser() try: @@ -380,79 +344,59 @@ class GuiTheme: self.colRepTag = self._loadColour(confParser, cnfSec, "replacetag") self.colMod = self._loadColour(confParser, cnfSec, "modifier") - logger.info("Loaded syntax theme '%s'", self.guiSyntax) - return True def listThemes(self): """Scan the GUI themes folder and list all themes. """ - if self.themeList: - return self.themeList + if self._themeList: + return self._themeList confParser = NWConfigParser() - for themeDir in os.listdir(os.path.join(self.mainConf.themeRoot, self.guiPath)): - themeConf = os.path.join( - self.mainConf.themeRoot, self.guiPath, themeDir, self.confName - ) - logger.verbose("Checking theme config for '%s'", themeDir) - try: - with open(themeConf, mode="r", encoding="utf-8") as inFile: - confParser.read_file(inFile) - except Exception as e: - self.theParent.makeAlert([ - self.tr("Could not load theme config file."), str(e) - ], nwAlert.ERROR) - continue - themeName = "" - if confParser.has_section("Main"): - if confParser.has_option("Main", "name"): - themeName = confParser.get("Main", "name") - logger.verbose("Theme name is '%s'", themeName) - if themeName != "": - self.themeList.append((themeDir, themeName)) + for themeKey, themePath in self._availThemes.items(): + logger.verbose("Checking theme config for '%s'", themeKey) + themeName = _loadInternalName(confParser, themePath) + if themeName: + self._themeList.append((themeKey, themeName)) - self.themeList = sorted(self.themeList, key=lambda x: x[1]) + self._themeList = sorted(self._themeList, key=lambda x: x[1]) - return self.themeList + return self._themeList def listSyntax(self): """Scan the syntax themes folder and list all themes. """ - if self.syntaxList: - return self.syntaxList + if self._syntaxList: + return self._syntaxList confParser = NWConfigParser() - syntaxDir = os.path.join(self.mainConf.themeRoot, self.syntaxPath) - for syntaxFile in os.listdir(syntaxDir): - syntaxPath = os.path.join(syntaxDir, syntaxFile) - if not os.path.isfile(syntaxPath): - continue - logger.verbose("Checking theme syntax for '%s'", syntaxFile) - try: - with open(syntaxPath, mode="r", encoding="utf-8") as inFile: - confParser.read_file(inFile) - except Exception as e: - self.theParent.makeAlert([ - self.tr("Could not load syntax file."), str(e) - ], nwAlert.ERROR) - return [] - syntaxName = "" - if confParser.has_section("Main"): - if confParser.has_option("Main", "name"): - syntaxName = confParser.get("Main", "name") - if len(syntaxFile) > 5 and syntaxName != "": - self.syntaxList.append((syntaxFile[:-5], syntaxName)) - logger.verbose("Syntax name is '%s'", syntaxName) + for syntaxKey, syntaxPath in self._availSyntax.items(): + logger.verbose("Checking theme syntax for '%s'", syntaxKey) + syntaxName = _loadInternalName(confParser, syntaxPath) + if syntaxName: + self._syntaxList.append((syntaxKey, syntaxName)) - self.syntaxList = sorted(self.syntaxList, key=lambda x: x[1]) + self._syntaxList = sorted(self._syntaxList, key=lambda x: x[1]) - return self.syntaxList + return self._syntaxList ## # Internal Functions ## + def _listConf(self, targetDict, checkDir): + """Scan for syntax and gui themes and populate the dictionary. + """ + if not os.path.isdir(checkDir): + return + + for checkFile in os.listdir(checkDir): + confPath = os.path.join(checkDir, checkFile) + if os.path.isfile(confPath) and confPath.endswith(".conf"): + targetDict[checkFile[:-5]] = confPath + + return + def _loadColour(self, confParser, cnfSec, cnfName): """Load a colour value from a config string. """ @@ -485,7 +429,7 @@ class GuiTheme: logger.error("Could not load theme colours for '%s' from config file", cnfName) return if len(readCol) == 3: - self.guiPalette.setColor(paletteVal, QColor(*readCol)) + self._guiPalette.setColor(paletteVal, QColor(*readCol)) return # End Class GuiTheme @@ -498,116 +442,57 @@ class GuiTheme: class GuiIcons: """The icon class manages the content of the assets/icons folder, and provides a simple interface for requesting icons. Only icons - listed in the ICON_MAP are handled. + listed in the ICON_KEYS are handled. Icons are loaded on first request, and then cached for further - requests. Each icon key in the ICON_MAP has a series of fallbacks: - * The first lookup is in the key-to-file map for the selected icon - theme. The map is specified in the icons.conf file in the theme - folder. The map makes it possible to preserve the original file - name from the icon theme were the icons were extracted. - * Second, if the icon does not exist in the theme map, the - GuiIcons class will check if there is a QStyle icon specified in - the ICON_MAP data tuple[0]. This will let Qt pull the closest - system icon. - * Third action is to look up the freedesktop icon theme name using - the fromTheme Qt call. This generally produces the same result - as the step above, but has more icons available in other cases. - * Fourth, and finally, the icon is looked up in the fallback - folder. Files in this folder must have the same file name as the - novelWriter internal icon key, with '-dark' appended to them for - the dark background version of the icon. If no dark icon exists, - the non-dark version will be returned. + requests. Each icon key in the ICON_KEYS set has standard icon set + in the icon theme conf file. The existence of the file, and the + definition of all keys are checked when the theme is loaded. + + When an icon is requested, the icon is loaded and cached. If it is + missing, a blank icon is returned and a warning issued. """ - ICON_MAP = { + ICON_KEYS = { # Project and GUI icons - "novelwriter": (None, None), - "cls_none": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_novel": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_plot": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_character": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_world": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_timeline": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_object": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_entity": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_custom": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_archive": (QStyle.SP_DriveHDIcon, "drive-harddisk"), - "cls_trash": (QStyle.SP_TrashIcon, "user-trash"), - "proj_document": (QStyle.SP_FileIcon, "x-office-document"), - "proj_title": (QStyle.SP_FileIcon, "x-office-document"), - "proj_chapter": (QStyle.SP_FileIcon, "x-office-document"), - "proj_scene": (QStyle.SP_FileIcon, "x-office-document"), - "proj_note": (QStyle.SP_FileIcon, "x-office-document"), - "proj_folder": (QStyle.SP_DirIcon, "folder"), - "proj_nwx": (None, None), - "status_lang": (None, None), - "status_time": (None, None), - "status_idle": (None, None), - "status_stats": (None, None), - "status_lines": (None, None), - "doc_h0": (QStyle.SP_FileIcon, "x-office-document"), - "doc_h1": (QStyle.SP_FileIcon, "x-office-document"), - "doc_h2": (QStyle.SP_FileIcon, "x-office-document"), - "doc_h3": (QStyle.SP_FileIcon, "x-office-document"), - "doc_h4": (QStyle.SP_FileIcon, "x-office-document"), - "search_case": (None, None), - "search_regex": (None, None), - "search_word": (None, None), - "search_loop": (None, None), - "search_project": (None, None), - "search_cancel": (None, None), - "search_preserve": (None, None), + "novelwriter", "proj_nwx", + "cls_none", "cls_novel", "cls_plot", "cls_character", "cls_world", + "cls_timeline", "cls_object", "cls_entity", "cls_custom", "cls_archive", "cls_trash", + "proj_document", "proj_title", "proj_chapter", "proj_scene", "proj_note", "proj_folder", + "status_lang", "status_time", "status_idle", "status_stats", "status_lines", + "doc_h0", "doc_h1", "doc_h2", "doc_h3", "doc_h4", + "search_case", "search_regex", "search_word", "search_loop", "search_project", + "search_cancel", "search_preserve", # General Button Icons - "folder-open": (QStyle.SP_DirOpenIcon, "folder-open"), - "delete": (QStyle.SP_DialogDiscardButton, "edit-delete"), - "close": (QStyle.SP_DialogCloseButton, "window-close"), - "done": (QStyle.SP_DialogApplyButton, None), - "clear": (QStyle.SP_LineEditClearButton, "clear_left"), - "save": (QStyle.SP_DialogSaveButton, "document-save"), - "add": (None, "list-add"), - "remove": (None, "list-remove"), - "search": (None, "edit-find"), - "search-replace": (None, "edit-find-replace"), - "edit": (None, None), - "check": (None, None), - "cross": (None, None), - "hash": (None, None), - "maximise": (None, None), - "minimise": (None, None), - "refresh": (None, None), - "reference": (None, None), - "backward": (None, None), - "forward": (None, None), - "settings": (None, None), + "delete", "close", "done", "clear", "save", "add", "remove", + "search", "search_replace", "edit", "check", "cross", "hash", + "maximise", "minimise", "refresh", "reference", "backward", + "forward", "settings", # Switches - "sticky-on": (None, None), - "sticky-off": (None, None), - "bullet-on": (None, None), - "bullet-off": (None, None), + "sticky-on", "sticky-off", + "bullet-on", "bullet-off", } DECO_MAP = { "wiz-back": "wizard-back.jpg", } - def __init__(self, theParent): + def __init__(self, theTheme): - self.mainConf = novelwriter.CONFIG - self.theParent = theParent + self.mainConf = novelwriter.CONFIG + self.theTheme = theTheme # Storage - self.qIcons = {} - self.themeMap = {} - self.themeList = [] - self.fbackName = "fallback" - self.confName = "icons.conf" + self._qIcons = {} + self._themeMap = {} + self._themeList = [] + self._confName = "icons.conf" # Icon Theme Path - self.iconPath = None - self.confFile = None + self._iconPath = os.path.join(self.mainConf.assetPath, "icons") + self._themePath = os.path.join(self._iconPath, "system") # Icon Theme Meta self.themeName = "" @@ -629,24 +514,23 @@ class GuiIcons: the GUI icons cannot really be replaced without writing specific update functions for the classes where they're used. """ - logger.debug("Loading icon theme files") - - self.themeMap = {} - checkPath = os.path.join(self.mainConf.iconPath, self.mainConf.guiIcons) - if os.path.isdir(checkPath): - logger.debug("Loading icon theme '%s'", self.mainConf.guiIcons) - self.iconPath = checkPath - self.confFile = os.path.join(checkPath, self.confName) - else: + self._themeMap = {} + themePath = self._getThemePath() + if themePath is None: + logger.warning("No icons loaded") return False + self._themePath = themePath + themeConf = os.path.join(themePath, self._confName) + logger.info("Loading icon theme '%s'", self.mainConf.guiIcons) + # Config File confParser = NWConfigParser() try: - with open(self.confFile, mode="r", encoding="utf-8") as inFile: + with open(themeConf, mode="r", encoding="utf-8") as inFile: confParser.read_file(inFile) except Exception: - logger.error("Could not load icon theme settings from: %s", self.confFile) + logger.error("Could not load icon theme settings from: %s", themeConf) novelwriter.logException() return False @@ -661,21 +545,28 @@ class GuiIcons: self.themeLicense = confParser.rdStr(cnfSec, "license", "N/A") self.themeLicenseUrl = confParser.rdStr(cnfSec, "licenseurl", "") - # Palette + # Populate Icon Map cnfSec = "Map" if confParser.has_section(cnfSec): for iconName, iconFile in confParser.items(cnfSec): - if iconName not in self.ICON_MAP: + if iconName not in self.ICON_KEYS: logger.error("Unknown icon name '%s' in config file", iconName) else: - iconPath = os.path.join(self.iconPath, iconFile) + iconPath = os.path.join(self._themePath, iconFile) if os.path.isfile(iconPath): - self.themeMap[iconName] = iconPath + self._themeMap[iconName] = iconPath logger.verbose("Icon slot '%s' using file '%s'", iconName, iconFile) else: logger.error("Icon file '%s' not in theme folder", iconFile) - logger.info("Loaded icon theme '%s'", self.mainConf.guiIcons) + # Check that icons have been defined + logger.debug("Scanning theme icons") + for iconKey in self.ICON_KEYS: + if iconKey in ("novelwriter", "proj_nwx"): + # These are not part of the theme itself + continue + if iconKey not in self._themeMap: + logger.error("No icon file specified for '%s'", iconKey) return True @@ -713,11 +604,11 @@ class GuiIcons: return, load it, and if it still doesn't exist, return an empty icon. """ - if iconKey in self.qIcons: - return self.qIcons[iconKey] + if iconKey in self._qIcons: + return self._qIcons[iconKey] else: qIcon = self._loadIcon(iconKey) - self.qIcons[iconKey] = qIcon + self._qIcons[iconKey] = qIcon return qIcon def getPixmap(self, iconKey, iconSize): @@ -758,89 +649,87 @@ class GuiIcons: def listThemes(self): """Scan the icons themes folder and list all themes. """ - if self.themeList: - return self.themeList + if self._themeList: + return self._themeList confParser = NWConfigParser() - for themeDir in os.listdir(self.mainConf.iconPath): - themePath = os.path.join(self.mainConf.iconPath, themeDir) - if not os.path.isdir(themePath) or themeDir == self.fbackName: + for themeDir in os.listdir(self._iconPath): + themePath = os.path.join(self._iconPath, themeDir) + if not os.path.isdir(themePath): continue - themeConf = os.path.join(themePath, self.confName) + logger.verbose("Checking icon theme config for '%s'", themeDir) - try: - with open(themeConf, mode="r", encoding="utf-8") as inFile: - confParser.read_file(inFile) - except Exception as e: - self.theParent.makeAlert([ - self.tr("Could not load theme config file."), str(e) - ], nwAlert.ERROR) - continue - themeName = "" - if confParser.has_section("Main"): - if confParser.has_option("Main", "name"): - themeName = confParser.get("Main", "name") - logger.verbose("Theme name is '%s'", themeName) - if themeName != "": - self.themeList.append((themeDir, themeName)) + themeConf = os.path.join(themePath, self._confName) + themeName = _loadInternalName(confParser, themeConf) + if themeName: + self._themeList.append((themeDir, themeName)) - self.themeList = sorted(self.themeList, key=lambda x: x[1]) + self._themeList = sorted(self._themeList, key=lambda x: x[1]) - return self.themeList + return self._themeList ## # Internal Functions ## - def _loadIcon(self, iconKey): - """Load an icon from the assets or themes folder, with a - preference for dark/light icons depending on theme type, if such - an icon exists. Prefer svg files over png files. Always returns - a QIcon. + def _getThemePath(self): + """Get a valid theme path. Returns None if it fails. """ - if iconKey not in self.ICON_MAP: + themePath = os.path.join(self.mainConf.assetPath, "icons", self.mainConf.guiIcons) + if not os.path.isdir(themePath): + logger.warning( + "Icon theme '%s' not found, resetting to default", self.mainConf.guiIcons + ) + self.mainConf.setDefaultIconTheme() + + themePath = os.path.join(self.mainConf.assetPath, "icons", self.mainConf.guiIcons) + if not os.path.isdir(themePath): + logger.error("Default icon theme not found") + return None + + return themePath + + def _loadIcon(self, iconKey): + """Load an icon from the assets themes folder. Is guaranteed to + return a QIcon. + """ + if iconKey not in self.ICON_KEYS: logger.error("Requested unknown icon name '%s'", iconKey) return QIcon() - # If we just want the app icon, return it right away + # If we just want the app icons, return right away if iconKey == "novelwriter": - return QIcon(os.path.join(self.mainConf.iconPath, "novelwriter.svg")) + return QIcon(os.path.join(self._iconPath, "novelwriter.svg")) + elif iconKey == "proj_nwx": + return QIcon(os.path.join(self._iconPath, "x-novelwriter-project.svg")) - # Otherwise, we start looking for it - # First in the theme folder - if iconKey in self.themeMap: - relPath = os.path.relpath(self.themeMap[iconKey], self.mainConf.iconPath) + # Otherwise, we load from the theme folder + if iconKey in self._themeMap: + relPath = os.path.relpath(self._themeMap[iconKey], self._iconPath) logger.verbose("Loading: %s", relPath) - return QIcon(self.themeMap[iconKey]) + return QIcon(self._themeMap[iconKey]) - # Next, we try to load the Qt style icons - if self.ICON_MAP[iconKey][0] is not None: - logger.verbose("Loading icon '%s' from Qt QStyle.standardIcon", iconKey) - return qApp.style().standardIcon(self.ICON_MAP[iconKey][0]) - - # If we're still here, try to set from system theme - if self.ICON_MAP[iconKey][1] is not None: - logger.verbose("Loading icon '%s' from system theme", iconKey) - if QIcon().hasThemeIcon(self.ICON_MAP[iconKey][1]): - return QIcon().fromTheme(self.ICON_MAP[iconKey][1]) - - # Finally. we check if we have a fallback icon - if self.mainConf.guiDark: - fbackIcon = os.path.join( - self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey - ) - if os.path.isfile(fbackIcon): - logger.verbose("Loading icon '%s' from fallback theme (dark mode)", iconKey) - return QIcon(fbackIcon) - - fbackIcon = os.path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey) - if os.path.isfile(fbackIcon): - logger.verbose("Loading icon '%s' from fallback theme (light mode)", iconKey) - return QIcon(fbackIcon) - - # Give up and return an empty icon + # If we didn't find one, give up and return an empty icon logger.warning("Did not load an icon for '%s'", iconKey) return QIcon() # END Class GuiIcons + + +# =============================================================================================== # +# Module Functions +# =============================================================================================== # + +def _loadInternalName(confParser, confFile): + """Open a conf file and read the 'name' setting. + """ + try: + with open(confFile, mode="r", encoding="utf-8") as inFile: + confParser.read_file(inFile) + except Exception: + logger.error("Could not load file: %s", confFile) + novelwriter.logException() + return "" + + return confParser.rdStr("Main", "name", "") diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index a2f30297..1b32718f 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -83,7 +83,7 @@ class GuiMain(QMainWindow): # ============ # Core Classes and Settings - self.theTheme = GuiTheme(self) + self.theTheme = GuiTheme() self.theProject = NWProject(self) self.theIndex = NWIndex(self.theProject) self.hasProject = False diff --git a/setup/debian/copyright b/setup/debian/copyright index 5d7e2a98..a60ea0d4 100644 --- a/setup/debian/copyright +++ b/setup/debian/copyright @@ -19,12 +19,6 @@ License: GPL-3.0-or-later You should have received a copy of the GNU General Public License along with this program. If not, see . -Files: novelwriter/assets/fonts/Cantarell/* -Copyright: 2009-2010, Understanding Limited -License: OFL-1.1 - This Font Software is licensed under the SIL Open Font License, Version 1.1. - This license is available with a FAQ at: http://scripts.sil.org/OFL - Files: novelwriter/assets/icons/typicons_*.svg Copyright: 2019, Stephen Hutchings License: CC-BY-SA-4.0 diff --git a/tests/reference/baseConfig_novelwriter.conf b/tests/reference/baseConfig_novelwriter.conf index 2b966644..8859e538 100644 --- a/tests/reference/baseConfig_novelwriter.conf +++ b/tests/reference/baseConfig_novelwriter.conf @@ -1,9 +1,8 @@ [Main] -timestamp = 2021-09-10 00:23:50 +timestamp = 2021-09-15 14:39:52 theme = default syntax = default_light icons = typicons_light -guidark = False guifont = guifontsize = 11 lastnotes = 0x0 diff --git a/tests/reference/guiPreferences_novelwriter.conf b/tests/reference/guiPreferences_novelwriter.conf index e498b229..f6c342ea 100644 --- a/tests/reference/guiPreferences_novelwriter.conf +++ b/tests/reference/guiPreferences_novelwriter.conf @@ -1,9 +1,8 @@ [Main] -timestamp = 2021-09-10 00:23:52 +timestamp = 2021-09-15 14:29:30 theme = default syntax = default_light icons = typicons_light -guidark = True guifont = Sans guifontsize = 12 lastnotes = 0x0 diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index 087cd5c1..25527513 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -29,12 +29,13 @@ from datetime import datetime from mock import causeOSError from tools import writeFile +from novelwriter.guimain import GuiMain from novelwriter.common import ( checkString, checkInt, checkBool, checkHandle, isHandle, isTitleTag, isItemClass, isItemType, isItemLayout, hexToInt, formatInt, formatTimeStamp, formatTime, parseTimeStamp, splitVersionNumber, - transferCase, fuzzyTime, numberToRoman, jsonEncode, makeFileNameSafe, - sha256sum, NWConfigParser + transferCase, fuzzyTime, numberToRoman, jsonEncode, readTextFile, + makeFileNameSafe, sha256sum, getGuiItem, NWConfigParser ) @@ -456,6 +457,24 @@ def testBaseCommon_JsonEncode(): # END Test testBaseCommon_JsonEncode +@pytest.mark.base +def testBaseCommon_ReadTextFile(monkeypatch, fncDir, ipsumText): + """Test the readTextFile function. + """ + testText = "\n\n".join(ipsumText) + "\n" + testFile = os.path.join(fncDir, "ipsum.txt") + writeFile(testFile, testText) + + assert readTextFile(os.path.join(fncDir, "not_a_file.txt")) == "" + assert readTextFile(testFile) == testText + + with monkeypatch.context() as mp: + mp.setattr("builtins.open", causeOSError) + assert readTextFile(testFile) == "" + +# END Test testBaseCommon_ReadTextFile + + @pytest.mark.base def testBaseCommon_MakeFileNameSafe(): """Test the makeFileNameSafe function. @@ -508,6 +527,16 @@ def testBaseCommon_Sha256Sum(monkeypatch, fncDir, ipsumText): # END Test testBaseCommon_Sha256Sum +@pytest.mark.base +def testBaseCommon_GetGuiItem(nwGUI): + """Check the GUI item function. + """ + assert getGuiItem("gibberish") is None + assert isinstance(getGuiItem("GuiMain"), GuiMain) + +# END Test testBaseCommon_GetGuiItem + + @pytest.mark.base def testBaseCommon_NWConfigParser(fncDir): """Test the NWConfigParser subclass. diff --git a/tests/test_base/test_base_config.py b/tests/test_base/test_base_config.py index 996d11c5..ae9301bb 100644 --- a/tests/test_base/test_base_config.py +++ b/tests/test_base/test_base_config.py @@ -139,7 +139,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir): assert os.path.isfile(confFile) copyfile(confFile, testFile) - assert cmpFiles(testFile, compFile, [2, 9, 10]) + assert cmpFiles(testFile, compFile, ignoreStart=("timestamp", "lastnotes", "guilang")) # Load and save with OSError with monkeypatch.context() as mp: @@ -255,7 +255,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir): assert theList == [("en_GB", "British English"), ("fr", "Français")] copyfile(confFile, testFile) - assert cmpFiles(testFile, compFile, [2, 9, 10]) + assert cmpFiles(testFile, compFile, ignoreStart=("timestamp", "lastnotes", "guilang")) # END Test testBaseConfig_Init @@ -539,7 +539,7 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir): assert tmpConf.confChanged is False copyfile(confFile, testFile) - assert cmpFiles(testFile, compFile, [2, 9, 10]) + assert cmpFiles(testFile, compFile, ignoreStart=("timestamp", "lastnotes", "guilang")) # END Test testBaseConfig_SettersGetters diff --git a/tests/test_dialogs/test_dlg_preferences.py b/tests/test_dialogs/test_dlg_preferences.py index 4b3cf847..52d2448a 100644 --- a/tests/test_dialogs/test_dlg_preferences.py +++ b/tests/test_dialogs/test_dlg_preferences.py @@ -84,11 +84,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): tabGeneral = nwPrefs.tabGeneral nwPrefs._tabBox.setCurrentWidget(tabGeneral) - qtbot.wait(keyDelay) - assert not tabGeneral.guiDark.isChecked() - qtbot.mouseClick(tabGeneral.guiDark, Qt.LeftButton) - assert tabGeneral.guiDark.isChecked() - qtbot.wait(keyDelay) assert tabGeneral.showFullPath.isChecked() qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton) @@ -249,8 +244,12 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf") compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf") copyfile(projFile, testFile) - ignoreLines = [2, 7, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 32, 33] - assert cmpFiles(testFile, compFile, ignoreLines) + ignTuple = ( + "timestamp", "guifont", "lastnotes", "guilang", "geometry", + "preferences", "treecols", "novelcols", "projcols", "mainpane", + "docpane", "viewpane", "outlinepane", "textfont", "textsize" + ) + assert cmpFiles(testFile, compFile, ignoreStart=ignTuple) # Clean up novelwriter.CONFIG = origConf diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py index 150b3af6..b35ffa36 100644 --- a/tests/test_gui/test_gui_theme.py +++ b/tests/test_gui/test_gui_theme.py @@ -23,7 +23,7 @@ import pytest import novelwriter from PyQt5.QtGui import QColor, QPixmap, QIcon -from PyQt5.QtWidgets import QStyle, QMessageBox +from PyQt5.QtWidgets import QMessageBox keyDelay = 2 typeDelay = 1 @@ -50,7 +50,6 @@ def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir): novelwriter.CONFIG.guiTheme = "default_dark" novelwriter.CONFIG.guiSyntax = "tomorrow_night_eighties" novelwriter.CONFIG.guiIcons = "typicons_colour_dark" - novelwriter.CONFIG.guiDark = True novelwriter.CONFIG.guiFont = "Cantarell" novelwriter.CONFIG.guiFontSize = 11 novelwriter.CONFIG.confChanged = True @@ -73,9 +72,8 @@ def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir): assert novelwriter.CONFIG.guiTheme == "default_dark" assert novelwriter.CONFIG.guiSyntax == "tomorrow_night_eighties" assert novelwriter.CONFIG.guiIcons == "typicons_dark" - assert novelwriter.CONFIG.guiDark is True - assert novelwriter.CONFIG.guiFont == "Cantarell" - assert novelwriter.CONFIG.guiFontSize == 11 + assert novelwriter.CONFIG.guiFont != "" + assert novelwriter.CONFIG.guiFontSize > 0 # Check GUI Colours thePalette = nwGUI.palette() @@ -119,9 +117,8 @@ def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir): # Test Icon class theIcons = nwGUI.theTheme.theIcons novelwriter.CONFIG.guiIcons = "invalid" - assert not theIcons.updateTheme() - novelwriter.CONFIG.guiIcons = "typicons_dark" - assert theIcons.updateTheme() + assert theIcons.updateTheme() is True + assert novelwriter.CONFIG.guiIcons == "typicons_light" # Ask for a non-existent key anImg = theIcons.loadDecoration("nonsense", 20, 20) @@ -168,17 +165,8 @@ def testGuiTheme_Main(qtbot, monkeypatch, nwMinimal, tmpDir): assert isinstance(anIcon, QIcon) assert not anIcon.isNull() - # Add test icons and test alternative load paths - theIcons.ICON_MAP["testicon1"] = (QStyle.SP_DriveHDIcon, None) - anIcon = theIcons.getIcon("testicon1") - assert isinstance(anIcon, QIcon) - assert not anIcon.isNull() - - theIcons.ICON_MAP["testicon2"] = (None, "folder") - anIcon = theIcons.getIcon("testicon2") - assert isinstance(anIcon, QIcon) - - theIcons.ICON_MAP["testicon3"] = (None, None) + # Check return empty icon if file not found + theIcons.ICON_KEYS.add("testicon3") anIcon = theIcons.getIcon("testicon3") assert isinstance(anIcon, QIcon) assert anIcon.isNull() diff --git a/tests/tools.py b/tests/tools.py index 03f23d34..450c4fed 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -25,7 +25,7 @@ import shutil from PyQt5.QtWidgets import qApp -def cmpFiles(fileOne, fileTwo, ignoreLines=None): +def cmpFiles(fileOne, fileTwo, ignoreLines=None, ignoreStart=None): """Compare two files, but optionally ignore lines given by a list. """ if ignoreLines is None: @@ -59,6 +59,11 @@ def cmpFiles(fileOne, fileTwo, ignoreLines=None): print("Ignoring line %d" % (n+1)) continue + if ignoreStart is not None: + if lnOne.startswith(ignoreStart): + print("Ignoring line %d" % (n+1)) + continue + if lnOne != lnTwo: print("Diff on line %d:" % (n+1)) print(" << '%s'" % lnOne)