mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-06-01 10:39:34 +12:00
Add character and remove character via button
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
parent
2aa65fc815
commit
29fbe2acbb
|
@ -8,6 +8,7 @@ from manuskript.data.color import Color
|
||||||
from manuskript.data.importance import Importance
|
from manuskript.data.importance import Importance
|
||||||
from manuskript.data.unique_id import UniqueIDHost
|
from manuskript.data.unique_id import UniqueIDHost
|
||||||
from manuskript.io.mmdFile import MmdFile
|
from manuskript.io.mmdFile import MmdFile
|
||||||
|
from manuskript.util import safeFilename
|
||||||
|
|
||||||
|
|
||||||
class Character:
|
class Character:
|
||||||
|
@ -34,6 +35,12 @@ class Character:
|
||||||
def allowPOV(self) -> bool:
|
def allowPOV(self) -> bool:
|
||||||
return True if self.POV is None else self.POV
|
return True if self.POV is None else self.POV
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
if self.UID is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.characters.removeByID(self.UID.value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loadAttribute(cls, metadata: dict, name: str, defaultValue=None):
|
def loadAttribute(cls, metadata: dict, name: str, defaultValue=None):
|
||||||
if name in metadata:
|
if name in metadata:
|
||||||
|
@ -104,14 +111,37 @@ class Characters:
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self.data.values().__iter__()
|
return self.data.values().__iter__()
|
||||||
|
|
||||||
|
def add(self, name: str = None) -> Character | None:
|
||||||
|
if name is None:
|
||||||
|
name = "New character"
|
||||||
|
|
||||||
|
UID = self.host.newID()
|
||||||
|
filename = safeFilename("%s-%s" % (str(UID), name), "txt")
|
||||||
|
|
||||||
|
path = os.path.join(self.dir_path, filename)
|
||||||
|
|
||||||
|
if os.path.exists(filename):
|
||||||
|
return None
|
||||||
|
|
||||||
|
character = Character(path, self)
|
||||||
|
character.UID = UID
|
||||||
|
character.name = name
|
||||||
|
|
||||||
|
self.data[character.UID.value] = character
|
||||||
|
|
||||||
|
return character
|
||||||
|
|
||||||
def getByID(self, ID: int) -> Character:
|
def getByID(self, ID: int) -> Character:
|
||||||
return self.data.get(ID, None)
|
return self.data.get(ID, None)
|
||||||
|
|
||||||
|
def removeByID(self, ID: int):
|
||||||
|
self.data.pop(ID)
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
self.data.clear()
|
self.data.clear()
|
||||||
|
|
||||||
for name in os.listdir(self.dir_path):
|
for filename in os.listdir(self.dir_path):
|
||||||
path = os.path.join(self.dir_path, name)
|
path = os.path.join(self.dir_path, filename)
|
||||||
|
|
||||||
if not os.path.isfile(path):
|
if not os.path.isfile(path):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -19,6 +19,9 @@ class Color:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, string: str):
|
def parse(cls, string: str):
|
||||||
|
if string is None:
|
||||||
|
return None
|
||||||
|
|
||||||
colorPattern = re.compile(r"\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})")
|
colorPattern = re.compile(r"\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})")
|
||||||
|
|
||||||
m = colorPattern.match(string)
|
m = colorPattern.match(string)
|
||||||
|
|
|
@ -12,19 +12,16 @@ from manuskript.data import Color
|
||||||
|
|
||||||
def rgbaFromColor(color: Color) -> Gdk.RGBA:
|
def rgbaFromColor(color: Color) -> Gdk.RGBA:
|
||||||
rgba = Gdk.RGBA()
|
rgba = Gdk.RGBA()
|
||||||
rgba.red = color.red / 255.
|
rgba.red = 0 if color is None else color.red / 255.
|
||||||
rgba.green = color.green / 255.
|
rgba.green = 0 if color is None else color.green / 255.
|
||||||
rgba.blue = color.blue / 255.
|
rgba.blue = 0 if color is None else color.blue / 255.
|
||||||
rgba.alpha = 1.
|
rgba.alpha = 1.
|
||||||
return rgba
|
return rgba
|
||||||
|
|
||||||
|
|
||||||
def pixbufFromColor(color: Color) -> GdkPixbuf:
|
def pixbufFromColor(color: Color) -> GdkPixbuf:
|
||||||
if color is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 16, 16)
|
pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 16, 16)
|
||||||
pixbuf.fill(color.getRGB())
|
pixbuf.fill(0 if color is None else color.getRGB())
|
||||||
return pixbuf
|
return pixbuf
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,7 @@ class CharactersView:
|
||||||
self.widget = builder.get_object("characters_view")
|
self.widget = builder.get_object("characters_view")
|
||||||
|
|
||||||
self.charactersStore = builder.get_object("characters_store")
|
self.charactersStore = builder.get_object("characters_store")
|
||||||
|
self.refreshCharacterStore()
|
||||||
for character in self.characters:
|
|
||||||
tree_iter = self.charactersStore.append()
|
|
||||||
|
|
||||||
if tree_iter is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
self.charactersStore.set_value(tree_iter, 0, character.UID.value)
|
|
||||||
self.charactersStore.set_value(tree_iter, 1, validString(character.name))
|
|
||||||
self.charactersStore.set_value(tree_iter, 2, pixbufFromColor(character.color))
|
|
||||||
self.charactersStore.set_value(tree_iter, 3, Importance.asValue(character.importance))
|
|
||||||
|
|
||||||
self.mainCharactersStore = builder.get_object("main_characters_store")
|
self.mainCharactersStore = builder.get_object("main_characters_store")
|
||||||
self.secondaryCharactersStore = builder.get_object("secondary_characters_store")
|
self.secondaryCharactersStore = builder.get_object("secondary_characters_store")
|
||||||
|
@ -56,6 +46,16 @@ class CharactersView:
|
||||||
for selection in self.characterSelections:
|
for selection in self.characterSelections:
|
||||||
selection.connect("changed", self.characterSelectionChanged)
|
selection.connect("changed", self.characterSelectionChanged)
|
||||||
|
|
||||||
|
self.addCharacterButton = builder.get_object("add_character")
|
||||||
|
self.removeCharacterButton = builder.get_object("remove_character")
|
||||||
|
self.filterCharactersBuffer = builder.get_object("filter_characters")
|
||||||
|
|
||||||
|
self.addCharacterButton.connect("clicked", self.addCharacterClicked)
|
||||||
|
self.removeCharacterButton.connect("clicked", self.removeCharacterClicked)
|
||||||
|
|
||||||
|
self.filterCharactersBuffer.connect("deleted-text", self.filterCharactersDeletedText)
|
||||||
|
self.filterCharactersBuffer.connect("inserted-text", self.filterCharactersInsertedText)
|
||||||
|
|
||||||
self.colorButton = builder.get_object("color")
|
self.colorButton = builder.get_object("color")
|
||||||
self.importanceCombo = builder.get_object("importance")
|
self.importanceCombo = builder.get_object("importance")
|
||||||
self.allowPOVCheck = builder.get_object("allow_POV")
|
self.allowPOVCheck = builder.get_object("allow_POV")
|
||||||
|
@ -100,6 +100,20 @@ class CharactersView:
|
||||||
|
|
||||||
self.unloadCharacterData()
|
self.unloadCharacterData()
|
||||||
|
|
||||||
|
def refreshCharacterStore(self):
|
||||||
|
self.charactersStore.clear()
|
||||||
|
|
||||||
|
for character in self.characters:
|
||||||
|
tree_iter = self.charactersStore.append()
|
||||||
|
|
||||||
|
if tree_iter is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.charactersStore.set_value(tree_iter, 0, character.UID.value)
|
||||||
|
self.charactersStore.set_value(tree_iter, 1, validString(character.name))
|
||||||
|
self.charactersStore.set_value(tree_iter, 2, pixbufFromColor(character.color))
|
||||||
|
self.charactersStore.set_value(tree_iter, 3, Importance.asValue(character.importance))
|
||||||
|
|
||||||
def loadCharacterData(self, character: Character):
|
def loadCharacterData(self, character: Character):
|
||||||
self.character = None
|
self.character = None
|
||||||
|
|
||||||
|
@ -166,6 +180,30 @@ class CharactersView:
|
||||||
else:
|
else:
|
||||||
self.loadCharacterData(character)
|
self.loadCharacterData(character)
|
||||||
|
|
||||||
|
def addCharacterClicked(self, button: Gtk.Button):
|
||||||
|
character = self.characters.add()
|
||||||
|
|
||||||
|
if character is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.refreshCharacterStore()
|
||||||
|
|
||||||
|
def removeCharacterClicked(self, button: Gtk.Button):
|
||||||
|
if self.character is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.character.remove()
|
||||||
|
self.refreshCharacterStore()
|
||||||
|
|
||||||
|
def filterCharactersChanged(self, buffer: Gtk.EntryBuffer):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def filterCharactersDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int):
|
||||||
|
self.filterCharactersChanged(buffer)
|
||||||
|
|
||||||
|
def filterCharactersInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int):
|
||||||
|
self.filterCharactersChanged(buffer)
|
||||||
|
|
||||||
def colorSet(self, button: Gtk.ColorButton):
|
def colorSet(self, button: Gtk.ColorButton):
|
||||||
if self.character is None:
|
if self.character is None:
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
from manuskript.util.counter import CharCounter, WordCounter, PageCounter
|
from manuskript.util.counter import CharCounter, WordCounter, PageCounter
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,3 +29,20 @@ def validInt(invalid: int) -> int:
|
||||||
|
|
||||||
def invalidInt(valid: int) -> int:
|
def invalidInt(valid: int) -> int:
|
||||||
return None if valid == 0 else valid
|
return None if valid == 0 else valid
|
||||||
|
|
||||||
|
|
||||||
|
def safeFilename(filename: str, extension: str = None) -> str:
|
||||||
|
if extension is not None:
|
||||||
|
filename = "%s.%s" % (filename, extension)
|
||||||
|
|
||||||
|
name = filename.encode('ascii', 'replace').decode('ascii')
|
||||||
|
filenamesToAvoid = list(["CON", "PRN", "AUX", "NUL"])
|
||||||
|
|
||||||
|
for i in range(1, 9):
|
||||||
|
filenamesToAvoid.append("COM" + str(i))
|
||||||
|
filenamesToAvoid.append("LPT" + str(i))
|
||||||
|
|
||||||
|
if name.upper() in filenamesToAvoid:
|
||||||
|
name = "_" + name
|
||||||
|
|
||||||
|
return re.sub(r"[^a-zA-Z0-9._\-+()]", "_", name)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Generated with glade 3.38.2
|
<!-- Generated with glade 3.40.0
|
||||||
|
|
||||||
Copyright (C) 2015-2021 Olivier Keshavjee et al.
|
Copyright (C) 2015-2021 Olivier Keshavjee et al.
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
||||||
</columns>
|
</columns>
|
||||||
</object>
|
</object>
|
||||||
<object class="GtkTextBuffer" id="epiphany"/>
|
<object class="GtkTextBuffer" id="epiphany"/>
|
||||||
|
<object class="GtkEntryBuffer" id="filter_characters"/>
|
||||||
<object class="GtkTextBuffer" id="goal"/>
|
<object class="GtkTextBuffer" id="goal"/>
|
||||||
<object class="GtkListStore" id="importance_store">
|
<object class="GtkListStore" id="importance_store">
|
||||||
<columns>
|
<columns>
|
||||||
|
@ -274,7 +275,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
||||||
<property name="margin-bottom">8</property>
|
<property name="margin-bottom">8</property>
|
||||||
<property name="spacing">4</property>
|
<property name="spacing">4</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton">
|
<object class="GtkButton" id="add_character">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
@ -293,7 +294,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton">
|
<object class="GtkButton" id="remove_character">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
@ -315,6 +316,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
||||||
<object class="GtkEntry">
|
<object class="GtkEntry">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
|
<property name="buffer">filter_characters</property>
|
||||||
<property name="placeholder-text" translatable="yes">Filter</property>
|
<property name="placeholder-text" translatable="yes">Filter</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
|
Loading…
Reference in a new issue