mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-17 03:12:27 +12:00
Implement basic outline overview
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
parent
792e68038d
commit
3481e40b4f
|
@ -3,12 +3,12 @@
|
|||
|
||||
from manuskript.data.characters import Characters, Character
|
||||
from manuskript.data.color import Color
|
||||
from manuskript.data.goal import GoalKind, Goal
|
||||
from manuskript.data.goal import Goal
|
||||
from manuskript.data.importance import Importance
|
||||
from manuskript.data.info import Info
|
||||
from manuskript.data.labels import LabelHost, Label
|
||||
from manuskript.data.links import LinkAction, Links
|
||||
from manuskript.data.outline import Outline, OutlineFolder, OutlineText
|
||||
from manuskript.data.outline import Outline, OutlineFolder, OutlineText, OutlineItem, OutlineState
|
||||
from manuskript.data.plots import Plots, PlotLine, PlotStep
|
||||
from manuskript.data.project import Project
|
||||
from manuskript.data.revisions import Revisions
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
|
||||
from enum import Enum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class GoalKind(Enum):
|
||||
WORDS = 0
|
||||
CHARACTERS = 1
|
||||
from manuskript.util import CounterKind, countText
|
||||
|
||||
|
||||
class Goal:
|
||||
|
||||
def __init__(self, value: int = 0, kind: GoalKind = GoalKind.WORDS):
|
||||
def __init__(self, value: int = 0, kind: CounterKind = CounterKind.WORDS):
|
||||
self.value = max(value, 0)
|
||||
self.kind = kind
|
||||
|
||||
|
@ -20,11 +14,14 @@ class Goal:
|
|||
return str(self.value) + " " + self.kind.name.lower()
|
||||
|
||||
def __str__(self):
|
||||
if self.kind != GoalKind.WORDS:
|
||||
if self.kind != CounterKind.WORDS:
|
||||
return self.prettyString()
|
||||
else:
|
||||
return str(self.value)
|
||||
|
||||
def count(self, text: str):
|
||||
return countText(text, self.kind)
|
||||
|
||||
@classmethod
|
||||
def parse(cls, string: str):
|
||||
if string is None:
|
||||
|
@ -34,7 +31,7 @@ class Goal:
|
|||
|
||||
try:
|
||||
value = int(parts[0])
|
||||
kind = GoalKind[parts[1].upper()] if len(parts) > 1 else GoalKind.WORDS
|
||||
kind = CounterKind[parts[1].upper()] if len(parts) > 1 else CounterKind.WORDS
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ import os
|
|||
from collections import OrderedDict
|
||||
from enum import Enum, unique
|
||||
from manuskript.data.goal import Goal
|
||||
from manuskript.data.plots import Plots
|
||||
from manuskript.data.unique_id import UniqueIDHost
|
||||
from manuskript.io.mmdFile import MmdFile
|
||||
from manuskript.util import CounterKind, countText, validString
|
||||
|
||||
|
||||
@unique
|
||||
|
@ -43,7 +45,9 @@ class OutlineItem:
|
|||
if ID is None:
|
||||
return
|
||||
|
||||
item.UID = item.outline.host.loadID(int(ID))
|
||||
if (item.UID is None) or (item.UID.value != int(ID)):
|
||||
item.UID = item.outline.host.loadID(int(ID))
|
||||
|
||||
item.title = metadata.get("title", None)
|
||||
item.type = metadata.get("type", "md")
|
||||
item.summarySentence = metadata.get("summarySentence", None)
|
||||
|
@ -76,6 +80,12 @@ class OutlineItem:
|
|||
|
||||
return metadata
|
||||
|
||||
def textCount(self, counterKind: CounterKind = None) -> int:
|
||||
return 0
|
||||
|
||||
def goalCount(self) -> int:
|
||||
return 0 if self.goal is None else self.goal.value
|
||||
|
||||
def load(self, optimized: bool = True):
|
||||
raise IOError('Loading undefined!')
|
||||
|
||||
|
@ -90,6 +100,12 @@ class OutlineText(OutlineItem):
|
|||
|
||||
self.text = ""
|
||||
|
||||
def textCount(self, counterKind: CounterKind = None) -> int:
|
||||
if counterKind is None:
|
||||
counterKind = CounterKind.WORDS if self.goal is None else self.goal.kind
|
||||
|
||||
return super().textCount(counterKind) + countText(self.text, counterKind)
|
||||
|
||||
def load(self, optimized: bool = True):
|
||||
metadata, body = self.file.loadMMD(optimized)
|
||||
OutlineItem.loadMetadata(self, metadata)
|
||||
|
@ -126,6 +142,7 @@ class OutlineFolder(OutlineItem):
|
|||
|
||||
names = os.listdir(folder.dir_path)
|
||||
names.remove("folder.txt")
|
||||
names.sort()
|
||||
|
||||
for name in names:
|
||||
path = os.path.join(folder.dir_path, name)
|
||||
|
@ -147,6 +164,17 @@ class OutlineFolder(OutlineItem):
|
|||
if type(item) is OutlineFolder:
|
||||
cls.loadItems(outline, item, recursive)
|
||||
|
||||
def textCount(self, counterKind: CounterKind = None) -> int:
|
||||
if counterKind is None:
|
||||
counterKind = CounterKind.WORDS if self.goal is None else self.goal.kind
|
||||
|
||||
count = super().textCount(counterKind)
|
||||
|
||||
for item in self.items:
|
||||
count += item.textCount(counterKind)
|
||||
|
||||
return count
|
||||
|
||||
def load(self, _: bool = True):
|
||||
metadata, _ = self.file.loadMMD(True)
|
||||
OutlineItem.loadMetadata(self, metadata)
|
||||
|
@ -170,14 +198,22 @@ class OutlineFolder(OutlineItem):
|
|||
|
||||
class Outline:
|
||||
|
||||
def __init__(self, path):
|
||||
def __init__(self, path, plots: Plots):
|
||||
self.dir_path = os.path.join(path, "outline")
|
||||
self.host = UniqueIDHost()
|
||||
self.plots = plots
|
||||
self.items = list()
|
||||
|
||||
def __iter__(self):
|
||||
return self.items.__iter__()
|
||||
|
||||
def getItemByID(self, ID: int) -> OutlineItem | None:
|
||||
for item in self.all():
|
||||
if item.UID.value == ID:
|
||||
return item
|
||||
|
||||
return None
|
||||
|
||||
def all(self):
|
||||
result = list()
|
||||
queue = list(self.items)
|
||||
|
@ -196,7 +232,10 @@ class Outline:
|
|||
def load(self):
|
||||
self.items.clear()
|
||||
|
||||
for name in os.listdir(self.dir_path):
|
||||
names = os.listdir(self.dir_path)
|
||||
names.sort()
|
||||
|
||||
for name in names:
|
||||
path = os.path.join(self.dir_path, name)
|
||||
|
||||
if os.path.isdir(path):
|
||||
|
|
|
@ -32,7 +32,7 @@ class Project:
|
|||
self.characters = Characters(self.file.dir_path)
|
||||
self.plots = Plots(self.file.dir_path, self.characters)
|
||||
self.world = World(self.file.dir_path)
|
||||
self.outline = Outline(self.file.dir_path)
|
||||
self.outline = Outline(self.file.dir_path, self.plots)
|
||||
self.revisions = Revisions(self.file.dir_path)
|
||||
|
||||
def __del__(self):
|
||||
|
|
|
@ -68,7 +68,7 @@ class MainWindow:
|
|||
self.charactersView = MainWindow.packViewIntoSlot(builder, "characters_slot", CharactersView, self.project.characters)
|
||||
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.outlineView = MainWindow.packViewIntoSlot(builder, "outline_slot", OutlineView, self.project.outline)
|
||||
self.editorView = MainWindow.packViewIntoSlot(builder, "editor_slot", EditorView)
|
||||
|
||||
self.startupWindow = StartupWindow(self)
|
||||
|
|
|
@ -6,14 +6,269 @@ import gi
|
|||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk
|
||||
|
||||
from manuskript.data import Outline, OutlineFolder, OutlineText, OutlineItem, OutlineState, Plots, PlotLine, Characters, Character, Importance, Goal
|
||||
from manuskript.ui.util import rgbaFromColor, pixbufFromColor
|
||||
from manuskript.util import validString, invalidString, validInt, invalidInt, CounterKind, countText
|
||||
|
||||
|
||||
class OutlineView:
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, outline: Outline):
|
||||
self.outline = outline
|
||||
self.outlineItem = None
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_file("ui/outline.glade")
|
||||
|
||||
self.widget = builder.get_object("outline_view")
|
||||
|
||||
self.plotsStore = builder.get_object("plots_store")
|
||||
self.refreshPlotsStore()
|
||||
|
||||
self.charactersStore = builder.get_object("characters_store")
|
||||
self.refreshCharactersStore()
|
||||
|
||||
self.outlineStore = builder.get_object("outline_store")
|
||||
self.refreshOutlineStore()
|
||||
|
||||
self.mainPlotsStore = builder.get_object("main_plots_store")
|
||||
self.secondaryPlotsStore = builder.get_object("secondary_plots_store")
|
||||
self.minorPlotsStore = builder.get_object("minor_plots_store")
|
||||
|
||||
self.mainPlotsStore.set_visible_func(
|
||||
lambda model, iter, userdata: model[iter][2] == Importance.MAIN.value)
|
||||
self.secondaryPlotsStore.set_visible_func(
|
||||
lambda model, iter, userdata: model[iter][2] == Importance.SECONDARY.value)
|
||||
self.minorPlotsStore.set_visible_func(
|
||||
lambda model, iter, userdata: model[iter][2] == Importance.MINOR.value)
|
||||
|
||||
self.mainPlotsStore.refilter()
|
||||
self.secondaryPlotsStore.refilter()
|
||||
self.minorPlotsStore.refilter()
|
||||
|
||||
self.plotSelections = [
|
||||
builder.get_object("minor_plot_selection"),
|
||||
builder.get_object("secondary_plot_selection"),
|
||||
builder.get_object("main_plot_selection")
|
||||
]
|
||||
|
||||
for selection in self.plotSelections:
|
||||
selection.connect("changed", self.plotSelectionChanged)
|
||||
|
||||
self.filterOutlineBuffer = builder.get_object("filter_outline")
|
||||
|
||||
self.filterOutlineBuffer.connect("deleted-text", self.filterOutlineDeletedText)
|
||||
self.filterOutlineBuffer.connect("inserted-text", self.filterOutlineInsertedText)
|
||||
|
||||
self.filteredOutlineStore = builder.get_object("filtered_outline_store")
|
||||
|
||||
self.filteredOutlineStore.set_visible_func(self.filterOutline)
|
||||
self.filteredOutlineStore.refilter()
|
||||
|
||||
self.outlineSelection = builder.get_object("outline_selection")
|
||||
|
||||
self.outlineSelection.connect("changed", self.outlineSelectionChanged)
|
||||
|
||||
self.goalBuffer = builder.get_object("goal")
|
||||
self.oneLineSummaryBuffer = builder.get_object("one_line_summary")
|
||||
self.fewSentencesSummaryBuffer = builder.get_object("few_sentences_summary")
|
||||
|
||||
self.goalBuffer.connect("deleted-text", self.goalDeletedText)
|
||||
self.goalBuffer.connect("inserted-text", self.goalInsertedText)
|
||||
|
||||
self.oneLineSummaryBuffer.connect("deleted-text", self.oneLineSummaryDeletedText)
|
||||
self.oneLineSummaryBuffer.connect("inserted-text", self.oneLineSummaryInsertedText)
|
||||
|
||||
self.fewSentencesSummaryBuffer.connect("changed", self.fewSentencesSummaryChanged)
|
||||
|
||||
self.unloadOutlineData()
|
||||
|
||||
def refreshPlotsStore(self):
|
||||
self.plotsStore.clear()
|
||||
|
||||
for plotLine in self.outline.plots:
|
||||
tree_iter = self.plotsStore.append()
|
||||
|
||||
if tree_iter is None:
|
||||
continue
|
||||
|
||||
self.plotsStore.set_value(tree_iter, 0, plotLine.UID.value)
|
||||
self.plotsStore.set_value(tree_iter, 1, validString(plotLine.name))
|
||||
self.plotsStore.set_value(tree_iter, 2, Importance.asValue(plotLine.importance))
|
||||
|
||||
def refreshCharactersStore(self):
|
||||
self.charactersStore.clear()
|
||||
|
||||
for character in self.outline.plots.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))
|
||||
|
||||
def __appendOutlineItem(self, outlineItem: OutlineItem, parent_iter=None):
|
||||
tree_iter = self.outlineStore.append(parent_iter)
|
||||
|
||||
if tree_iter is None:
|
||||
return
|
||||
|
||||
if outlineItem.state != OutlineState.COMPLETE:
|
||||
outlineItem.load(False)
|
||||
|
||||
if type(outlineItem) is OutlineFolder:
|
||||
for item in outlineItem:
|
||||
self.__appendOutlineItem(item, tree_iter)
|
||||
|
||||
wordCount = validInt(outlineItem.textCount())
|
||||
goal = validInt(outlineItem.goalCount())
|
||||
progress = 0
|
||||
|
||||
if goal > wordCount:
|
||||
progress = 100 * wordCount / goal
|
||||
elif goal > 0:
|
||||
progress = 100
|
||||
|
||||
self.outlineStore.set_value(tree_iter, 0, outlineItem.UID.value)
|
||||
self.outlineStore.set_value(tree_iter, 1, validString(outlineItem.title))
|
||||
self.outlineStore.set_value(tree_iter, 2, validString(outlineItem.label))
|
||||
self.outlineStore.set_value(tree_iter, 3, validString(outlineItem.status))
|
||||
self.outlineStore.set_value(tree_iter, 4, outlineItem.compile)
|
||||
self.outlineStore.set_value(tree_iter, 5, wordCount)
|
||||
self.outlineStore.set_value(tree_iter, 6, goal)
|
||||
self.outlineStore.set_value(tree_iter, 7, progress)
|
||||
|
||||
def refreshOutlineStore(self):
|
||||
self.outlineStore.clear()
|
||||
|
||||
for item in self.outline.items:
|
||||
self.__appendOutlineItem(item)
|
||||
|
||||
def plotSelectionChanged(self, selection: Gtk.TreeSelection):
|
||||
model, tree_iter = selection.get_selected()
|
||||
|
||||
if tree_iter is None:
|
||||
return
|
||||
|
||||
for other in self.plotSelections:
|
||||
if other != selection:
|
||||
other.unselect_all()
|
||||
|
||||
def loadOutlineData(self, outlineItem: OutlineItem):
|
||||
self.outlineItem = None
|
||||
|
||||
self.goalBuffer.set_text(validString(outlineItem.goal), -1)
|
||||
self.oneLineSummaryBuffer.set_text(validString(outlineItem.summarySentence), -1)
|
||||
self.fewSentencesSummaryBuffer.set_text(validString(outlineItem.summaryFull), -1)
|
||||
|
||||
self.outlineItem = outlineItem
|
||||
|
||||
def unloadOutlineData(self):
|
||||
self.outlineItem = None
|
||||
|
||||
self.goalBuffer.set_text("", -1)
|
||||
self.oneLineSummaryBuffer.set_text("", -1)
|
||||
self.fewSentencesSummaryBuffer.set_text("", -1)
|
||||
|
||||
def outlineSelectionChanged(self, selection: Gtk.TreeSelection):
|
||||
model, tree_iter = selection.get_selected()
|
||||
|
||||
if tree_iter is None:
|
||||
self.unloadOutlineData()
|
||||
return
|
||||
|
||||
outlineItem = self.outline.getItemByID(model[tree_iter][0])
|
||||
|
||||
if outlineItem is None:
|
||||
self.unloadOutlineData()
|
||||
else:
|
||||
self.loadOutlineData(outlineItem)
|
||||
|
||||
def __matchOutlineItemByText(self, outlineItem: OutlineItem, text: str):
|
||||
if type(outlineItem) is OutlineFolder:
|
||||
for item in outlineItem:
|
||||
if self.__matchOutlineItemByText(item, text):
|
||||
return True
|
||||
|
||||
title = validString(outlineItem.title)
|
||||
return text in title.lower()
|
||||
|
||||
def filterOutline(self, model, iter, userdata):
|
||||
outlineItem = self.outline.getItemByID(model[iter][0])
|
||||
|
||||
if outlineItem is None:
|
||||
return False
|
||||
|
||||
text = validString(self.filterOutlineBuffer.get_text())
|
||||
return self.__matchOutlineItemByText(outlineItem, text.lower())
|
||||
|
||||
def filterOutlineChanged(self, buffer: Gtk.EntryBuffer):
|
||||
self.filteredOutlineStore.refilter()
|
||||
|
||||
def filterOutlineDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int):
|
||||
self.filterOutlineChanged(buffer)
|
||||
|
||||
def filterOutlineInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int):
|
||||
self.filterOutlineChanged(buffer)
|
||||
|
||||
def goalChanged(self, buffer: Gtk.EntryBuffer):
|
||||
if self.outlineItem is None:
|
||||
return
|
||||
|
||||
text = buffer.get_text()
|
||||
|
||||
self.outlineItem.goal = Goal.parse(text)
|
||||
|
||||
outline_id = self.outlineItem.UID.value
|
||||
|
||||
wordCount = validInt(self.outlineItem.textCount())
|
||||
goal = validInt(self.outlineItem.goalCount())
|
||||
progress = 0
|
||||
|
||||
if goal > wordCount:
|
||||
progress = 100 * wordCount / goal
|
||||
elif goal > 0:
|
||||
progress = 100
|
||||
|
||||
for row in self.outlineStore:
|
||||
if row[0] == outline_id:
|
||||
row[6] = goal
|
||||
row[7] = progress
|
||||
break
|
||||
|
||||
def goalDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int):
|
||||
self.goalChanged(buffer)
|
||||
|
||||
def goalInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int):
|
||||
self.goalChanged(buffer)
|
||||
|
||||
def oneLineSummaryChanged(self, buffer: Gtk.EntryBuffer):
|
||||
if self.outlineItem is None:
|
||||
return
|
||||
|
||||
text = buffer.get_text()
|
||||
summary = invalidString(text)
|
||||
|
||||
self.outlineItem.summarySentence = summary
|
||||
|
||||
def oneLineSummaryDeletedText(self, buffer: Gtk.EntryBuffer, position: int, n_chars: int):
|
||||
self.oneLineSummaryChanged(buffer)
|
||||
|
||||
def oneLineSummaryInsertedText(self, buffer: Gtk.EntryBuffer, position: int, chars: str, n_chars: int):
|
||||
self.oneLineSummaryChanged(buffer)
|
||||
|
||||
def fewSentencesSummaryChanged(self, buffer: Gtk.TextBuffer):
|
||||
if self.outlineItem is None:
|
||||
return
|
||||
|
||||
start_iter = buffer.get_start_iter()
|
||||
end_iter = buffer.get_end_iter()
|
||||
|
||||
text = buffer.get_text(start_iter, end_iter, False)
|
||||
|
||||
self.outlineItem.summaryFull = invalidString(text)
|
||||
|
||||
def show(self):
|
||||
self.widget.show_all()
|
||||
|
|
|
@ -59,7 +59,7 @@ class WorldView:
|
|||
|
||||
self.unloadWorldData()
|
||||
|
||||
def __appendWorldItem(self, worldItem: WorldItem, parent_iter = None):
|
||||
def __appendWorldItem(self, worldItem: WorldItem, parent_iter=None):
|
||||
tree_iter = self.worldStore.append(parent_iter)
|
||||
|
||||
if tree_iter is None:
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
from manuskript.util.counter import CharCounter, WordCounter, PageCounter
|
||||
|
||||
from manuskript.util.counter import CounterKind, CharCounter, WordCounter, PageCounter
|
||||
|
||||
|
||||
def safeInt(s: str, d: int) -> int:
|
||||
|
@ -15,16 +16,16 @@ def safeInt(s: str, d: int) -> int:
|
|||
return d
|
||||
|
||||
|
||||
def validString(invalid: str) -> str:
|
||||
return "" if invalid is None else invalid
|
||||
def validString(invalid) -> str:
|
||||
return "" if invalid is None else str(invalid)
|
||||
|
||||
|
||||
def invalidString(valid: str) -> str:
|
||||
return None if len(valid) == 0 else valid
|
||||
|
||||
|
||||
def validInt(invalid: int) -> int:
|
||||
return 0 if invalid is None else invalid
|
||||
def validInt(invalid) -> int:
|
||||
return 0 if invalid is None else int(invalid)
|
||||
|
||||
|
||||
def invalidInt(valid: int) -> int:
|
||||
|
@ -46,3 +47,17 @@ def safeFilename(filename: str, extension: str = None) -> str:
|
|||
name = "_" + name
|
||||
|
||||
return re.sub(r"[^a-zA-Z0-9._\-+()]", "_", name)
|
||||
|
||||
|
||||
def countText(text: str, kind: CounterKind = CounterKind.WORDS):
|
||||
if text is None:
|
||||
return 0
|
||||
|
||||
if kind == CounterKind.CHARACTERS:
|
||||
return CharCounter.count(text)
|
||||
elif kind == CounterKind.WORDS:
|
||||
return WordCounter.count(text)
|
||||
elif kind == CounterKind.PAGES:
|
||||
return PageCounter.count(text)
|
||||
else:
|
||||
return 0
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
|
||||
import re
|
||||
|
||||
from enum import Enum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class CounterKind(Enum):
|
||||
WORDS = 0
|
||||
CHARACTERS = 1
|
||||
PAGES = 2
|
||||
|
||||
|
||||
class CharCounter:
|
||||
|
||||
|
|
126
ui/outline.glade
126
ui/outline.glade
|
@ -1,5 +1,5 @@
|
|||
<?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.
|
||||
|
||||
|
@ -25,16 +25,24 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<!-- interface-name Manuskript -->
|
||||
<!-- interface-description Manuskript is an open-source tool for writers. -->
|
||||
<!-- interface-copyright 2015-2021 Olivier Keshavjee et al. -->
|
||||
<object class="GtkListStore" id="character_store">
|
||||
<object class="GtkListStore" id="characters_store">
|
||||
<columns>
|
||||
<!-- column-name ID -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name color -->
|
||||
<column type="GdkPixbuf"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTextBuffer" id="few_sentences_summary"/>
|
||||
<object class="GtkEntryBuffer" id="filter_outline"/>
|
||||
<object class="GtkEntryBuffer" id="goal"/>
|
||||
<object class="GtkEntryBuffer" id="one_line_summary"/>
|
||||
<object class="GtkTreeStore" id="outline_store">
|
||||
<columns>
|
||||
<!-- column-name ID -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name title -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name label -->
|
||||
|
@ -47,25 +55,31 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<column type="gulong"/>
|
||||
<!-- column-name goal -->
|
||||
<column type="gulong"/>
|
||||
<!-- column-name progress -->
|
||||
<column type="gint"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTreeStore" id="plot_main_store">
|
||||
<object class="GtkTreeModelFilter" id="filtered_outline_store">
|
||||
<property name="child-model">outline_store</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="plots_store">
|
||||
<columns>
|
||||
<!-- column-name ID -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name importance -->
|
||||
<column type="gint"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTreeStore" id="plot_minor_store">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<object class="GtkTreeModelFilter" id="main_plots_store">
|
||||
<property name="child-model">plots_store</property>
|
||||
</object>
|
||||
<object class="GtkTreeStore" id="plot_secondary_store">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<object class="GtkTreeModelFilter" id="minor_plots_store">
|
||||
<property name="child-model">plots_store</property>
|
||||
</object>
|
||||
<object class="GtkTreeModelFilter" id="secondary_plots_store">
|
||||
<property name="child-model">plots_store</property>
|
||||
</object>
|
||||
<object class="GtkScrolledWindow" id="outline_view">
|
||||
<property name="visible">True</property>
|
||||
|
@ -102,10 +116,21 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="model">plot_main_store</property>
|
||||
<property name="model">main_plots_store</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="search-column">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
<object class="GtkTreeSelection" id="main_plot_selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -130,10 +155,21 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="model">plot_secondary_store</property>
|
||||
<property name="model">secondary_plots_store</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="search-column">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
<object class="GtkTreeSelection" id="secondary_plot_selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -158,10 +194,21 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="model">plot_minor_store</property>
|
||||
<property name="model">minor_plots_store</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="search-column">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
<object class="GtkTreeSelection" id="minor_plot_selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -206,11 +253,11 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="model">outline_store</property>
|
||||
<property name="model">filtered_outline_store</property>
|
||||
<property name="search-column">0</property>
|
||||
<property name="enable-grid-lines">both</property>
|
||||
<property name="enable-tree-lines">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
<object class="GtkTreeSelection" id="outline_selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
|
@ -218,7 +265,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -229,7 +276,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<child>
|
||||
<object class="GtkCellRendererCombo"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -240,7 +287,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<child>
|
||||
<object class="GtkCellRendererCombo"/>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -251,7 +298,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<child>
|
||||
<object class="GtkCellRendererToggle"/>
|
||||
<attributes>
|
||||
<attribute name="active">3</attribute>
|
||||
<attribute name="active">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -260,9 +307,9 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Word count</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<object class="GtkCellRendererSpin"/>
|
||||
<attributes>
|
||||
<attribute name="text">4</attribute>
|
||||
<attribute name="text">5</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -271,9 +318,9 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Goal</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<object class="GtkCellRendererSpin"/>
|
||||
<attributes>
|
||||
<attribute name="text">5</attribute>
|
||||
<attribute name="text">6</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -284,7 +331,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<child>
|
||||
<object class="GtkCellRendererProgress"/>
|
||||
<attributes>
|
||||
<attribute name="value">4</attribute>
|
||||
<attribute name="value">7</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -311,7 +358,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<property name="can-focus">False</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkButton" id="add_folder">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
@ -330,7 +377,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkButton" id="add_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
@ -349,7 +396,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkButton" id="remove">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
@ -371,6 +418,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="buffer">filter_outline</property>
|
||||
<property name="placeholder-text" translatable="yes">Filter</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -407,6 +455,8 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="buffer">goal</property>
|
||||
<property name="placeholder-text" translatable="yes">0</property>
|
||||
<property name="input-purpose">digits</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -433,17 +483,17 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="model">character_store</property>
|
||||
<property name="model">characters_store</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf"/>
|
||||
<attributes>
|
||||
<attribute name="pixbuf">1</attribute>
|
||||
<attribute name="pixbuf">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -478,6 +528,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="buffer">one_line_summary</property>
|
||||
<property name="placeholder-text" translatable="yes">One line summary</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -512,6 +563,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="buffer">few_sentences_summary</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
|
|
Loading…
Reference in a new issue