From c6f3a904d5ce508997b36c140f1676ff8995e5a7 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Tue, 10 Jan 2023 07:39:27 -0500 Subject: [PATCH 01/21] Added all the files deleted extra saved things Deleted backups Delete character_details_template_editor.glade~ --- test_io.py | 24 +++ ui/about.glade | 8 +- ui/character_details_template_editor.glade | 202 +++++++++++++++++++++ ui/characters.glade | 15 +- ui/general.glade | 17 +- ui/main.glade | 8 + ui/quote_of_the_day.glade | 71 ++++++++ 7 files changed, 340 insertions(+), 5 deletions(-) create mode 100644 test_io.py create mode 100644 ui/character_details_template_editor.glade create mode 100644 ui/quote_of_the_day.glade diff --git a/test_io.py b/test_io.py new file mode 100644 index 00000000..a4971543 --- /dev/null +++ b/test_io.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# I put this here because otherwise I couldn't run it. +# I also added some tests and had to modify this to get it to run -- ShadowOfHassen +import os +import sys + +# gi +import gi +gi.require_version('GdkPixbuf', '2.0') +from gi.repository import GdkPixbuf + +realpath = os.path.realpath(__file__) +LOGO_FILE = 'icons/Manuskript/manuskript.svg' +#sys.path.insert(1, os.path.join(os.path.dirname(realpath), '..')) + +from manuskript.ui import MainWindow + + +window = MainWindow("sample-projects/book-of-acts" + ".msk") +# Let's make this a bit fancier +window.window.set_icon(GdkPixbuf.Pixbuf.new_from_file(LOGO_FILE)) + +window.run() diff --git a/ui/about.glade b/ui/about.glade index b96638e1..b29464fd 100644 --- a/ui/about.glade +++ b/ui/about.glade @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + False + + + True + False + vertical + + + True + False + + + True + False + Edit Charecter Details Template + + + True + True + True + 4 + 4 + 4 + 4 + + + True + False + go-previous-symbolic + + + + + + + + + False + True + 0 + + + + + True + False + + + True + False + vertical + + + 200 + True + False + True + True + 0 + 0 + + + True + True + in + + + True + False + + + True + True + details_store + True + 0 + both + + + + + + Name + + + True + + + 0 + + + + + + + Value + + + True + + + 1 + + + + + + + + + + + + + + + + True + True + 0 + + + + + True + False + 4 + + + True + True + True + + + True + False + list-add + + + + + False + True + 0 + + + + + True + True + True + + + True + False + list-remove + + + + + False + True + 1 + + + + + + + + False + False + 1 + + + + + + + False + True + 1 + + + + + + diff --git a/ui/characters.glade b/ui/characters.glade index e17aae5b..a1559d09 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -933,10 +933,23 @@ summary False True - end 3 + + + Append Detail Template + True + True + True + + + + False + True + 4 + + False diff --git a/ui/general.glade b/ui/general.glade index 7f894133..44c04442 100644 --- a/ui/general.glade +++ b/ui/general.glade @@ -1,5 +1,5 @@ - + + + + True + False + + + True + False + + + -1 + + + + + + True + False + True + 20 + True + + + True + False + label + + + 2 + 1 + + + + + True + False + label + + + 2 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8f899b1accb9de1246df5201aac6f6015e8c2cfb Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Tue, 10 Jan 2023 07:39:27 -0500 Subject: [PATCH 02/21] Added all the files deleted extra saved things Deleted backups Delete character_details_template_editor.glade~ Fixed Some things that should have been there. --- manuskript/data/characters_template.py | 30 +++ manuskript/data/project.py | 7 + manuskript/ui/mainWindow.py | 8 +- .../ui/tools/Character_Template_Editor.py | 150 +++++++++++++ manuskript/ui/tools/__init__.py | 1 + manuskript/ui/views/charactersView.py | 35 ++- manuskript/util/unique_name_checker.py | 16 ++ test_io.py | 24 +++ ui/about.glade | 8 +- ui/character_details_template_editor.glade | 202 ++++++++++++++++++ ui/characters.glade | 15 +- ui/general.glade | 17 +- ui/main.glade | 8 + ui/quote_of_the_day.glade | 71 ++++++ 14 files changed, 579 insertions(+), 13 deletions(-) create mode 100644 manuskript/data/characters_template.py create mode 100644 manuskript/ui/tools/Character_Template_Editor.py create mode 100644 manuskript/util/unique_name_checker.py create mode 100644 test_io.py create mode 100644 ui/character_details_template_editor.glade create mode 100644 ui/quote_of_the_day.glade diff --git a/manuskript/data/characters_template.py b/manuskript/data/characters_template.py new file mode 100644 index 00000000..b613892c --- /dev/null +++ b/manuskript/data/characters_template.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +import os + +#from io.jsonFile import* # I need to figure out how to import this. io is also a package in python +from collections import OrderedDict + + +# So this is a template for charecter details +# It is edited by the Charecter Template Editor +# Most of the code is taken from charecters.py +# I think this should have a custom save that's like a .json file in the main part of the manuskript save + +#Main Class +class CharacterDetailTemplate: + + details = {'Age':'','Birthdate':'', + 'Eye Color':'','Hair Color':'', + 'Handed':''} # We'll make a default template + + + + # TODO saving + def save(self): + pass + + def load(self): + pass + diff --git a/manuskript/data/project.py b/manuskript/data/project.py index ebce4e42..488e7d9d 100644 --- a/manuskript/data/project.py +++ b/manuskript/data/project.py @@ -1,9 +1,12 @@ #!/usr/bin/env python # --!-- coding: utf8 --!-- +# Imports +# Python bundled modules import os from zipfile import BadZipFile +# Manuskript modules from manuskript.data.version import Version, CURRENT_MSK_VERSION from manuskript.data.info import Info from manuskript.data.summary import Summary @@ -15,6 +18,9 @@ from manuskript.data.plots import Plots from manuskript.data.world import World from manuskript.data.outline import Outline from manuskript.data.revisions import Revisions +# This is for the charecter template +from manuskript.data.characters_template import CharacterDetailTemplate + from manuskript.io.mskFile import MskFile @@ -34,6 +40,7 @@ class Project: self.world = World(self.file.dir_path) self.outline = Outline(self.file.dir_path, self.plots, self.labels, self.statuses) self.revisions = Revisions(self.file.dir_path) + self.character_template = CharacterDetailTemplate() def __del__(self): del self.file diff --git a/manuskript/ui/mainWindow.py b/manuskript/ui/mainWindow.py index 87756323..d92ad3b3 100644 --- a/manuskript/ui/mainWindow.py +++ b/manuskript/ui/mainWindow.py @@ -65,7 +65,7 @@ class MainWindow: self.generalView = MainWindow.packViewIntoSlot(builder, "general_slot", GeneralView, self.project.info) self.summaryView = MainWindow.packViewIntoSlot(builder, "summary_slot", SummaryView, self.project.summary) - self.charactersView = MainWindow.packViewIntoSlot(builder, "characters_slot", CharactersView, self.project.characters) + self.charactersView = MainWindow.packViewIntoSlot(builder, "characters_slot", CharactersView, self.project) # Just project because we need it for characters and the template self.plotView = MainWindow.packViewIntoSlot(builder, "plot_slot", PlotView, self.project.plots) self.worldView = MainWindow.packViewIntoSlot(builder, "world_slot", WorldView, self.project.world) self.outlineView = MainWindow.packViewIntoSlot(builder, "outline_slot", OutlineView, self.project.outline) @@ -74,12 +74,14 @@ class MainWindow: self.startupWindow = StartupWindow(self) self.aboutDialog = AboutDialog(self) self.frequencyWindow = FrequencyWindow(self) + self.character_template_window = CharacterTemplateEditorWindow(self) self.settingsWindow = SettingsWindow(self) self.windows = [ self.startupWindow, self.aboutDialog, self.frequencyWindow, + self.character_template_window, self.settingsWindow ] @@ -90,6 +92,7 @@ class MainWindow: bindMenuItem(builder, "settings_menu_item", self.settingsAction) bindMenuItem(builder, "frequency_menu_item", self.frequencyAction) + bindMenuItem(builder, "character_details_template_editor", self.character_details_template_editor_action) bindMenuItem(builder, "about_menu_item", self.aboutAction) def getProject(self): @@ -119,6 +122,9 @@ class MainWindow: def frequencyAction(self, menuItem: Gtk.MenuItem): self.frequencyWindow.show() + + def character_details_template_editor_action(self, menuItem: Gtk.MenuItem): + self.character_template_window.show() def aboutAction(self, menuItem: Gtk.MenuItem): self.aboutDialog.show() diff --git a/manuskript/ui/tools/Character_Template_Editor.py b/manuskript/ui/tools/Character_Template_Editor.py new file mode 100644 index 00000000..ecbf7dd5 --- /dev/null +++ b/manuskript/ui/tools/Character_Template_Editor.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +# Imports +# Gi +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GObject, Gtk, Handy + +# Manuskript +from manuskript.ui.abstractDialog import AbstractDialog +from manuskript.util import unique_name_checker + +# I lifted a lot of this code from frequencyWindow +# With a bit more stuff from charactersView + +class CharacterTemplateEditorWindow(AbstractDialog): + + def __init__(self, mainWindow): + AbstractDialog.__init__(self, mainWindow, "ui/character_details_template_editor.glade", "character_details_template_editor") + + self.headerBar = None + self.back = None + self.wordLeaflet = None + self.analyzeWords = None + self.analyzePhrases = None + + def initWindow(self, builder, window): + self.headerBar = builder.get_object("header_bar") + self.back = builder.get_object("back") + + self.character_leaflet = builder.get_object("character_details_leaflet") + + self.character_leaflet.bind_property("folded", self.back, "visible", GObject.BindingFlags.SYNC_CREATE) + self.character_leaflet.bind_property("folded", self.headerBar, "show-close-button", GObject.BindingFlags.SYNC_CREATE | + GObject.BindingFlags.INVERT_BOOLEAN) + + + self.back.connect("clicked", self._backClicked) + + #Liking Stuff stole from charactersView + self.detailsStore = builder.get_object("details_store") + self.detailsSelection = builder.get_object("details_selection") + self.addDetailsButton = builder.get_object("add_details") + self.removeDetailsButton = builder.get_object("remove_details") + self.append_details_template_button = builder.get_object("appened_details_template") + self.detailsNameRenderer = builder.get_object("details_name") + self.detailsValueRenderer = builder.get_object("details_value") + + self.addDetailsButton.connect("clicked", self.addDetailsClicked) + self.removeDetailsButton.connect("clicked", self.removeDetailsClicked) + + self.detailsNameRenderer.connect("edited", self.detailsNameEdited) + self.detailsValueRenderer.connect("edited", self.detailsValueEdited) + + self.populate_tree() + + + + def _backClicked(self, button: Gtk.Button): + if self.wordLeaflet.get_visible_child_name() == "wordlist_view": + self.wordLeaflet.set_visible_child_name("wordfilter_view") + else: + self.hide() + + # So this adds any previously added parts to the template + def populate_tree(self): + for name, value in self.mainWindow.project.character_template.details.items(): + tree_iter = self.detailsStore.append() + + if tree_iter is None: + return + + + self.detailsStore.set_value(tree_iter, 0, name) + self.detailsStore.set_value(tree_iter, 1, value) + +# Functions stole From charactersView + def addDetailsClicked(self, button: Gtk.Button): + + tree_iter = self.detailsStore.append() + + if tree_iter is None: + return + + name = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, "Description") + value = "Value" + + self.detailsStore.set_value(tree_iter, 0, name) + self.detailsStore.set_value(tree_iter, 1, value) + + self.mainWindow.project.character_template.details[name] = value + + def removeDetailsClicked(self, button: Gtk.Button): + + model, tree_iter = self.detailsSelection.get_selected() + + if (model is None) or (tree_iter is None): + return + + name = model.get_value(tree_iter, 0) + model.remove(tree_iter) + + self.mainWindow.project.character_template.details.pop(name) + + def detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): + + model, tree_iter = self.detailsSelection.get_selected() + + if (model is None) or (tree_iter is None): + return + text_to_set = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, text) + name = model.get_value(tree_iter, 0) + model.set_value(tree_iter, 0, text_to_set) + # There was an error with this line but it didn't seem to do anything bad. + self.mainWindow.project.character_template.details[text_to_set] = self.mainWindow.project.character_template.details.pop(name) + + def detailsValueEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): + + model, tree_iter = self.detailsSelection.get_selected() + + if (model is None) or (tree_iter is None): + return + + name = model.get_value(tree_iter, 0) + model.set_value(tree_iter, 1, text) + + self.mainWindow.project.character_template.details[name] = text + + def nameChanged(self, buffer: Gtk.EntryBuffer): + + text = buffer.get_text() + name = invalidString(text) + + self.character.name = name + + character_id = self.character.UID.value + + for row in self.charactersStore: + if row[0] == character_id: + row[1] = validString(name) + break + + def nameDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int): + self.nameChanged(buffer) + + def nameInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int): + self.nameChanged(buffer) diff --git a/manuskript/ui/tools/__init__.py b/manuskript/ui/tools/__init__.py index 7cd78588..ff95f6bf 100644 --- a/manuskript/ui/tools/__init__.py +++ b/manuskript/ui/tools/__init__.py @@ -2,3 +2,4 @@ # -*- coding: utf-8 -*- from manuskript.ui.tools.frequencyWindow import FrequencyWindow +from manuskript.ui.tools.Character_Template_Editor import CharacterTemplateEditorWindow \ No newline at end of file diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index 1a32619c..dbcc69de 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -8,13 +8,14 @@ from gi.repository import Gtk from manuskript.data import Characters, Character, Importance, Color from manuskript.ui.util import rgbaFromColor, pixbufFromColor -from manuskript.util import validString, invalidString, validInt, invalidInt +from manuskript.util import validString, invalidString, validInt, invalidInt, unique_name_checker class CharactersView: - def __init__(self, characters: Characters): - self.characters = characters + def __init__(self,project): + self.character_template = project.character_template # The template for detailed info + self.characters = project.characters self.character = None builder = Gtk.Builder() @@ -74,13 +75,19 @@ class CharactersView: self.detailsSelection = builder.get_object("details_selection") self.addDetailsButton = builder.get_object("add_details") self.removeDetailsButton = builder.get_object("remove_details") + self.append_details_template_button = builder.get_object("appened_details_template") self.detailsNameRenderer = builder.get_object("details_name") self.detailsValueRenderer = builder.get_object("details_value") self.addDetailsButton.connect("clicked", self.addDetailsClicked) self.removeDetailsButton.connect("clicked", self.removeDetailsClicked) + # This is to append the template + self.append_details_template_button.connect("clicked", self.append_template_clicked) + self.detailsNameRenderer.connect("edited", self.detailsNameEdited) self.detailsValueRenderer.connect("edited", self.detailsValueEdited) + + self.nameBuffer = builder.get_object("name") self.motivationBuffer = builder.get_object("motivation") @@ -105,6 +112,7 @@ class CharactersView: self.notesBuffer.connect("changed", self.notesChanged) self.unloadCharacterData() + def refreshCharacterStore(self): self.charactersStore.clear() @@ -297,7 +305,7 @@ class CharactersView: if tree_iter is None: return - name = "Description" + name = unique_name_checker.get_unique_name_for_dictionary(self.character.details, "Description") value = "Value" self.detailsStore.set_value(tree_iter, 0, name) @@ -318,6 +326,18 @@ class CharactersView: model.remove(tree_iter) self.character.details.pop(name) + + # This is the the template code + # It appends the template onto the code + def append_template_clicked(self, button): + if self.character is None: + return + # This following bit could be turned into a def + for x in self.character_template.details: + self.character.details[x]= self.character_template.details[x] + + #We have to reload the charecter + self.loadCharacterData(self.character) def detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): if self.character is None: @@ -327,11 +347,12 @@ class CharactersView: if (model is None) or (tree_iter is None): return - + + text_to_set = unique_name_checker.get_unique_name_for_dictionary(self.character.details, text) name = model.get_value(tree_iter, 0) - model.set_value(tree_iter, 0, text) + model.set_value(tree_iter, 0, text_to_set) - self.character.details[text] = self.character.details.pop(name) + self.character.details[text_to_set] = self.character.details.pop(name) def detailsValueEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): if self.character is None: diff --git a/manuskript/util/unique_name_checker.py b/manuskript/util/unique_name_checker.py new file mode 100644 index 00000000..423ef52e --- /dev/null +++ b/manuskript/util/unique_name_checker.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# So this thing changes a name until it works with a dictionary +# Ie. if you have a dictioary {'Item':1,'Item2':1,'Item3':1} and if you add an item it'll be Item4 +# It works only on strings + +def get_unique_name_for_dictionary(dictionary, name): + count = 1 + test_name = name + while test_name in dictionary: + count += 1 + test_name = str(name) +(str(count)) + + return test_name + diff --git a/test_io.py b/test_io.py new file mode 100644 index 00000000..a4971543 --- /dev/null +++ b/test_io.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# I put this here because otherwise I couldn't run it. +# I also added some tests and had to modify this to get it to run -- ShadowOfHassen +import os +import sys + +# gi +import gi +gi.require_version('GdkPixbuf', '2.0') +from gi.repository import GdkPixbuf + +realpath = os.path.realpath(__file__) +LOGO_FILE = 'icons/Manuskript/manuskript.svg' +#sys.path.insert(1, os.path.join(os.path.dirname(realpath), '..')) + +from manuskript.ui import MainWindow + + +window = MainWindow("sample-projects/book-of-acts" + ".msk") +# Let's make this a bit fancier +window.window.set_icon(GdkPixbuf.Pixbuf.new_from_file(LOGO_FILE)) + +window.run() diff --git a/ui/about.glade b/ui/about.glade index b96638e1..b29464fd 100644 --- a/ui/about.glade +++ b/ui/about.glade @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + False + + + True + False + vertical + + + True + False + + + True + False + Edit Charecter Details Template + + + True + True + True + 4 + 4 + 4 + 4 + + + True + False + go-previous-symbolic + + + + + + + + + False + True + 0 + + + + + True + False + + + True + False + vertical + + + 200 + True + False + True + True + 0 + 0 + + + True + True + in + + + True + False + + + True + True + details_store + True + 0 + both + + + + + + Name + + + True + + + 0 + + + + + + + Value + + + True + + + 1 + + + + + + + + + + + + + + + + True + True + 0 + + + + + True + False + 4 + + + True + True + True + + + True + False + list-add + + + + + False + True + 0 + + + + + True + True + True + + + True + False + list-remove + + + + + False + True + 1 + + + + + + + + False + False + 1 + + + + + + + False + True + 1 + + + + + + diff --git a/ui/characters.glade b/ui/characters.glade index e17aae5b..a1559d09 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -933,10 +933,23 @@ summary False True - end 3 + + + Append Detail Template + True + True + True + + + + False + True + 4 + + False diff --git a/ui/general.glade b/ui/general.glade index 7f894133..44c04442 100644 --- a/ui/general.glade +++ b/ui/general.glade @@ -1,5 +1,5 @@ - + + + + True + False + + + True + False + + + -1 + + + + + + True + False + True + 20 + True + + + True + False + label + + + 2 + 1 + + + + + True + False + label + + + 2 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4ccd78bc7de02a2288a730d6f977131674010cc4 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Fri, 3 Feb 2023 16:01:17 +0100 Subject: [PATCH 03/21] Fix multiple warnings, errors and naming issues Signed-off-by: TheJackiMonster --- manuskript/ui/mainWindow.py | 2 +- manuskript/ui/tools/__init__.py | 2 +- ...e_Editor.py => characterTemplateWindow.py} | 91 +++------ ui/character_details_template_editor.glade | 191 +++++++++--------- ui/characters.glade | 5 +- ui/frequency.glade | 10 +- 6 files changed, 128 insertions(+), 173 deletions(-) rename manuskript/ui/tools/{Character_Template_Editor.py => characterTemplateWindow.py} (55%) diff --git a/manuskript/ui/mainWindow.py b/manuskript/ui/mainWindow.py index 302898c2..a063d7f7 100644 --- a/manuskript/ui/mainWindow.py +++ b/manuskript/ui/mainWindow.py @@ -75,7 +75,7 @@ class MainWindow: self.startupWindow = StartupWindow(self) self.aboutDialog = AboutDialog(self) self.frequencyWindow = FrequencyWindow(self) - self.characterTemplateWindow = CharacterTemplateEditorWindow(self) + self.characterTemplateWindow = CharacterTemplateWindow(self) self.settingsWindow = SettingsWindow(self) self.windows = [ diff --git a/manuskript/ui/tools/__init__.py b/manuskript/ui/tools/__init__.py index ff95f6bf..674f8ba8 100644 --- a/manuskript/ui/tools/__init__.py +++ b/manuskript/ui/tools/__init__.py @@ -2,4 +2,4 @@ # -*- coding: utf-8 -*- from manuskript.ui.tools.frequencyWindow import FrequencyWindow -from manuskript.ui.tools.Character_Template_Editor import CharacterTemplateEditorWindow \ No newline at end of file +from manuskript.ui.tools.characterTemplateWindow import CharacterTemplateWindow diff --git a/manuskript/ui/tools/Character_Template_Editor.py b/manuskript/ui/tools/characterTemplateWindow.py similarity index 55% rename from manuskript/ui/tools/Character_Template_Editor.py rename to manuskript/ui/tools/characterTemplateWindow.py index ecbf7dd5..75c10148 100644 --- a/manuskript/ui/tools/Character_Template_Editor.py +++ b/manuskript/ui/tools/characterTemplateWindow.py @@ -11,81 +11,75 @@ from gi.repository import GObject, Gtk, Handy # Manuskript from manuskript.ui.abstractDialog import AbstractDialog -from manuskript.util import unique_name_checker +from manuskript.util import unique_name_checker, invalidString, validString + # I lifted a lot of this code from frequencyWindow # With a bit more stuff from charactersView -class CharacterTemplateEditorWindow(AbstractDialog): +class CharacterTemplateWindow(AbstractDialog): def __init__(self, mainWindow): - AbstractDialog.__init__(self, mainWindow, "ui/character_details_template_editor.glade", "character_details_template_editor") + AbstractDialog.__init__(self, mainWindow, "ui/character_details_template_editor.glade", + "character_details_template_editor") self.headerBar = None self.back = None - self.wordLeaflet = None - self.analyzeWords = None - self.analyzePhrases = None + + self.detailsStore = None + self.detailsSelection = None + self.addDetailsButton = None + self.removeDetailsButton = None + self.appendDetailsTemplateButton = None + self.detailsNameRenderer = None + self.detailsValueRenderer = None def initWindow(self, builder, window): self.headerBar = builder.get_object("header_bar") self.back = builder.get_object("back") - - self.character_leaflet = builder.get_object("character_details_leaflet") - - self.character_leaflet.bind_property("folded", self.back, "visible", GObject.BindingFlags.SYNC_CREATE) - self.character_leaflet.bind_property("folded", self.headerBar, "show-close-button", GObject.BindingFlags.SYNC_CREATE | - GObject.BindingFlags.INVERT_BOOLEAN) - self.back.connect("clicked", self._backClicked) - #Liking Stuff stole from charactersView + # Liking Stuff stole from charactersView self.detailsStore = builder.get_object("details_store") self.detailsSelection = builder.get_object("details_selection") self.addDetailsButton = builder.get_object("add_details") self.removeDetailsButton = builder.get_object("remove_details") - self.append_details_template_button = builder.get_object("appened_details_template") + self.appendDetailsTemplateButton = builder.get_object("appened_details_template") self.detailsNameRenderer = builder.get_object("details_name") self.detailsValueRenderer = builder.get_object("details_value") - self.addDetailsButton.connect("clicked", self.addDetailsClicked) - self.removeDetailsButton.connect("clicked", self.removeDetailsClicked) + self.addDetailsButton.connect("clicked", self._addDetailsClicked) + self.removeDetailsButton.connect("clicked", self._removeDetailsClicked) - self.detailsNameRenderer.connect("edited", self.detailsNameEdited) - self.detailsValueRenderer.connect("edited", self.detailsValueEdited) + self.detailsNameRenderer.connect("edited", self._detailsNameEdited) + self.detailsValueRenderer.connect("edited", self._detailsValueEdited) - self.populate_tree() - - + self.loadCharacterTemplate() def _backClicked(self, button: Gtk.Button): - if self.wordLeaflet.get_visible_child_name() == "wordlist_view": - self.wordLeaflet.set_visible_child_name("wordfilter_view") - else: - self.hide() + self.hide() # So this adds any previously added parts to the template - def populate_tree(self): + def loadCharacterTemplate(self): for name, value in self.mainWindow.project.character_template.details.items(): tree_iter = self.detailsStore.append() if tree_iter is None: return - self.detailsStore.set_value(tree_iter, 0, name) self.detailsStore.set_value(tree_iter, 1, value) # Functions stole From charactersView - def addDetailsClicked(self, button: Gtk.Button): - + def _addDetailsClicked(self, button: Gtk.Button): tree_iter = self.detailsStore.append() if tree_iter is None: return - name = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, "Description") + name = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, + "Description") value = "Value" self.detailsStore.set_value(tree_iter, 0, name) @@ -93,8 +87,7 @@ class CharacterTemplateEditorWindow(AbstractDialog): self.mainWindow.project.character_template.details[name] = value - def removeDetailsClicked(self, button: Gtk.Button): - + def _removeDetailsClicked(self, button: Gtk.Button): model, tree_iter = self.detailsSelection.get_selected() if (model is None) or (tree_iter is None): @@ -105,20 +98,20 @@ class CharacterTemplateEditorWindow(AbstractDialog): self.mainWindow.project.character_template.details.pop(name) - def detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): - + def _detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): model, tree_iter = self.detailsSelection.get_selected() if (model is None) or (tree_iter is None): return - text_to_set = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, text) + text_to_set = unique_name_checker.get_unique_name_for_dictionary( + self.mainWindow.project.character_template.details, text) name = model.get_value(tree_iter, 0) model.set_value(tree_iter, 0, text_to_set) # There was an error with this line but it didn't seem to do anything bad. - self.mainWindow.project.character_template.details[text_to_set] = self.mainWindow.project.character_template.details.pop(name) - - def detailsValueEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): + self.mainWindow.project.character_template.details[text_to_set] = \ + self.mainWindow.project.character_template.details.pop(name) + def _detailsValueEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): model, tree_iter = self.detailsSelection.get_selected() if (model is None) or (tree_iter is None): @@ -128,23 +121,3 @@ class CharacterTemplateEditorWindow(AbstractDialog): model.set_value(tree_iter, 1, text) self.mainWindow.project.character_template.details[name] = text - - def nameChanged(self, buffer: Gtk.EntryBuffer): - - text = buffer.get_text() - name = invalidString(text) - - self.character.name = name - - character_id = self.character.UID.value - - for row in self.charactersStore: - if row[0] == character_id: - row[1] = validString(name) - break - - def nameDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int): - self.nameChanged(buffer) - - def nameInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int): - self.nameChanged(buffer) diff --git a/ui/character_details_template_editor.glade b/ui/character_details_template_editor.glade index 4409bf47..72d0e4b2 100644 --- a/ui/character_details_template_editor.glade +++ b/ui/character_details_template_editor.glade @@ -3,14 +3,6 @@ - - - - - - - - False @@ -32,8 +24,6 @@ True True True - 4 - 4 4 4 @@ -55,68 +45,64 @@ - + True False + 8 + vertical + 8 - + + 200 True False - vertical + True + True + 0 + 0 - - 200 + True - False - True - True - 0 - 0 + True + in - + True - True - in + False - + True - False + True + details_store + True + 0 + both + + + - - True - True - details_store - True - 0 - both - - - + + Name - - Name - - - True - - - 0 - - + + True + + 0 + + + + + + Value - - Value - - - True - - - 1 - - + + True + + 1 + @@ -124,74 +110,71 @@ - - + + + + + + + + True + True + 0 + + + + + True + False + 4 + + + True + True + True + + + True + False + list-add + - True + False True 0 - + True - False - 4 + True + True - + True - True - True - - - True - False - list-add - - + False + list-remove - - False - True - 0 - - - - - True - True - True - - - True - False - list-remove - - - - - False - True - 1 - - - - False - False + True 1 + + False + False + 1 + - False + True True 1 @@ -199,4 +182,12 @@ + + + + + + + + diff --git a/ui/characters.glade b/ui/characters.glade index a1559d09..78a0ba85 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -795,10 +795,7 @@ summary True False - 8 - 8 - 8 - 8 + 8 vertical 8 diff --git a/ui/frequency.glade b/ui/frequency.glade index 45ba2c95..7589b2da 100644 --- a/ui/frequency.glade +++ b/ui/frequency.glade @@ -102,10 +102,7 @@ along with Manuskript. If not, see . 300 True False - 8 - 8 - 8 - 8 + 8 vertical 8 @@ -311,11 +308,8 @@ along with Manuskript. If not, see . 250 True True - 8 - 8 - 8 - 8 True + 8 in From fbbf497449c51ccd76460d58f392043fba41158e Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Sat, 4 Feb 2023 13:11:28 -0500 Subject: [PATCH 04/21] Fixed Name of the Button There is no icon and I can't make the text any smaller --- ui/characters.glade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/characters.glade b/ui/characters.glade index 78a0ba85..23e70247 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -935,7 +935,7 @@ summary - Append Detail Template + Append Template True True True From 45889d6279b1077f466a99b162b1f8ded5f84a13 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Sat, 4 Feb 2023 13:11:28 -0500 Subject: [PATCH 05/21] Changed Template Manager I also added glade back up files to gitignore. It wasn't. --- .gitignore | 1 + ...rs_template.py => characters_templates.py} | 19 +- manuskript/data/project.py | 4 +- manuskript/ui/mainWindow.py | 2 - manuskript/ui/tools/__init__.py | 3 +- .../ui/tools/characterTemplateWindow.py | 123 ----------- manuskript/ui/views/charactersView.py | 58 ++++- test_io.py | 0 ui/character_details_template_editor.glade | 193 ----------------- ui/characters.glade | 203 +++++++++++++++++- ui/main.glade | 8 - 11 files changed, 266 insertions(+), 348 deletions(-) rename manuskript/data/{characters_template.py => characters_templates.py} (56%) delete mode 100644 manuskript/ui/tools/characterTemplateWindow.py mode change 100644 => 100755 test_io.py delete mode 100644 ui/character_details_template_editor.glade diff --git a/.gitignore b/.gitignore index 75595ae8..d0e9cc37 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ manuskript.log snowflake* test-projects main.pyproject.user +*.glade# diff --git a/manuskript/data/characters_template.py b/manuskript/data/characters_templates.py similarity index 56% rename from manuskript/data/characters_template.py rename to manuskript/data/characters_templates.py index b613892c..d2deadf3 100644 --- a/manuskript/data/characters_template.py +++ b/manuskript/data/characters_templates.py @@ -7,21 +7,22 @@ import os from collections import OrderedDict -# So this is a template for charecter details -# It is edited by the Charecter Template Editor -# Most of the code is taken from charecters.py +# So this is a template for character details +# It is edited by the Character Template Editor +# Most of the code is taken from characters.py # I think this should have a custom save that's like a .json file in the main part of the manuskript save #Main Class -class CharacterDetailTemplate: - - details = {'Age':'','Birthdate':'', +class CharacterDetailTemplates: +# Basic Template + templates = {'Basic Human': + {'Age':'','Birthdate':'', 'Eye Color':'','Hair Color':'', - 'Handed':''} # We'll make a default template - + 'Handed':''}, + } - # TODO saving + # TODO: saving def save(self): pass diff --git a/manuskript/data/project.py b/manuskript/data/project.py index f1f6c351..4c9884ec 100644 --- a/manuskript/data/project.py +++ b/manuskript/data/project.py @@ -19,7 +19,7 @@ from manuskript.data.world import World from manuskript.data.outline import Outline from manuskript.data.revisions import Revisions # This is for the charecter template -from manuskript.data.characters_template import CharacterDetailTemplate +from manuskript.data.characters_templates import CharacterDetailTemplates from manuskript.io.mskFile import MskFile from manuskript.util import profileTime @@ -41,7 +41,7 @@ class Project: self.world = World(self.file.dir_path) self.outline = Outline(self.file.dir_path, self.plots, self.labels, self.statuses) self.revisions = Revisions(self.file.dir_path) - self.character_template = CharacterDetailTemplate() + self.character_templates = CharacterDetailTemplates() # TODO: RENAME PROPERALLY def __del__(self): del self.file diff --git a/manuskript/ui/mainWindow.py b/manuskript/ui/mainWindow.py index a063d7f7..ed9a2d38 100644 --- a/manuskript/ui/mainWindow.py +++ b/manuskript/ui/mainWindow.py @@ -75,14 +75,12 @@ class MainWindow: self.startupWindow = StartupWindow(self) self.aboutDialog = AboutDialog(self) self.frequencyWindow = FrequencyWindow(self) - self.characterTemplateWindow = CharacterTemplateWindow(self) self.settingsWindow = SettingsWindow(self) self.windows = [ self.startupWindow, self.aboutDialog, self.frequencyWindow, - self.characterTemplateWindow, self.settingsWindow ] diff --git a/manuskript/ui/tools/__init__.py b/manuskript/ui/tools/__init__.py index 674f8ba8..3efbdd35 100644 --- a/manuskript/ui/tools/__init__.py +++ b/manuskript/ui/tools/__init__.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from manuskript.ui.tools.frequencyWindow import FrequencyWindow -from manuskript.ui.tools.characterTemplateWindow import CharacterTemplateWindow +from manuskript.ui.tools.frequencyWindow import FrequencyWindow \ No newline at end of file diff --git a/manuskript/ui/tools/characterTemplateWindow.py b/manuskript/ui/tools/characterTemplateWindow.py deleted file mode 100644 index 75c10148..00000000 --- a/manuskript/ui/tools/characterTemplateWindow.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - - -# Imports -# Gi -import gi - -gi.require_version("Gtk", "3.0") -from gi.repository import GObject, Gtk, Handy - -# Manuskript -from manuskript.ui.abstractDialog import AbstractDialog -from manuskript.util import unique_name_checker, invalidString, validString - - -# I lifted a lot of this code from frequencyWindow -# With a bit more stuff from charactersView - -class CharacterTemplateWindow(AbstractDialog): - - def __init__(self, mainWindow): - AbstractDialog.__init__(self, mainWindow, "ui/character_details_template_editor.glade", - "character_details_template_editor") - - self.headerBar = None - self.back = None - - self.detailsStore = None - self.detailsSelection = None - self.addDetailsButton = None - self.removeDetailsButton = None - self.appendDetailsTemplateButton = None - self.detailsNameRenderer = None - self.detailsValueRenderer = None - - def initWindow(self, builder, window): - self.headerBar = builder.get_object("header_bar") - self.back = builder.get_object("back") - - self.back.connect("clicked", self._backClicked) - - # Liking Stuff stole from charactersView - self.detailsStore = builder.get_object("details_store") - self.detailsSelection = builder.get_object("details_selection") - self.addDetailsButton = builder.get_object("add_details") - self.removeDetailsButton = builder.get_object("remove_details") - self.appendDetailsTemplateButton = builder.get_object("appened_details_template") - self.detailsNameRenderer = builder.get_object("details_name") - self.detailsValueRenderer = builder.get_object("details_value") - - self.addDetailsButton.connect("clicked", self._addDetailsClicked) - self.removeDetailsButton.connect("clicked", self._removeDetailsClicked) - - self.detailsNameRenderer.connect("edited", self._detailsNameEdited) - self.detailsValueRenderer.connect("edited", self._detailsValueEdited) - - self.loadCharacterTemplate() - - def _backClicked(self, button: Gtk.Button): - self.hide() - - # So this adds any previously added parts to the template - def loadCharacterTemplate(self): - for name, value in self.mainWindow.project.character_template.details.items(): - tree_iter = self.detailsStore.append() - - if tree_iter is None: - return - - self.detailsStore.set_value(tree_iter, 0, name) - self.detailsStore.set_value(tree_iter, 1, value) - -# Functions stole From charactersView - def _addDetailsClicked(self, button: Gtk.Button): - tree_iter = self.detailsStore.append() - - if tree_iter is None: - return - - name = unique_name_checker.get_unique_name_for_dictionary(self.mainWindow.project.character_template.details, - "Description") - value = "Value" - - self.detailsStore.set_value(tree_iter, 0, name) - self.detailsStore.set_value(tree_iter, 1, value) - - self.mainWindow.project.character_template.details[name] = value - - def _removeDetailsClicked(self, button: Gtk.Button): - model, tree_iter = self.detailsSelection.get_selected() - - if (model is None) or (tree_iter is None): - return - - name = model.get_value(tree_iter, 0) - model.remove(tree_iter) - - self.mainWindow.project.character_template.details.pop(name) - - def _detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): - model, tree_iter = self.detailsSelection.get_selected() - - if (model is None) or (tree_iter is None): - return - text_to_set = unique_name_checker.get_unique_name_for_dictionary( - self.mainWindow.project.character_template.details, text) - name = model.get_value(tree_iter, 0) - model.set_value(tree_iter, 0, text_to_set) - # There was an error with this line but it didn't seem to do anything bad. - self.mainWindow.project.character_template.details[text_to_set] = \ - self.mainWindow.project.character_template.details.pop(name) - - def _detailsValueEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): - model, tree_iter = self.detailsSelection.get_selected() - - if (model is None) or (tree_iter is None): - return - - name = model.get_value(tree_iter, 0) - model.set_value(tree_iter, 1, text) - - self.mainWindow.project.character_template.details[name] = text diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index a6ceac1e..0e92b8bf 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -14,7 +14,7 @@ from manuskript.util import validString, invalidString, validInt, invalidInt, un class CharactersView: def __init__(self, project): - self.characterTemplate = project.character_template # The template for detailed info + self.characterTemplates = project.character_templates # The template for detailed info self.characters = project.characters self.character = None @@ -78,13 +78,19 @@ class CharactersView: self.detailsSelection = builder.get_object("details_selection") self.addDetailsButton = builder.get_object("add_details") self.removeDetailsButton = builder.get_object("remove_details") - self.appendDetailsTemplateButton = builder.get_object("appened_details_template") + self.charecterDetailsMenuButton = builder.get_object("characters_details_menu_button") + self.newTemplateButton = builder.get_object("new_template_button") + self.newTemplateEntry = builder.get_object("new_template_entry") + self.newTemplateEntryBuffer = builder.get_object("new_template_entry_buffer") + self.charecterDetailsMenuAppendBox = builder.get_object("template_select_box") + self.charecterDetailsMenuTemplateBox = builder.get_object("template_select_box2") self.detailsNameRenderer = builder.get_object("details_name") self.detailsValueRenderer = builder.get_object("details_value") self.addDetailsButton.connect("clicked", self._addDetailsClicked) self.removeDetailsButton.connect("clicked", self._removeDetailsClicked) - self.appendDetailsTemplateButton.connect("clicked", self._appendTemplateClicked) + self.charecterDetailsMenuButton.connect("clicked", self._onCharecterDetailsMenuClicked) + self.newTemplateButton.connect("clicked", self._onNewTemplateButtonClicked) self.detailsNameRenderer.connect("edited", self._detailsNameEdited) self.detailsValueRenderer.connect("edited", self._detailsValueEdited) @@ -325,17 +331,56 @@ class CharactersView: model.remove(tree_iter) self.character.details.pop(name) + + def _updateCharecterDetailsMenu(self): + def clear_container(container): + data = container.get_children() + for d in data: + container.remove(d) + clear_container( self.charecterDetailsMenuAppendBox) + clear_container(self.charecterDetailsMenuTemplateBox) + for x in self.characterTemplates.templates: + button = Gtk.Button(label=x,) # TODO: turn into ModelButton + button.connect("clicked", self._appendTemplateClicked, x) + self.charecterDetailsMenuAppendBox.add(button) + # Now we do the buttons for charecterDetailsMenuTemplateBox + button2 = Gtk.Button(label=x,) # TODO: turn into ModelButton + button2.connect("clicked", self._updateTemplateClicked, x) + self.charecterDetailsMenuTemplateBox.add(button2) - def _appendTemplateClicked(self, button: Gtk.Button): + self.charecterDetailsMenuAppendBox.show_all() + self.charecterDetailsMenuTemplateBox.show_all() + + def _onCharecterDetailsMenuClicked(self, button: Gtk.MenuButton): + self._updateCharecterDetailsMenu() + + def _updateTemplateClicked(self, button: Gtk.ModelButton, template): + if self.character is None: + return + self.characterTemplates.templates[template] = self.character.details # TODO: Add A warning? Or should there be undo/ redo when revisions are written. + + def _appendTemplateClicked(self, button: Gtk.ModelButton, template): if self.character is None: return # This following bit could be turned into a def - for (key, value) in self.characterTemplate.details.items(): + for (key, value) in self.characterTemplates.templates[template].items(): self.character.details[key]= value - #We have to reload the charecter + # We have to reload the character self.loadCharacterData(self.character) + def _onNewTemplateButtonClicked(self, button: Gtk.Button): + text = self.newTemplateEntryBuffer.get_text() + if text == "": + return + if text in self.characterTemplates.templates: + new_text = unique_name_checker.get_unique_name_for_dictionary(self.characterTemplates.templates, text) + self.newTemplateEntryBuffer.set_text(new_text, -1) # TODO: Add a warning + return + else: + self.characterTemplates.templates[text] = self.character.details + self._updateCharecterDetailsMenu() + def _detailsNameEdited(self, renderer: Gtk.CellRendererText, path: str, text: str): if self.character is None: return @@ -477,3 +522,4 @@ class CharactersView: def show(self): self.widget.show_all() + diff --git a/test_io.py b/test_io.py old mode 100644 new mode 100755 diff --git a/ui/character_details_template_editor.glade b/ui/character_details_template_editor.glade deleted file mode 100644 index 72d0e4b2..00000000 --- a/ui/character_details_template_editor.glade +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - False - - - True - False - vertical - - - True - False - - - True - False - Edit Charecter Details Template - - - True - True - True - 4 - 4 - - - True - False - go-previous-symbolic - - - - - - - - - False - True - 0 - - - - - True - False - 8 - vertical - 8 - - - 200 - True - False - True - True - 0 - 0 - - - True - True - in - - - True - False - - - True - True - details_store - True - 0 - both - - - - - - Name - - - True - - - 0 - - - - - - - Value - - - True - - - 1 - - - - - - - - - - - - - - - - True - True - 0 - - - - - True - False - 4 - - - True - True - True - - - True - False - list-add - - - - - False - True - 0 - - - - - True - True - True - - - True - False - list-remove - - - - - False - True - 1 - - - - - False - False - 1 - - - - - True - True - 1 - - - - - - - - - - - - - - diff --git a/ui/characters.glade b/ui/characters.glade index 78a0ba85..231faffd 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -85,6 +85,195 @@ along with Manuskript. If not, see . + + + 200 + False + + + True + False + vertical + + + True + True + True + Append Template + main + True + + + False + True + 0 + + + + + True + True + True + in + + + True + False + + + True + False + none + False + + + + + + + True + True + 1 + + + + + append_template + 1 + + + + + True + False + vertical + + + True + True + True + Set info to template + main + True + + + False + True + 0 + + + + + True + True + True + in + + + True + False + + + True + False + none + False + + + + + + + True + True + 1 + + + + + True + False + + + True + True + new_template_entry_buffer + Enter a unique name + GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE + + + False + True + 0 + + + + + New template + True + True + True + Adds a new template with the content of the current charecter's details. + + + False + True + 2 + + + + + False + True + 2 + + + + + edit_template + 2 + + + + + True + False + vertical + + + True + True + True + Append Template + append_template + + + False + True + 0 + + + + + True + True + True + Set info to template + edit_template + + + False + True + 1 + + + + + main + 3 + + + @@ -934,12 +1123,20 @@ summary - - Append Detail Template + True True + False True - + up + charecter_options_popover + + + True + False + open-menu-symbolic + + False diff --git a/ui/main.glade b/ui/main.glade index c2289edf..32d9a619 100644 --- a/ui/main.glade +++ b/ui/main.glade @@ -619,14 +619,6 @@ along with Manuskript. If not, see . True - - - True - False - _Edit Character Details Template - True - - From 1d20efcfbc09be1434dc7a90ee6119133f0306ea Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Mon, 6 Feb 2023 17:11:32 -0500 Subject: [PATCH 06/21] Update project.py --- manuskript/data/project.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manuskript/data/project.py b/manuskript/data/project.py index 2aaf034a..57c30f73 100644 --- a/manuskript/data/project.py +++ b/manuskript/data/project.py @@ -8,7 +8,6 @@ import os from zipfile import BadZipFile # Manuskript modules -======= from manuskript.data.abstractData import AbstractData from manuskript.data.version import Version, CURRENT_MSK_VERSION @@ -30,7 +29,7 @@ from manuskript.util import profileTime class Project(AbstractData): - def __init__(self, path): + def __init__(self, path): AbstractData.__init__(self, path) self.file = MskFile(self.dataPath) @@ -45,6 +44,8 @@ class Project(AbstractData): self.world = World(self.file.directoryPath) self.outline = Outline(self.file.directoryPath, self.plots, self.labels, self.statuses) self.revisions = Revisions(self.file.directoryPath) + self.character_templates = CharacterDetailTemplates() # TODO: RENAME PROPERALLY + def __del__(self): del self.file From 546a9bebf2663ee420da5d56d02266d19bac1c9b Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:15:48 -0500 Subject: [PATCH 07/21] Update startupWindow.py I did this so that the startup menu (Normal start up in Manuksript) would not cause the program to crash) it's because some actions called the function() when it is now _functon() --- manuskript/ui/startupWindow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manuskript/ui/startupWindow.py b/manuskript/ui/startupWindow.py index 4173d573..c1c3f5fa 100644 --- a/manuskript/ui/startupWindow.py +++ b/manuskript/ui/startupWindow.py @@ -45,10 +45,10 @@ class StartupWindow(AbstractDialog): GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN) - bindMenuItem(builder, "open_menu_item", self.mainWindow.openAction) - bindMenuItem(builder, "quit_menu_item", self.mainWindow.quitAction) + bindMenuItem(builder, "open_menu_item", self.mainWindow._openAction) + bindMenuItem(builder, "quit_menu_item", self.mainWindow._quitAction) - bindMenuItem(builder, "about_menu_item", self.mainWindow.aboutAction) + bindMenuItem(builder, "about_menu_item", self.mainWindow._aboutAction) self.templatesStore = builder.get_object("templates_store") From 1852676b129006de7283101ff04a0c33e36509f8 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:35:33 -0500 Subject: [PATCH 08/21] Update charactersView.py I found the update function and it works a lot better. --- manuskript/ui/views/charactersView.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index 0e92b8bf..168b760d 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -362,9 +362,7 @@ class CharactersView: def _appendTemplateClicked(self, button: Gtk.ModelButton, template): if self.character is None: return - # This following bit could be turned into a def - for (key, value) in self.characterTemplates.templates[template].items(): - self.character.details[key]= value + self.character.details.update(self.characterTemplates.templates[template]) # We have to reload the character self.loadCharacterData(self.character) From 52c63a4763e02787f105395ab4de0684b9a906aa Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:04:08 -0400 Subject: [PATCH 09/21] Added Deleting templates --- manuskript/ui/views/charactersView.py | 17 ++++++- ui/characters.glade | 70 ++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index 168b760d..540b0fae 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -84,6 +84,7 @@ class CharactersView: self.newTemplateEntryBuffer = builder.get_object("new_template_entry_buffer") self.charecterDetailsMenuAppendBox = builder.get_object("template_select_box") self.charecterDetailsMenuTemplateBox = builder.get_object("template_select_box2") + self.characterDetaisMenuDeleteBox = builder.get_object("delete_select_box") self.detailsNameRenderer = builder.get_object("details_name") self.detailsValueRenderer = builder.get_object("details_value") @@ -339,6 +340,7 @@ class CharactersView: container.remove(d) clear_container( self.charecterDetailsMenuAppendBox) clear_container(self.charecterDetailsMenuTemplateBox) + clear_container(self.characterDetaisMenuDeleteBox) for x in self.characterTemplates.templates: button = Gtk.Button(label=x,) # TODO: turn into ModelButton button.connect("clicked", self._appendTemplateClicked, x) @@ -347,10 +349,19 @@ class CharactersView: button2 = Gtk.Button(label=x,) # TODO: turn into ModelButton button2.connect("clicked", self._updateTemplateClicked, x) self.charecterDetailsMenuTemplateBox.add(button2) + # now we do delete templates + box = Gtk.Box() + label = Gtk.Label(label=x) + box.pack_start(label, False, False, 0) + button3 = Gtk.Button(label='delete') # TODO: Make this red + button3.connect("clicked", self._deleteTemplateClicked, x) + box.pack_start(button3, False, False, 0) + self.characterDetaisMenuDeleteBox.add(box) self.charecterDetailsMenuAppendBox.show_all() self.charecterDetailsMenuTemplateBox.show_all() - + self.characterDetaisMenuDeleteBox.show_all() + def _onCharecterDetailsMenuClicked(self, button: Gtk.MenuButton): self._updateCharecterDetailsMenu() @@ -359,6 +370,10 @@ class CharactersView: return self.characterTemplates.templates[template] = self.character.details # TODO: Add A warning? Or should there be undo/ redo when revisions are written. + def _deleteTemplateClicked(self, button: Gtk.ModelButton, template): + del self.characterTemplates.templates[template] + self._updateCharecterDetailsMenu() + def _appendTemplateClicked(self, button: Gtk.ModelButton, template): if self.character is None: return diff --git a/ui/characters.glade b/ui/characters.glade index 231faffd..327434c9 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -139,7 +139,6 @@ along with Manuskript. If not, see . append_template - 1 @@ -231,7 +230,7 @@ along with Manuskript. If not, see . edit_template - 2 + 1 @@ -267,9 +266,76 @@ along with Manuskript. If not, see . 1 + + + True + True + True + Delete Template + delete_template + + + False + True + 2 + + main + 2 + + + + + True + False + vertical + + + True + True + True + Delete Template + main + True + + + False + True + 0 + + + + + True + True + True + in + + + True + False + + + True + False + none + False + + + + + + + True + True + 1 + + + + + delete_template 3 From d9c09386148292ac422d186b9ba1dfc717a1ca3e Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Wed, 22 Mar 2023 08:26:09 +0100 Subject: [PATCH 10/21] Improve optimized MMD loading to skip empty files later on Signed-off-by: TheJackiMonster --- manuskript/data/outline.py | 3 ++- manuskript/io/mmdFile.py | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/manuskript/data/outline.py b/manuskript/data/outline.py index fafa097e..fa5f7a9c 100644 --- a/manuskript/data/outline.py +++ b/manuskript/data/outline.py @@ -156,8 +156,9 @@ class OutlineText(OutlineItem): metadata, body = self.file.loadMMD(optimized) OutlineItem.loadMetadata(self, metadata) - if not optimized: + if body is not None: self.text = body + optimized = False self.complete(optimized=optimized) diff --git a/manuskript/io/mmdFile.py b/manuskript/io/mmdFile.py index 40ec50dc..f89c58b7 100644 --- a/manuskript/io/mmdFile.py +++ b/manuskript/io/mmdFile.py @@ -24,7 +24,8 @@ class MmdFile(AbstractFile): metaValue = None with open(self.path, 'rt', encoding='utf-8') as file: - for line in file: + line = file.readline() + while line: m = metaPattern.match(line) if not (m is None): @@ -33,14 +34,15 @@ class MmdFile(AbstractFile): metaKey = m.group(1) metaValue = m.group(2) - continue + else: + m = metaValuePattern.match(line) - m = metaValuePattern.match(line) + if not (m is None): + metaValue += "\n" + m.group(2) + elif line == "\n": + break - if not (m is None): - metaValue += "\n" + m.group(2) - elif line == "\n": - break + line = file.readline() if not (metaKey is None): metadata[metaKey] = metaValue @@ -50,6 +52,14 @@ class MmdFile(AbstractFile): if (len(body) > 0) and (body[0] == "\n"): body = body[1:] + elif file.seekable(): + currentPosition = file.tell() + + file.seek(0, 2) + endPosition = file.tell() + + if endPosition - currentPosition == 1: + body = "" return metadata, body From f85e85a1592b23e4c67e5c767aad4c9b0c9bb23d Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 15:58:19 +0200 Subject: [PATCH 11/21] Start implementing import and compile dialog Signed-off-by: TheJackiMonster --- manuskript/ui/__init__.py | 2 + manuskript/ui/compileWindow.py | 53 ++ manuskript/ui/importWindow.py | 51 ++ manuskript/ui/mainWindow.py | 12 + ui/compile.glade | 875 +++++++++++++++++++++++++++++++++ ui/import.glade | 114 +++-- 6 files changed, 1053 insertions(+), 54 deletions(-) create mode 100644 manuskript/ui/compileWindow.py create mode 100644 manuskript/ui/importWindow.py create mode 100644 ui/compile.glade diff --git a/manuskript/ui/__init__.py b/manuskript/ui/__init__.py index 9b8ce307..51d8e08e 100644 --- a/manuskript/ui/__init__.py +++ b/manuskript/ui/__init__.py @@ -4,6 +4,8 @@ from manuskript.ui.util import * from manuskript.ui.aboutDialog import AboutDialog +from manuskript.ui.compileWindow import CompileWindow +from manuskript.ui.importWindow import ImportWindow from manuskript.ui.mainWindow import MainWindow from manuskript.ui.settingsWindow import SettingsWindow from manuskript.ui.startupWindow import StartupWindow diff --git a/manuskript/ui/compileWindow.py b/manuskript/ui/compileWindow.py new file mode 100644 index 00000000..03e46755 --- /dev/null +++ b/manuskript/ui/compileWindow.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GObject, Gtk, Handy + +Handy.init() + +from manuskript.ui.abstractDialog import AbstractDialog + +from manuskript.data import Project + + +class CompileWindow(AbstractDialog): + + def __init__(self, mainWindow): + AbstractDialog.__init__(self, mainWindow, "ui/compile.glade", "compile_window") + + self.headerBar = None + self.back = None + self.forward = None + self.previewLeaflet = None + self.manageExportersButton = None + + def initWindow(self, builder, window): + self.headerBar = builder.get_object("header_bar") + self.back = builder.get_object("back") + self.forward = builder.get_object("forward") + self.previewLeaflet = builder.get_object("preview_leaflet") + self.manageExportersButton = builder.get_object("manage_exporters") + + self.previewLeaflet.bind_property("folded", self.back, "visible", + GObject.BindingFlags.SYNC_CREATE) + self.previewLeaflet.bind_property("folded", self.forward, "visible", + GObject.BindingFlags.SYNC_CREATE) + self.previewLeaflet.bind_property("folded", self.headerBar, "show-close-button", + GObject.BindingFlags.SYNC_CREATE | + GObject.BindingFlags.INVERT_BOOLEAN) + + self.back.connect("clicked", self._backClicked) + self.forward.connect("clicked", self._forwardClicked) + + def _backClicked(self, button: Gtk.Button): + if self.previewLeaflet.get_visible_child_name() == "preview_box": + self.previewLeaflet.set_visible_child_name("settings_box") + else: + self.hide() + + def _forwardClicked(self, button: Gtk.Button): + if self.previewLeaflet.get_visible_child_name() == "settings_box": + self.previewLeaflet.set_visible_child_name("preview_box") diff --git a/manuskript/ui/importWindow.py b/manuskript/ui/importWindow.py new file mode 100644 index 00000000..56a8a910 --- /dev/null +++ b/manuskript/ui/importWindow.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GObject, Gtk, Handy + +Handy.init() + +from manuskript.ui.abstractDialog import AbstractDialog + +from manuskript.data import Project + + +class ImportWindow(AbstractDialog): + + def __init__(self, mainWindow): + AbstractDialog.__init__(self, mainWindow, "ui/import.glade", "import_window") + + self.headerBar = None + self.back = None + self.forward = None + self.previewLeaflet = None + + def initWindow(self, builder, window): + self.headerBar = builder.get_object("header_bar") + self.back = builder.get_object("back") + self.forward = builder.get_object("forward") + self.previewLeaflet = builder.get_object("preview_leaflet") + + self.previewLeaflet.bind_property("folded", self.back, "visible", + GObject.BindingFlags.SYNC_CREATE) + self.previewLeaflet.bind_property("folded", self.forward, "visible", + GObject.BindingFlags.SYNC_CREATE) + self.previewLeaflet.bind_property("folded", self.headerBar, "show-close-button", + GObject.BindingFlags.SYNC_CREATE | + GObject.BindingFlags.INVERT_BOOLEAN) + + self.back.connect("clicked", self._backClicked) + self.forward.connect("clicked", self._forwardClicked) + + def _backClicked(self, button: Gtk.Button): + if self.previewLeaflet.get_visible_child_name() == "preview_box": + self.previewLeaflet.set_visible_child_name("settings_box") + else: + self.hide() + + def _forwardClicked(self, button: Gtk.Button): + if self.previewLeaflet.get_visible_child_name() == "settings_box": + self.previewLeaflet.set_visible_child_name("preview_box") diff --git a/manuskript/ui/mainWindow.py b/manuskript/ui/mainWindow.py index 9efbf75e..15edfc18 100644 --- a/manuskript/ui/mainWindow.py +++ b/manuskript/ui/mainWindow.py @@ -16,6 +16,8 @@ from manuskript.ui.views import * from manuskript.ui.chooser import openFileDialog, saveFileDialog, FileFilter from manuskript.ui.tools import * from manuskript.ui.aboutDialog import AboutDialog +from manuskript.ui.compileWindow import CompileWindow +from manuskript.ui.importWindow import ImportWindow from manuskript.ui.settingsWindow import SettingsWindow from manuskript.ui.startupWindow import StartupWindow from manuskript.ui.util import bindMenuItem, packViewIntoSlot, unpackFromSlot @@ -61,6 +63,8 @@ class MainWindow: self.aboutDialog = AboutDialog(self) self.frequencyWindow = FrequencyWindow(self) self.settingsWindow = SettingsWindow(self) + self.importWindow = ImportWindow(self) + self.compileWindow = CompileWindow(self) self.windows = [ self.startupWindow, @@ -76,6 +80,8 @@ class MainWindow: bindMenuItem(builder, "save_menu_item", self._saveAction) bindMenuItem(builder, "saveas_menu_item", self._saveAsAction) bindMenuItem(builder, "close_menu_item", self._closeAction) + bindMenuItem(builder, "import_menu_item", self._importAction) + bindMenuItem(builder, "compile_menu_item", self._compileAction) bindMenuItem(builder, "quit_menu_item", self._quitAction) bindMenuItem(builder, "settings_menu_item", self._settingsAction) @@ -157,6 +163,12 @@ class MainWindow: def _closeAction(self, menuItem: Gtk.MenuItem): self.closeProject() + + def _importAction(self, menuItem: Gtk.MenuItem): + self.importWindow.show() + + def _compileAction(self, menuItem: Gtk.MenuItem): + self.compileWindow.show() def _quitAction(self, menuItem: Gtk.MenuItem): self.exit(True) diff --git a/ui/compile.glade b/ui/compile.glade new file mode 100644 index 00000000..64d054b2 --- /dev/null +++ b/ui/compile.glade @@ -0,0 +1,875 @@ + + + + + + + + + + + + + + + + + + + + + + Markdown + text/markdown + text-x-generic + + + Folder + directory + folder + + + OPML + text/opml + text-x-generic-template + + + Mind Map + text/mind-map + text-x-generic-template + + + + + False + + + True + False + vertical + + + True + False + + + True + False + Export + + + True + True + True + + + True + False + go-previous-symbolic + + + + + + + True + True + True + + + True + False + go-next-symbolic + + + + + end + 1 + + + + + + + False + True + 0 + + + + + True + False + + + 300 + True + False + vertical + + + True + False + + + True + False + 4 + 4 + 8 + + + True + False + Format: + + + + + + False + True + 0 + + + + + True + False + file_format_store + 0 + + + + 2 + + + + + + 0 + + + + + False + True + 1 + + + + + True + True + True + + + True + False + 4 + + + True + False + preferences-other-symbolic + + + False + True + 0 + + + + + True + False + Manage Exporters + end + + + False + True + 1 + + + + + + + False + True + 2 + + + + + + + False + True + end + 4 + + + + + True + False + 8 + 8 + 8 + 8 + vertical + 8 + + + True + False + 6 + 6 + Settings + 0 + + + + + + False + True + 0 + + + + + True + True + + + True + False + 8 + vertical + + + True + False + Decide here what will be included in the final export. + True + word-char + end + 0 + + + False + True + 0 + + + + + + True + False + 4 + True + + + True + False + Type + + + 0 + 0 + + + + + True + False + Title + + + 1 + 0 + + + + + True + False + Text + + + 2 + 0 + + + + + + True + True + False + True + + + 1 + 1 + + + + + + True + True + False + True + + + 2 + 2 + + + + + + True + True + False + True + + + 1 + 2 + + + + + True + False + 4 + + + True + False + folder-symbolic + + + False + True + 0 + + + + + True + False + Folder + + + False + True + 1 + + + + + 0 + 1 + + + + + True + False + 4 + + + True + False + text-x-generic-symbolic + + + False + True + 0 + + + + + True + False + Folder + + + False + True + 1 + + + + + 0 + 2 + + + + + + + + False + True + 1 + + + + + I need more granularity + True + True + False + True + + + False + True + 2 + + + + + True + False + + + False + True + 3 + + + + + True + False + 4 + vertical + + + True + True + + + True + False + vertical + + + True + False + Filters what items will be included in the final export. +(Not fully implemented yet.) + True + word-char + end + 0 + + + False + True + 0 + + + + + Ignore compile status (include all items) + True + True + False + True + + + False + True + 1 + + + + + Subitems of: + True + True + False + True + + + False + True + 2 + + + + + Labels + True + True + False + True + + + False + True + 3 + + + + + Status + True + True + False + True + + + False + True + 4 + + + + + + + True + False + Filters + + + + + False + True + 0 + + + + + False + True + 4 + + + + + + + True + False + Content + + + + + False + True + 1 + + + + + True + True + + + + + + True + False + Separations + + + + + False + True + 2 + + + + + True + True + + + + + + True + False + Transformations + + + + + False + True + 3 + + + + + True + True + + + + + + True + False + Preview + + + + + False + True + 4 + + + + + True + True + 5 + + + + + settings_box + + + + + 250 + True + False + True + vertical + + + True + False + 8 + 8 + 8 + 8 + vertical + 8 + + + True + False + 6 + 6 + Preview + 0 + + + + + + False + True + 0 + + + + + True + False + vertical + + + + + + True + True + 1 + + + + + True + True + 0 + + + + + True + False + False + 8 + + + True + False + 4 + 4 + 8 + + + True + True + True + + + True + False + 4 + + + True + False + emblem-synchronizing-symbolic + + + False + True + 0 + + + + + True + False + Preview + + + False + True + 1 + + + + + + + False + True + 0 + + + + + True + True + True + + + True + False + 4 + + + True + False + document-revert-symbolic + + + False + True + 0 + + + + + True + False + Export + + + False + True + 1 + + + + + + + False + True + 1 + + + + + end + 1 + + + + + False + True + end + 2 + + + + + preview_box + + + + + True + True + 1 + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/import.glade b/ui/import.glade index cc89e89d..2a8a9689 100644 --- a/ui/import.glade +++ b/ui/import.glade @@ -1,5 +1,5 @@ - - + + + + + + + + + + + + Markdown + text/markdown + text-x-generic + + + Folder + directory + folder + + + OPML + text/opml + text-x-generic-template + + + Mind Map + text/mind-map + text-x-generic-template + + + + + + + + + + + + + + + + + + + + False @@ -39,12 +87,12 @@ along with Manuskript. If not, see . True False - + True False Import - + True True True @@ -58,7 +106,7 @@ along with Manuskript. If not, see . - + True True True @@ -85,7 +133,7 @@ along with Manuskript. If not, see . - + True False @@ -366,6 +414,9 @@ along with Manuskript. If not, see . + + settings_box + @@ -609,6 +660,9 @@ along with Manuskript. If not, see . + + preview_box + @@ -620,52 +674,4 @@ along with Manuskript. If not, see . - - - - - - - - - - - - Markdown - text/markdown - text-x-generic - - - Folder - directory - folder - - - OPML - text/opml - text-x-generic-template - - - Mind Map - text/mind-map - text-x-generic-template - - - - - - - - - - - - - - - - - - - From 13b6e26b13cc2c5eb6e32ddccdbbd3430fc404c7 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 17:08:21 +0200 Subject: [PATCH 12/21] Adjust frequency analyzer Signed-off-by: TheJackiMonster --- manuskript/ui/tools/frequencyWindow.py | 49 ++++++++++ ui/frequency.glade | 123 ++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 12 deletions(-) diff --git a/manuskript/ui/tools/frequencyWindow.py b/manuskript/ui/tools/frequencyWindow.py index 26b030f4..989aea20 100644 --- a/manuskript/ui/tools/frequencyWindow.py +++ b/manuskript/ui/tools/frequencyWindow.py @@ -17,15 +17,35 @@ class FrequencyWindow(AbstractDialog): self.headerBar = None self.back = None self.wordLeaflet = None + self.wordsProgress = None self.analyzeWords = None + self.phrasesProgress = None self.analyzePhrases = None + self.wordEntry = None + self.removeWord = None + self.addWord = None + + self.excludeWordSelection = None + self.excludeWordsStore = None + self.wordsFrequencyStore = None + self.phrasesFrequencyStore = None def initWindow(self, builder, window): self.headerBar = builder.get_object("header_bar") self.back = builder.get_object("back") self.wordLeaflet = builder.get_object("word_leaflet") + self.wordsProgress = builder.get_object("words_progress") self.analyzeWords = builder.get_object("analyze_words") + self.phrasesProgress = builder.get_object("phrases_progress") self.analyzePhrases = builder.get_object("analyze_phrases") + self.wordEntry = builder.get_object("word_entry") + self.removeWord = builder.get_object("remove_word") + self.addWord = builder.get_object("add_word") + + self.excludeWordSelection = builder.get_object("exclude_word_selection") + self.excludeWordsStore = builder.get_object("exclude_words_store") + self.wordsFrequencyStore = builder.get_object("words_frequency_store") + self.phrasesFrequencyStore = builder.get_object("phrases_frequency_store") self.wordLeaflet.bind_property("folded", self.back, "visible", GObject.BindingFlags.SYNC_CREATE) @@ -35,6 +55,10 @@ class FrequencyWindow(AbstractDialog): self.back.connect("clicked", self._backClicked) self.analyzeWords.connect("clicked", self._analyzeWordsClicked) + self.analyzePhrases.connect("clicked", self._analyzePhrasesClicked) + self.excludeWordSelection.connect("changed", self._excludeWordSelectionChanged) + self.removeWord.connect("clicked", self._removeWordClicked) + self.addWord.connect("clicked", self._addWordClicked) def _backClicked(self, button: Gtk.Button): if self.wordLeaflet.get_visible_child_name() == "wordlist_view": @@ -44,3 +68,28 @@ class FrequencyWindow(AbstractDialog): def _analyzeWordsClicked(self, button: Gtk.Button): self.wordLeaflet.set_visible_child_name("wordlist_view") + + def _analyzePhrasesClicked(self, button: Gtk.Button): + pass + + def _excludeWordSelectionChanged(self, selection: Gtk.TreeSelection): + model, tree_iter = selection.get_selected() + + self.removeWord.set_sensitive(tree_iter is not None) + + def _removeWordClicked(self, button: Gtk.Button): + model, tree_iter = self.excludeWordSelection.get_selected() + + if tree_iter is None: + return + + self.excludeWordsStore.remove(tree_iter) + + def _addWordClicked(self, button: Gtk.Button): + tree_iter = self.excludeWordsStore.append() + + if tree_iter is None: + return + + word = self.wordEntry.get_buffer().get_text() + self.excludeWordsStore.set_value(tree_iter, 0, word) diff --git a/ui/frequency.glade b/ui/frequency.glade index 45ba2c95..09bb4a26 100644 --- a/ui/frequency.glade +++ b/ui/frequency.glade @@ -27,6 +27,12 @@ along with Manuskript. If not, see . + + + + + + 2 99 @@ -41,6 +47,14 @@ along with Manuskript. If not, see . 1 10 + + + + + + + + 1 99 @@ -48,6 +62,14 @@ along with Manuskript. If not, see . 1 10 + + + + + + + + False @@ -184,9 +206,26 @@ along with Manuskript. If not, see . True False - + True - False + True + exclude_words_store + False + False + + + + + + Word + + + + 0 + + + + @@ -204,8 +243,9 @@ along with Manuskript. If not, see . False 8 - + True + False True True @@ -223,7 +263,7 @@ along with Manuskript. If not, see . - + True True @@ -234,7 +274,7 @@ along with Manuskript. If not, see . - + True True True @@ -277,10 +317,9 @@ along with Manuskript. If not, see . - + True False - 12 False @@ -322,9 +361,39 @@ along with Manuskript. If not, see . True False - + True - False + True + words_frequency_store + + + + + + Word + True + True + + + + 0 + + + + + + + Frequency + True + True + + + + 1 + + + + @@ -490,9 +559,39 @@ along with Manuskript. If not, see . True False - + True - False + True + phrases_frequency_store + + + + + + Phrase + True + True + + + + 0 + + + + + + + Frequency + True + True + + + + 1 + + + + @@ -506,7 +605,7 @@ along with Manuskript. If not, see . - + True False From 07a8197bcdcbc3ef5208b27e1cb321557e05b0ab Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 18:46:30 +0200 Subject: [PATCH 13/21] Implement async frequency analyzing Signed-off-by: TheJackiMonster --- manuskript/ui/tools/frequencyWindow.py | 137 ++++++++++++++++++++++++- ui/frequency.glade | 6 ++ 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/manuskript/ui/tools/frequencyWindow.py b/manuskript/ui/tools/frequencyWindow.py index 989aea20..a1e5fea8 100644 --- a/manuskript/ui/tools/frequencyWindow.py +++ b/manuskript/ui/tools/frequencyWindow.py @@ -4,9 +4,22 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import GObject, Gtk, Handy +from gi.repository import GObject, Gtk +import re + +from enum import Enum, unique + +from manuskript.data import OutlineFolder, OutlineText, OutlineState, Project from manuskript.ui.abstractDialog import AbstractDialog +from manuskript.util import validString, validInt + + +@unique +class AnalyzeStatus(Enum): + NONE = 0 + WORDS = 1 + PHRASES = 2 class FrequencyWindow(AbstractDialog): @@ -14,6 +27,11 @@ class FrequencyWindow(AbstractDialog): def __init__(self, mainWindow): AbstractDialog.__init__(self, mainWindow, "ui/frequency.glade", "frequency_window") + self.analyzeStatus = AnalyzeStatus.NONE + self.frequencies = dict() + self.outlineCompletion = list() + self.analyzeCompleted = 0 + self.headerBar = None self.back = None self.wordLeaflet = None @@ -30,6 +48,10 @@ class FrequencyWindow(AbstractDialog): self.wordsFrequencyStore = None self.phrasesFrequencyStore = None + self.phraseMinimum = None + self.phraseMaximum = None + self.wordSize = None + def initWindow(self, builder, window): self.headerBar = builder.get_object("header_bar") self.back = builder.get_object("back") @@ -47,6 +69,10 @@ class FrequencyWindow(AbstractDialog): self.wordsFrequencyStore = builder.get_object("words_frequency_store") self.phrasesFrequencyStore = builder.get_object("phrases_frequency_store") + self.phraseMinimum = builder.get_object("phrase_minimum") + self.phraseMaximum = builder.get_object("phrase_maximum") + self.wordSize = builder.get_object("word_size") + self.wordLeaflet.bind_property("folded", self.back, "visible", GObject.BindingFlags.SYNC_CREATE) self.wordLeaflet.bind_property("folded", self.headerBar, "show-close-button", @@ -59,18 +85,123 @@ class FrequencyWindow(AbstractDialog): self.excludeWordSelection.connect("changed", self._excludeWordSelectionChanged) self.removeWord.connect("clicked", self._removeWordClicked) self.addWord.connect("clicked", self._addWordClicked) + + def getProject(self) -> Project: + return self.mainWindow.getProject() def _backClicked(self, button: Gtk.Button): if self.wordLeaflet.get_visible_child_name() == "wordlist_view": self.wordLeaflet.set_visible_child_name("wordfilter_view") else: self.hide() + + def __analyzeOutlineText(self, outlineText: OutlineText): + if self.analyzeStatus == AnalyzeStatus.WORDS: + word_size = validInt(self.wordSize.get_value()) + + patterns = [re.compile(r"\w{" + str(word_size) + r",}")] + elif self.analyzeStatus == AnalyzeStatus.PHRASES: + patterns = [] + + phrase_minimum = validInt(self.phraseMinimum.get_value()) + phrase_maximum = validInt(self.phraseMaximum.get_value()) + + for n in range(phrase_minimum, phrase_maximum + 1): + patterns.append(re.compile(r"\w+" + r"\s+\w+" * (n - 1))) + else: + return + + for pattern in patterns: + for match in pattern.findall(outlineText.text): + if match in self.frequencies: + self.frequencies[match] = self.frequencies[match] + 1 + else: + self.frequencies[match] = 1 + + def __completeOutlineItem(self): + outline_item = self.outlineCompletion.pop(0) + + if outline_item.state != OutlineState.COMPLETE: + outline_item.load(False) + + if isinstance(outline_item, OutlineFolder): + for item in outline_item: + self.outlineCompletion.append(item) + elif isinstance(outline_item, OutlineText): + self.__analyzeOutlineText(outline_item) + + self.analyzeCompleted = self.analyzeCompleted + 1 + + incomplete = len(self.outlineCompletion) + complete = self.analyzeCompleted + fraction = 1.0 * complete / (complete + incomplete) + + if self.analyzeStatus == AnalyzeStatus.WORDS: + self.wordsProgress.set_fraction(fraction) + elif self.analyzeStatus == AnalyzeStatus.PHRASES: + self.phrasesProgress.set_fraction(fraction) + + if incomplete > 0: + return True + + if self.analyzeStatus == AnalyzeStatus.WORDS: + self.wordsFrequencyStore.clear() + + for word, frequency in self.frequencies.items(): + tree_iter = self.wordsFrequencyStore.append() + + if tree_iter is None: + continue + + self.wordsFrequencyStore.set_value(tree_iter, 0, validString(word)) + self.wordsFrequencyStore.set_value(tree_iter, 1, validInt(frequency)) + + self.wordLeaflet.set_visible_child_name("wordlist_view") + elif self.analyzeStatus == AnalyzeStatus.PHRASES: + self.phrasesFrequencyStore.clear() + + for phrase, frequency in self.frequencies.items(): + tree_iter = self.phrasesFrequencyStore.append() + + if tree_iter is None: + continue + + self.phrasesFrequencyStore.set_value(tree_iter, 0, validString(phrase)) + self.phrasesFrequencyStore.set_value(tree_iter, 1, validInt(frequency)) + + self.analyzeStatus = AnalyzeStatus.NONE + self.frequencies = dict() + return False + + def analyze(self, status: AnalyzeStatus): + if self.analyzeStatus != AnalyzeStatus.NONE: + return + + project = self.getProject() + + if project is None: + return + + self.analyzeStatus = status + + if len(self.outlineCompletion) == 0: + self.frequencies = dict() + self.analyzeCompleted = 0 + + if self.analyzeStatus == AnalyzeStatus.WORDS: + self.wordsProgress.set_fraction(0.0) + elif self.analyzeStatus == AnalyzeStatus.PHRASES: + self.phrasesProgress.set_fraction(0.0) + + GObject.idle_add(self.__completeOutlineItem) + for outline_item in project.outline: + self.outlineCompletion.append(outline_item) def _analyzeWordsClicked(self, button: Gtk.Button): - self.wordLeaflet.set_visible_child_name("wordlist_view") + self.analyze(AnalyzeStatus.WORDS) def _analyzePhrasesClicked(self, button: Gtk.Button): - pass + self.analyze(AnalyzeStatus.PHRASES) def _excludeWordSelectionChanged(self, selection: Gtk.TreeSelection): model, tree_iter = selection.get_selected() diff --git a/ui/frequency.glade b/ui/frequency.glade index 09bb4a26..7e123c48 100644 --- a/ui/frequency.glade +++ b/ui/frequency.glade @@ -365,6 +365,8 @@ along with Manuskript. If not, see . True True words_frequency_store + 0 + False @@ -373,6 +375,7 @@ along with Manuskript. If not, see . Word True True + 0 @@ -386,6 +389,7 @@ along with Manuskript. If not, see . Frequency True True + 1 @@ -571,6 +575,7 @@ along with Manuskript. If not, see . Phrase True True + 0 @@ -584,6 +589,7 @@ along with Manuskript. If not, see . Frequency True True + 1 From 55bd817540969bb1f1d928208f03f53b826b5cf7 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 18:55:58 +0200 Subject: [PATCH 14/21] Tweak async loading of outline elements Signed-off-by: TheJackiMonster --- manuskript/ui/tools/frequencyWindow.py | 6 +++--- ui/frequency.glade | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/manuskript/ui/tools/frequencyWindow.py b/manuskript/ui/tools/frequencyWindow.py index a1e5fea8..3afb03c5 100644 --- a/manuskript/ui/tools/frequencyWindow.py +++ b/manuskript/ui/tools/frequencyWindow.py @@ -121,13 +121,13 @@ class FrequencyWindow(AbstractDialog): def __completeOutlineItem(self): outline_item = self.outlineCompletion.pop(0) - if outline_item.state != OutlineState.COMPLETE: - outline_item.load(False) - if isinstance(outline_item, OutlineFolder): for item in outline_item: self.outlineCompletion.append(item) elif isinstance(outline_item, OutlineText): + if outline_item.state != OutlineState.COMPLETE: + outline_item.load(False) + self.__analyzeOutlineText(outline_item) self.analyzeCompleted = self.analyzeCompleted + 1 diff --git a/ui/frequency.glade b/ui/frequency.glade index 7e123c48..e40236fb 100644 --- a/ui/frequency.glade +++ b/ui/frequency.glade @@ -367,6 +367,7 @@ along with Manuskript. If not, see . words_frequency_store 0 False + 0 @@ -374,7 +375,6 @@ along with Manuskript. If not, see . Word True - True 0 @@ -567,6 +567,9 @@ along with Manuskript. If not, see . True True phrases_frequency_store + 0 + False + 0 @@ -574,7 +577,6 @@ along with Manuskript. If not, see . Phrase True - True 0 From 8adcd3e2695c8c185464ea60cc2639e3db6d2b6b Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 19:27:16 +0200 Subject: [PATCH 15/21] Implement exclusion filter Signed-off-by: TheJackiMonster --- manuskript/ui/tools/frequencyWindow.py | 35 ++++++++++++++++++++++++++ ui/frequency.glade | 5 +++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/manuskript/ui/tools/frequencyWindow.py b/manuskript/ui/tools/frequencyWindow.py index 3afb03c5..7b589cfb 100644 --- a/manuskript/ui/tools/frequencyWindow.py +++ b/manuskript/ui/tools/frequencyWindow.py @@ -69,6 +69,11 @@ class FrequencyWindow(AbstractDialog): self.wordsFrequencyStore = builder.get_object("words_frequency_store") self.phrasesFrequencyStore = builder.get_object("phrases_frequency_store") + self.filteredFrequencyStore = builder.get_object("filtered_frequency_store") + + self.filteredFrequencyStore.set_visible_func(self._filterFrequencies) + self.filteredFrequencyStore.refilter() + self.phraseMinimum = builder.get_object("phrase_minimum") self.phraseMaximum = builder.get_object("phrase_maximum") self.wordSize = builder.get_object("word_size") @@ -82,12 +87,34 @@ class FrequencyWindow(AbstractDialog): self.back.connect("clicked", self._backClicked) self.analyzeWords.connect("clicked", self._analyzeWordsClicked) self.analyzePhrases.connect("clicked", self._analyzePhrasesClicked) + self.wordSize.connect("value-changed", self._wordSizeChanged) self.excludeWordSelection.connect("changed", self._excludeWordSelectionChanged) self.removeWord.connect("clicked", self._removeWordClicked) self.addWord.connect("clicked", self._addWordClicked) def getProject(self) -> Project: return self.mainWindow.getProject() + + def _filterFrequencies(self, model, iterator, userdata): + word = model[iterator][0] + + if word is None: + return False + + word_size = validInt(self.wordSize.get_value()) + + if len(word) < word_size: + return False + + iter = self.excludeWordsStore.get_iter_first() + while iter is not None: + excluded = self.excludeWordsStore.get_value(iter, 0) + if word == excluded: + return False + + iter = self.excludeWordsStore.iter_next(iter) + + return True def _backClicked(self, button: Gtk.Button): if self.wordLeaflet.get_visible_child_name() == "wordlist_view": @@ -113,6 +140,9 @@ class FrequencyWindow(AbstractDialog): for pattern in patterns: for match in pattern.findall(outlineText.text): + if match is None: + continue + if match in self.frequencies: self.frequencies[match] = self.frequencies[match] + 1 else: @@ -203,6 +233,9 @@ class FrequencyWindow(AbstractDialog): def _analyzePhrasesClicked(self, button: Gtk.Button): self.analyze(AnalyzeStatus.PHRASES) + def _wordSizeChanged(self, adjustment: Gtk.Adjustment): + self.filteredFrequencyStore.refilter() + def _excludeWordSelectionChanged(self, selection: Gtk.TreeSelection): model, tree_iter = selection.get_selected() @@ -215,6 +248,7 @@ class FrequencyWindow(AbstractDialog): return self.excludeWordsStore.remove(tree_iter) + self.filteredFrequencyStore.refilter() def _addWordClicked(self, button: Gtk.Button): tree_iter = self.excludeWordsStore.append() @@ -224,3 +258,4 @@ class FrequencyWindow(AbstractDialog): word = self.wordEntry.get_buffer().get_text() self.excludeWordsStore.set_value(tree_iter, 0, word) + self.filteredFrequencyStore.refilter() diff --git a/ui/frequency.glade b/ui/frequency.glade index e40236fb..728e9e1d 100644 --- a/ui/frequency.glade +++ b/ui/frequency.glade @@ -70,6 +70,9 @@ along with Manuskript. If not, see . + + words_frequency_store + False @@ -364,7 +367,7 @@ along with Manuskript. If not, see . True True - words_frequency_store + filtered_frequency_store 0 False 0 From d5a0b563870c1dd79ca4b355419152f6f7d2066b Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 8 Jun 2023 19:37:30 +0200 Subject: [PATCH 16/21] Improve speed of frequency tool Signed-off-by: TheJackiMonster --- manuskript/ui/tools/frequencyWindow.py | 74 ++++++++++++++------------ 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/manuskript/ui/tools/frequencyWindow.py b/manuskript/ui/tools/frequencyWindow.py index 7b589cfb..e41e5231 100644 --- a/manuskript/ui/tools/frequencyWindow.py +++ b/manuskript/ui/tools/frequencyWindow.py @@ -28,7 +28,7 @@ class FrequencyWindow(AbstractDialog): AbstractDialog.__init__(self, mainWindow, "ui/frequency.glade", "frequency_window") self.analyzeStatus = AnalyzeStatus.NONE - self.frequencies = dict() + self.analyzeTexts = list() self.outlineCompletion = list() self.analyzeCompleted = 0 @@ -70,7 +70,7 @@ class FrequencyWindow(AbstractDialog): self.phrasesFrequencyStore = builder.get_object("phrases_frequency_store") self.filteredFrequencyStore = builder.get_object("filtered_frequency_store") - + self.filteredFrequencyStore.set_visible_func(self._filterFrequencies) self.filteredFrequencyStore.refilter() @@ -122,32 +122,6 @@ class FrequencyWindow(AbstractDialog): else: self.hide() - def __analyzeOutlineText(self, outlineText: OutlineText): - if self.analyzeStatus == AnalyzeStatus.WORDS: - word_size = validInt(self.wordSize.get_value()) - - patterns = [re.compile(r"\w{" + str(word_size) + r",}")] - elif self.analyzeStatus == AnalyzeStatus.PHRASES: - patterns = [] - - phrase_minimum = validInt(self.phraseMinimum.get_value()) - phrase_maximum = validInt(self.phraseMaximum.get_value()) - - for n in range(phrase_minimum, phrase_maximum + 1): - patterns.append(re.compile(r"\w+" + r"\s+\w+" * (n - 1))) - else: - return - - for pattern in patterns: - for match in pattern.findall(outlineText.text): - if match is None: - continue - - if match in self.frequencies: - self.frequencies[match] = self.frequencies[match] + 1 - else: - self.frequencies[match] = 1 - def __completeOutlineItem(self): outline_item = self.outlineCompletion.pop(0) @@ -157,8 +131,8 @@ class FrequencyWindow(AbstractDialog): elif isinstance(outline_item, OutlineText): if outline_item.state != OutlineState.COMPLETE: outline_item.load(False) - - self.__analyzeOutlineText(outline_item) + + self.analyzeTexts.append(outline_item.text) self.analyzeCompleted = self.analyzeCompleted + 1 @@ -174,10 +148,36 @@ class FrequencyWindow(AbstractDialog): if incomplete > 0: return True + patterns = list() + + if self.analyzeStatus == AnalyzeStatus.WORDS: + word_size = validInt(self.wordSize.get_value()) + + patterns.append(re.compile(r"\w{" + str(word_size) + r",}")) + elif self.analyzeStatus == AnalyzeStatus.PHRASES: + phrase_minimum = validInt(self.phraseMinimum.get_value()) + phrase_maximum = validInt(self.phraseMaximum.get_value()) + + for n in range(phrase_minimum, phrase_maximum + 1): + patterns.append(re.compile(r"\w+" + r"\s+\w+" * (n - 1))) + + frequencies = dict() + text = "\n".join(self.analyzeTexts) + + for pattern in patterns: + for match in pattern.findall(text): + if match is None: + continue + + if match in frequencies: + frequencies[match] = frequencies[match] + 1 + else: + frequencies[match] = 1 + if self.analyzeStatus == AnalyzeStatus.WORDS: self.wordsFrequencyStore.clear() - for word, frequency in self.frequencies.items(): + for word, frequency in frequencies.items(): tree_iter = self.wordsFrequencyStore.append() if tree_iter is None: @@ -190,7 +190,7 @@ class FrequencyWindow(AbstractDialog): elif self.analyzeStatus == AnalyzeStatus.PHRASES: self.phrasesFrequencyStore.clear() - for phrase, frequency in self.frequencies.items(): + for phrase, frequency in frequencies.items(): tree_iter = self.phrasesFrequencyStore.append() if tree_iter is None: @@ -200,7 +200,10 @@ class FrequencyWindow(AbstractDialog): self.phrasesFrequencyStore.set_value(tree_iter, 1, validInt(frequency)) self.analyzeStatus = AnalyzeStatus.NONE - self.frequencies = dict() + self.analyzeTexts = list() + + self.analyzeWords.set_sensitive(True) + self.analyzePhrases.set_sensitive(True) return False def analyze(self, status: AnalyzeStatus): @@ -212,10 +215,13 @@ class FrequencyWindow(AbstractDialog): if project is None: return + self.analyzeWords.set_sensitive(False) + self.analyzePhrases.set_sensitive(False) + self.analyzeStatus = status if len(self.outlineCompletion) == 0: - self.frequencies = dict() + self.analyzeTexts = list() self.analyzeCompleted = 0 if self.analyzeStatus == AnalyzeStatus.WORDS: From 3d469e671e2993393e783cc5b320a2c194e2a3b1 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Fri, 16 Jun 2023 00:26:40 +0200 Subject: [PATCH 17/21] Fix editor view texts Signed-off-by: TheJackiMonster --- manuskript/ui/views/editorView.py | 2 -- ui/editor.glade | 29 +++++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/manuskript/ui/views/editorView.py b/manuskript/ui/views/editorView.py index 6d32d55d..bea71764 100644 --- a/manuskript/ui/views/editorView.py +++ b/manuskript/ui/views/editorView.py @@ -270,8 +270,6 @@ class EditorView: self.editorItems = self.project.outline.items elif type(outlineItem) is OutlineFolder: self.editorItems = outlineItem.items - elif type(outlineItem) is OutlineText: - self.__appendOutlineItemText(outlineItem) if outlineItem is None: for item in self.editorItems: diff --git a/ui/editor.glade b/ui/editor.glade index 3755d625..569fb31a 100644 --- a/ui/editor.glade +++ b/ui/editor.glade @@ -65,16 +65,6 @@ along with Manuskript. If not, see . False - - - Normal - - - - - Normal - - h2 @@ -173,7 +163,21 @@ along with Manuskript. If not, see . p Normal + 4 + 4 + 8 20 + 8 + + + + + line + Normal + False + 4 + True + 4 @@ -397,6 +401,11 @@ along with Manuskript. If not, see . True True word-char + 8 + 8 + 4 + 4 + 4 editor_text GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_NONE From c20ee8d07a8c8eba7dc78497ce23f5c1e71be690 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Sat, 1 Apr 2023 10:36:42 -0400 Subject: [PATCH 18/21] I simplified the UI for templates --- manuskript/ui/views/charactersView.py | 22 ++++---- ui/characters.glade | 80 ++++----------------------- ui/quote_of_the_day.glade | 71 ------------------------ 3 files changed, 21 insertions(+), 152 deletions(-) delete mode 100644 ui/quote_of_the_day.glade diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index 540b0fae..e8f5ecc7 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -84,7 +84,6 @@ class CharactersView: self.newTemplateEntryBuffer = builder.get_object("new_template_entry_buffer") self.charecterDetailsMenuAppendBox = builder.get_object("template_select_box") self.charecterDetailsMenuTemplateBox = builder.get_object("template_select_box2") - self.characterDetaisMenuDeleteBox = builder.get_object("delete_select_box") self.detailsNameRenderer = builder.get_object("details_name") self.detailsValueRenderer = builder.get_object("details_value") @@ -340,27 +339,28 @@ class CharactersView: container.remove(d) clear_container( self.charecterDetailsMenuAppendBox) clear_container(self.charecterDetailsMenuTemplateBox) - clear_container(self.characterDetaisMenuDeleteBox) for x in self.characterTemplates.templates: button = Gtk.Button(label=x,) # TODO: turn into ModelButton button.connect("clicked", self._appendTemplateClicked, x) self.charecterDetailsMenuAppendBox.add(button) # Now we do the buttons for charecterDetailsMenuTemplateBox - button2 = Gtk.Button(label=x,) # TODO: turn into ModelButton - button2.connect("clicked", self._updateTemplateClicked, x) - self.charecterDetailsMenuTemplateBox.add(button2) - # now we do delete templates box = Gtk.Box() label = Gtk.Label(label=x) box.pack_start(label, False, False, 0) - button3 = Gtk.Button(label='delete') # TODO: Make this red - button3.connect("clicked", self._deleteTemplateClicked, x) - box.pack_start(button3, False, False, 0) - self.characterDetaisMenuDeleteBox.add(box) + overwrite_button = Gtk.Button() + overwrite_button.add(Gtk.Image(icon_name='emblem-insync-syncing')) + overwrite_button.connect("clicked", self._updateTemplateClicked, x) + overwrite_button.set_tooltip_markup ('Overwrite template with text of current file') # TODO: This might be an issue when it comes to translating + delete_button = Gtk.Button() + delete_button.add(Gtk.Image(icon_name='app-remove-symbolic')) + delete_button.set_tooltip_markup ('Delete') # TODO: This might be an issue when it comes to translating + delete_button.connect("clicked", self._deleteTemplateClicked, x) + box.pack_start(overwrite_button, False, False, 0) + box.pack_start(delete_button, False, False, 0) + self.charecterDetailsMenuTemplateBox.add(box) self.charecterDetailsMenuAppendBox.show_all() self.charecterDetailsMenuTemplateBox.show_all() - self.characterDetaisMenuDeleteBox.show_all() def _onCharecterDetailsMenuClicked(self, button: Gtk.MenuButton): self._updateCharecterDetailsMenu() diff --git a/ui/characters.glade b/ui/characters.glade index 327434c9..a6cefe00 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -89,58 +89,6 @@ along with Manuskript. If not, see . 200 False - - - True - False - vertical - - - True - True - True - Append Template - main - True - - - False - True - 0 - - - - - True - True - True - in - - - True - False - - - True - False - none - False - - - - - - - True - True - 1 - - - - - append_template - - True @@ -257,7 +205,7 @@ along with Manuskript. If not, see . True True True - Set info to template + Mange Templates edit_template @@ -267,18 +215,7 @@ along with Manuskript. If not, see . - - True - True - True - Delete Template - delete_template - - - False - True - 2 - + @@ -287,7 +224,10 @@ along with Manuskript. If not, see . - + + + + True False vertical @@ -296,7 +236,7 @@ along with Manuskript. If not, see . True True True - Delete Template + Append Template main True @@ -317,7 +257,7 @@ along with Manuskript. If not, see . True False - + True False none @@ -335,8 +275,8 @@ along with Manuskript. If not, see . - delete_template - 3 + append_template + 4 diff --git a/ui/quote_of_the_day.glade b/ui/quote_of_the_day.glade deleted file mode 100644 index 2e24848d..00000000 --- a/ui/quote_of_the_day.glade +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - True - False - - - True - False - - - -1 - - - - - - True - False - True - 20 - True - - - True - False - label - - - 2 - 1 - - - - - True - False - label - - - 2 - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - From 355f02afd5378ffab3cfdd6f5bc62fa2832d0226 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Sat, 17 Jun 2023 08:44:46 -0400 Subject: [PATCH 19/21] Update --- test_io.py | 24 ------------------------ ui/about.glade | 2 +- 2 files changed, 1 insertion(+), 25 deletions(-) delete mode 100755 test_io.py diff --git a/test_io.py b/test_io.py deleted file mode 100755 index a4971543..00000000 --- a/test_io.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# I put this here because otherwise I couldn't run it. -# I also added some tests and had to modify this to get it to run -- ShadowOfHassen -import os -import sys - -# gi -import gi -gi.require_version('GdkPixbuf', '2.0') -from gi.repository import GdkPixbuf - -realpath = os.path.realpath(__file__) -LOGO_FILE = 'icons/Manuskript/manuskript.svg' -#sys.path.insert(1, os.path.join(os.path.dirname(realpath), '..')) - -from manuskript.ui import MainWindow - - -window = MainWindow("sample-projects/book-of-acts" + ".msk") -# Let's make this a bit fancier -window.window.set_icon(GdkPixbuf.Pixbuf.new_from_file(LOGO_FILE)) - -window.run() diff --git a/ui/about.glade b/ui/about.glade index b29464fd..4aa56b78 100644 --- a/ui/about.glade +++ b/ui/about.glade @@ -31,7 +31,7 @@ along with Manuskript. If not, see . center-on-parent dialog Manuskript - Gtk Working Version (Last Version 0.14.0) + Gtk Working Version (Last Version 0.15.0) Copyright © 2015-2021 Olivier Keshavjee et al. This is a Gtk Version Still In Development https://www.theologeek.ch/manuskript/ From 828ee817839fe4c4a7d30a5e2e20eea1987078b3 Mon Sep 17 00:00:00 2001 From: TheShadowOfHassen <94244235+TheShadowOfHassen@users.noreply.github.com> Date: Sun, 25 Jun 2023 18:10:53 -0400 Subject: [PATCH 20/21] Update charactersView.py --- manuskript/ui/views/charactersView.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index e8f5ecc7..d1b8e3bf 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -346,9 +346,8 @@ class CharactersView: # Now we do the buttons for charecterDetailsMenuTemplateBox box = Gtk.Box() label = Gtk.Label(label=x) - box.pack_start(label, False, False, 0) overwrite_button = Gtk.Button() - overwrite_button.add(Gtk.Image(icon_name='emblem-insync-syncing')) + overwrite_button.add(Gtk.Image(icon_name='system-restart-symbolic')) overwrite_button.connect("clicked", self._updateTemplateClicked, x) overwrite_button.set_tooltip_markup ('Overwrite template with text of current file') # TODO: This might be an issue when it comes to translating delete_button = Gtk.Button() @@ -357,6 +356,7 @@ class CharactersView: delete_button.connect("clicked", self._deleteTemplateClicked, x) box.pack_start(overwrite_button, False, False, 0) box.pack_start(delete_button, False, False, 0) + box.pack_start(label, False, False, 0) self.charecterDetailsMenuTemplateBox.add(box) self.charecterDetailsMenuAppendBox.show_all() From b0d9ac29e7708a02b984a2f6918bc169371fbbde Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 3 Aug 2023 23:41:52 +0200 Subject: [PATCH 21/21] Adjust variable, layout, icon and alignment Signed-off-by: TheJackiMonster --- manuskript/ui/views/charactersView.py | 34 ++--- ui/characters.glade | 206 ++++++++++++++------------ 2 files changed, 125 insertions(+), 115 deletions(-) diff --git a/manuskript/ui/views/charactersView.py b/manuskript/ui/views/charactersView.py index d1b8e3bf..6b93e5a0 100644 --- a/manuskript/ui/views/charactersView.py +++ b/manuskript/ui/views/charactersView.py @@ -339,24 +339,24 @@ class CharactersView: container.remove(d) clear_container( self.charecterDetailsMenuAppendBox) clear_container(self.charecterDetailsMenuTemplateBox) - for x in self.characterTemplates.templates: - button = Gtk.Button(label=x,) # TODO: turn into ModelButton - button.connect("clicked", self._appendTemplateClicked, x) + for template_name in self.characterTemplates.templates: + button = Gtk.Button(label=template_name) # TODO: turn into ModelButton + button.connect("clicked", self._appendTemplateClicked, template_name) self.charecterDetailsMenuAppendBox.add(button) # Now we do the buttons for charecterDetailsMenuTemplateBox box = Gtk.Box() - label = Gtk.Label(label=x) + label = Gtk.Label(label=template_name) overwrite_button = Gtk.Button() - overwrite_button.add(Gtk.Image(icon_name='system-restart-symbolic')) - overwrite_button.connect("clicked", self._updateTemplateClicked, x) + overwrite_button.add(Gtk.Image(icon_name='emblem-synchronizing-symbolic')) + overwrite_button.connect("clicked", self._updateTemplateClicked, template_name) overwrite_button.set_tooltip_markup ('Overwrite template with text of current file') # TODO: This might be an issue when it comes to translating delete_button = Gtk.Button() - delete_button.add(Gtk.Image(icon_name='app-remove-symbolic')) + delete_button.add(Gtk.Image(icon_name='list-remove-symbolic')) delete_button.set_tooltip_markup ('Delete') # TODO: This might be an issue when it comes to translating - delete_button.connect("clicked", self._deleteTemplateClicked, x) - box.pack_start(overwrite_button, False, False, 0) - box.pack_start(delete_button, False, False, 0) - box.pack_start(label, False, False, 0) + delete_button.connect("clicked", self._deleteTemplateClicked, template_name) + box.pack_end(delete_button, False, False, 0) + box.pack_end(overwrite_button, False, False, 0) + box.pack_start(label, True, False, 0) self.charecterDetailsMenuTemplateBox.add(box) self.charecterDetailsMenuAppendBox.show_all() @@ -365,19 +365,19 @@ class CharactersView: def _onCharecterDetailsMenuClicked(self, button: Gtk.MenuButton): self._updateCharecterDetailsMenu() - def _updateTemplateClicked(self, button: Gtk.ModelButton, template): + def _updateTemplateClicked(self, button: Gtk.ModelButton, template_name): if self.character is None: return - self.characterTemplates.templates[template] = self.character.details # TODO: Add A warning? Or should there be undo/ redo when revisions are written. + self.characterTemplates.templates[template_name] = self.character.details # TODO: Add A warning? Or should there be undo/ redo when revisions are written. - def _deleteTemplateClicked(self, button: Gtk.ModelButton, template): - del self.characterTemplates.templates[template] + def _deleteTemplateClicked(self, button: Gtk.ModelButton, template_name): + del self.characterTemplates.templates[template_name] self._updateCharecterDetailsMenu() - def _appendTemplateClicked(self, button: Gtk.ModelButton, template): + def _appendTemplateClicked(self, button: Gtk.ModelButton, template_name): if self.character is None: return - self.character.details.update(self.characterTemplates.templates[template]) + self.character.details.update(self.characterTemplates.templates[template_name]) # We have to reload the character self.loadCharacterData(self.character) diff --git a/ui/characters.glade b/ui/characters.glade index a6cefe00..1b0333a6 100644 --- a/ui/characters.glade +++ b/ui/characters.glade @@ -87,100 +87,9 @@ along with Manuskript. If not, see . - 200 + 350 + 250 False - - - True - False - vertical - - - True - True - True - Set info to template - main - True - - - False - True - 0 - - - - - True - True - True - in - - - True - False - - - True - False - none - False - - - - - - - True - True - 1 - - - - - True - False - - - True - True - new_template_entry_buffer - Enter a unique name - GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE - - - False - True - 0 - - - - - New template - True - True - True - Adds a new template with the content of the current charecter's details. - - - False - True - 2 - - - - - False - True - 2 - - - - - edit_template - 1 - - True @@ -220,12 +129,8 @@ along with Manuskript. If not, see . main - 2 - - - True @@ -251,6 +156,7 @@ along with Manuskript. If not, see . True True True + 4 in @@ -276,7 +182,111 @@ along with Manuskript. If not, see . append_template - 4 + 1 + + + + + True + False + vertical + + + True + True + True + Set info to template + main + True + + + False + True + 0 + + + + + True + True + True + 4 + in + + + True + False + + + True + False + none + False + + + + + + + True + True + 1 + + + + + True + False + 4 + 4 + 4 + 4 + + + True + True + new_template_entry_buffer + Enter a unique name + GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE + + + True + True + 0 + + + + + True + True + True + Adds a new template with the content of the current charecter's details. + + + True + False + list-add-symbolic + + + + + False + True + end + 2 + + + + + False + True + 2 + + + + + edit_template + 2