diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3a0e73..2f04b21a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,56 @@ # novelWriter Changelog +## Version 1.3 Beta 1 [2021-03-28] + +### Release Notes + +This is a pre-release of 1.3. The primary feature of release 1.3 is the addition of +internationalisation (i18n) of novelWriter. The release introduces support for Portuguese, French, +and Norwegian in addition to the default English. + +This is a beta release. Use with caution on live project. + +### Detailed Changelog + +**Internationalisation** + +* Added support to the source code for internationalisation of the GUI. Thanks to Bruno Meneguello + (@bkmeneguello) for doing most of the work. Issue #93. PRs #673, #680 and #684. +* Build Novel Project localisation has been added as well. This is separate from the GUI + localisation as the project may not be written in the same language as the GUI is set to. PRs + #676 and #682. +* The text editor's auto-replace features now support inserting spaces automatically when replacing + quotes, as well as in front of major punctuation. These features are common for writing tools + supporting French and Spanish for instance. Issue #703. PR #704. + +**User Interface** + +* The Preferences dialog has been updated to be more responsive to varying text label lengths due + to different needs for different languages. PRs #687 and #711. +* The Project Settings dialog has been improved to be more consistent and user friendly across the + Status, Importance and Auto-Replace tabs. Issue #691. PR #695. +* The About dialog has been updated to contain more information on contributions. PR #698. + +**Translations** + +* Portuguese translation added by Bruno Meneguello (@bkmeneguello). PRs #673, #681, #686 and #697. +* Norwegian translation added by Veronica Olsen (@vkbo). PR #679. +* German translation added (Build tool only) by Marian Lückhof (@Number042). PR #683. +* French translation added by Jan Lüdke (@jyhelle). PRs #692, #711 and #713. +* American English added by Veronica Olsen (@vkbo). PR #693. + +**Installation** + +* Added i18n support to the setup script. PRs #673 and #729. + +**Code Maintenance** + +* The ISO lookup dictionary for language codes has been removed and replaced with the lookup + features available in Qt5 through QLocal. The remaining two source files in the constants folder + have been moved up a level as well. PRs #673 and #730. + +---- + ## Version 1.2.2 [2021-03-28] ### Release Notes diff --git a/README.md b/README.md index ca06da60..0a2cf90b 100644 --- a/README.md +++ b/README.md @@ -25,14 +25,13 @@ The plain text files are suitable for version control software, and also well su synchronisation tools. The core project structure is stored in a single project XML file. Other meta data is primarily saved in JSON files. -The full documentation is available at -[novelwriter.readthedocs.io](https://novelwriter.readthedocs.io). +The full documentation is available on [readthedocs.io](https://novelwriter.readthedocs.io). ## Implementation The application is written in Python 3 using Qt5 via PyQt5. It is developed on Linux, but it should -in principle work fine on other operating systems as well, as long as dependencies are met. The -unit tests are run on the latest versions of Ubuntu Linux, Windows Server and macOS. +in principle work fine on other operating systems as well, as long as dependencies are met. It is +regularly tested on Ubuntu Linux, Windows, and macOS. ## Project Contributions @@ -40,9 +39,9 @@ Contributions to this project are welcome. However, please read the [Contributing Guide](https://github.com/vkbo/novelWriter/blob/main/CONTRIBUTING.md) before submitting larger additions or changes to this project. -# Key Features +## Key Features -Some features of novelWriter are listed below. Consult the +Some key features of novelWriter are listed below. Consult the [documentation](https://novelwriter.readthedocs.io) for more information. ### Markdown Flavour @@ -113,99 +112,83 @@ These have their separate root folders. These are optional files. ### Visualisation of Story Elements -The different notes can be assigned tags, which other files can refer back to using the `@` meta -keywords. This information can be used to display an outline of the story, showing where each scene -connects to the plot, and which characters, etc. occur in them. In addition, the tags themselves -are clickable in the document view pane, and control-clickable in the editor. They make it possible -to quickly navigate between the documents while editing. +The different notes can be assigned tags, which other files can refer back to using `@`-prefixed +meta keywords. This information can be used to display an outline of the story, showing where each +scene connects to the plot, and which characters, etc. occur in them. In addition, the tags +themselves are clickable in the document view pane, and control-clickable in the editor. They make +it possible to quickly navigate between the documents while editing. -# Installing and Running +## Standard Installation -For install instructions, please check the -[Getting Started](https://novelwriter.readthedocs.io/en/latest/int_started.html) section in -the [documentation](https://novelwriter.readthedocs.io/). +For a regular installation, it is recommended that you download one of the minimal zip files from +the [Releases](https://github.com/vkbo/novelWriter/releases) page or the +[novelwriter.io](https://novelwriter.io/) website. +The [documentation](https://novelwriter.readthedocs.io/) has detailed install instructions for +[Linux](https://novelwriter.readthedocs.io/en/latest/setup_linux.html), +[Windows](https://novelwriter.readthedocs.io/en/latest/setup_windows.html), and +[macOS](https://novelwriter.readthedocs.io/en/latest/setup_mac.html). +They are pretty straightforward. -## TLDR Instructions +## Running from Source If you want to run novelWriter directly from the source code, you must run the `novelWriter.py` -file from command line. For installations on Linux, macOS or Windows, see below. +file from command line. **Note:** You may need to replace `python` with `python3` and `pip` with `pip3` in the instructions below on some systems. You may also want to add the `--user` flag for `pip` to install in your user space only. -### Install from PyPi +### Dependencies -novelWriter is available on [pypi.org](https://pypi.org/project/novelWriter/), and can be installed -with: -```bash -pip install novelwriter -``` -Dependencies should be installed automatically, but can also be installed directly with: +Dependencies can be installed from PyPi with: ```bash pip install pyqt5 lxml pyenchant ``` -When installing via pip, novelWriter can be launched from command line with: + +### Additional Steps for Linux + +On Linux, you can most likely find the dependencies in your distribution's repository. On Ubuntu +and Debian, run: ```bash -novelWriter +sudo apt install python3-pyqt5 python3-lxml python3-enchant ``` -Make sure the install location for pip is in your PATH variable. This is not always the case by -default. - -### Setup on Linux - -If you're installing from source, the following commands will set up novelWriter on Linux: +If you want to set up a launcher on Linux, you can run: ```bash -pip install -r requirements.txt -python setup.py install python setup.py xdg-install ``` -This should make novelWriter available as a regular application on your system, with a launceher -icon, and file association with novelWriter project files. +### Additional Steps for macOS -**Note:** If you don't want to install the dependencies from pip and instead use your distro's own -packages, you must manually install `python3-pyqt5`, `python3-lxml` and `python3-enchant` -(Debian/Ubuntu), or the corresponding packages for your distro. - -### Setup on macOS - -If you're installing from source, the following commands will set up novelWriter on macOS: +First, make sure you have properly set up Python3 with Homebrew. If not, check their +[documentation](https://docs.brew.sh/Homebrew-and-Python). +In addition, the following steps are necessary to install all dependencies: ```bash brew install enchant pip3 install --user -r requirements.txt pip3 install --user pyobjc -python3 setup.py install ``` -At present, novelWriter isn't further integrated into the OS, so you must launch it from command -line with: -```bash -novelWriter -``` +### Additional Steps for Windows -If you want to help improve the setup process on macOS, it would be much appreciated. +Windows doesn't by default come with Python installed. If you haven't installed it already, get it +from [python.org/downloads](https://www.python.org/downloads/). Remember to select "Add Python to +PATH" during the installation. -### Setup on Windows +## Internationalisation -For Windows, first ensure that you have Python installed. If not, get it from -[python.org/downloads](https://www.python.org/downloads/). Remember to select "Add Python to PATH" -during the installation, otherwise novelWriter will not start. - -Then, download the `novelWriter-x.y.z-minimal-win.zip` file, where `x.y.z` is the version number, -from the [releases](https://github.com/vkbo/novelWriter/releases) page. You can extract it to -wherever you want to keep novelWriter on your PC, and run the `setup_windows.bat` file in it -(double-clicking it should work). This will install the necessary dependencies from -[pypi.org](https://pypi.org/) and create desktop and start menu icons. +If you install from source, you must build the translation files yourself if you want to switch to +a different GUI language than British English. This requires that you have the Qt translation +framework installed. Check the specific instruction in the README in the `i18n` source folder for +how to build the translation files. ## Debugging -If you need to debug novelWriter, you must run it from command line. It takes a few parameters, +If you need to debug novelWriter, you must run it from the command line. It takes a few parameters, which can be listed with the switch `--help`. The `--info`, `--debug` or `--verbose` flags are particularly useful for increasing logging output for debugging. -# Licenses +## Licenses This is Open Source software, and novelWriter is licensed under GPLv3. See the [GNU General Public License website](https://www.gnu.org/licenses/gpl-3.0.en.html) for more @@ -231,7 +214,7 @@ Bundled assets have the following licenses: the main repo is available at [sdras/night-owl-vscode-theme](https://github.com/sdras/night-owl-vscode-theme). -# Screenshot +## Screenshot **novelWriter with default system theme:** ![Screenshot 1](https://raw.githubusercontent.com/vkbo/novelWriter/main/docs/source/images/screenshot_default.png) diff --git a/docs/source/int_started.rst b/docs/source/int_started.rst index 385f99fc..bcf6195d 100644 --- a/docs/source/int_started.rst +++ b/docs/source/int_started.rst @@ -99,6 +99,30 @@ Make sure the install location for pip is in your PATH variable. This is not alw default. +.. _a_started_i18n: + +Building the Translation Files +============================== + +If you installed novelWriter from a package, the translation files should be pre-built and +included. If you're running novelWriter from the source code, you will need to generate the files +yourself. The files you need will be written to the ``i18n`` folder, and will have the ``.qm`` file +extension. + +You can build the ``.qm`` files with: + +.. code-block:: console + + python3 setup.py qtlrelease + +This requires that the Python package ``pylupdate5`` to be installed. + +.. note:: + If you want to improve novelWriter with translation files for another language, or update an + existing translation, instructions for how to contribute can be found in the README file in the + ``i18n`` folder of the source code. + + .. _a_started_docs: Building the Documentation diff --git a/i18n/nw_en_US.ts b/i18n/nw_en_US.ts index ffc2d6a5..781732b3 100644 --- a/i18n/nw_en_US.ts +++ b/i18n/nw_en_US.ts @@ -798,22 +798,22 @@ GuiDocEditFooter - + Status - + Line: {0} ({1}) - + Words: {0} ({1}) - + Document size is {0} bytes @@ -821,22 +821,22 @@ GuiDocEditHeader - + Edit document meta - + Search document - + Toggle Focus Mode - + Close the document @@ -1379,7 +1379,7 @@ - + Changes are saved automatically. @@ -1419,102 +1419,102 @@ - + Text files ({0}) - + Markdown files ({0}) - + novelWriter files ({0}) - + All files ({0}) - + Import File - + Could not read file. The file must be an existing text file. - + Please open a document to import the text file into. - + Import Document - + Importing the file will overwrite the current content of the document. Do you want to proceed? - + Indexing: '{0}' - + Unknown item - + Indexing completed in {0} ms - + The project index has been successfully rebuilt. - + Information - + Warning - + Error - + This is a bug! - + Internal Error - + Exit - + Do you want to exit novelWriter? diff --git a/i18n/nw_fr.ts b/i18n/nw_fr.ts index ade25b13..2a173460 100644 --- a/i18n/nw_fr.ts +++ b/i18n/nw_fr.ts @@ -798,22 +798,22 @@ GuiDocEditFooter - + Status État - + Line: {0} ({1}) Ligne: {0} ({1}) - + Words: {0} ({1}) Mots: {0} ({1}) - + Document size is {0} bytes La taille du document est de {0} octets @@ -821,22 +821,22 @@ GuiDocEditHeader - + Edit document meta Modifier les métadonnées du document - + Search document Chercher dans le document - + Toggle Focus Mode Basculer le mode focus - + Close the document Fermer le document @@ -1379,7 +1379,7 @@ Fermer le projet en cours ? - + Changes are saved automatically. Les changements sont enregistrés automatiquement. @@ -1419,102 +1419,102 @@ L'index du projet est périmé ou endommagé. Reconstruction de l'index en cours. - + Text files ({0}) Fichiers de texte ({0}) - + Markdown files ({0}) Fichiers Markdown ({0}) - + novelWriter files ({0}) fichiers novelWriter ({0}) - + All files ({0}) Tous les filchiers ({0}) - + Import File Importer un fichier - + Could not read file. The file must be an existing text file. Lecture du fichier impossible. Il faut un fichier texte existant. - + Please open a document to import the text file into. Veuillez ouvrir un document dans lequel sera importé le texte. - + Import Document Importer un document - + Importing the file will overwrite the current content of the document. Do you want to proceed? Le contenu du fichier importé va remplacer le contenu actuel du document. Faut-il continuer ? - + Indexing: '{0}' Indexation d e: '{0}' - + Unknown item Item inconnu - + Indexing completed in {0} ms Indexation effectuée en {0} ms - + The project index has been successfully rebuilt. L'index du projet a été correctement reconstruit. - + Information Information - + Warning Avertissement - + Error Erreur - + This is a bug! Ceci est un bug ! - + Internal Error Erreur interne - + Exit Sortir - + Do you want to exit novelWriter? Voulez-vous sortir de novelWriter ? diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index 390da818..edaa254c 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -1,5 +1,6 @@ - + + Common @@ -798,22 +799,22 @@ GuiDocEditFooter - + Status Status - + Line: {0} ({1}) Linje: {0} ({1}) - + Words: {0} ({1}) Ord: {0} ({1}) - + Document size is {0} bytes Dokumentet er {0} byte @@ -821,22 +822,22 @@ GuiDocEditHeader - + Edit document meta Rediger dokumentinstillinger - + Search document Søk i dokumentet - + Toggle Focus Mode Slå av/på "Fokus-modus" - + Close the document Lukk dokumentet @@ -1321,7 +1322,7 @@ Novel - Innhold + Roman @@ -1346,7 +1347,7 @@ Outline - Disposisjon + Oversikt @@ -1374,7 +1375,7 @@ Ønsker du å lukke dette prosjektet? - + Changes are saved automatically. Endringer lagres automatisk. @@ -1414,102 +1415,102 @@ Prosjektets indeks er utdatert eller skadet. Bygger indeksen på nytt. - + Text files ({0}) Tekstfiler ({0}) - + Markdown files ({0}) Markdown-filer ({0}) - + novelWriter files ({0}) novelWriter-filer ({0}) - + All files ({0}) Alle filer ({0}) - + Import File Importer fil - + Could not read file. The file must be an existing text file. Kunne ikke lese filen. Filen må eksistere fra før av. - + Please open a document to import the text file into. Vennligst åpne et dokument hvor teksten i filen kan importeres. - + Import Document Importer dokument - + Importing the file will overwrite the current content of the document. Do you want to proceed? Å importere filen vil overskrive all eksisterende tekst i dokumentet. Ønsker du å fortsette? - + Indexing: '{0}' Indekserer: '{0}' - + Unknown item Ukjent enhet - + Indexing completed in {0} ms Indekseringen tok {0} ms - + The project index has been successfully rebuilt. Prosjektets indeks har blitt bygget på nytt. - + Information Informasjon - + Warning Advarsel - + Error Feil - + This is a bug! Dette er en systemfeil! - + Internal Error Intern feil - + Exit Avslutt - + Do you want to exit novelWriter? Ønsker du å avslutte novelWriter? @@ -1934,7 +1935,7 @@ Focus Outline - Gå til disposisjon + Gå til oversikt diff --git a/i18n/nw_pt.ts b/i18n/nw_pt.ts index 268c0853..110abae7 100644 --- a/i18n/nw_pt.ts +++ b/i18n/nw_pt.ts @@ -798,22 +798,22 @@ GuiDocEditFooter - + Line: {0} ({1}) Linha: {0} ({1}) - + Words: {0} ({1}) Palavras: {0} ({1}) - + Status Estado - + Document size is {0} bytes O tamanho do documento é {0} bytes @@ -821,22 +821,22 @@ GuiDocEditHeader - + Edit document meta Editar os meta-dados do documento - + Search document Procurar no documento - + Toggle Focus Mode Alternar o "Modo Foco" - + Close the document Fechar o documento @@ -1329,32 +1329,32 @@ Nota: Se o programa ou o computador sofreu uma falha anteriormente, o bloqueio pode ser sobrescrito com segurança. Se, no entanto, outra instância do novelWriter esteja com o projeto aberto, sobrescrever o bloqueio pode corromper o projeto e não é recomendado. - + Unknown item Item desconhecido - + Information Informação - + Warning Alerta - + Error Erro - + This is a bug! Isto é um bug! - + Internal Error Erro Interno @@ -1389,7 +1389,7 @@ Fechar o projeto atual? - + Changes are saved automatically. As alterações serão salvas automaticamente. @@ -1409,47 +1409,47 @@ Projeto Bloqueado - + Import File Importar Arquivo - + Could not read file. The file must be an existing text file. Não foi possível ler o arquivo. O arquivo deve ser um arquivo de texto existente. - + Please open a document to import the text file into. Por favor, abra um documento para importar o text nele. - + Import Document Importar Documento - + Importing the file will overwrite the current content of the document. Do you want to proceed? Importar o arquivo vai sobrescrever o conteúdo atual do documento. Você deseja continuar? - + The project index has been successfully rebuilt. O índice do projeto foi reconstruído com sucesso. - + Exit Sair - + Do you want to exit novelWriter? Você deseja realmente sair do novelWriter? - + Indexing completed in {0} ms Indexação completa em {0} ms @@ -1489,27 +1489,27 @@ O projeto foi bloqueado pelo computador '{0}' ({1} {2}), ativo pela última vez em {3}. - + Indexing: '{0}' Indexando: '{0}' - + Text files ({0}) Arquivos de texto ({0}) - + Markdown files ({0}) Arquivos Markdown ({0}) - + novelWriter files ({0}) Arquivos do novelWriter ({0}) - + All files ({0}) Todos os arquivos ({0}) diff --git a/nw/assets/text/release_notes.htm b/nw/assets/text/release_notes.htm index 864521b1..aad94e41 100644 --- a/nw/assets/text/release_notes.htm +++ b/nw/assets/text/release_notes.htm @@ -2,103 +2,14 @@ - -

Release Notes for 1.2.2

+

Release Notes for 1.3 Beta 1

Released on 28 March 2021

-

This patch release is a bug fix release addressing some inconsistencies and issues with the -document header buttons when Focus Mode is active. The keyboard shortcuts for search and replace -should now also work in Focus Mode. In addition, the setup script for novelWriter has been improved -when installing on Windows.

+

This is a pre-release of 1.3. The primary feature of release 1.3 is the addition of +internationalisation (i18n) of novelWriter. The release introduces support for Portuguese, French, +and Norwegian in addition to the default English.

+

This is a beta release. Use with caution on live project.

See also the Releases page.

-
- -

Release Notes for 1.2.1

-

Released on 21 March 2021

-

This patch release is a bug fix release addressing issues with the document editor's search and -replace tool. Due to some recently added restrictions on when various tools are active, depending -on which part of the main window has the user's focus, the search tool keyboard shortcuts and -buttons were blocked when they shouldn't. This release resolves these issues.

- -
- -

Release Notes for 1.2

-

Released on 14 March 2021

-

This release is mainly focused on the Build Novel Project tool. Completely new export classes -have been written to support Open Document and Markdown exports. In addition, the way document -layouts are handled have been automated a little to assist the user in keeping header levels and -document layout flags in sync. The third new additoion is the ability to record and log idle time -during a writing session to improve the writing statistics information as requested by several -users. Finally, it is now possible to directly edit the project dictionary via a new, simple GUI -dialog.

- -

The Build Novel Project Tool

-

The main changes for this release are to the Build Novel Project tool. The Open Document export, -as well as the Markdown export, is now handled entirely by code written for novelWriter. -Previously, these export features depended on the underlying Qt library's save routines connected -to the preview document shown in the build dialog. Using this method of export both meant that the -content of the document was dependent on the preview being generated first, and it also meant that -the exported document had limited support for novelWriter-specific features and custom formatting. -The new export class should generate a much better result, especially for the Open Document -formats. The Open Document standard is supported by Open Office, Libre Office, Google Docs, -Microsoft Word, and probably a number of other applications too. The Markdown export hasn't changed -a lot, but should be a slight improvement on the previous export feature.

-

These changes to the build tool also imply that the saving process is now independent of the -content of the preview window, meaning you don't have to rebuild the preview before saving, which -was previously the case. To make this more consistent, the PDF export option has been moved to the -print button as it is actually a print-to-file feature under the hood, not technically a proper PDF -export format. It is exactly the same as printing to file from the print preview dialog.

-

In addition to the changes to the export features, the Build Novel Project tool now also has -controls for line height, which applies to all rich text export formats, and the option to replace -unicode characters with appropriate html entities for html export.

- -

Document Layout Automation

-

Among other changes in this release are a few improvements to the process of creating and -changing documents. When a new document is first created, the header is generated from the assigned -label and layout.

-

In addition, for some document layouts, when the user changes the header level of the first -header of the document, the document layout setting is updated accordingly. This should reduce the -need for the user to maintain two ways of assigning the role of a given document. This automation -only applies to combinations of header level and current document layouts where there is no -ambiguity. For instance, changing the header level in a "Scene" document from level 3 to 2 changes -the document layout automatically to "Chapter". But changing the first header of a "Book" layout -document from 1 to 2 does not change the document's layout as the "Book" layout is a generic -document layout and it's perfectly reasonable for its first header to be a chapter header.

-

Keep in mind that novelWriter treats documents with layout "Book", "Chapter" and "Scene" exactly -the same during exports. The distinction is only meant as a way to indicate the purpose of a -document in the project tree. This new automation is meant to assist in keeping this information up -to date. The other layouts do have an effect on formatting during export, and are generally left -alone.

- -

The Session Timer and Idle Time

-

Another change that has been requested by a couple of users is to have the session timer in the -status bar stop counting when the user is inactive (idle). This feature is optional, and can be -controlled from Preferences. The definition of "idle" in this context is either that the user is -active in a different application than novelWriter (loss of focus) or that the user has not made -any changes to the current document for a given amount of time. The time threshold is by default -five minutes, but can be altered in Preferences.

-

In addition, the idle time is also recorded in the session log, and can be viewed in the Writing -Statistics dialog and exported with the rest of the information. The idle time is recorder in the -logs regardless of whether the status bar clock takes idle time into consideration or not. So even -if you turn off the idle time switch in Preferences, the other idle time setting still affects the -writing stats log entries.

- -

Other Changes

-

The user dictionary of the project, where words added to the dictionary from the document editor -go, can now be viewed and edited with a new "Project Word List" tool in the "Tools" menu.

-

A small additional feature added is also the ability to undo the last move of an item in the -project tree. The keyboard shortcut for this is `Ctrl+Shift+Z`, or it can be accessed from the -menu. The feature can only undo the last move, but it includes both documents moved to trash, moves -by up/down keypress or menu entries, and drag and drop moves.

-

A new keyword has been added to mark characters in the story. The new keyword is intended to tag -a character as the focus character for a chapter or scene. This is useful for stories where the -point-of-view character and the focus character are different.

-

Lastly, two bugfixes have been made as well. The Empty Trash feature was no longer working due -to an earlier fix solving another issue. The feature has now been restored. In addition, the -indexer now checks that a keyword (tag or reference) is valid before saving it to the index. -Previously, an invalid keyword could be saved to the index and potentially crash the application. -

- diff --git a/nw/assets/text/release_notes_1.2.htm b/nw/assets/text/release_notes_1.2.htm new file mode 100644 index 00000000..864521b1 --- /dev/null +++ b/nw/assets/text/release_notes_1.2.htm @@ -0,0 +1,104 @@ + + + + + +

Release Notes for 1.2.2

+

Released on 28 March 2021

+

This patch release is a bug fix release addressing some inconsistencies and issues with the +document header buttons when Focus Mode is active. The keyboard shortcuts for search and replace +should now also work in Focus Mode. In addition, the setup script for novelWriter has been improved +when installing on Windows.

+ +

See also the Releases page.

+ +
+ +

Release Notes for 1.2.1

+

Released on 21 March 2021

+

This patch release is a bug fix release addressing issues with the document editor's search and +replace tool. Due to some recently added restrictions on when various tools are active, depending +on which part of the main window has the user's focus, the search tool keyboard shortcuts and +buttons were blocked when they shouldn't. This release resolves these issues.

+ +
+ +

Release Notes for 1.2

+

Released on 14 March 2021

+

This release is mainly focused on the Build Novel Project tool. Completely new export classes +have been written to support Open Document and Markdown exports. In addition, the way document +layouts are handled have been automated a little to assist the user in keeping header levels and +document layout flags in sync. The third new additoion is the ability to record and log idle time +during a writing session to improve the writing statistics information as requested by several +users. Finally, it is now possible to directly edit the project dictionary via a new, simple GUI +dialog.

+ +

The Build Novel Project Tool

+

The main changes for this release are to the Build Novel Project tool. The Open Document export, +as well as the Markdown export, is now handled entirely by code written for novelWriter. +Previously, these export features depended on the underlying Qt library's save routines connected +to the preview document shown in the build dialog. Using this method of export both meant that the +content of the document was dependent on the preview being generated first, and it also meant that +the exported document had limited support for novelWriter-specific features and custom formatting. +The new export class should generate a much better result, especially for the Open Document +formats. The Open Document standard is supported by Open Office, Libre Office, Google Docs, +Microsoft Word, and probably a number of other applications too. The Markdown export hasn't changed +a lot, but should be a slight improvement on the previous export feature.

+

These changes to the build tool also imply that the saving process is now independent of the +content of the preview window, meaning you don't have to rebuild the preview before saving, which +was previously the case. To make this more consistent, the PDF export option has been moved to the +print button as it is actually a print-to-file feature under the hood, not technically a proper PDF +export format. It is exactly the same as printing to file from the print preview dialog.

+

In addition to the changes to the export features, the Build Novel Project tool now also has +controls for line height, which applies to all rich text export formats, and the option to replace +unicode characters with appropriate html entities for html export.

+ +

Document Layout Automation

+

Among other changes in this release are a few improvements to the process of creating and +changing documents. When a new document is first created, the header is generated from the assigned +label and layout.

+

In addition, for some document layouts, when the user changes the header level of the first +header of the document, the document layout setting is updated accordingly. This should reduce the +need for the user to maintain two ways of assigning the role of a given document. This automation +only applies to combinations of header level and current document layouts where there is no +ambiguity. For instance, changing the header level in a "Scene" document from level 3 to 2 changes +the document layout automatically to "Chapter". But changing the first header of a "Book" layout +document from 1 to 2 does not change the document's layout as the "Book" layout is a generic +document layout and it's perfectly reasonable for its first header to be a chapter header.

+

Keep in mind that novelWriter treats documents with layout "Book", "Chapter" and "Scene" exactly +the same during exports. The distinction is only meant as a way to indicate the purpose of a +document in the project tree. This new automation is meant to assist in keeping this information up +to date. The other layouts do have an effect on formatting during export, and are generally left +alone.

+ +

The Session Timer and Idle Time

+

Another change that has been requested by a couple of users is to have the session timer in the +status bar stop counting when the user is inactive (idle). This feature is optional, and can be +controlled from Preferences. The definition of "idle" in this context is either that the user is +active in a different application than novelWriter (loss of focus) or that the user has not made +any changes to the current document for a given amount of time. The time threshold is by default +five minutes, but can be altered in Preferences.

+

In addition, the idle time is also recorded in the session log, and can be viewed in the Writing +Statistics dialog and exported with the rest of the information. The idle time is recorder in the +logs regardless of whether the status bar clock takes idle time into consideration or not. So even +if you turn off the idle time switch in Preferences, the other idle time setting still affects the +writing stats log entries.

+ +

Other Changes

+

The user dictionary of the project, where words added to the dictionary from the document editor +go, can now be viewed and edited with a new "Project Word List" tool in the "Tools" menu.

+

A small additional feature added is also the ability to undo the last move of an item in the +project tree. The keyboard shortcut for this is `Ctrl+Shift+Z`, or it can be accessed from the +menu. The feature can only undo the last move, but it includes both documents moved to trash, moves +by up/down keypress or menu entries, and drag and drop moves.

+

A new keyword has been added to mark characters in the story. The new keyword is intended to tag +a character as the focus character for a chapter or scene. This is useful for stories where the +point-of-view character and the focus character are different.

+

Lastly, two bugfixes have been made as well. The Empty Trash feature was no longer working due +to an earlier fix solving another issue. The feature has now been restored. In addition, the +indexer now checks that a keyword (tag or reference) is valid before saving it to the index. +Previously, an invalid keyword could be saved to the index and potentially crash the application. +

+ + + diff --git a/nw/common.py b/nw/common.py index 1cf4e9a9..d093be2d 100644 --- a/nw/common.py +++ b/nw/common.py @@ -31,9 +31,8 @@ from datetime import datetime from PyQt5.QtWidgets import qApp from PyQt5.QtCore import QCoreApplication -from nw.constants import ( - nwConst, nwUnicode, nwItemClass, nwItemType, nwItemLayout -) +from nw.enum import nwItemClass, nwItemType, nwItemLayout +from nw.constants import nwConst, nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/config.py b/nw/config.py index 64d3b678..bea508bc 100644 --- a/nw/config.py +++ b/nw/config.py @@ -39,9 +39,9 @@ from PyQt5.QtCore import ( QTranslator ) -from nw.constants import nwConst, nwFiles, nwUnicode -from nw.common import splitVersionNumber, formatTimeStamp from nw.error import logException +from nw.common import splitVersionNumber, formatTimeStamp +from nw.constants import nwConst, nwFiles, nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/constants/constants.py b/nw/constants.py similarity index 99% rename from nw/constants/constants.py rename to nw/constants.py index a3ab3580..abf399c5 100644 --- a/nw/constants/constants.py +++ b/nw/constants.py @@ -26,9 +26,7 @@ along with this program. If not, see . from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP -from nw.constants.enum import ( - nwItemClass, nwItemLayout, nwItemType, nwOutline -) +from nw.enum import nwItemClass, nwItemLayout, nwItemType, nwOutline def trConst(tString): """Wrapper function for locally translating constants. diff --git a/nw/constants/__init__.py b/nw/constants/__init__.py deleted file mode 100644 index f0f12c60..00000000 --- a/nw/constants/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -from nw.constants.constants import ( - trConst, nwConst, nwLists, nwRegEx, nwFiles, nwKeyWords, nwLabels, - nwQuotes, nwUnicode, nwHtmlUnicode -) -from nw.constants.enum import ( - nwAlert, nwDocAction, nwItemClass, nwItemLayout, nwItemType, nwOutline, - nwDocInsert, nwWidget -) - -__all__ = [ - "trConst", - "nwConst", - "nwLists", - "nwRegEx", - "nwFiles", - "nwKeyWords", - "nwLabels", - "nwQuotes", - "nwUnicode", - "nwHtmlUnicode", - "nwAlert", - "nwDocAction", - "nwItemClass", - "nwItemLayout", - "nwItemType", - "nwOutline", - "nwDocInsert", - "nwWidget", -] diff --git a/nw/core/document.py b/nw/core/document.py index d0c3f664..1d7600c2 100644 --- a/nw/core/document.py +++ b/nw/core/document.py @@ -31,9 +31,8 @@ from functools import partial from PyQt5.QtCore import QCoreApplication -from nw.constants import nwAlert +from nw.enum import nwAlert, nwItemLayout, nwItemClass from nw.common import isHandle -from nw.constants import nwItemLayout, nwItemClass logger = logging.getLogger(__name__) diff --git a/nw/core/index.py b/nw/core/index.py index a6054071..986e4f93 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -32,12 +32,10 @@ import os from time import time -from nw.constants import ( - nwFiles, nwKeyWords, nwItemType, nwItemClass, nwItemLayout, nwAlert, - nwUnicode -) -from nw.core.document import NWDoc +from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert from nw.common import isHandle, isTitleTag, isItemClass, isItemLayout +from nw.constants import nwFiles, nwKeyWords, nwUnicode +from nw.core.document import NWDoc logger = logging.getLogger(__name__) diff --git a/nw/core/item.py b/nw/core/item.py index 62460e7e..18eada78 100644 --- a/nw/core/item.py +++ b/nw/core/item.py @@ -28,10 +28,8 @@ import logging from lxml import etree -from nw.constants import nwItemType, nwItemClass, nwItemLayout -from nw.common import ( - checkInt, isHandle, isItemClass, isItemLayout, isItemType -) +from nw.enum import nwItemType, nwItemClass, nwItemLayout +from nw.common import checkInt, isHandle, isItemClass, isItemLayout, isItemType logger = logging.getLogger(__name__) diff --git a/nw/core/project.py b/nw/core/project.py index 5f2862ac..99bd0d1a 100644 --- a/nw/core/project.py +++ b/nw/core/project.py @@ -45,9 +45,8 @@ from nw.common import ( checkString, checkBool, checkInt, isHandle, formatTimeStamp, makeFileNameSafe, hexToInt ) -from nw.constants import ( - trConst, nwFiles, nwItemType, nwItemClass, nwItemLayout, nwLabels, nwAlert -) +from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert +from nw.constants import trConst, nwFiles, nwLabels logger = logging.getLogger(__name__) diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py index 9b0e7379..412efe4f 100644 --- a/nw/core/tohtml.py +++ b/nw/core/tohtml.py @@ -27,7 +27,7 @@ along with this program. If not, see . import logging from nw.core.tokenizer import Tokenizer -from nw.constants import nwLabels, nwKeyWords, nwHtmlUnicode +from nw.constants import nwKeyWords, nwLabels, nwHtmlUnicode logger = logging.getLogger(__name__) diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index ff88a274..921f7cef 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -32,9 +32,10 @@ from functools import partial from PyQt5.QtCore import QCoreApplication, QRegularExpression -from nw.core.document import NWDoc +from nw.enum import nwItemLayout, nwItemType from nw.common import numberToRoman -from nw.constants import nwConst, nwUnicode, nwItemLayout, nwItemType, nwRegEx +from nw.constants import nwConst, nwRegEx, nwUnicode +from nw.core.document import NWDoc logger = logging.getLogger(__name__) diff --git a/nw/core/tomd.py b/nw/core/tomd.py index 3167b204..53e3ab80 100644 --- a/nw/core/tomd.py +++ b/nw/core/tomd.py @@ -26,8 +26,8 @@ along with this program. If not, see . import logging -from nw.core.tokenizer import Tokenizer from nw.constants import nwLabels +from nw.core.tokenizer import Tokenizer logger = logging.getLogger(__name__) diff --git a/nw/core/toodt.py b/nw/core/toodt.py index d1519a9d..89b74148 100644 --- a/nw/core/toodt.py +++ b/nw/core/toodt.py @@ -29,11 +29,11 @@ import logging from lxml import etree from hashlib import sha256 -from datetime import datetime from zipfile import ZipFile +from datetime import datetime +from nw.constants import nwKeyWords, nwLabels from nw.core.tokenizer import Tokenizer -from nw.constants import nwLabels, nwKeyWords logger = logging.getLogger(__name__) diff --git a/nw/core/tree.py b/nw/core/tree.py index 5fdc55ba..b0c0340c 100644 --- a/nw/core/tree.py +++ b/nw/core/tree.py @@ -29,14 +29,13 @@ import logging import os from lxml import etree -from hashlib import sha256 from time import time +from hashlib import sha256 -from nw.core.item import NWItem +from nw.enum import nwItemType, nwItemClass, nwItemLayout from nw.common import checkHandle -from nw.constants import ( - nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst, nwLists -) +from nw.constants import nwConst, nwLists, nwFiles +from nw.core.item import NWItem logger = logging.getLogger(__name__) diff --git a/nw/constants/enum.py b/nw/enum.py similarity index 100% rename from nw/constants/enum.py rename to nw/enum.py diff --git a/nw/gui/build.py b/nw/gui/build.py index 2a2be0e8..58526af5 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -44,12 +44,11 @@ from PyQt5.QtWidgets import ( QSizePolicy, QDoubleSpinBox, QComboBox ) -from nw.common import fuzzyTime, makeFileNameSafe -from nw.gui.custom import QSwitch from nw.core import ToHtml, ToOdt, ToMarkdown -from nw.constants import ( - nwConst, nwAlert, nwFiles, nwItemType, nwItemLayout, nwItemClass -) +from nw.enum import nwAlert, nwItemType, nwItemLayout, nwItemClass +from nw.common import fuzzyTime, makeFileNameSafe +from nw.constants import nwConst, nwFiles +from nw.gui.custom import QSwitch logger = logging.getLogger(__name__) diff --git a/nw/gui/custom.py b/nw/gui/custom.py index 7df275f8..e41c54dd 100644 --- a/nw/gui/custom.py +++ b/nw/gui/custom.py @@ -40,7 +40,7 @@ from PyQt5.QtWidgets import ( QLineEdit ) -from nw.constants import trConst, nwUnicode, nwQuotes +from nw.constants import trConst, nwQuotes, nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index e0aee4d3..91abfce9 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -50,12 +50,10 @@ from PyQt5.QtWidgets import ( ) from nw.core import NWDoc, NWSpellSimple, countWords -from nw.gui.dochighlight import GuiDocHighlighter +from nw.enum import nwAlert, nwDocAction, nwDocInsert, nwItemClass from nw.common import transferCase -from nw.constants import ( - trConst, nwConst, nwAlert, nwUnicode, nwDocAction, nwDocInsert, - nwItemClass, nwKeyWords, nwLabels -) +from nw.constants import nwConst, trConst, nwKeyWords, nwLabels, nwUnicode +from nw.gui.dochighlight import GuiDocHighlighter logger = logging.getLogger(__name__) diff --git a/nw/gui/dochighlight.py b/nw/gui/dochighlight.py index 620b8b74..ea9df173 100644 --- a/nw/gui/dochighlight.py +++ b/nw/gui/dochighlight.py @@ -34,7 +34,7 @@ from PyQt5.QtGui import ( QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush ) -from nw.constants import nwUnicode, nwRegEx +from nw.constants import nwRegEx, nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/gui/docmerge.py b/nw/gui/docmerge.py index c804c794..4a6fe00f 100644 --- a/nw/gui/docmerge.py +++ b/nw/gui/docmerge.py @@ -33,9 +33,9 @@ from PyQt5.QtWidgets import ( QListWidgetItem, QDialogButtonBox ) -from nw.constants import nwAlert, nwItemType -from nw.gui.custom import QHelpLabel from nw.core import NWDoc +from nw.enum import nwAlert, nwItemType +from nw.gui.custom import QHelpLabel logger = logging.getLogger(__name__) diff --git a/nw/gui/docsplit.py b/nw/gui/docsplit.py index 2bffb28f..da5b27f0 100644 --- a/nw/gui/docsplit.py +++ b/nw/gui/docsplit.py @@ -34,10 +34,9 @@ from PyQt5.QtWidgets import ( ) from nw.core import NWDoc +from nw.enum import nwAlert, nwItemType, nwItemClass, nwItemLayout +from nw.constants import nwConst from nw.gui.custom import QHelpLabel -from nw.constants import ( - nwAlert, nwItemType, nwItemClass, nwItemLayout, nwConst -) logger = logging.getLogger(__name__) diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py index 638622f4..0feaa101 100644 --- a/nw/gui/docviewer.py +++ b/nw/gui/docviewer.py @@ -41,7 +41,8 @@ from PyQt5.QtWidgets import ( ) from nw.core import ToHtml -from nw.constants import nwAlert, nwItemType, nwDocAction, nwUnicode +from nw.enum import nwAlert, nwItemType, nwDocAction +from nw.constants import nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/gui/itemdetails.py b/nw/gui/itemdetails.py index 608aa6ba..79162382 100644 --- a/nw/gui/itemdetails.py +++ b/nw/gui/itemdetails.py @@ -31,9 +31,8 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel -from nw.constants import ( - trConst, nwLabels, nwItemClass, nwItemType, nwItemLayout -) +from nw.enum import nwItemClass, nwItemType, nwItemLayout +from nw.constants import trConst, nwLabels logger = logging.getLogger(__name__) diff --git a/nw/gui/itemeditor.py b/nw/gui/itemeditor.py index 07926d33..b2c0f496 100644 --- a/nw/gui/itemeditor.py +++ b/nw/gui/itemeditor.py @@ -33,8 +33,9 @@ from PyQt5.QtWidgets import ( QDialogButtonBox ) +from nw.enum import nwItemLayout, nwItemType +from nw.constants import trConst, nwLists, nwLabels from nw.gui.custom import QSwitch -from nw.constants import trConst, nwLabels, nwItemLayout, nwItemType, nwLists logger = logging.getLogger(__name__) diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index 3f2579fd..402e40a9 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -31,10 +31,8 @@ from PyQt5.QtCore import QUrl, QProcess from PyQt5.QtGui import QDesktopServices from PyQt5.QtWidgets import QMenuBar, QAction -from nw.constants import ( - trConst, nwItemType, nwItemClass, nwDocAction, nwDocInsert, nwKeyWords, - nwLabels, nwUnicode, nwWidget -) +from nw.enum import nwItemType, nwItemClass, nwDocAction, nwDocInsert, nwWidget +from nw.constants import trConst, nwKeyWords, nwLabels, nwUnicode logger = logging.getLogger(__name__) diff --git a/nw/gui/noveltree.py b/nw/gui/noveltree.py index 7dde6aeb..c559f414 100644 --- a/nw/gui/noveltree.py +++ b/nw/gui/noveltree.py @@ -32,8 +32,8 @@ from time import time from PyQt5.QtCore import Qt, QSize from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QAbstractItemView -from nw.constants import nwKeyWords from nw.common import checkInt +from nw.constants import nwKeyWords logger = logging.getLogger(__name__) diff --git a/nw/gui/outline.py b/nw/gui/outline.py index 7a54c6be..55359e52 100644 --- a/nw/gui/outline.py +++ b/nw/gui/outline.py @@ -34,7 +34,8 @@ from PyQt5.QtWidgets import ( QTreeWidget, QTreeWidgetItem, QMenu, QAction, QAbstractItemView ) -from nw.constants import trConst, nwKeyWords, nwLabels, nwOutline +from nw.enum import nwOutline +from nw.constants import trConst, nwKeyWords, nwLabels logger = logging.getLogger(__name__) diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py index 8a1bc101..a4d032b5 100644 --- a/nw/gui/outlinedetails.py +++ b/nw/gui/outlinedetails.py @@ -32,8 +32,8 @@ from PyQt5.QtWidgets import ( QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel ) -from nw.constants import trConst, nwLabels, nwKeyWords from nw.common import checkInt +from nw.constants import trConst, nwKeyWords, nwLabels logger = logging.getLogger(__name__) diff --git a/nw/gui/preferences.py b/nw/gui/preferences.py index 529c71bc..16b1ba8d 100644 --- a/nw/gui/preferences.py +++ b/nw/gui/preferences.py @@ -35,9 +35,10 @@ from PyQt5.QtWidgets import ( QLineEdit, QFileDialog, QFontDialog, QDoubleSpinBox ) -from nw.gui.custom import QSwitch, QConfigLayout, PagedDialog, QuotesDialog from nw.core import NWSpellSimple, NWSpellEnchant -from nw.constants import nwConst, nwAlert +from nw.enum import nwAlert +from nw.constants import nwConst +from nw.gui.custom import QSwitch, QConfigLayout, PagedDialog, QuotesDialog logger = logging.getLogger(__name__) diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py index ba393261..74e315c4 100644 --- a/nw/gui/projdetails.py +++ b/nw/gui/projdetails.py @@ -35,9 +35,9 @@ from PyQt5.QtWidgets import ( QLabel, QSpinBox, QGridLayout, QHBoxLayout, QLineEdit, QAbstractItemView ) -from nw.gui.custom import PagedDialog, QSwitch -from nw.constants import nwUnicode from nw.common import numberToRoman +from nw.constants import nwUnicode +from nw.gui.custom import PagedDialog, QSwitch logger = logging.getLogger(__name__) diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index 44ae65e4..55fd3d8c 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -35,7 +35,7 @@ from PyQt5.QtWidgets import ( QComboBox ) -from nw.constants import nwAlert +from nw.enum import nwAlert from nw.gui.custom import QSwitch, PagedDialog, QConfigLayout logger = logging.getLogger(__name__) diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 54a4acfb..e0d5b4b3 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -37,10 +37,8 @@ from PyQt5.QtWidgets import ( ) from nw.core import NWDoc -from nw.constants import ( - trConst, nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, - nwConst, nwLists -) +from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert +from nw.constants import nwConst, trConst, nwLists, nwLabels logger = logging.getLogger(__name__) diff --git a/nw/gui/projwizard.py b/nw/gui/projwizard.py index 951b8211..81b885e8 100644 --- a/nw/gui/projwizard.py +++ b/nw/gui/projwizard.py @@ -35,8 +35,9 @@ from PyQt5.QtWidgets import ( QGroupBox, QGridLayout, QSpinBox ) +from nw.enum import nwItemClass from nw.common import makeFileNameSafe -from nw.constants import trConst, nwLabels, nwItemClass +from nw.constants import trConst, nwLabels from nw.gui.custom import QSwitch logger = logging.getLogger(__name__) diff --git a/nw/gui/theme.py b/nw/gui/theme.py index 946a6435..cec8ee4e 100644 --- a/nw/gui/theme.py +++ b/nw/gui/theme.py @@ -39,7 +39,7 @@ from PyQt5.QtGui import ( QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap ) -from nw.constants import nwAlert +from nw.enum import nwAlert logger = logging.getLogger(__name__) diff --git a/nw/gui/wordlist.py b/nw/gui/wordlist.py index 6f1cd490..7b7d810f 100644 --- a/nw/gui/wordlist.py +++ b/nw/gui/wordlist.py @@ -34,7 +34,8 @@ from PyQt5.QtWidgets import ( QAbstractItemView, QPushButton, QLineEdit, QLabel ) -from nw.constants import nwFiles, nwAlert +from nw.enum import nwAlert +from nw.constants import nwFiles logger = logging.getLogger(__name__) diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index d87d22df..cd50a3dd 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -38,8 +38,9 @@ from PyQt5.QtWidgets import ( QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout ) +from nw.enum import nwAlert from nw.common import formatTime, checkInt -from nw.constants import nwConst, nwFiles, nwAlert +from nw.constants import nwConst, nwFiles from nw.gui.custom import QSwitch logger = logging.getLogger(__name__) diff --git a/nw/guimain.py b/nw/guimain.py index d6da8940..ba8a5ebc 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -46,8 +46,9 @@ from nw.gui import ( GuiProjectTree, GuiProjectWizard, GuiTheme, GuiWordList, GuiWritingStats ) from nw.core import NWProject, NWDoc, NWIndex -from nw.constants import nwItemType, nwItemClass, nwAlert, nwLists, nwWidget +from nw.enum import nwItemType, nwItemClass, nwAlert, nwWidget from nw.common import getGuiItem, hexToInt +from nw.constants import nwLists logger = logging.getLogger(__name__) diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index c4351b24..dad308da 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,13 +1,13 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 1054 + 1057 166 - 49435 + 49506 False diff --git a/setup.py b/setup.py index dc47aca3..91d6f45f 100755 --- a/setup.py +++ b/setup.py @@ -274,6 +274,14 @@ def makeMinimalPackage(targetOS): print(str(e)) sys.exit(1) + # Make translation files + try: + buildQtI18n() + except Exception as e: + print("Failed with error:") + print(str(e)) + sys.exit(1) + print("") print("Building Minimal ZIP File") print("=========================") @@ -318,6 +326,15 @@ def makeMinimalPackage(targetOS): continue zipObj.write(os.path.join(nRoot, aFile)) + for aFile in os.listdir("i18n"): + i18File = os.path.join("i18n", aFile) + if not os.path.isfile(i18File): + continue + + if i18File.endswith((".json", ".qm")): + zipObj.write(i18File) + print("Adding File: %s" % i18File) + if targetOS == OS_WIN: zipObj.write("novelWriter.py", "novelWriter.pyw") print("Adding File: novelWriter.pyw") diff --git a/tests/test_core/test_core_document.py b/tests/test_core/test_core_document.py index f1084f84..1eab9824 100644 --- a/tests/test_core/test_core_document.py +++ b/tests/test_core/test_core_document.py @@ -27,7 +27,7 @@ from dummy import causeOSError from nw.core import NWProject, NWDoc from nw.core.item import NWItem -from nw.constants import nwItemClass, nwItemLayout +from nw.enum import nwItemClass, nwItemLayout @pytest.mark.core def testCoreDocument_LoadSave(monkeypatch, dummyGUI, nwMinimal): diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index 927a506c..95b83a81 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -31,7 +31,7 @@ from tools import cmpFiles from nw.core.project import NWProject from nw.core.index import NWIndex, countWords -from nw.constants import nwItemClass, nwItemLayout +from nw.enum import nwItemClass, nwItemLayout @pytest.mark.core def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir): diff --git a/tests/test_core/test_core_item.py b/tests/test_core/test_core_item.py index 6b615dcd..e4ed227e 100644 --- a/tests/test_core/test_core_item.py +++ b/tests/test_core/test_core_item.py @@ -26,7 +26,7 @@ from lxml import etree from nw.core import NWProject from nw.core.item import NWItem -from nw.constants import nwItemClass, nwItemType, nwItemLayout +from nw.enum import nwItemClass, nwItemType, nwItemLayout @pytest.mark.core def testCoreItem_Setters(dummyGUI): diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 3265cea9..8eb918ec 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -31,8 +31,9 @@ from tools import cmpFiles, writeFile, readFile from dummy import causeOSError from nw.core.project import NWProject -from nw.constants import nwItemClass, nwItemType, nwItemLayout, nwFiles +from nw.enum import nwItemClass, nwItemType, nwItemLayout from nw.common import formatTimeStamp +from nw.constants import nwFiles @pytest.mark.core def testCoreProject_NewMinimal(fncDir, outDir, refDir, tmpDir, dummyGUI): diff --git a/tests/test_core/test_core_tree.py b/tests/test_core/test_core_tree.py index b80bb784..803e88c4 100644 --- a/tests/test_core/test_core_tree.py +++ b/tests/test_core/test_core_tree.py @@ -26,7 +26,8 @@ import pytest from lxml import etree from nw.core.project import NWProject, NWItem, NWTree -from nw.constants import nwItemClass, nwItemType, nwItemLayout, nwFiles +from nw.enum import nwItemClass, nwItemType, nwItemLayout +from nw.constants import nwFiles @pytest.fixture(scope="function") def dummyItems(dummyGUI): diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index b53da662..a4d0c43b 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -33,7 +33,7 @@ from PyQt5.QtWidgets import QAction, QMessageBox, QDialog from nw.gui.itemeditor import GuiItemEditor from nw.gui.doceditor import GuiDocEditor from nw.gui.projtree import GuiProjectTree -from nw.constants import nwItemType, nwDocAction, nwWidget +from nw.enum import nwItemType, nwDocAction, nwWidget keyDelay = 2 typeDelay = 1 diff --git a/tests/test_gui/test_gui_docviewer.py b/tests/test_gui/test_gui_docviewer.py index 3585c8c8..ed77dcc4 100644 --- a/tests/test_gui/test_gui_docviewer.py +++ b/tests/test_gui/test_gui_docviewer.py @@ -26,7 +26,7 @@ from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QTextCursor from PyQt5.QtWidgets import qApp, QAction, QMessageBox -from nw.constants import nwDocAction +from nw.enum import nwDocAction keyDelay = 2 typeDelay = 1 diff --git a/tests/test_gui/test_gui_itemeditor.py b/tests/test_gui/test_gui_itemeditor.py index aacdd4b7..d4c8b7db 100644 --- a/tests/test_gui/test_gui_itemeditor.py +++ b/tests/test_gui/test_gui_itemeditor.py @@ -29,7 +29,7 @@ from tools import cmpFiles, getGuiItem from PyQt5.QtWidgets import QAction, QMessageBox from nw.gui import GuiItemEditor, GuiProjectTree -from nw.constants import nwItemLayout +from nw.enum import nwItemLayout keyDelay = 2 typeDelay = 1 diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py index e2ef781a..2c718704 100644 --- a/tests/test_gui/test_gui_mainmenu.py +++ b/tests/test_gui/test_gui_mainmenu.py @@ -28,9 +28,8 @@ from PyQt5.QtGui import QTextCursor, QTextBlock from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox from nw.gui.doceditor import GuiDocEditor -from nw.constants import ( - nwUnicode, nwDocAction, nwDocInsert, nwKeyWords, nwWidget -) +from nw.enum import nwDocAction, nwDocInsert, nwWidget +from nw.constants import nwKeyWords, nwUnicode keyDelay = 2 typeDelay = 1 diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py index bfeb2f96..53724636 100644 --- a/tests/test_gui/test_gui_outline.py +++ b/tests/test_gui/test_gui_outline.py @@ -25,7 +25,7 @@ import pytest from PyQt5.QtCore import Qt, QPoint from PyQt5.QtWidgets import QAction, QTreeWidgetItem, QMessageBox -from nw.constants import nwOutline +from nw.enum import nwOutline keyDelay = 2 typeDelay = 1 diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py index 07fbc312..c595eaf1 100644 --- a/tests/test_gui/test_gui_projtree.py +++ b/tests/test_gui/test_gui_projtree.py @@ -30,7 +30,7 @@ from PyQt5.QtWidgets import QAction, QMessageBox from nw.guimain import GuiMain from nw.gui.projtree import GuiProjectTree -from nw.constants import nwItemType, nwItemClass +from nw.enum import nwItemType, nwItemClass @pytest.mark.gui def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal): diff --git a/tests/test_gui/test_gui_projwizard.py b/tests/test_gui/test_gui_projwizard.py index 0825eea6..02f7b00a 100644 --- a/tests/test_gui/test_gui_projwizard.py +++ b/tests/test_gui/test_gui_projwizard.py @@ -30,7 +30,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QFileDialog, QWizard, QMessageBox from nw.gui import GuiProjectWizard -from nw.constants import nwItemClass +from nw.enum import nwItemClass from nw.gui.projwizard import ( ProjWizardIntroPage, ProjWizardFolderPage, ProjWizardPopulatePage, ProjWizardCustomPage, ProjWizardFinalPage