mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-06-02 02:54:33 +12:00
Compare commits
96 commits
Author | SHA1 | Date | |
---|---|---|---|
50b9fd4980 | |||
5a109250bb | |||
8beea301ec | |||
f274cd489f | |||
41e59d71c1 | |||
98d6eb4975 | |||
530352c78b | |||
82fe3262af | |||
3707d9e0ee | |||
d0e4c81132 | |||
4d79bef20c | |||
a7abc68f8e | |||
3d4eef2b49 | |||
1fd8762f5a | |||
d93e8eb544 | |||
79ba7b59ed | |||
892f8f0592 | |||
14392909c3 | |||
5f3933bde2 | |||
cf4ff9f35a | |||
b963186071 | |||
1c7b246e80 | |||
56dac84932 | |||
161290686b | |||
7d31628977 | |||
919df53b5f | |||
fbab930c44 | |||
87da52efd4 | |||
d149ae45e7 | |||
18089ae44f | |||
11294a5914 | |||
dccfa85d1f | |||
f25b47149b | |||
6f6abc6f65 | |||
80e90b5ddc | |||
8a5dd11075 | |||
e267699667 | |||
6ee7e881be | |||
42245d38c3 | |||
cc0fc29b28 | |||
1933d53c1c | |||
13486ad083 | |||
4ebbf5efd6 | |||
40a9cabece | |||
14dd845e4c | |||
e36c31f3a9 | |||
15b9d6f0e1 | |||
0ce2ae61a0 | |||
b05377b417 | |||
8932adf635 | |||
549a089eb0 | |||
4abc6cacfd | |||
e8199931d9 | |||
69fec580cb | |||
8e298c0788 | |||
2f93c2f6fe | |||
e84056ecbe | |||
8ffdeefbdf | |||
d8fbea13ba | |||
5f9335cc91 | |||
cdad1aa2d4 | |||
131bdc5505 | |||
7de81a96f3 | |||
1dc709fa20 | |||
fe213894cb | |||
60ea5f9e14 | |||
7d4151328c | |||
863e8df483 | |||
9b372eac73 | |||
389cb19f55 | |||
1164c3c988 | |||
3faaf1187a | |||
5e068c0603 | |||
7d76bd6726 | |||
b1e23fd9fc | |||
e62432307f | |||
5f8569718d | |||
66f6aecf1c | |||
763d9284f0 | |||
91b22292cc | |||
92b1e0b648 | |||
1fd45ba1d2 | |||
2ead298b00 | |||
953ce4bd15 | |||
06f8ab3519 | |||
66df68af69 | |||
b5dfee59d7 | |||
5d0a9d3019 | |||
77f7018cb2 | |||
fc7a716c76 | |||
25b64ad971 | |||
d55e88599d | |||
49fb32deab | |||
fc86ed5df6 | |||
eaebfa9dfa | |||
a046656acf |
2
.github/workflows/build_windows.yml
vendored
2
.github/workflows/build_windows.yml
vendored
|
@ -38,7 +38,7 @@ jobs:
|
||||||
- name: Install Python build dependencies
|
- name: Install Python build dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install pyqt5==5.15.7 lxml pytest pytest-faulthandler language_tool_python symspellpy pyspellchecker pyenchant
|
pip install pyqt5==5.15.7 lxml pytest pytest-faulthandler markdown language_tool_python symspellpy pyspellchecker pyenchant
|
||||||
pip install pyinstaller
|
pip install pyinstaller
|
||||||
- name: pyinstaller build
|
- name: pyinstaller build
|
||||||
run: |
|
run: |
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@
|
||||||
*.msk
|
*.msk
|
||||||
*.nja
|
*.nja
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.glade~
|
||||||
.cache
|
.cache
|
||||||
.directory
|
.directory
|
||||||
.idea
|
.idea
|
||||||
|
|
69
CHANGELOG.md
69
CHANGELOG.md
|
@ -1,6 +1,51 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [0.15.0](https://github.com/olivierkes/manuskript/tree/0.14.0) (2023-03-04)
|
## [0.16.1](https://github.com/olivierkes/manuskript/tree/0.16.1) (2023-12-14)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/olivierkes/manuskript/compare/0.16.0...0.16.1)
|
||||||
|
|
||||||
|
**Fixed bugs:**
|
||||||
|
|
||||||
|
- Characters, Plots and Worlds are greyed out [\#1249](https://github.com/olivierkes/manuskript/issues/1249)
|
||||||
|
- Missing Pages with Version 0.16.0 [\#1248](https://github.com/olivierkes/manuskript/issues/1248)
|
||||||
|
- Software crashing every time I open [\#1247](https://github.com/olivierkes/manuskript/issues/1247)
|
||||||
|
|
||||||
|
## [0.16.0](https://github.com/olivierkes/manuskript/tree/0.16.0) (2023-12-07)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/olivierkes/manuskript/compare/0.15.0...0.16.0)
|
||||||
|
|
||||||
|
**Fixed bugs:**
|
||||||
|
|
||||||
|
- my manuskript is not launching i don't know why [\#1207](https://github.com/olivierkes/manuskript/issues/1207)
|
||||||
|
- cannot download to ubuntu [\#1199](https://github.com/olivierkes/manuskript/issues/1199)
|
||||||
|
- LanguageTool crashes app [\#1143](https://github.com/olivierkes/manuskript/issues/1143)
|
||||||
|
- can't load LanguageTool [\#1142](https://github.com/olivierkes/manuskript/issues/1142)
|
||||||
|
- Crash on spellcheck context menu [\#1224](https://github.com/olivierkes/manuskript/issues/1224)
|
||||||
|
- Trouble launching 0.15 in Windows 10 Home [\#1222](https://github.com/olivierkes/manuskript/issues/1222)
|
||||||
|
- Crash on Search [\#1218](https://github.com/olivierkes/manuskript/issues/1218)
|
||||||
|
- Crash on Mac not on windows with same project [\#1169](https://github.com/olivierkes/manuskript/issues/1169)
|
||||||
|
- Fedora 38 application crashes when cycling through the home options at first launch [\#1163](https://github.com/olivierkes/manuskript/issues/1163)
|
||||||
|
- RuntimeError with manuskriptw.exe \(sys.stderr is None\) [\#1138](https://github.com/olivierkes/manuskript/issues/1138)
|
||||||
|
|
||||||
|
**Closed issues:**
|
||||||
|
|
||||||
|
- Allow chapter/scene cards to be scrolled [\#1170](https://github.com/olivierkes/manuskript/issues/1170)
|
||||||
|
- Kubuntu 20.40.6 getting undefined symbol: krb5\_ser\_context\_init, version krb5\_3\_MIT [\#1155](https://github.com/olivierkes/manuskript/issues/1155)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- Bulk Info Manager bug fix and style changes. [\#1144](https://github.com/olivierkes/manuskript/pull/1144) ([tntscreed](https://github.com/tntscreed))
|
||||||
|
- I added a feature to add "detailed info" entries to multiple characters simultaneously via a dialog box. [\#1137](https://github.com/olivierkes/manuskript/pull/1137) ([tntscreed](https://github.com/tntscreed))
|
||||||
|
- Crash on spellcheck context menu \#1224 [\#1226](https://github.com/olivierkes/manuskript/pull/1226) ([drmousse](https://github.com/drmousse))
|
||||||
|
- Update spellchecker.py And Fixed crashing [\#1214](https://github.com/olivierkes/manuskript/pull/1214) ([TheShadowblast123](https://github.com/TheShadowblast123))
|
||||||
|
- Fix regex for ignoring multi-line comments. [\#1212](https://github.com/olivierkes/manuskript/pull/1212) ([sagev9000](https://github.com/sagev9000))
|
||||||
|
- Skip comments in word count [\#1205](https://github.com/olivierkes/manuskript/pull/1205) ([sagev9000](https://github.com/sagev9000))
|
||||||
|
- added extra check for the filebase dir not to start with an . [\#1198](https://github.com/olivierkes/manuskript/pull/1198) ([Niwreg](https://github.com/Niwreg))
|
||||||
|
- Fix inconsistent newline handling across operating systems [\#1196](https://github.com/olivierkes/manuskript/pull/1196) ([Dreaded-Gnu](https://github.com/Dreaded-Gnu))
|
||||||
|
- Fix manuskriptw startup error [\#1195](https://github.com/olivierkes/manuskript/pull/1195) ([Dreaded-Gnu](https://github.com/Dreaded-Gnu))
|
||||||
|
- Simple history back/forward navigation [\#1165](https://github.com/olivierkes/manuskript/pull/1165) ([alfar](https://github.com/alfar))
|
||||||
|
|
||||||
|
## [0.15.0](https://github.com/olivierkes/manuskript/tree/0.15.0) (2023-03-04)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/olivierkes/manuskript/compare/0.14.0...0.15.0)
|
[Full Changelog](https://github.com/olivierkes/manuskript/compare/0.14.0...0.15.0)
|
||||||
|
|
||||||
|
@ -10,42 +55,42 @@
|
||||||
|
|
||||||
**Fixed bugs:**
|
**Fixed bugs:**
|
||||||
|
|
||||||
|
- 0.14 won't open [\#1105](https://github.com/olivierkes/manuskript/issues/1105)
|
||||||
|
- click on "Plan" makes Manuskript 0.14.0 crash [\#1094](https://github.com/olivierkes/manuskript/issues/1094)
|
||||||
|
- mouse over goes blank in fiction [\#1093](https://github.com/olivierkes/manuskript/issues/1093)
|
||||||
|
- Crashes on hitting "+" while editing plot step summary [\#1081](https://github.com/olivierkes/manuskript/issues/1081)
|
||||||
|
- Type error on launch [\#1043](https://github.com/olivierkes/manuskript/issues/1043)
|
||||||
|
- Plot-step summary disappearing and not being saved! [\#1008](https://github.com/olivierkes/manuskript/issues/1008)
|
||||||
|
- Don't open msk from command line [\#993](https://github.com/olivierkes/manuskript/issues/993)
|
||||||
|
- Metadata: References [\#756](https://github.com/olivierkes/manuskript/issues/756)
|
||||||
|
- Context/right click Menu slow and only in english [\#487](https://github.com/olivierkes/manuskript/issues/487)
|
||||||
- Translations breaks shortcuts [\#1135](https://github.com/olivierkes/manuskript/issues/1135)
|
- Translations breaks shortcuts [\#1135](https://github.com/olivierkes/manuskript/issues/1135)
|
||||||
- Missing visual indicator for collapsables like metadata fields [\#1132](https://github.com/olivierkes/manuskript/issues/1132)
|
- Missing visual indicator for collapsables like metadata fields [\#1132](https://github.com/olivierkes/manuskript/issues/1132)
|
||||||
- New search bug [\#1125](https://github.com/olivierkes/manuskript/issues/1125)
|
- New search bug [\#1125](https://github.com/olivierkes/manuskript/issues/1125)
|
||||||
- One-time glitch: dragged "World" entry to top of list and it disappeared [\#1122](https://github.com/olivierkes/manuskript/issues/1122)
|
- One-time glitch: dragged "World" entry to top of list and it disappeared [\#1122](https://github.com/olivierkes/manuskript/issues/1122)
|
||||||
- Loading Error with fileno [\#1121](https://github.com/olivierkes/manuskript/issues/1121)
|
- Loading Error with fileno [\#1121](https://github.com/olivierkes/manuskript/issues/1121)
|
||||||
- 0.14 won't open [\#1105](https://github.com/olivierkes/manuskript/issues/1105)
|
|
||||||
- Search no longer works [\#1095](https://github.com/olivierkes/manuskript/issues/1095)
|
- Search no longer works [\#1095](https://github.com/olivierkes/manuskript/issues/1095)
|
||||||
- click on "Plan" makes Manuskript 0.14.0 crash [\#1094](https://github.com/olivierkes/manuskript/issues/1094)
|
|
||||||
- mouse over goes blank in fiction [\#1093](https://github.com/olivierkes/manuskript/issues/1093)
|
|
||||||
- Crash when opening a plot in the cheat sheet containing deleted characters [\#1082](https://github.com/olivierkes/manuskript/issues/1082)
|
- Crash when opening a plot in the cheat sheet containing deleted characters [\#1082](https://github.com/olivierkes/manuskript/issues/1082)
|
||||||
- Crashes on hitting "+" while editing plot step summary [\#1081](https://github.com/olivierkes/manuskript/issues/1081)
|
|
||||||
- CTD Crash To Desktop after "inserting link" [\#1071](https://github.com/olivierkes/manuskript/issues/1071)
|
- CTD Crash To Desktop after "inserting link" [\#1071](https://github.com/olivierkes/manuskript/issues/1071)
|
||||||
- Spellcheck intermittantly looses location in editor [\#1065](https://github.com/olivierkes/manuskript/issues/1065)
|
- Spellcheck intermittantly looses location in editor [\#1065](https://github.com/olivierkes/manuskript/issues/1065)
|
||||||
- Translation - missing lines in .ts file etc. issues [\#1052](https://github.com/olivierkes/manuskript/issues/1052)
|
- Translation - missing lines in .ts file etc. issues [\#1052](https://github.com/olivierkes/manuskript/issues/1052)
|
||||||
- Debian installer zst compression error [\#1047](https://github.com/olivierkes/manuskript/issues/1047)
|
- Debian installer zst compression error [\#1047](https://github.com/olivierkes/manuskript/issues/1047)
|
||||||
- manuskriptw.exe can not be executed due to unhandled exception "NullWriter" [\#1044](https://github.com/olivierkes/manuskript/issues/1044)
|
- manuskriptw.exe can not be executed due to unhandled exception "NullWriter" [\#1044](https://github.com/olivierkes/manuskript/issues/1044)
|
||||||
- Type error on launch [\#1043](https://github.com/olivierkes/manuskript/issues/1043)
|
|
||||||
- Crash when attempting to add an inexistent reference [\#1042](https://github.com/olivierkes/manuskript/issues/1042)
|
- Crash when attempting to add an inexistent reference [\#1042](https://github.com/olivierkes/manuskript/issues/1042)
|
||||||
- Setting the language to German deletes shortcut-functions like "Ctrl+S" [\#1012](https://github.com/olivierkes/manuskript/issues/1012)
|
- Setting the language to German deletes shortcut-functions like "Ctrl+S" [\#1012](https://github.com/olivierkes/manuskript/issues/1012)
|
||||||
- Plot-step summary disappearing and not being saved! [\#1008](https://github.com/olivierkes/manuskript/issues/1008)
|
|
||||||
- Don't open msk from command line [\#993](https://github.com/olivierkes/manuskript/issues/993)
|
|
||||||
- Open in new tab doesn't work from tree [\#919](https://github.com/olivierkes/manuskript/issues/919)
|
- Open in new tab doesn't work from tree [\#919](https://github.com/olivierkes/manuskript/issues/919)
|
||||||
- Metadata: References [\#756](https://github.com/olivierkes/manuskript/issues/756)
|
|
||||||
- \[Bug\] Next Button in Characters Pane [\#584](https://github.com/olivierkes/manuskript/issues/584)
|
- \[Bug\] Next Button in Characters Pane [\#584](https://github.com/olivierkes/manuskript/issues/584)
|
||||||
- Context/right click Menu slow and only in english [\#487](https://github.com/olivierkes/manuskript/issues/487)
|
|
||||||
- Top level World items with sub-items do not visually indicate sub-items exist [\#305](https://github.com/olivierkes/manuskript/issues/305)
|
- Top level World items with sub-items do not visually indicate sub-items exist [\#305](https://github.com/olivierkes/manuskript/issues/305)
|
||||||
- saving error [\#274](https://github.com/olivierkes/manuskript/issues/274)
|
- saving error [\#274](https://github.com/olivierkes/manuskript/issues/274)
|
||||||
- Crashing when creating a new project - locale C [\#130](https://github.com/olivierkes/manuskript/issues/130)
|
- Crashing when creating a new project - locale C [\#130](https://github.com/olivierkes/manuskript/issues/130)
|
||||||
|
|
||||||
**Closed issues:**
|
**Closed issues:**
|
||||||
|
|
||||||
- Update files about languages [\#1133](https://github.com/olivierkes/manuskript/issues/1133)
|
|
||||||
- Adding a clearer discription to contributing guidlines [\#1115](https://github.com/olivierkes/manuskript/issues/1115)
|
- Adding a clearer discription to contributing guidlines [\#1115](https://github.com/olivierkes/manuskript/issues/1115)
|
||||||
- I can't click boxes to edit them [\#1104](https://github.com/olivierkes/manuskript/issues/1104)
|
- I can't click boxes to edit them [\#1104](https://github.com/olivierkes/manuskript/issues/1104)
|
||||||
- Minor Python error during Installation - Linux Mint 20.3 [\#1097](https://github.com/olivierkes/manuskript/issues/1097)
|
- Minor Python error during Installation - Linux Mint 20.3 [\#1097](https://github.com/olivierkes/manuskript/issues/1097)
|
||||||
- Package as App Bundle for macOS [\#567](https://github.com/olivierkes/manuskript/issues/567)
|
- Package as App Bundle for macOS [\#567](https://github.com/olivierkes/manuskript/issues/567)
|
||||||
|
- Update files about languages [\#1133](https://github.com/olivierkes/manuskript/issues/1133)
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
@ -335,7 +380,7 @@
|
||||||
- Fix Linux Travis CI build error - pyenv: version `3.6.3' not installed [\#610](https://github.com/olivierkes/manuskript/pull/610) ([gedakc](https://github.com/gedakc))
|
- Fix Linux Travis CI build error - pyenv: version `3.6.3' not installed [\#610](https://github.com/olivierkes/manuskript/pull/610) ([gedakc](https://github.com/gedakc))
|
||||||
- Fix crash when setting word Goal on new Text \(scene\) in Outline pane [\#609](https://github.com/olivierkes/manuskript/pull/609) ([gedakc](https://github.com/gedakc))
|
- Fix crash when setting word Goal on new Text \(scene\) in Outline pane [\#609](https://github.com/olivierkes/manuskript/pull/609) ([gedakc](https://github.com/gedakc))
|
||||||
- Spelling: Manuscript, could not, process, … No content [\#588](https://github.com/olivierkes/manuskript/pull/588) ([comradekingu](https://github.com/comradekingu))
|
- Spelling: Manuscript, could not, process, … No content [\#588](https://github.com/olivierkes/manuskript/pull/588) ([comradekingu](https://github.com/comradekingu))
|
||||||
- fix issue \#468 'unit' is reset [\#587](https://github.com/olivierkes/manuskript/pull/587) ([NocturnalFred](https://github.com/NocturnalFred))
|
- fix issue \#468 'unit' is reset [\#587](https://github.com/olivierkes/manuskript/pull/587) ([SOLIDFred](https://github.com/SOLIDFred))
|
||||||
- Fix pandoc export crashes is project title is empty [\#585](https://github.com/olivierkes/manuskript/pull/585) ([gedakc](https://github.com/gedakc))
|
- Fix pandoc export crashes is project title is empty [\#585](https://github.com/olivierkes/manuskript/pull/585) ([gedakc](https://github.com/gedakc))
|
||||||
- Track dirty state and have the UI behave accordingly [\#583](https://github.com/olivierkes/manuskript/pull/583) ([worstje](https://github.com/worstje))
|
- Track dirty state and have the UI behave accordingly [\#583](https://github.com/olivierkes/manuskript/pull/583) ([worstje](https://github.com/worstje))
|
||||||
- Fix crash if invalid character is inserted into the text. [\#578](https://github.com/olivierkes/manuskript/pull/578) ([kakaroto](https://github.com/kakaroto))
|
- Fix crash if invalid character is inserted into the text. [\#578](https://github.com/olivierkes/manuskript/pull/578) ([kakaroto](https://github.com/kakaroto))
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
[Manuskript](https://www.theologeek.ch/manuskript) is an open-source
|
[Manuskript](https://www.theologeek.ch/manuskript) is an open-source
|
||||||
tool for writers.
|
tool for writers.
|
||||||
|
|
||||||
|
[![pytest](https://github.com/olivierkes/manuskript/workflows/Pytest%20Run%20%28Linux%29/badge.svg)](https://github.com/olivierkes/manuskript/actions/workflows/pytest.yml)
|
||||||
[![manuskript](https://snapcraft.io/manuskript/badge.svg)](https://snapcraft.io/manuskript)
|
[![manuskript](https://snapcraft.io/manuskript/badge.svg)](https://snapcraft.io/manuskript)
|
||||||
[![translations](https://hosted.weblate.org/widgets/manuskript/-/translations/svg-badge.svg)](https://hosted.weblate.org/projects/manuskript/translations)
|
[![translations](https://hosted.weblate.org/widgets/manuskript/-/translations/svg-badge.svg)](https://hosted.weblate.org/projects/manuskript/translations)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -8,6 +8,8 @@ from manuskript.exporter.manuskript.markdown import markdown
|
||||||
from manuskript.exporter.manuskript.plainText import plainText
|
from manuskript.exporter.manuskript.plainText import plainText
|
||||||
from manuskript.functions import appPath, safeTranslate
|
from manuskript.functions import appPath, safeTranslate
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class manuskriptExporter(basicExporter):
|
class manuskriptExporter(basicExporter):
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ class manuskriptExporter(basicExporter):
|
||||||
HTML(),
|
HTML(),
|
||||||
basicFormat("OPML", icon="text-x-opml+xml")
|
basicFormat("OPML", icon="text-x-opml+xml")
|
||||||
]
|
]
|
||||||
icon = appPath("icons/Manuskript/icon-256px.png")
|
icon = appPath(os.path.join("icons", "Manuskript", "icon-256px.png"))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def isValid(cls):
|
def isValid(cls):
|
||||||
|
|
|
@ -96,7 +96,7 @@ class plainText(basicFormat):
|
||||||
LOGGER.error("No content. Nothing saved.")
|
LOGGER.error("No content. Nothing saved.")
|
||||||
return
|
return
|
||||||
|
|
||||||
with open(filename, "w", encoding='utf8') as f:
|
with open(filename, "wt", encoding="utf8", newline="\n") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
def preview(self, settingsWidget, previewWidget):
|
def preview(self, settingsWidget, previewWidget):
|
||||||
|
@ -217,4 +217,3 @@ class plainText(basicFormat):
|
||||||
content += "\n"
|
content += "\n"
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ def safeTranslate(qApp, group, text):
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def wordCount(text):
|
def wordCount(text):
|
||||||
return len(re.findall(r"\S+", text))
|
return len(re.findall(r"\S+", re.sub(r"(<!--).+?(-->)", "", text, flags=re.DOTALL)))
|
||||||
|
|
||||||
|
|
||||||
def charCount(text, use_spaces = True):
|
def charCount(text, use_spaces = True):
|
||||||
|
@ -252,7 +252,7 @@ def colorifyPixmap(pixmap, color):
|
||||||
|
|
||||||
|
|
||||||
def appPath(suffix=None):
|
def appPath(suffix=None):
|
||||||
p = os.path.realpath(os.path.join(os.path.split(__file__)[0], "../.."))
|
p = os.path.realpath(os.path.join(os.path.split(__file__)[0], os.path.join("..", "..")))
|
||||||
if suffix:
|
if suffix:
|
||||||
p = os.path.join(p, suffix)
|
p = os.path.join(p, suffix)
|
||||||
return p
|
return p
|
||||||
|
@ -305,7 +305,7 @@ def findBackground(filename):
|
||||||
"""
|
"""
|
||||||
Returns the full path to a background file of name filename within resources folders.
|
Returns the full path to a background file of name filename within resources folders.
|
||||||
"""
|
"""
|
||||||
return findFirstFile(re.escape(filename), "resources/backgrounds")
|
return findFirstFile(re.escape(filename), os.path.join("resources", "backgrounds"))
|
||||||
|
|
||||||
|
|
||||||
def findFirstFile(regex, path="resources"):
|
def findFirstFile(regex, path="resources"):
|
||||||
|
@ -511,7 +511,7 @@ def getManuskriptPath(follow_symlinks=True):
|
||||||
path = os.path.abspath(sys.executable)
|
path = os.path.abspath(sys.executable)
|
||||||
else:
|
else:
|
||||||
import inspect
|
import inspect
|
||||||
path = inspect.getabsfile(getManuskriptPath) + "/../.."
|
path = os.path.join(inspect.getabsfile(getManuskriptPath), "..", "..")
|
||||||
if follow_symlinks:
|
if follow_symlinks:
|
||||||
path = os.path.realpath(path)
|
path = os.path.realpath(path)
|
||||||
return os.path.dirname(path)
|
return os.path.dirname(path)
|
||||||
|
|
56
manuskript/functions/history/History.py
Normal file
56
manuskript/functions/history/History.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
from manuskript.functions.history.NavigatedEvent import NavigatedEvent
|
||||||
|
from manuskript.functions.history.Signal import Signal
|
||||||
|
|
||||||
|
|
||||||
|
class History():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._entries = []
|
||||||
|
self._position = 0
|
||||||
|
self.navigated = Signal()
|
||||||
|
self._navigating = False
|
||||||
|
|
||||||
|
def next(self, entry):
|
||||||
|
if self._navigating:
|
||||||
|
return
|
||||||
|
|
||||||
|
while self._position < len(self._entries) - 1:
|
||||||
|
self._entries.pop()
|
||||||
|
|
||||||
|
self._entries.append(entry)
|
||||||
|
self._position = len(self._entries) - 1
|
||||||
|
self._navigating = True
|
||||||
|
self.navigated.fire(NavigatedEvent(self._position, len(self._entries), entry))
|
||||||
|
self._navigating = False
|
||||||
|
|
||||||
|
|
||||||
|
def replace(self, entry):
|
||||||
|
if self._navigating:
|
||||||
|
return
|
||||||
|
|
||||||
|
while self._position < len(self._entries):
|
||||||
|
self._entries.pop()
|
||||||
|
|
||||||
|
self._entries.append(entry)
|
||||||
|
self._position = len(self._entries) - 1
|
||||||
|
self._navigating = True
|
||||||
|
self.navigated.fire(NavigatedEvent(self._position, len(self._entries), entry))
|
||||||
|
self._navigating = False
|
||||||
|
|
||||||
|
def forward(self):
|
||||||
|
if self._position < len(self._entries) - 1:
|
||||||
|
self._position += 1
|
||||||
|
self._navigating = True
|
||||||
|
self.navigated.fire(NavigatedEvent(self._position, len(self._entries), self._entries[self._position]))
|
||||||
|
self._navigating = False
|
||||||
|
|
||||||
|
def back(self):
|
||||||
|
if self._position > 0:
|
||||||
|
self._position -= 1
|
||||||
|
self._navigating = True
|
||||||
|
self.navigated.fire(NavigatedEvent(self._position, len(self._entries), self._entries[self._position]))
|
||||||
|
self._navigating = False
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._entries.clear()
|
||||||
|
self._position = 0
|
||||||
|
self.navigated.fire(NavigatedEvent(self._position, len(self._entries), None))
|
5
manuskript/functions/history/NavigatedEvent.py
Normal file
5
manuskript/functions/history/NavigatedEvent.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class NavigatedEvent():
|
||||||
|
def __init__(self, position, count, entry) -> None:
|
||||||
|
self.position = position
|
||||||
|
self.count = count
|
||||||
|
self.entry = entry
|
23
manuskript/functions/history/Signal.py
Normal file
23
manuskript/functions/history/Signal.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
class Signal():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._methods = []
|
||||||
|
|
||||||
|
def connect(self, func):
|
||||||
|
self._methods.append(func)
|
||||||
|
|
||||||
|
def disconnect(self, func):
|
||||||
|
try:
|
||||||
|
self._methods.remove(func)
|
||||||
|
except ValueError:
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
if len(self._methods) == 0:
|
||||||
|
raise TypeError
|
||||||
|
self._methods.pop()
|
||||||
|
|
||||||
|
def fire(self, data):
|
||||||
|
for m in self._methods:
|
||||||
|
m(data)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# --!-- coding: utf8 --!--
|
# --!-- coding: utf8 --!--
|
||||||
|
|
||||||
import os, gzip, json, glob, re
|
import os, gzip, json, glob, re, string
|
||||||
from PyQt5.QtCore import QLocale
|
from PyQt5.QtCore import QLocale
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from manuskript.functions import writablePath
|
from manuskript.functions import writablePath
|
||||||
|
@ -23,7 +23,7 @@ try:
|
||||||
|
|
||||||
if distutils.version.LooseVersion(symspellpy.__version__) < SYMSPELLPY_MIN_VERSION:
|
if distutils.version.LooseVersion(symspellpy.__version__) < SYMSPELLPY_MIN_VERSION:
|
||||||
symspellpy = None
|
symspellpy = None
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
symspellpy = None
|
symspellpy = None
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class BasicDictionary:
|
||||||
self._customDict = set()
|
self._customDict = set()
|
||||||
customPath = self.getCustomDictionaryPath()
|
customPath = self.getCustomDictionaryPath()
|
||||||
try:
|
try:
|
||||||
with gzip.open(customPath, "rt", encoding='utf-8') as f:
|
with gzip.open(customPath, 'rt', encoding='utf-8') as f:
|
||||||
self._customDict = set(json.loads(f.read()))
|
self._customDict = set(json.loads(f.read()))
|
||||||
for word in self._customDict:
|
for word in self._customDict:
|
||||||
self._dict.create_dictionary_entry(word, self.CUSTOM_COUNT)
|
self._dict.create_dictionary_entry(word, self.CUSTOM_COUNT)
|
||||||
|
@ -187,6 +187,7 @@ class BasicDictionary:
|
||||||
def checkText(self, text):
|
def checkText(self, text):
|
||||||
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
|
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
|
||||||
WORDS = r'(?iu)((?:[^_\W]|\')+)[^A-Za-z0-9\']'
|
WORDS = r'(?iu)((?:[^_\W]|\')+)[^A-Za-z0-9\']'
|
||||||
|
|
||||||
# (?iu) means case insensitive and Unicode
|
# (?iu) means case insensitive and Unicode
|
||||||
# ((?:[^_\W]|\')+) means words exclude underscores but include apostrophes
|
# ((?:[^_\W]|\')+) means words exclude underscores but include apostrophes
|
||||||
# [^A-Za-z0-9\'] used with above hack to prevent spellcheck while typing word
|
# [^A-Za-z0-9\'] used with above hack to prevent spellcheck while typing word
|
||||||
|
@ -197,8 +198,30 @@ class BasicDictionary:
|
||||||
|
|
||||||
for word_object in re.finditer(WORDS, text):
|
for word_object in re.finditer(WORDS, text):
|
||||||
word = word_object.group(1)
|
word = word_object.group(1)
|
||||||
|
mispelled = self.isMisspelled(word)
|
||||||
|
if mispelled == False:
|
||||||
|
continue
|
||||||
|
punctuation = string.punctuation.replace('-', '')
|
||||||
|
|
||||||
|
FALSE_POSITIVE = r'^[^\w]|([^{}])$'.format(punctuation)
|
||||||
|
|
||||||
|
#inorder to prevent apostrophes causing false positives and keep the same functionality otherwise,
|
||||||
|
#check that the word doesn't have any additional punctuation on it.
|
||||||
|
if re.match(FALSE_POSITIVE, word):
|
||||||
|
# ^[^\w] checks that it doesn't start with a word character
|
||||||
|
# ([\p{P}'])$ checks it doesn't end with punctuation characters
|
||||||
|
|
||||||
|
apostrophe_WORDS = r'(?iu)\b(?<=[\s\'"(])((?:[a-zA-Z]|\')+)(?=\b)'
|
||||||
|
|
||||||
|
# \b(?<=[\s\'"(]) looks for nonword characters and starts grouping after
|
||||||
|
# (?=\b) looks for the word boundary
|
||||||
|
# ((?:[a-zA-Z]|\')+) greedily matches for letters and apostrophes
|
||||||
|
|
||||||
|
temp = re.match(apostrophe_WORDS, word)
|
||||||
|
mispelled = self.isMisspelled(temp.group(1)) if temp else False
|
||||||
|
|
||||||
|
if (mispelled and not self.isCustomWord(word)):
|
||||||
|
|
||||||
if (self.isMisspelled(word) and not self.isCustomWord(word)):
|
|
||||||
matches.append(BasicMatch(
|
matches.append(BasicMatch(
|
||||||
word_object.start(1), word_object.end(1)
|
word_object.start(1), word_object.end(1)
|
||||||
))
|
))
|
||||||
|
@ -250,7 +273,7 @@ class BasicDictionary:
|
||||||
|
|
||||||
def _saveCustomDict(self):
|
def _saveCustomDict(self):
|
||||||
customPath = self.getCustomDictionaryPath()
|
customPath = self.getCustomDictionaryPath()
|
||||||
with gzip.open(customPath, "wt") as f:
|
with gzip.open(customPath, "wt", newline="\n") as f:
|
||||||
f.write(json.dumps(list(self._customDict)))
|
f.write(json.dumps(list(self._customDict)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -363,7 +386,7 @@ class PySpellcheckerDictionary(BasicDictionary):
|
||||||
|
|
||||||
def getSuggestions(self, word):
|
def getSuggestions(self, word):
|
||||||
candidates = self._dict.candidates(word)
|
candidates = self._dict.candidates(word)
|
||||||
if word in candidates:
|
if candidates and word in candidates:
|
||||||
candidates.remove(word)
|
candidates.remove(word)
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
|
@ -393,7 +416,7 @@ class SymSpellDictionary(BasicDictionary):
|
||||||
if pyspellchecker:
|
if pyspellchecker:
|
||||||
path = os.path.join(pyspellchecker.__path__[0], "resources", "{}.json.gz".format(self.name))
|
path = os.path.join(pyspellchecker.__path__[0], "resources", "{}.json.gz".format(self.name))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
with gzip.open(path, "rt", encoding='utf-8') as f:
|
with gzip.open(path, 'rt', encoding='utf-8') as f:
|
||||||
data = json.loads(f.read())
|
data = json.loads(f.read())
|
||||||
for key in data:
|
for key in data:
|
||||||
self._dict.create_dictionary_entry(key, data[key])
|
self._dict.create_dictionary_entry(key, data[key])
|
||||||
|
|
|
@ -46,7 +46,7 @@ class folderImporter(abstractImporter):
|
||||||
fName, fExt = os.path.splitext(f)
|
fName, fExt = os.path.splitext(f)
|
||||||
if fExt.lower() in ext:
|
if fExt.lower() in ext:
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(dirpath, f), "r", encoding="utf-8") as fr:
|
with open(os.path.join(dirpath, f), 'rt', encoding="utf-8") as fr:
|
||||||
content = fr.read()
|
content = fr.read()
|
||||||
child = outlineItem(title=fName, _type="md", parent=item)
|
child = outlineItem(title=fName, _type="md", parent=item)
|
||||||
child._data[Outline.text] = content
|
child._data[Outline.text] = content
|
||||||
|
@ -122,7 +122,3 @@ class folderImporter(abstractImporter):
|
||||||
self.addSettingsTo(group)
|
self.addSettingsTo(group)
|
||||||
|
|
||||||
return widget
|
return widget
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ class markdownImporter(abstractImporter):
|
||||||
|
|
||||||
if not fromString:
|
if not fromString:
|
||||||
# Read file
|
# Read file
|
||||||
with open(filePath, "r", encoding="utf-8") as f:
|
with open(filePath, 'rt', encoding="utf-8") as f:
|
||||||
txt = f.read()
|
txt = f.read()
|
||||||
else:
|
else:
|
||||||
txt = fromString
|
txt = fromString
|
||||||
|
|
|
@ -56,7 +56,7 @@ def loadProject(project):
|
||||||
|
|
||||||
# Not a zip
|
# Not a zip
|
||||||
else:
|
else:
|
||||||
with open(project, "r", encoding="utf-8") as f:
|
with open(project, 'rt', encoding="utf-8") as f:
|
||||||
version = int(f.read())
|
version = int(f.read())
|
||||||
|
|
||||||
LOGGER.info("Loading: %s", project)
|
LOGGER.info("Loading: %s", project)
|
||||||
|
|
|
@ -388,7 +388,7 @@ def saveProject(zip=None):
|
||||||
filesWithPermissionErrors.append(filename)
|
filesWithPermissionErrors.append(filename)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(filename, "w", encoding='utf8') as f:
|
with open(filename, "wt", encoding="utf8", newline="\n") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
LOGGER.error("Cannot open file " + filename + " for writing: " + e.strerror)
|
LOGGER.error("Cannot open file " + filename + " for writing: " + e.strerror)
|
||||||
|
@ -423,7 +423,7 @@ def saveProject(zip=None):
|
||||||
|
|
||||||
# Write the project file's content
|
# Write the project file's content
|
||||||
try:
|
try:
|
||||||
with open(project, "w", encoding='utf8') as f:
|
with open(project, "wt", encoding="utf8", newline="\n") as f:
|
||||||
f.write("1") # Format number
|
f.write("1") # Format number
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
LOGGER.error("Cannot open file " + project + " for writing: " + e.strerror)
|
LOGGER.error("Cannot open file " + project + " for writing: " + e.strerror)
|
||||||
|
@ -678,6 +678,9 @@ def loadProject(project, zip=None):
|
||||||
# Skip directories that begin with a period
|
# Skip directories that begin with a period
|
||||||
if p[:1] == ".":
|
if p[:1] == ".":
|
||||||
continue
|
continue
|
||||||
|
#skip if the basedir of the file starts with an .
|
||||||
|
if os.path.basename(p)[:1] == ".":
|
||||||
|
continue
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
# Skip filenames that begin with a period
|
# Skip filenames that begin with a period
|
||||||
if f[:1] == ".":
|
if f[:1] == ".":
|
||||||
|
@ -689,7 +692,7 @@ def loadProject(project, zip=None):
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
filename = os.path.join(dirpath, f)
|
filename = os.path.join(dirpath, f)
|
||||||
with open(filename, "r", encoding="utf8") as fo:
|
with open(filename, 'rt', encoding="utf8") as fo:
|
||||||
files[os.path.join(p, f)] = fo.read()
|
files[os.path.join(p, f)] = fo.read()
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
LOGGER.error("Cannot open file " + filename + ": " + e.strerror)
|
LOGGER.error("Cannot open file " + filename + ": " + e.strerror)
|
||||||
|
@ -1127,5 +1130,3 @@ def parseMMDFile(text, asDict=False):
|
||||||
return md, body
|
return md, body
|
||||||
else:
|
else:
|
||||||
return mdd, body
|
return mdd, body
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ from manuskript.version import getVersion
|
||||||
|
|
||||||
try:
|
try:
|
||||||
faulthandler.enable()
|
faulthandler.enable()
|
||||||
except AttributeError:
|
except (AttributeError, RuntimeError):
|
||||||
print("Faulthandler failed")
|
print("Faulthandler failed")
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -45,7 +45,7 @@ def prepare(arguments, tests=False):
|
||||||
|
|
||||||
icon = QIcon()
|
icon = QIcon()
|
||||||
for i in [16, 32, 64, 128, 256, 512]:
|
for i in [16, 32, 64, 128, 256, 512]:
|
||||||
icon.addFile(appPath("icons/Manuskript/icon-{}px.png".format(i)))
|
icon.addFile(appPath(os.path.join("icons", "Manuskript", "icon-{}px.png".format(i))))
|
||||||
qApp.setWindowIcon(icon)
|
qApp.setWindowIcon(icon)
|
||||||
|
|
||||||
app.setStyle("Fusion")
|
app.setStyle("Fusion")
|
||||||
|
|
|
@ -7,15 +7,16 @@ import re
|
||||||
from PyQt5.Qt import qVersion, PYQT_VERSION_STR
|
from PyQt5.Qt import qVersion, PYQT_VERSION_STR
|
||||||
from PyQt5.QtCore import (pyqtSignal, QSignalMapper, QTimer, QSettings, Qt, QPoint,
|
from PyQt5.QtCore import (pyqtSignal, QSignalMapper, QTimer, QSettings, Qt, QPoint,
|
||||||
QRegExp, QUrl, QSize, QModelIndex)
|
QRegExp, QUrl, QSize, QModelIndex)
|
||||||
from PyQt5.QtGui import QStandardItemModel, QIcon, QColor
|
from PyQt5.QtGui import QStandardItemModel, QIcon, QColor, QStandardItem
|
||||||
from PyQt5.QtWidgets import QMainWindow, QHeaderView, qApp, QMenu, QActionGroup, QAction, QStyle, QListWidgetItem, \
|
from PyQt5.QtWidgets import QMainWindow, QHeaderView, qApp, QMenu, QActionGroup, QAction, QStyle, QListWidgetItem, \
|
||||||
QLabel, QDockWidget, QWidget, QMessageBox, QLineEdit
|
QLabel, QDockWidget, QWidget, QMessageBox, QLineEdit, QTextEdit, QTreeView, QDialog, QTableView
|
||||||
|
|
||||||
from manuskript import settings
|
from manuskript import settings
|
||||||
from manuskript.enums import Character, PlotStep, Plot, World, Outline
|
from manuskript.enums import Character, PlotStep, Plot, World, Outline
|
||||||
from manuskript.functions import wordCount, appPath, findWidgetsOfClass, openURL, showInFolder
|
from manuskript.functions import wordCount, appPath, findWidgetsOfClass, openURL, showInFolder
|
||||||
import manuskript.functions as F
|
import manuskript.functions as F
|
||||||
from manuskript import loadSave
|
from manuskript import loadSave
|
||||||
|
from manuskript.functions.history.History import History
|
||||||
from manuskript.logging import getLogFilePath
|
from manuskript.logging import getLogFilePath
|
||||||
from manuskript.models.characterModel import characterModel
|
from manuskript.models.characterModel import characterModel
|
||||||
from manuskript.models import outlineModel
|
from manuskript.models import outlineModel
|
||||||
|
@ -23,6 +24,7 @@ from manuskript.models.plotModel import plotModel
|
||||||
from manuskript.models.worldModel import worldModel
|
from manuskript.models.worldModel import worldModel
|
||||||
from manuskript.settingsWindow import settingsWindow
|
from manuskript.settingsWindow import settingsWindow
|
||||||
from manuskript.ui import style
|
from manuskript.ui import style
|
||||||
|
from manuskript.ui import characterInfoDialog
|
||||||
from manuskript.ui.about import aboutDialog
|
from manuskript.ui.about import aboutDialog
|
||||||
from manuskript.ui.collapsibleDockWidgets import collapsibleDockWidgets
|
from manuskript.ui.collapsibleDockWidgets import collapsibleDockWidgets
|
||||||
from manuskript.ui.importers.importer import importerDialog
|
from manuskript.ui.importers.importer import importerDialog
|
||||||
|
@ -35,6 +37,7 @@ from manuskript.ui.views.outlineDelegates import outlineCharacterDelegate
|
||||||
from manuskript.ui.views.plotDelegate import plotDelegate
|
from manuskript.ui.views.plotDelegate import plotDelegate
|
||||||
from manuskript.ui.views.MDEditView import MDEditView
|
from manuskript.ui.views.MDEditView import MDEditView
|
||||||
from manuskript.ui.statusLabel import statusLabel
|
from manuskript.ui.statusLabel import statusLabel
|
||||||
|
from manuskript.ui.bulkInfoManager import Ui_BulkInfoManager
|
||||||
|
|
||||||
# Spellcheck support
|
# Spellcheck support
|
||||||
from manuskript.ui.views.textEditView import textEditView
|
from manuskript.ui.views.textEditView import textEditView
|
||||||
|
@ -71,6 +74,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# value. In manuskript.main.
|
# value. In manuskript.main.
|
||||||
self._autoLoadProject = None # Used to load a command line project
|
self._autoLoadProject = None # Used to load a command line project
|
||||||
self.sessionStartWordCount = 0 # Used to track session targets
|
self.sessionStartWordCount = 0 # Used to track session targets
|
||||||
|
self.history = History()
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
|
||||||
self.readSettings()
|
self.readSettings()
|
||||||
|
|
||||||
|
@ -102,7 +107,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# Main Menu
|
# Main Menu
|
||||||
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
||||||
self.menuEdit, self.menuView, self.menuOrganize,
|
self.menuEdit, self.menuView, self.menuOrganize,
|
||||||
self.menuTools, self.menuHelp, self.actImport,
|
self.menuNavigate, self.menuTools, self.menuHelp, self.actImport,
|
||||||
self.actCompile, self.actSettings]:
|
self.actCompile, self.actSettings]:
|
||||||
i.setEnabled(False)
|
i.setEnabled(False)
|
||||||
|
|
||||||
|
@ -156,6 +161,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
self.actSplitCursor.triggered.connect(self.documentsSplitCursor)
|
self.actSplitCursor.triggered.connect(self.documentsSplitCursor)
|
||||||
self.actMerge.triggered.connect(self.documentsMerge)
|
self.actMerge.triggered.connect(self.documentsMerge)
|
||||||
|
|
||||||
|
# Main menu:: Navigate
|
||||||
|
self.actBack.triggered.connect(self.navigateBack)
|
||||||
|
self.actForward.triggered.connect(self.navigateForward)
|
||||||
|
|
||||||
# Main Menu:: view
|
# Main Menu:: view
|
||||||
self.generateViewMenu()
|
self.generateViewMenu()
|
||||||
self.actModeGroup = QActionGroup(self)
|
self.actModeGroup = QActionGroup(self)
|
||||||
|
@ -179,6 +188,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
# self.loadProject(os.path.join(appPath(), "test_project.zip"))
|
# self.loadProject(os.path.join(appPath(), "test_project.zip"))
|
||||||
|
|
||||||
|
# Bulk Character Info Management
|
||||||
|
self.tabsData = self.saveCharacterTabs() # Used for restoring tabsData with loadCharacterTabs() methods.
|
||||||
|
self.BulkManageUi = None
|
||||||
|
self.bulkAffectedCharacters = []
|
||||||
|
self.isPersoBulkModeEnabled = False
|
||||||
|
|
||||||
def updateDockVisibility(self, restore=False):
|
def updateDockVisibility(self, restore=False):
|
||||||
"""
|
"""
|
||||||
Saves the state of the docks visibility. Or if `restore` is True,
|
Saves the state of the docks visibility. Or if `restore` is True,
|
||||||
|
@ -248,6 +263,54 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
self.actDelete,
|
self.actDelete,
|
||||||
self.actRename]:
|
self.actRename]:
|
||||||
i.setEnabled(tabIsEditor)
|
i.setEnabled(tabIsEditor)
|
||||||
|
tabIndex = self.tabMain.currentIndex()
|
||||||
|
|
||||||
|
if tabIndex == self.TabPersos:
|
||||||
|
selectedCharacters = self.lstCharacters.currentCharacters()
|
||||||
|
characterSelectionIsEmpty = not any(selectedCharacters)
|
||||||
|
|
||||||
|
if characterSelectionIsEmpty:
|
||||||
|
self.pushHistory(("character", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
else:
|
||||||
|
character = selectedCharacters[0]
|
||||||
|
self.pushHistory(("character", character.ID()))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
elif tabIndex == self.TabPlots:
|
||||||
|
id = self.lstPlots.currentPlotID()
|
||||||
|
self.pushHistory(("plot", id))
|
||||||
|
self._previousSelectionEmpty = id is None
|
||||||
|
elif tabIndex == self.TabWorld:
|
||||||
|
index = self.mdlWorld.selectedIndex()
|
||||||
|
|
||||||
|
if index.isValid():
|
||||||
|
id = self.mdlWorld.ID(index)
|
||||||
|
self.pushHistory(("world", id))
|
||||||
|
self._previousSelectionEmpty = id is not None
|
||||||
|
else:
|
||||||
|
self.pushHistory(("world", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
elif tabIndex == self.TabOutline:
|
||||||
|
index = self.treeOutlineOutline.selectionModel().currentIndex()
|
||||||
|
if index.isValid():
|
||||||
|
id = self.mdlOutline.ID(index)
|
||||||
|
self.pushHistory(("outline", id))
|
||||||
|
self._previousSelectionEmpty = id is not None
|
||||||
|
else:
|
||||||
|
self.pushHistory(("outline", None))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
elif tabIndex == self.TabRedac:
|
||||||
|
index = self.treeRedacOutline.selectionModel().currentIndex()
|
||||||
|
if index.isValid():
|
||||||
|
id = self.mdlOutline.ID(index)
|
||||||
|
self.pushHistory(("redac", id))
|
||||||
|
self._previousSelectionEmpty = id is not None
|
||||||
|
else:
|
||||||
|
self.pushHistory(("redac", None))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
else:
|
||||||
|
self.pushHistory(("main", self.tabMain.currentIndex()))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
def focusChanged(self, old, new):
|
def focusChanged(self, old, new):
|
||||||
"""
|
"""
|
||||||
|
@ -287,6 +350,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# OUTLINE
|
# OUTLINE
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
def outlineChanged(self, selected, deselected):
|
||||||
|
index = self.treeOutlineOutline.selectionModel().currentIndex()
|
||||||
|
if not index.isValid():
|
||||||
|
self.pushHistory(("outline", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
return
|
||||||
|
|
||||||
|
self.pushHistory(("outline", self.mdlOutline.ID(index)))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
|
|
||||||
def outlineRemoveItemsRedac(self):
|
def outlineRemoveItemsRedac(self):
|
||||||
self.treeRedacOutline.delete()
|
self.treeRedacOutline.delete()
|
||||||
|
|
||||||
|
@ -297,18 +371,177 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# CHARACTERS
|
# CHARACTERS
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
def changeCurrentCharacter(self, trash=None):
|
def setPersoBulkMode(self, enabled: bool):
|
||||||
"""
|
if enabled and self.BulkManageUi is None: # Delete all tabs and create the manager one
|
||||||
|
# Create the widget
|
||||||
|
bulkPersoInfoManager = QWidget()
|
||||||
|
bulkPersoInfoManagerUi = Ui_BulkInfoManager()
|
||||||
|
bulkPersoInfoManagerUi.setupUi(bulkPersoInfoManager)
|
||||||
|
|
||||||
@return:
|
self.BulkManageUi = bulkPersoInfoManagerUi # for global use
|
||||||
"""
|
|
||||||
c = self.lstCharacters.currentCharacter()
|
model = QStandardItemModel()
|
||||||
if not c:
|
|
||||||
self.tabPersos.setEnabled(False)
|
# Set the column headers
|
||||||
|
model.setColumnCount(2)
|
||||||
|
model.setHorizontalHeaderLabels([self.tr("Name"), self.tr("Value")])
|
||||||
|
|
||||||
|
# Set the width
|
||||||
|
self.updatePersoInfoView(bulkPersoInfoManagerUi.tableView)
|
||||||
|
|
||||||
|
bulkPersoInfoManagerUi.tableView.setModel(model) # Set the model of tableView
|
||||||
|
|
||||||
|
self.tabPersos.clear()
|
||||||
|
self.tabPersos.addTab(bulkPersoInfoManager, self.tr("Bulk Info Manager"))
|
||||||
|
self.isPersoBulkModeEnabled = True
|
||||||
|
self.refreshBulkAffectedCharacters()
|
||||||
|
|
||||||
|
# Showing the character names on the label
|
||||||
|
labelText = self.createCharacterSelectionString()
|
||||||
|
bulkPersoInfoManagerUi.lblCharactersDynamic.setText(labelText)
|
||||||
|
|
||||||
|
# Making the connections
|
||||||
|
self.makeBulkInfoConnections(bulkPersoInfoManagerUi)
|
||||||
|
|
||||||
|
elif enabled and self.BulkManageUi is not None: # If yet another character is selected, refresh the label
|
||||||
|
labelText = self.createCharacterSelectionString()
|
||||||
|
self.BulkManageUi.lblCharactersDynamic.setText(labelText)
|
||||||
|
|
||||||
|
else: # Delete manager tab and restore the others
|
||||||
|
if self.BulkManageUi is not None:
|
||||||
|
self.tabPersos.clear()
|
||||||
|
self.loadCharacterTabs()
|
||||||
|
self.BulkManageUi = None
|
||||||
|
self.bulkAffectedCharacters.clear()
|
||||||
|
|
||||||
|
def createCharacterSelectionString(self):
|
||||||
|
self.refreshBulkAffectedCharacters()
|
||||||
|
labelText = ""
|
||||||
|
length = len(self.bulkAffectedCharacters)
|
||||||
|
for i in range(length-1):
|
||||||
|
labelText += '"' + self.bulkAffectedCharacters[i] + '"' + ", "
|
||||||
|
|
||||||
|
labelText += '"' + self.bulkAffectedCharacters[length-1] + '"'
|
||||||
|
|
||||||
|
return labelText
|
||||||
|
|
||||||
|
def makeBulkInfoConnections(self, bulkUi):
|
||||||
|
# A lambda has to be used to pass in the argument
|
||||||
|
bulkUi.btnPersoBulkAddInfo.clicked.connect(lambda: self.addBulkInfo(bulkUi))
|
||||||
|
bulkUi.btnPersoBulkRmInfo.clicked.connect(lambda: self.removeBulkInfo(bulkUi))
|
||||||
|
bulkUi.btnPersoBulkApply.clicked.connect(lambda: self.applyBulkInfo(bulkUi))
|
||||||
|
|
||||||
|
def applyBulkInfo(self, bulkUi):
|
||||||
|
selectedItems = self.lstCharacters.currentCharacterIDs()
|
||||||
|
|
||||||
|
# Get the data from the tableview
|
||||||
|
model = bulkUi.tableView.model()
|
||||||
|
if model.rowCount() == 0:
|
||||||
|
QMessageBox.warning(self, self.tr("No Entries!"),
|
||||||
|
self.tr("Please add entries to apply to the selected characters."))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Loop through each selected character and add the bulk info to them
|
||||||
|
for ID in selectedItems:
|
||||||
|
for row in range(model.rowCount()):
|
||||||
|
description = model.item(row, 0).text()
|
||||||
|
value = model.item(row, 1).text()
|
||||||
|
self.lstCharacters._model.addCharacterInfo(ID, description, value)
|
||||||
|
|
||||||
|
QMessageBox.information(self, self.tr("Bulk Info Applied"),
|
||||||
|
self.tr("The bulk info has been applied to the selected characters."))
|
||||||
|
|
||||||
|
# Remove all rows from the table
|
||||||
|
model.removeRows(0, model.rowCount())
|
||||||
|
|
||||||
|
def addBulkInfo(self, bulkUi): # Adds an item to the list
|
||||||
|
charInfoDialog = QDialog()
|
||||||
|
charInfoUi = characterInfoDialog.Ui_characterInfoDialog()
|
||||||
|
charInfoUi.setupUi(charInfoDialog)
|
||||||
|
|
||||||
|
if charInfoDialog.exec_() == QDialog.Accepted:
|
||||||
|
# User clicked OK, get the input values
|
||||||
|
description = charInfoUi.descriptionLineEdit.text()
|
||||||
|
value = charInfoUi.valueLineEdit.text()
|
||||||
|
|
||||||
|
# Add a new row to the model with the description and value
|
||||||
|
row = [QStandardItem(description), QStandardItem(value)]
|
||||||
|
|
||||||
|
bulkUi.tableView.model().appendRow(row)
|
||||||
|
|
||||||
|
bulkUi.tableView.update()
|
||||||
|
|
||||||
|
def removeBulkInfo(self, bulkUi):
|
||||||
|
# Get the selected rows
|
||||||
|
selection = bulkUi.tableView.selectionModel().selectedRows()
|
||||||
|
|
||||||
|
# Iterate over the rows and remove them (reversed, so the iteration is not affected)
|
||||||
|
for index in reversed(selection):
|
||||||
|
bulkUi.tableView.model().removeRow(index.row())
|
||||||
|
|
||||||
|
def saveCharacterTabs(self):
|
||||||
|
tabsData = []
|
||||||
|
for i in range(self.tabPersos.count()):
|
||||||
|
tabData = {}
|
||||||
|
widget = self.tabPersos.widget(i)
|
||||||
|
tabData['widget'] = widget
|
||||||
|
tabData['title'] = self.tabPersos.tabText(i)
|
||||||
|
tabsData.append(tabData)
|
||||||
|
return tabsData
|
||||||
|
|
||||||
|
def loadCharacterTabs(self):
|
||||||
|
for tabData in self.tabsData:
|
||||||
|
widget = tabData['widget']
|
||||||
|
title = tabData['title']
|
||||||
|
self.tabPersos.addTab(widget, title)
|
||||||
|
|
||||||
|
def handleCharacterSelectionChanged(self):
|
||||||
|
selectedCharacters = self.lstCharacters.currentCharacters()
|
||||||
|
characterSelectionIsEmpty = not any(selectedCharacters)
|
||||||
|
if characterSelectionIsEmpty:
|
||||||
|
self.pushHistory(("character", None))
|
||||||
|
self.tabPersos.setEnabled(False)
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
return
|
||||||
|
|
||||||
|
cList = list(filter(None, self.lstCharacters.currentCharacters())) #cList contains all valid characters
|
||||||
|
character = cList[0]
|
||||||
|
self.changeCurrentCharacter(character)
|
||||||
|
|
||||||
|
self.pushHistory(("character", character.ID()))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
|
if len(selectedCharacters) > 1:
|
||||||
|
self.setPersoBulkMode(True)
|
||||||
|
else:
|
||||||
|
if self.BulkManageUi is not None:
|
||||||
|
self.refreshBulkAffectedCharacters()
|
||||||
|
self.BulkManageUi.lblCharactersDynamic.setText( self.createCharacterSelectionString() )
|
||||||
|
|
||||||
|
tableview_model = self.BulkManageUi.tableView.model()
|
||||||
|
if tableview_model.rowCount() > 0:
|
||||||
|
confirm = QMessageBox.warning(
|
||||||
|
self, self.tr("Un-applied data!"),
|
||||||
|
self.tr("There are un-applied entries in this tab. Discard them?"),
|
||||||
|
QMessageBox.Yes | QMessageBox.No,
|
||||||
|
defaultButton = QMessageBox.No
|
||||||
|
)
|
||||||
|
if confirm != QMessageBox.Yes:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setPersoBulkMode(False)
|
||||||
self.tabPersos.setEnabled(True)
|
self.tabPersos.setEnabled(True)
|
||||||
index = c.index()
|
|
||||||
|
def refreshBulkAffectedCharacters(self): # Characters affected by a potential bulk-info modification
|
||||||
|
self.bulkAffectedCharacters = []
|
||||||
|
for character in self.lstCharacters.currentCharacters():
|
||||||
|
self.bulkAffectedCharacters.append(character.name())
|
||||||
|
|
||||||
|
def changeCurrentCharacter(self, character):
|
||||||
|
if character is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
index = character.index()
|
||||||
|
|
||||||
for w in [
|
for w in [
|
||||||
self.txtPersoName,
|
self.txtPersoName,
|
||||||
|
@ -325,24 +558,25 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
w.setCurrentModelIndex(index)
|
w.setCurrentModelIndex(index)
|
||||||
|
|
||||||
# Button color
|
# Button color
|
||||||
self.updateCharacterColor(c.ID())
|
self.updateCharacterColor(character.ID())
|
||||||
|
|
||||||
# Slider importance
|
# Slider importance
|
||||||
self.updateCharacterImportance(c.ID())
|
self.updateCharacterImportance(character.ID())
|
||||||
|
|
||||||
# POV state
|
# POV state
|
||||||
self.updateCharacterPOVState(c.ID())
|
self.updateCharacterPOVState(character.ID())
|
||||||
|
|
||||||
# Character Infos
|
# Character Infos
|
||||||
self.tblPersoInfos.setRootIndex(index)
|
self.tblPersoInfos.setRootIndex(index)
|
||||||
|
|
||||||
if self.mdlCharacter.rowCount(index):
|
if self.mdlCharacter.rowCount(index):
|
||||||
self.updatePersoInfoView()
|
self.updatePersoInfoView(self.tblPersoInfos)
|
||||||
|
|
||||||
def updatePersoInfoView(self):
|
def updatePersoInfoView(self, infoView):
|
||||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
|
infoView.horizontalHeader().setStretchLastSection(True)
|
||||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
|
infoView.horizontalHeader().setMinimumSectionSize(20)
|
||||||
self.tblPersoInfos.verticalHeader().hide()
|
infoView.horizontalHeader().setMaximumSectionSize(500)
|
||||||
|
infoView.verticalHeader().hide()
|
||||||
|
|
||||||
def updateCharacterColor(self, ID):
|
def updateCharacterColor(self, ID):
|
||||||
c = self.mdlCharacter.getCharacterByID(ID)
|
c = self.mdlCharacter.getCharacterByID(ID)
|
||||||
|
@ -370,7 +604,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def deleteCharacter(self):
|
def deleteCharacter(self):
|
||||||
ID = self.lstCharacters.removeCharacter()
|
ID = self.lstCharacters.removeCharacters()
|
||||||
if ID is None:
|
if ID is None:
|
||||||
return
|
return
|
||||||
for itemID in self.mdlOutline.findItemsByPOV(ID):
|
for itemID in self.mdlOutline.findItemsByPOV(ID):
|
||||||
|
@ -384,11 +618,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
def changeCurrentPlot(self):
|
def changeCurrentPlot(self):
|
||||||
index = self.lstPlots.currentPlotIndex()
|
index = self.lstPlots.currentPlotIndex()
|
||||||
|
id = self.lstPlots.currentPlotID()
|
||||||
|
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
self.tabPlot.setEnabled(False)
|
self.tabPlot.setEnabled(False)
|
||||||
|
self.pushHistory(("plot", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.pushHistory(("plot", id))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
self.tabPlot.setEnabled(True)
|
self.tabPlot.setEnabled(True)
|
||||||
self.txtPlotName.setCurrentModelIndex(index)
|
self.txtPlotName.setCurrentModelIndex(index)
|
||||||
self.txtPlotDescription.setCurrentModelIndex(index)
|
self.txtPlotDescription.setCurrentModelIndex(index)
|
||||||
|
@ -457,8 +697,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
self.tabWorld.setEnabled(False)
|
self.tabWorld.setEnabled(False)
|
||||||
|
self.pushHistory(("world", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.pushHistory(("world", self.mdlWorld.ID(index)))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
self.tabWorld.setEnabled(True)
|
self.tabWorld.setEnabled(True)
|
||||||
self.txtWorldName.setCurrentModelIndex(index)
|
self.txtWorldName.setCurrentModelIndex(index)
|
||||||
self.txtWorldDescription.setCurrentModelIndex(index)
|
self.txtWorldDescription.setCurrentModelIndex(index)
|
||||||
|
@ -469,6 +714,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# EDITOR
|
# EDITOR
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
def redacOutlineChanged(self):
|
||||||
|
index = self.treeRedacOutline.selectionModel().currentIndex()
|
||||||
|
if not index.isValid():
|
||||||
|
self.pushHistory(("redac", None))
|
||||||
|
self._previousSelectionEmpty = True
|
||||||
|
return
|
||||||
|
|
||||||
|
self.pushHistory(("redac", self.mdlOutline.ID(index)))
|
||||||
|
self._previousSelectionEmpty = False
|
||||||
|
|
||||||
def openIndex(self, index):
|
def openIndex(self, index):
|
||||||
self.treeRedacOutline.setCurrentIndex(index)
|
self.treeRedacOutline.setCurrentIndex(index)
|
||||||
|
|
||||||
|
@ -566,6 +821,92 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
"Merges selected item(s)."
|
"Merges selected item(s)."
|
||||||
if self._lastFocus: self._lastFocus.merge()
|
if self._lastFocus: self._lastFocus.merge()
|
||||||
|
|
||||||
|
# Navigate
|
||||||
|
|
||||||
|
def navigateBack(self):
|
||||||
|
self.history.back()
|
||||||
|
|
||||||
|
def navigateForward(self):
|
||||||
|
self.history.forward()
|
||||||
|
|
||||||
|
def pushHistory(self, entry):
|
||||||
|
if self._previousSelectionEmpty:
|
||||||
|
self.history.replace(entry)
|
||||||
|
else:
|
||||||
|
self.history.next(entry)
|
||||||
|
|
||||||
|
def navigated(self, event):
|
||||||
|
if event.entry:
|
||||||
|
first_entry = event.entry[0]
|
||||||
|
|
||||||
|
if first_entry == "character":
|
||||||
|
if self.tabMain.currentIndex() != self.TabPersos:
|
||||||
|
self.tabMain.setCurrentIndex(self.TabPersos)
|
||||||
|
|
||||||
|
if event.entry[1] is None:
|
||||||
|
self.lstCharacters.setCurrentItem(None)
|
||||||
|
self.lstCharacters.clearSelection()
|
||||||
|
else:
|
||||||
|
if self.lstCharacters.currentCharacterID() != event.entry[1]:
|
||||||
|
char = self.lstCharacters.getItemByID(event.entry[1])
|
||||||
|
if char != None:
|
||||||
|
self.lstCharacters.clearSelection()
|
||||||
|
self.lstCharacters.setCurrentItem(char)
|
||||||
|
elif first_entry == "plot":
|
||||||
|
if self.tabMain.currentIndex() != self.TabPlots:
|
||||||
|
self.tabMain.setCurrentIndex(self.TabPlots)
|
||||||
|
|
||||||
|
if event.entry[1] is None:
|
||||||
|
self.lstPlots.setCurrentItem(None)
|
||||||
|
else:
|
||||||
|
index = self.lstPlots.currentPlotIndex()
|
||||||
|
if index and index.row() != event.entry[1]:
|
||||||
|
plot = self.lstPlots.getItemByID(event.entry[1])
|
||||||
|
if plot != None:
|
||||||
|
self.lstPlots.setCurrentItem(plot)
|
||||||
|
elif first_entry == "world":
|
||||||
|
if self.tabMain.currentIndex() != self.TabWorld:
|
||||||
|
self.tabMain.setCurrentIndex(self.TabWorld)
|
||||||
|
|
||||||
|
if event.entry[1] is None:
|
||||||
|
self.treeWorld.selectionModel().clear()
|
||||||
|
else:
|
||||||
|
index = self.mdlWorld.selectedIndex()
|
||||||
|
if index and self.mdlWorld.ID(index) != event.entry[1]:
|
||||||
|
world = self.mdlWorld.indexByID(event.entry[1])
|
||||||
|
if world != None:
|
||||||
|
self.treeWorld.setCurrentIndex(world)
|
||||||
|
elif first_entry == "outline":
|
||||||
|
if self.tabMain.currentIndex() != self.TabOutline:
|
||||||
|
self.tabMain.setCurrentIndex(self.TabOutline)
|
||||||
|
|
||||||
|
if event.entry[1] is None:
|
||||||
|
self.treeOutlineOutline.selectionModel().clear()
|
||||||
|
else:
|
||||||
|
index = self.treeOutlineOutline.selectionModel().currentIndex()
|
||||||
|
if index and self.mdlOutline.ID(index) != event.entry[1]:
|
||||||
|
outline = self.mdlOutline.getIndexByID(event.entry[1])
|
||||||
|
if outline is not None:
|
||||||
|
self.treeOutlineOutline.setCurrentIndex(outline)
|
||||||
|
elif first_entry == "redac":
|
||||||
|
if self.tabMain.currentIndex() != self.TabRedac:
|
||||||
|
self.tabMain.setCurrentIndex(self.TabRedac)
|
||||||
|
|
||||||
|
if event.entry[1] is None:
|
||||||
|
self.treeRedacOutline.selectionModel().clear()
|
||||||
|
else:
|
||||||
|
index = self.treeRedacOutline.selectionModel().currentIndex()
|
||||||
|
if index and self.mdlOutline.ID(index) != event.entry[1]:
|
||||||
|
outline = self.mdlOutline.getIndexByID(event.entry[1])
|
||||||
|
if outline is not None:
|
||||||
|
self.treeRedacOutline.setCurrentIndex(outline)
|
||||||
|
elif first_entry == "main":
|
||||||
|
if self.tabMain.currentIndex() != event.entry[1]:
|
||||||
|
self.lstTabs.setCurrentRow(event.entry[1])
|
||||||
|
|
||||||
|
self.actBack.setEnabled(event.position > 0)
|
||||||
|
self.actForward.setEnabled(event.position < event.count - 1)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# LOAD AND SAVE
|
# LOAD AND SAVE
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -575,6 +916,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
If ``loadFromFile`` is False, then it does not load datas from file.
|
If ``loadFromFile`` is False, then it does not load datas from file.
|
||||||
It assumes that the datas have been populated in a different way."""
|
It assumes that the datas have been populated in a different way."""
|
||||||
|
|
||||||
|
# Convert project path to OS norm
|
||||||
|
project = os.path.normpath(project)
|
||||||
|
|
||||||
if loadFromFile and not os.path.exists(project):
|
if loadFromFile and not os.path.exists(project):
|
||||||
LOGGER.warning("The file {} does not exist. Has it been moved or deleted?".format(project))
|
LOGGER.warning("The file {} does not exist. Has it been moved or deleted?".format(project))
|
||||||
F.statusMessage(
|
F.statusMessage(
|
||||||
|
@ -642,6 +987,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
i.setEnabled(False)
|
i.setEnabled(False)
|
||||||
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
||||||
self.menuEdit, self.menuView, self.menuOrganize,
|
self.menuEdit, self.menuView, self.menuOrganize,
|
||||||
|
self.menuNavigate,
|
||||||
self.menuTools, self.menuHelp, self.actImport,
|
self.menuTools, self.menuHelp, self.actImport,
|
||||||
self.actCompile, self.actSettings]:
|
self.actCompile, self.actSettings]:
|
||||||
i.setEnabled(True)
|
i.setEnabled(True)
|
||||||
|
@ -659,6 +1005,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# Add project name to Window's name
|
# Add project name to Window's name
|
||||||
self.setWindowTitle(self.projectName() + " - " + self.tr("Manuskript"))
|
self.setWindowTitle(self.projectName() + " - " + self.tr("Manuskript"))
|
||||||
|
|
||||||
|
# Reset history
|
||||||
|
self.history.reset()
|
||||||
|
|
||||||
# Show main Window
|
# Show main Window
|
||||||
self.switchToProject()
|
self.switchToProject()
|
||||||
|
|
||||||
|
@ -903,12 +1252,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
def makeUIConnections(self):
|
def makeUIConnections(self):
|
||||||
"Connections that have to be made once only, even when a new project is loaded."
|
"Connections that have to be made once only, even when a new project is loaded."
|
||||||
self.lstCharacters.currentItemChanged.connect(self.changeCurrentCharacter, F.AUC)
|
# Characters
|
||||||
|
self.txtPersosFilter.textChanged.connect(self.lstCharacters.setFilter, F.AUC)
|
||||||
|
self.lstCharacters.itemSelectionChanged.connect(self.handleCharacterSelectionChanged, F.AUC)
|
||||||
|
|
||||||
|
# Plots
|
||||||
self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, F.AUC)
|
self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, F.AUC)
|
||||||
self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, F.AUC)
|
self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, F.AUC)
|
||||||
self.lstSubPlots.clicked.connect(self.changeCurrentSubPlot, F.AUC)
|
self.lstSubPlots.clicked.connect(self.changeCurrentSubPlot, F.AUC)
|
||||||
|
|
||||||
|
# Outline
|
||||||
self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder, F.AUC)
|
self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder, F.AUC)
|
||||||
self.btnOutlineAddFolder.clicked.connect(self.treeOutlineOutline.addFolder, F.AUC)
|
self.btnOutlineAddFolder.clicked.connect(self.treeOutlineOutline.addFolder, F.AUC)
|
||||||
self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText, F.AUC)
|
self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText, F.AUC)
|
||||||
|
@ -919,6 +1272,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
self.tabMain.currentChanged.connect(self.toolbar.setCurrentGroup)
|
self.tabMain.currentChanged.connect(self.toolbar.setCurrentGroup)
|
||||||
self.tabMain.currentChanged.connect(self.tabMainChanged)
|
self.tabMain.currentChanged.connect(self.tabMainChanged)
|
||||||
|
|
||||||
|
self.history.navigated.connect(self.navigated)
|
||||||
|
|
||||||
qApp.focusChanged.connect(self.focusChanged)
|
qApp.focusChanged.connect(self.focusChanged)
|
||||||
|
|
||||||
def makeConnections(self):
|
def makeConnections(self):
|
||||||
|
@ -956,6 +1311,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))
|
widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))
|
||||||
|
|
||||||
# Characters
|
# Characters
|
||||||
|
self.updatePersoInfoView(self.tblPersoInfos)
|
||||||
self.lstCharacters.setCharactersModel(self.mdlCharacter)
|
self.lstCharacters.setCharactersModel(self.mdlCharacter)
|
||||||
self.tblPersoInfos.setModel(self.mdlCharacter)
|
self.tblPersoInfos.setModel(self.mdlCharacter)
|
||||||
try:
|
try:
|
||||||
|
@ -1056,10 +1412,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
# self.redacEditor.setModel(self.mdlOutline)
|
# self.redacEditor.setModel(self.mdlOutline)
|
||||||
self.storylineView.setModels(self.mdlOutline, self.mdlCharacter, self.mdlPlots)
|
self.storylineView.setModels(self.mdlOutline, self.mdlCharacter, self.mdlPlots)
|
||||||
|
|
||||||
|
self.treeOutlineOutline.selectionModel().selectionChanged.connect(self.outlineChanged, F.AUC)
|
||||||
self.treeOutlineOutline.selectionModel().selectionChanged.connect(self.outlineItemEditor.selectionChanged, F.AUC)
|
self.treeOutlineOutline.selectionModel().selectionChanged.connect(self.outlineItemEditor.selectionChanged, F.AUC)
|
||||||
self.treeOutlineOutline.clicked.connect(self.outlineItemEditor.selectionChanged, F.AUC)
|
self.treeOutlineOutline.clicked.connect(self.outlineItemEditor.selectionChanged, F.AUC)
|
||||||
|
|
||||||
# Sync selection
|
# Sync selection
|
||||||
|
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacOutlineChanged, F.AUC)
|
||||||
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacMetadata.selectionChanged, F.AUC)
|
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacMetadata.selectionChanged, F.AUC)
|
||||||
self.treeRedacOutline.clicked.connect(self.redacMetadata.selectionChanged, F.AUC)
|
self.treeRedacOutline.clicked.connect(self.redacMetadata.selectionChanged, F.AUC)
|
||||||
|
|
||||||
|
@ -1167,6 +1525,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||||
lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
|
lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
|
||||||
self.tblDebugPlots.selectionModel().currentIndex().row(),
|
self.tblDebugPlots.selectionModel().currentIndex().row(),
|
||||||
Plot.steps)))
|
Plot.steps)))
|
||||||
|
|
||||||
|
self.disconnectAll(self.history.navigated)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# HELP
|
# HELP
|
||||||
|
|
|
@ -220,6 +220,17 @@ class characterModel(QAbstractItemModel, searchableModel):
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
mainWindow().updatePersoInfoView()
|
mainWindow().updatePersoInfoView()
|
||||||
|
def addCharacterInfo(self, ID, description, value):
|
||||||
|
c = self.getCharacterByID(ID)
|
||||||
|
self.beginInsertRows(c.index(), len(c.infos), len(c.infos))
|
||||||
|
c.infos.append(CharacterInfo(
|
||||||
|
c,
|
||||||
|
description=self.tr(description),
|
||||||
|
value=self.tr(value)
|
||||||
|
))
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
mainWindow().updatePersoInfoView(mainWindow().tblPersoInfos)
|
||||||
|
|
||||||
def removeCharacterInfo(self, ID):
|
def removeCharacterInfo(self, ID):
|
||||||
c = self.getCharacterByID(ID)
|
c = self.getCharacterByID(ID)
|
||||||
|
|
|
@ -351,7 +351,8 @@ class plotItemSearchWrapper(searchableItem):
|
||||||
return [self.translate("Plot")] + _path(self.getItem(self.rowIndex, Plot.name)) + [self.translate(self.searchColumnLabel(column))]
|
return [self.translate("Plot")] + _path(self.getItem(self.rowIndex, Plot.name)) + [self.translate(self.searchColumnLabel(column))]
|
||||||
|
|
||||||
def searchData(self, column):
|
def searchData(self, column):
|
||||||
return self.getItem(self.rowIndex, column).text()
|
item = self.getItem(self.rowIndex, column)
|
||||||
|
return item.text() if item else None
|
||||||
|
|
||||||
def plotStepPath(self, plotName, plotStepName, column):
|
def plotStepPath(self, plotName, plotStepName, column):
|
||||||
return [self.translate("Plot"), plotName, plotStepName, self.translate(self.searchColumnLabel(column))]
|
return [self.translate("Plot"), plotName, plotStepName, self.translate(self.searchColumnLabel(column))]
|
||||||
|
|
|
@ -513,7 +513,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
||||||
# self.cmbDelegate = cmbPixmapDelegate()
|
# self.cmbDelegate = cmbPixmapDelegate()
|
||||||
# self.cmbCorkImage.setItemDelegate(self.cmbDelegate)
|
# self.cmbCorkImage.setItemDelegate(self.cmbDelegate)
|
||||||
|
|
||||||
paths = allPaths("resources/backgrounds")
|
paths = allPaths(os.path.join("resources", "backgrounds"))
|
||||||
cmb.clear()
|
cmb.clear()
|
||||||
cmb.addItem(QIcon.fromTheme("list-remove"), "", "")
|
cmb.addItem(QIcon.fromTheme("list-remove"), "", "")
|
||||||
for p in paths:
|
for p in paths:
|
||||||
|
@ -541,7 +541,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
||||||
valid = px.load(filename)
|
valid = px.load(filename)
|
||||||
del px
|
del px
|
||||||
if valid:
|
if valid:
|
||||||
shutil.copy(filename, writablePath("resources/backgrounds"))
|
shutil.copy(filename, writablePath(os.path.join("resources", "backgrounds")))
|
||||||
return os.path.basename(filename)
|
return os.path.basename(filename)
|
||||||
else:
|
else:
|
||||||
QMessageBox.warning(self, self.tr("Error"),
|
QMessageBox.warning(self, self.tr("Error"),
|
||||||
|
@ -727,7 +727,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
||||||
self.btnThemeRemove.setEnabled(False)
|
self.btnThemeRemove.setEnabled(False)
|
||||||
|
|
||||||
def newTheme(self):
|
def newTheme(self):
|
||||||
path = writablePath("resources/themes")
|
path = writablePath(os.path.join("resources", "themes"))
|
||||||
name = self.tr("newtheme")
|
name = self.tr("newtheme")
|
||||||
if os.path.exists(os.path.join(path, "{}.theme".format(name))):
|
if os.path.exists(os.path.join(path, "{}.theme".format(name))):
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -756,7 +756,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
||||||
self.populatesThemesList()
|
self.populatesThemesList()
|
||||||
|
|
||||||
def populatesThemesList(self):
|
def populatesThemesList(self):
|
||||||
paths = allPaths("resources/themes")
|
paths = allPaths(os.path.join("resources", "themes"))
|
||||||
current = settings.fullScreenTheme
|
current = settings.fullScreenTheme
|
||||||
self.lstThemes.clear()
|
self.lstThemes.clear()
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
"""Tests for functions"""
|
"""Tests for functions"""
|
||||||
|
|
||||||
import re
|
import re, os
|
||||||
from manuskript import functions as F
|
from manuskript import functions as F
|
||||||
|
|
||||||
def test_wordCount():
|
def test_wordCount():
|
||||||
|
@ -81,7 +81,7 @@ def test_paths():
|
||||||
assert len(F.allPaths("suffix")) == 2
|
assert len(F.allPaths("suffix")) == 2
|
||||||
assert F.tempFile("yop") != None
|
assert F.tempFile("yop") != None
|
||||||
f = F.findBackground("spacedreams.jpg")
|
f = F.findBackground("spacedreams.jpg")
|
||||||
assert "resources/backgrounds/spacedreams.jpg" in f
|
assert os.path.join("resources", "backgrounds", "spacedreams.jpg") in f
|
||||||
assert len(F.customIcons()) > 1
|
assert len(F.customIcons()) > 1
|
||||||
|
|
||||||
def test_mainWindow():
|
def test_mainWindow():
|
||||||
|
|
|
@ -10,6 +10,9 @@ from manuskript.functions import appPath
|
||||||
from manuskript.ui.about_ui import Ui_about
|
from manuskript.ui.about_ui import Ui_about
|
||||||
from manuskript.version import getVersion
|
from manuskript.version import getVersion
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class aboutDialog(QWidget, Ui_about):
|
class aboutDialog(QWidget, Ui_about):
|
||||||
def __init__(self, parent=None, mw=None):
|
def __init__(self, parent=None, mw=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
|
@ -19,10 +22,10 @@ class aboutDialog(QWidget, Ui_about):
|
||||||
|
|
||||||
def populateFields(self):
|
def populateFields(self):
|
||||||
# Fill in all the fields in the About dialog
|
# Fill in all the fields in the About dialog
|
||||||
iconPic = appPath("icons/Manuskript/icon-64px.png")
|
iconPic = appPath(os.path.join("icons", "Manuskript", "icon-64px.png"))
|
||||||
self.setWindowIcon(QIcon(iconPic))
|
self.setWindowIcon(QIcon(iconPic))
|
||||||
|
|
||||||
logoPic = QPixmap(appPath("icons/Manuskript/logo-400x104.png"))
|
logoPic = QPixmap(appPath(os.path.join("icons", "Manuskript", "logo-400x104.png")))
|
||||||
self.labelLogo.setPixmap(logoPic)
|
self.labelLogo.setPixmap(logoPic)
|
||||||
|
|
||||||
self.labelManuskriptVersion.setText(
|
self.labelManuskriptVersion.setText(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'manuskript/ui/about_ui.ui'
|
# Form implementation generated from reading ui file 'manuskript/ui/about_ui.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
85
manuskript/ui/bulkInfoManager.py
Normal file
85
manuskript/ui/bulkInfoManager.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'manuskript\manuskript\ui\bulkInfoManager.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.4
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_BulkInfoManager(object):
|
||||||
|
def setupUi(self, BulkInfoManager):
|
||||||
|
BulkInfoManager.setObjectName("BulkInfoManager")
|
||||||
|
BulkInfoManager.setWindowModality(QtCore.Qt.WindowModal)
|
||||||
|
BulkInfoManager.resize(644, 556)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(BulkInfoManager)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.lblStaticMessage = QtWidgets.QLabel(BulkInfoManager)
|
||||||
|
self.lblStaticMessage.setObjectName("lblStaticMessage")
|
||||||
|
self.verticalLayout.addWidget(self.lblStaticMessage)
|
||||||
|
self.lblCharactersDynamic = QtWidgets.QLabel(BulkInfoManager)
|
||||||
|
self.lblCharactersDynamic.setObjectName("lblCharactersDynamic")
|
||||||
|
self.verticalLayout.addWidget(self.lblCharactersDynamic)
|
||||||
|
self.tableView = QtWidgets.QTableView(BulkInfoManager)
|
||||||
|
self.tableView.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
|
||||||
|
self.tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
|
||||||
|
self.tableView.setAlternatingRowColors(True)
|
||||||
|
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
self.tableView.setTextElideMode(QtCore.Qt.ElideNone)
|
||||||
|
self.tableView.setCornerButtonEnabled(False)
|
||||||
|
self.tableView.setObjectName("tableView")
|
||||||
|
self.tableView.verticalHeader().setVisible(False)
|
||||||
|
self.verticalLayout.addWidget(self.tableView)
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.btnPersoBulkAddInfo = QtWidgets.QPushButton(BulkInfoManager)
|
||||||
|
self.btnPersoBulkAddInfo.setText("")
|
||||||
|
icon = QtGui.QIcon.fromTheme("list-add")
|
||||||
|
self.btnPersoBulkAddInfo.setIcon(icon)
|
||||||
|
self.btnPersoBulkAddInfo.setObjectName("btnPersoBulkAddInfo")
|
||||||
|
self.horizontalLayout.addWidget(self.btnPersoBulkAddInfo)
|
||||||
|
self.btnPersoBulkRmInfo = QtWidgets.QPushButton(BulkInfoManager)
|
||||||
|
self.btnPersoBulkRmInfo.setText("")
|
||||||
|
icon = QtGui.QIcon.fromTheme("list-remove")
|
||||||
|
self.btnPersoBulkRmInfo.setIcon(icon)
|
||||||
|
self.btnPersoBulkRmInfo.setObjectName("btnPersoBulkRmInfo")
|
||||||
|
self.horizontalLayout.addWidget(self.btnPersoBulkRmInfo)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
|
self.btnPersoBulkApply = QtWidgets.QPushButton(BulkInfoManager)
|
||||||
|
self.btnPersoBulkApply.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
|
||||||
|
self.btnPersoBulkApply.setObjectName("btnPersoBulkApply")
|
||||||
|
self.horizontalLayout.addWidget(self.btnPersoBulkApply)
|
||||||
|
self.horizontalLayout.setStretch(0, 1)
|
||||||
|
self.horizontalLayout.setStretch(1, 1)
|
||||||
|
self.horizontalLayout.setStretch(2, 5)
|
||||||
|
self.horizontalLayout.setStretch(3, 1)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
|
||||||
|
self.retranslateUi(BulkInfoManager)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(BulkInfoManager)
|
||||||
|
|
||||||
|
def retranslateUi(self, BulkInfoManager):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
BulkInfoManager.setWindowTitle(_translate("BulkInfoManager", "Form"))
|
||||||
|
self.lblStaticMessage.setText(_translate("BulkInfoManager", "Affected Characters:"))
|
||||||
|
self.lblCharactersDynamic.setText(_translate("BulkInfoManager", "NONE"))
|
||||||
|
self.btnPersoBulkAddInfo.setToolTip(_translate("BulkInfoManager", "Add entry to the list."))
|
||||||
|
self.btnPersoBulkRmInfo.setToolTip(_translate("BulkInfoManager", "Remove entry from the list."))
|
||||||
|
self.btnPersoBulkApply.setToolTip(_translate("BulkInfoManager", "Adds all items to the selected characters."))
|
||||||
|
self.btnPersoBulkApply.setText(_translate("BulkInfoManager", "Apply Changes"))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
BulkInfoManager = QtWidgets.QWidget()
|
||||||
|
ui = Ui_BulkInfoManager()
|
||||||
|
ui.setupUi(BulkInfoManager)
|
||||||
|
BulkInfoManager.show()
|
||||||
|
sys.exit(app.exec_())
|
124
manuskript/ui/bulkInfoManager.ui
Normal file
124
manuskript/ui/bulkInfoManager.ui
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BulkInfoManager</class>
|
||||||
|
<widget class="QWidget" name="BulkInfoManager">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>644</width>
|
||||||
|
<height>556</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblStaticMessage">
|
||||||
|
<property name="text">
|
||||||
|
<string>Affected Characters:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblCharactersDynamic">
|
||||||
|
<property name="text">
|
||||||
|
<string>NONE</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView">
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedKingdom"/>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="textElideMode">
|
||||||
|
<enum>Qt::ElideNone</enum>
|
||||||
|
</property>
|
||||||
|
<property name="cornerButtonEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,5,1">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPersoBulkAddInfo">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add entry to the list.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-add">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPersoBulkRmInfo">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove entry from the list.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-remove">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPersoBulkApply">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Adds all items to the selected characters.</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedKingdom"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply Changes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
96
manuskript/ui/characterInfoDialog.py
Normal file
96
manuskript/ui/characterInfoDialog.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'manuskript/ui/characterInfoDialog.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_characterInfoDialog(object):
|
||||||
|
def setupUi(self, characterInfoDialog):
|
||||||
|
characterInfoDialog.setObjectName("characterInfoDialog")
|
||||||
|
characterInfoDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||||
|
characterInfoDialog.resize(481, 148)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(characterInfoDialog.sizePolicy().hasHeightForWidth())
|
||||||
|
characterInfoDialog.setSizePolicy(sizePolicy)
|
||||||
|
characterInfoDialog.setMinimumSize(QtCore.QSize(481, 148))
|
||||||
|
characterInfoDialog.setMaximumSize(QtCore.QSize(481, 148))
|
||||||
|
characterInfoDialog.setTabletTracking(False)
|
||||||
|
characterInfoDialog.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
characterInfoDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
|
||||||
|
self.gridLayout = QtWidgets.QGridLayout(characterInfoDialog)
|
||||||
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
self.label_2 = QtWidgets.QLabel(characterInfoDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
|
||||||
|
self.label_2.setSizePolicy(sizePolicy)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.horizontalLayout_2.addWidget(self.label_2)
|
||||||
|
self.valueLineEdit = QtWidgets.QLineEdit(characterInfoDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.valueLineEdit.sizePolicy().hasHeightForWidth())
|
||||||
|
self.valueLineEdit.setSizePolicy(sizePolicy)
|
||||||
|
self.valueLineEdit.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||||
|
self.valueLineEdit.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||||
|
self.valueLineEdit.setObjectName("valueLineEdit")
|
||||||
|
self.horizontalLayout_2.addWidget(self.valueLineEdit)
|
||||||
|
self.gridLayout.addLayout(self.horizontalLayout_2, 3, 0, 1, 1)
|
||||||
|
self.horizontalLayout_1 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_1.setObjectName("horizontalLayout_1")
|
||||||
|
self.label = QtWidgets.QLabel(characterInfoDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
|
||||||
|
self.label.setSizePolicy(sizePolicy)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.horizontalLayout_1.addWidget(self.label)
|
||||||
|
self.descriptionLineEdit = QtWidgets.QLineEdit(characterInfoDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.descriptionLineEdit.sizePolicy().hasHeightForWidth())
|
||||||
|
self.descriptionLineEdit.setSizePolicy(sizePolicy)
|
||||||
|
self.descriptionLineEdit.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||||
|
self.descriptionLineEdit.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||||
|
self.descriptionLineEdit.setObjectName("descriptionLineEdit")
|
||||||
|
self.horizontalLayout_1.addWidget(self.descriptionLineEdit)
|
||||||
|
self.gridLayout.addLayout(self.horizontalLayout_1, 2, 0, 1, 1)
|
||||||
|
self.buttonBox = QtWidgets.QDialogButtonBox(characterInfoDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.buttonBox.setSizePolicy(sizePolicy)
|
||||||
|
self.buttonBox.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||||
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
|
self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 1)
|
||||||
|
|
||||||
|
self.retranslateUi(characterInfoDialog)
|
||||||
|
self.buttonBox.accepted.connect(characterInfoDialog.accept) # type: ignore
|
||||||
|
self.buttonBox.rejected.connect(characterInfoDialog.reject) # type: ignore
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(characterInfoDialog)
|
||||||
|
characterInfoDialog.setTabOrder(self.descriptionLineEdit, self.valueLineEdit)
|
||||||
|
|
||||||
|
def retranslateUi(self, characterInfoDialog):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
characterInfoDialog.setWindowTitle(_translate("characterInfoDialog", "Add Character Info"))
|
||||||
|
self.label_2.setText(_translate("characterInfoDialog", "Value:"))
|
||||||
|
self.label.setText(_translate("characterInfoDialog", "Name:"))
|
176
manuskript/ui/characterInfoDialog.ui
Normal file
176
manuskript/ui/characterInfoDialog.ui
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>characterInfoDialog</class>
|
||||||
|
<widget class="QDialog" name="characterInfoDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>481</width>
|
||||||
|
<height>148</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>481</width>
|
||||||
|
<height>148</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>481</width>
|
||||||
|
<height>148</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="tabletTracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Add Character Info</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedKingdom"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="3" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Value:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="valueLineEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::RightToLeft</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="descriptionLineEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::RightToLeft</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>descriptionLineEdit</tabstop>
|
||||||
|
<tabstop>valueLineEdit</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>characterInfoDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>259</x>
|
||||||
|
<y>136</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>147</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>characterInfoDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>327</x>
|
||||||
|
<y>136</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>147</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -116,7 +116,7 @@ class fullScreenEditor(QWidget):
|
||||||
self.bottomPanel.layout().addSpacing(24)
|
self.bottomPanel.layout().addSpacing(24)
|
||||||
self.lstThemes = QComboBox(self)
|
self.lstThemes = QComboBox(self)
|
||||||
self.lstThemes.setAttribute(Qt.WA_TranslucentBackground)
|
self.lstThemes.setAttribute(Qt.WA_TranslucentBackground)
|
||||||
paths = allPaths("resources/themes")
|
paths = allPaths(os.path.join("resources", "themes"))
|
||||||
for p in paths:
|
for p in paths:
|
||||||
lst = [i for i in os.listdir(p) if os.path.splitext(i)[1] == ".theme"]
|
lst = [i for i in os.listdir(p) if os.path.splitext(i)[1] == ".theme"]
|
||||||
for t in lst:
|
for t in lst:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# --!-- coding: utf8 --!--
|
# --!-- coding: utf8 --!--
|
||||||
import locale
|
import locale, os
|
||||||
|
|
||||||
from PyQt5.QtCore import QModelIndex, QRect, QPoint
|
from PyQt5.QtCore import QModelIndex, QRect, QPoint
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
@ -95,11 +95,11 @@ class mainEditor(QWidget, Ui_mainEditor):
|
||||||
# Cf. https://github.com/qtproject/qtbase/commit/a8621a3f85e64f1252a80ae81a6e22554f7b3f44
|
# Cf. https://github.com/qtproject/qtbase/commit/a8621a3f85e64f1252a80ae81a6e22554f7b3f44
|
||||||
# Since those are important, we provide fallback.
|
# Since those are important, we provide fallback.
|
||||||
self.btnRedacFolderCork.setIcon(QIcon.fromTheme("view-cards",
|
self.btnRedacFolderCork.setIcon(QIcon.fromTheme("view-cards",
|
||||||
QIcon(appPath("icons/NumixMsk/256x256/actions/view-cards.svg"))))
|
QIcon(appPath(os.path.join("icons", "NumixMsk", "256x256", "actions", "view-cards.svg")))))
|
||||||
self.btnRedacFolderOutline.setIcon(QIcon.fromTheme("view-outline",
|
self.btnRedacFolderOutline.setIcon(QIcon.fromTheme("view-outline",
|
||||||
QIcon(appPath("icons/NumixMsk/256x256/actions/view-outline.svg"))))
|
QIcon(appPath(os.path.join("icons", "NumixMsk", "256x256", "actions", "view-outline.svg")))))
|
||||||
self.btnRedacFolderText.setIcon(QIcon.fromTheme("view-text",
|
self.btnRedacFolderText.setIcon(QIcon.fromTheme("view-text",
|
||||||
QIcon(appPath("icons/NumixMsk/256x256/actions/view-text.svg"))))
|
QIcon(appPath(os.path.join("icons", "NumixMsk", "256x256", "actions", "view-text.svg")))))
|
||||||
|
|
||||||
for btn in [self.btnRedacFolderCork, self.btnRedacFolderText, self.btnRedacFolderOutline]:
|
for btn in [self.btnRedacFolderCork, self.btnRedacFolderText, self.btnRedacFolderOutline]:
|
||||||
btn.setToolTip(btn.text())
|
btn.setToolTip(btn.text())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# --!-- coding: utf8 --!--
|
# --!-- coding: utf8 --!--
|
||||||
import locale
|
import locale, os
|
||||||
|
|
||||||
from PyQt5.QtCore import QModelIndex, QRect, QPoint, Qt, QObject, QSize
|
from PyQt5.QtCore import QModelIndex, QRect, QPoint, Qt, QObject, QSize
|
||||||
from PyQt5.QtGui import QIcon, QPalette
|
from PyQt5.QtGui import QIcon, QPalette
|
||||||
|
@ -150,7 +150,7 @@ class tabSplitter(QWidget, Ui_tabSplitter):
|
||||||
self.updateTargetIcon(self.isTarget)
|
self.updateTargetIcon(self.isTarget)
|
||||||
|
|
||||||
def updateTargetIcon(self, val):
|
def updateTargetIcon(self, val):
|
||||||
icon = QIcon.fromTheme("set-target", QIcon(appPath("icons/NumixMsk/256x256/actions/set-target.svg")))
|
icon = QIcon.fromTheme("set-target", QIcon(appPath(os.path.join("icons", "NumixMsk", "256x256", "actions", "set-target.svg"))))
|
||||||
if not val:
|
if not val:
|
||||||
icon = QIcon(icon.pixmap(128, 128, icon.Disabled))
|
icon = QIcon(icon.pixmap(128, 128, icon.Disabled))
|
||||||
self.btnTarget.setIcon(icon)
|
self.btnTarget.setIcon(icon)
|
||||||
|
|
|
@ -135,9 +135,9 @@ def createThemePreview(theme, screenRect, size=QSize(200, 120)):
|
||||||
|
|
||||||
|
|
||||||
def findThemePath(themeName):
|
def findThemePath(themeName):
|
||||||
p = findFirstFile(re.escape("{}.theme".format(themeName)), "resources/themes")
|
p = findFirstFile(re.escape("{}.theme".format(themeName)), os.path.join("resources", "themes"))
|
||||||
if not p:
|
if not p:
|
||||||
return findFirstFile(r".*\.theme", "resources/themes")
|
return findFirstFile(r".*\.theme", os.path.join("resources", "themes"))
|
||||||
else:
|
else:
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ def addThemePreviewText(pixmap, themeDatas, screenRect):
|
||||||
previewText.setFrameStyle(QFrame.NoFrame)
|
previewText.setFrameStyle(QFrame.NoFrame)
|
||||||
previewText.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
previewText.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
previewText.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
previewText.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
f = QFile(appPath("resources/themes/preview.txt"))
|
f = QFile(appPath(os.path.join("resources", "themes", "preview.txt")))
|
||||||
f.open(QIODevice.ReadOnly)
|
f.open(QIODevice.ReadOnly)
|
||||||
previewText.setPlainText(QTextStream(f).readAll())
|
previewText.setPlainText(QTextStream(f).readAll())
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ class exporterSettings(QWidget, Ui_exporterSettings):
|
||||||
def loadSettings(self):
|
def loadSettings(self):
|
||||||
filename = self.getSettingsPath()
|
filename = self.getSettingsPath()
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
with open(filename, 'r', encoding="utf-8") as f:
|
||||||
self.settings = json.load(f)
|
self.settings = json.load(f)
|
||||||
self.updateFromSettings()
|
self.updateFromSettings()
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class exporterSettings(QWidget, Ui_exporterSettings):
|
||||||
|
|
||||||
def writeSettings(self):
|
def writeSettings(self):
|
||||||
self.getSettings()
|
self.getSettings()
|
||||||
with open(self.getSettingsPath(), 'w', encoding="utf-8") as f:
|
with open(self.getSettingsPath(), 'w', encoding="utf-8", newline="\n") as f:
|
||||||
# json.dumps(json.loads(json.dumps(allSettings)), indent=4, sort_keys=True)
|
# json.dumps(json.loads(json.dumps(allSettings)), indent=4, sort_keys=True)
|
||||||
json.dump(self.settings, f, indent=4, sort_keys=True)
|
json.dump(self.settings, f, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
@ -419,6 +419,3 @@ class exporterSettings(QWidget, Ui_exporterSettings):
|
||||||
|
|
||||||
lst.setMinimumSize(QSize(0, h+2))
|
lst.setMinimumSize(QSize(0, h+2))
|
||||||
lst.setMaximumSize(QSize(16777215, h+2))
|
lst.setMaximumSize(QSize(16777215, h+2))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'manuskript/ui/listDialog_ui.ui'
|
# Form implementation generated from reading ui file 'manuskript/ui/listDialog_ui.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.7
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'manuskript/ui/mainWindow.ui'
|
# Form implementation generated from reading ui file 'manuskript/ui/mainWindow.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
@ -315,6 +315,7 @@ class Ui_MainWindow(object):
|
||||||
self.lstCharacters = characterTreeView(self.groupBox)
|
self.lstCharacters = characterTreeView(self.groupBox)
|
||||||
self.lstCharacters.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.lstCharacters.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.lstCharacters.setDragEnabled(True)
|
self.lstCharacters.setDragEnabled(True)
|
||||||
|
self.lstCharacters.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
self.lstCharacters.setObjectName("lstCharacters")
|
self.lstCharacters.setObjectName("lstCharacters")
|
||||||
self.lstCharacters.headerItem().setText(0, "1")
|
self.lstCharacters.headerItem().setText(0, "1")
|
||||||
self.verticalLayout_8.addWidget(self.lstCharacters)
|
self.verticalLayout_8.addWidget(self.lstCharacters)
|
||||||
|
@ -1015,6 +1016,8 @@ class Ui_MainWindow(object):
|
||||||
self.menuMode.setObjectName("menuMode")
|
self.menuMode.setObjectName("menuMode")
|
||||||
self.menuOrganize = QtWidgets.QMenu(self.menubar)
|
self.menuOrganize = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuOrganize.setObjectName("menuOrganize")
|
self.menuOrganize.setObjectName("menuOrganize")
|
||||||
|
self.menuNavigate = QtWidgets.QMenu(self.menubar)
|
||||||
|
self.menuNavigate.setObjectName("menuNavigate")
|
||||||
MainWindow.setMenuBar(self.menubar)
|
MainWindow.setMenuBar(self.menubar)
|
||||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||||
self.statusbar.setObjectName("statusbar")
|
self.statusbar.setObjectName("statusbar")
|
||||||
|
@ -1199,6 +1202,16 @@ class Ui_MainWindow(object):
|
||||||
self.actMoveDown.setIcon(icon)
|
self.actMoveDown.setIcon(icon)
|
||||||
self.actMoveDown.setShortcut("Ctrl+Shift+Down")
|
self.actMoveDown.setShortcut("Ctrl+Shift+Down")
|
||||||
self.actMoveDown.setObjectName("actMoveDown")
|
self.actMoveDown.setObjectName("actMoveDown")
|
||||||
|
self.actBack = QtWidgets.QAction(MainWindow)
|
||||||
|
icon = QtGui.QIcon.fromTheme("arrow-left")
|
||||||
|
self.actBack.setIcon(icon)
|
||||||
|
self.actBack.setShortcut("Ctrl+<")
|
||||||
|
self.actBack.setObjectName("actBack")
|
||||||
|
self.actForward = QtWidgets.QAction(MainWindow)
|
||||||
|
icon = QtGui.QIcon.fromTheme("arrow-right")
|
||||||
|
self.actForward.setIcon(icon)
|
||||||
|
self.actForward.setShortcut("Ctrl+>")
|
||||||
|
self.actForward.setObjectName("actForward")
|
||||||
self.actRename = QtWidgets.QAction(MainWindow)
|
self.actRename = QtWidgets.QAction(MainWindow)
|
||||||
icon = QtGui.QIcon.fromTheme("edit-rename")
|
icon = QtGui.QIcon.fromTheme("edit-rename")
|
||||||
self.actRename.setIcon(icon)
|
self.actRename.setIcon(icon)
|
||||||
|
@ -1354,9 +1367,12 @@ class Ui_MainWindow(object):
|
||||||
self.menuOrganize.addAction(self.actMerge)
|
self.menuOrganize.addAction(self.actMerge)
|
||||||
self.menuOrganize.addAction(self.actSplitDialog)
|
self.menuOrganize.addAction(self.actSplitDialog)
|
||||||
self.menuOrganize.addAction(self.actSplitCursor)
|
self.menuOrganize.addAction(self.actSplitCursor)
|
||||||
|
self.menuNavigate.addAction(self.actBack)
|
||||||
|
self.menuNavigate.addAction(self.actForward)
|
||||||
self.menubar.addAction(self.menuFile.menuAction())
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
self.menubar.addAction(self.menuEdit.menuAction())
|
self.menubar.addAction(self.menuEdit.menuAction())
|
||||||
self.menubar.addAction(self.menuOrganize.menuAction())
|
self.menubar.addAction(self.menuOrganize.menuAction())
|
||||||
|
self.menubar.addAction(self.menuNavigate.menuAction())
|
||||||
self.menubar.addAction(self.menuView.menuAction())
|
self.menubar.addAction(self.menuView.menuAction())
|
||||||
self.menubar.addAction(self.menuTools.menuAction())
|
self.menubar.addAction(self.menuTools.menuAction())
|
||||||
self.menubar.addAction(self.menuHelp.menuAction())
|
self.menubar.addAction(self.menuHelp.menuAction())
|
||||||
|
@ -1558,6 +1574,7 @@ class Ui_MainWindow(object):
|
||||||
self.menuView.setTitle(_translate("MainWindow", "&View"))
|
self.menuView.setTitle(_translate("MainWindow", "&View"))
|
||||||
self.menuMode.setTitle(_translate("MainWindow", "&Mode"))
|
self.menuMode.setTitle(_translate("MainWindow", "&Mode"))
|
||||||
self.menuOrganize.setTitle(_translate("MainWindow", "Organi&ze"))
|
self.menuOrganize.setTitle(_translate("MainWindow", "Organi&ze"))
|
||||||
|
self.menuNavigate.setTitle(_translate("MainWindow", "&Navigate"))
|
||||||
self.dckCheatSheet.setWindowTitle(_translate("MainWindow", "Cheat Sheet"))
|
self.dckCheatSheet.setWindowTitle(_translate("MainWindow", "Cheat Sheet"))
|
||||||
self.dckSearch.setWindowTitle(_translate("MainWindow", "Search"))
|
self.dckSearch.setWindowTitle(_translate("MainWindow", "Search"))
|
||||||
self.dckNavigation.setWindowTitle(_translate("MainWindow", "&Navigation"))
|
self.dckNavigation.setWindowTitle(_translate("MainWindow", "&Navigation"))
|
||||||
|
@ -1591,6 +1608,8 @@ class Ui_MainWindow(object):
|
||||||
self.actDelete.setText(_translate("MainWindow", "&Delete"))
|
self.actDelete.setText(_translate("MainWindow", "&Delete"))
|
||||||
self.actMoveUp.setText(_translate("MainWindow", "&Move Up"))
|
self.actMoveUp.setText(_translate("MainWindow", "&Move Up"))
|
||||||
self.actMoveDown.setText(_translate("MainWindow", "M&ove Down"))
|
self.actMoveDown.setText(_translate("MainWindow", "M&ove Down"))
|
||||||
|
self.actBack.setText(_translate("MainWindow", "Go &back"))
|
||||||
|
self.actForward.setText(_translate("MainWindow", "Go &forward"))
|
||||||
self.actRename.setText(_translate("MainWindow", "&Rename"))
|
self.actRename.setText(_translate("MainWindow", "&Rename"))
|
||||||
self.actHeaderSetextL1.setText(_translate("MainWindow", "&Level 1 (setext)"))
|
self.actHeaderSetextL1.setText(_translate("MainWindow", "&Level 1 (setext)"))
|
||||||
self.actHeaderSetextL2.setText(_translate("MainWindow", "Level &2"))
|
self.actHeaderSetextL2.setText(_translate("MainWindow", "Level &2"))
|
||||||
|
|
|
@ -670,6 +670,9 @@
|
||||||
<property name="dragEnabled">
|
<property name="dragEnabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
|
</property>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">1</string>
|
<string notr="true">1</string>
|
||||||
|
@ -2121,9 +2124,17 @@
|
||||||
<addaction name="actSplitDialog"/>
|
<addaction name="actSplitDialog"/>
|
||||||
<addaction name="actSplitCursor"/>
|
<addaction name="actSplitCursor"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuNavigate">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Navigate</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actBack"/>
|
||||||
|
<addaction name="actForward"/>
|
||||||
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuEdit"/>
|
<addaction name="menuEdit"/>
|
||||||
<addaction name="menuOrganize"/>
|
<addaction name="menuOrganize"/>
|
||||||
|
<addaction name="menuNavigate"/>
|
||||||
<addaction name="menuView"/>
|
<addaction name="menuView"/>
|
||||||
<addaction name="menuTools"/>
|
<addaction name="menuTools"/>
|
||||||
<addaction name="menuHelp"/>
|
<addaction name="menuHelp"/>
|
||||||
|
@ -2565,6 +2576,30 @@
|
||||||
<string notr="true">Ctrl+Shift+Down</string>
|
<string notr="true">Ctrl+Shift+Down</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actBack">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="arrow-left">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Go &back</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string notr="true">Ctrl+<</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actForward">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="arrow-right">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Go &forward</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string notr="true">Ctrl+></string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actRename">
|
<action name="actRename">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="edit-rename">
|
<iconset theme="edit-rename">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'manuskript/ui/settings_ui.ui'
|
# Form implementation generated from reading ui file 'manuskript/ui/settings_ui.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
# --!-- coding: utf8 --!--
|
# --!-- coding: utf8 --!--
|
||||||
from PyQt5.QtCore import QSize, QModelIndex, Qt
|
from PyQt5.QtCore import QSize, QModelIndex, Qt
|
||||||
from PyQt5.QtGui import QPixmap, QColor, QIcon, QBrush
|
from PyQt5.QtGui import QPixmap, QColor, QIcon, QBrush
|
||||||
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QColorDialog
|
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QColorDialog, QDialog, QMessageBox
|
||||||
|
|
||||||
from manuskript.enums import Character
|
from manuskript.enums import Character
|
||||||
from manuskript.functions import iconColor, mainWindow
|
from manuskript.functions import iconColor, mainWindow
|
||||||
from manuskript.ui import style as S
|
from manuskript.ui import style as S
|
||||||
|
from manuskript.ui import characterInfoDialog
|
||||||
|
|
||||||
|
|
||||||
class characterTreeView(QTreeWidget):
|
class characterTreeView(QTreeWidget):
|
||||||
|
@ -137,15 +138,29 @@ class characterTreeView(QTreeWidget):
|
||||||
|
|
||||||
self._model.addCharacter(importance=curr_importance)
|
self._model.addCharacter(importance=curr_importance)
|
||||||
|
|
||||||
def removeCharacter(self):
|
def removeCharacters(self):
|
||||||
"""
|
"""
|
||||||
Removes selected character.
|
Removes selected characters.
|
||||||
"""
|
"""
|
||||||
ID = self.currentCharacterID()
|
IDs = self.currentCharacterIDs()
|
||||||
if ID is None:
|
|
||||||
|
# If none of the IDs are valid, do nothing.
|
||||||
|
if not any(IDs):
|
||||||
return None
|
return None
|
||||||
self._model.removeCharacter(ID)
|
|
||||||
return ID
|
#Get confirmation from user
|
||||||
|
confirm = QMessageBox.warning(
|
||||||
|
self, "Delete selected character(s)?",
|
||||||
|
"Are you sure you want to delete the selected character(s)?",
|
||||||
|
QMessageBox.Yes | QMessageBox.No
|
||||||
|
)
|
||||||
|
if confirm != QMessageBox.Yes:
|
||||||
|
return None
|
||||||
|
|
||||||
|
#Delete all selected characters
|
||||||
|
for ID in IDs:
|
||||||
|
self._model.removeCharacter(ID)
|
||||||
|
return IDs
|
||||||
|
|
||||||
def choseCharacterColor(self):
|
def choseCharacterColor(self):
|
||||||
ID = self.currentCharacterID()
|
ID = self.currentCharacterID()
|
||||||
|
@ -170,7 +185,21 @@ class characterTreeView(QTreeWidget):
|
||||||
mainWindow().updateCharacterPOVState(ID)
|
mainWindow().updateCharacterPOVState(ID)
|
||||||
|
|
||||||
def addCharacterInfo(self):
|
def addCharacterInfo(self):
|
||||||
self._model.addCharacterInfo(self.currentCharacterID())
|
#Setting up dialog
|
||||||
|
charInfoDialog = QDialog()
|
||||||
|
charInfoUi = characterInfoDialog.Ui_characterInfoDialog()
|
||||||
|
charInfoUi.setupUi(charInfoDialog)
|
||||||
|
|
||||||
|
if charInfoDialog.exec_() == QDialog.Accepted:
|
||||||
|
# User clicked OK, get the input values
|
||||||
|
description = charInfoUi.descriptionLineEdit.text()
|
||||||
|
value = charInfoUi.valueLineEdit.text()
|
||||||
|
|
||||||
|
# Add the character info with the input values
|
||||||
|
ID = self.currentCharacterID()
|
||||||
|
self._model.addCharacterInfo(ID, description, value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def removeCharacterInfo(self):
|
def removeCharacterInfo(self):
|
||||||
self._model.removeCharacterInfo(self.currentCharacterID())
|
self._model.removeCharacterInfo(self.currentCharacterID())
|
||||||
|
@ -182,6 +211,14 @@ class characterTreeView(QTreeWidget):
|
||||||
|
|
||||||
return ID
|
return ID
|
||||||
|
|
||||||
|
def currentCharacterIDs(self): #Exactly like currentCharacterID(), except for multiselection
|
||||||
|
IDs = []
|
||||||
|
for item in self.selectedItems():
|
||||||
|
ID = item.data(0, Qt.UserRole)
|
||||||
|
if ID is not None:
|
||||||
|
IDs.append(ID)
|
||||||
|
return IDs
|
||||||
|
|
||||||
def currentCharacter(self):
|
def currentCharacter(self):
|
||||||
"""
|
"""
|
||||||
Returns the selected character
|
Returns the selected character
|
||||||
|
@ -189,6 +226,16 @@ class characterTreeView(QTreeWidget):
|
||||||
"""
|
"""
|
||||||
ID = self.currentCharacterID()
|
ID = self.currentCharacterID()
|
||||||
return self._model.getCharacterByID(ID)
|
return self._model.getCharacterByID(ID)
|
||||||
|
def currentCharacters(self):
|
||||||
|
"""
|
||||||
|
Returns the selected characters (when multiple are selected)
|
||||||
|
@return: List of Characters
|
||||||
|
"""
|
||||||
|
IDs = self.currentCharacterIDs()
|
||||||
|
characters = []
|
||||||
|
for ID in IDs:
|
||||||
|
characters.append(self._model.getCharacterByID(ID))
|
||||||
|
return characters
|
||||||
|
|
||||||
def getItemByID(self, ID):
|
def getItemByID(self, ID):
|
||||||
for t in range(self.topLevelItemCount()):
|
for t in range(self.topLevelItemCount()):
|
||||||
|
|
|
@ -320,6 +320,7 @@ class corkDelegate(QStyledItemDelegate):
|
||||||
# Draw title
|
# Draw title
|
||||||
p.save()
|
p.save()
|
||||||
text = index.data()
|
text = index.data()
|
||||||
|
textColor = None
|
||||||
|
|
||||||
if text:
|
if text:
|
||||||
p.setPen(Qt.black)
|
p.setPen(Qt.black)
|
||||||
|
@ -384,7 +385,7 @@ class corkDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
# Draw Summary
|
# Draw Summary
|
||||||
# One line
|
# One line
|
||||||
if lineSummary:
|
if lineSummary and textColor:
|
||||||
p.save()
|
p.save()
|
||||||
f = QFont(option.font)
|
f = QFont(option.font)
|
||||||
f.setBold(True)
|
f.setBold(True)
|
||||||
|
@ -396,7 +397,7 @@ class corkDelegate(QStyledItemDelegate):
|
||||||
p.restore()
|
p.restore()
|
||||||
|
|
||||||
# Full summary
|
# Full summary
|
||||||
if fullSummary:
|
if fullSummary and textColor:
|
||||||
p.save()
|
p.save()
|
||||||
p.setFont(option.font)
|
p.setFont(option.font)
|
||||||
p.setPen(textColor)
|
p.setPen(textColor)
|
||||||
|
|
|
@ -65,13 +65,17 @@ class plotTreeView(QTreeWidget):
|
||||||
return find(self.invisibleRootItem(), ID)
|
return find(self.invisibleRootItem(), ID)
|
||||||
|
|
||||||
def currentPlotIndex(self):
|
def currentPlotIndex(self):
|
||||||
"Returns index of the current item in plot model."
|
"Returns index of the current item in plot model."
|
||||||
|
return self._model.getIndexFromID(self.currentPlotID())
|
||||||
|
|
||||||
|
def currentPlotID(self):
|
||||||
|
"Returns ID of the current item in plot model."
|
||||||
ID = None
|
ID = None
|
||||||
if self.currentItem():
|
if self.currentItem():
|
||||||
ID = self.currentItem().data(0, Qt.UserRole)
|
ID = self.currentItem().data(0, Qt.UserRole)
|
||||||
|
|
||||||
return self._model.getIndexFromID(ID)
|
return ID
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# UPDATES
|
# UPDATES
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue