mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-16 10:52:29 +12:00
Implement grid view with navigation
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
parent
cc001aba9f
commit
7fd205cd7f
|
@ -40,6 +40,16 @@ class OutlineItem:
|
|||
self.compile = True
|
||||
self.goal = None
|
||||
|
||||
def parentItem(self):
|
||||
for item in self.outline.all():
|
||||
if item.contains(self):
|
||||
return item
|
||||
|
||||
return None
|
||||
|
||||
def contains(self, item):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def loadMetadata(cls, item, metadata: dict):
|
||||
ID = metadata.get("ID")
|
||||
|
@ -144,6 +154,9 @@ class OutlineFolder(OutlineItem):
|
|||
def __iter__(self):
|
||||
return self.items.__iter__()
|
||||
|
||||
def contains(self, item):
|
||||
return item in self.items
|
||||
|
||||
@classmethod
|
||||
def loadItems(cls, outline, folder, recursive: bool = True):
|
||||
folder.items.clear()
|
||||
|
|
4
manuskript/ui/editor/__init__.py
Normal file
4
manuskript/ui/editor/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from manuskript.ui.editor.gridItem import GridItem
|
38
manuskript/ui/editor/gridItem.py
Normal file
38
manuskript/ui/editor/gridItem.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gdk, Gtk
|
||||
|
||||
from manuskript.data import OutlineItem
|
||||
from manuskript.ui.util import iconByOutlineItemType
|
||||
from manuskript.util import validString
|
||||
|
||||
|
||||
class GridItem:
|
||||
|
||||
def __init__(self, outlineItem: OutlineItem):
|
||||
self.outlineItem = outlineItem
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_file("ui/editor/grid-item.glade")
|
||||
|
||||
self.widget = builder.get_object("grid_item")
|
||||
|
||||
self.iconImage = builder.get_object("icon")
|
||||
self.titleLabel = builder.get_object("title")
|
||||
self.summaryLabel = builder.get_object("summary")
|
||||
|
||||
self.reloadOutlineItem()
|
||||
|
||||
def reloadOutlineItem(self):
|
||||
icon = iconByOutlineItemType(self.outlineItem)
|
||||
|
||||
self.iconImage.set_from_icon_name(icon, Gtk.IconSize.MENU)
|
||||
self.titleLabel.set_text(validString(self.outlineItem.title))
|
||||
self.summaryLabel.set_text(validString(self.outlineItem.summaryFull))
|
||||
|
||||
def show(self):
|
||||
self.widget.show_all()
|
|
@ -66,4 +66,3 @@ class TemplateEntry:
|
|||
|
||||
def show(self):
|
||||
self.widget.show_all()
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ gi.require_version('Gdk', '3.0')
|
|||
gi.require_version('GdkPixbuf', '2.0')
|
||||
from gi.repository import GdkPixbuf, Gdk
|
||||
|
||||
from manuskript.data import Color
|
||||
from manuskript.data import Color, OutlineItem, OutlineText, OutlineFolder
|
||||
|
||||
|
||||
def rgbaFromColor(color: Color) -> Gdk.RGBA:
|
||||
|
@ -32,3 +32,12 @@ def bindMenuItem(builder, id, action):
|
|||
return
|
||||
|
||||
menuItem.connect("activate", action)
|
||||
|
||||
|
||||
def iconByOutlineItemType(outlineItem: OutlineItem) -> str:
|
||||
if type(outlineItem) is OutlineFolder:
|
||||
return "folder-symbolic"
|
||||
elif type(outlineItem) is OutlineText:
|
||||
return "emblem-documents-symbolic"
|
||||
else:
|
||||
return "folder-documents-symbolic"
|
||||
|
|
|
@ -6,9 +6,10 @@ import gi
|
|||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Pango
|
||||
|
||||
from manuskript.data import Project, 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
|
||||
from manuskript.data import Project, OutlineFolder, OutlineText, OutlineItem, OutlineState
|
||||
from manuskript.ui.editor import GridItem
|
||||
from manuskript.ui.util import pixbufFromColor, iconByOutlineItemType
|
||||
from manuskript.util import validString, validInt
|
||||
|
||||
import inspect
|
||||
|
||||
|
@ -17,6 +18,7 @@ class EditorView:
|
|||
|
||||
def __init__(self, project: Project):
|
||||
self.project = project
|
||||
self.outlineItem = None
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_file("ui/editor.glade")
|
||||
|
@ -32,10 +34,22 @@ class EditorView:
|
|||
self.outlineStore = builder.get_object("outline_store")
|
||||
self.refreshOutlineStore()
|
||||
|
||||
self.editorTextBuffer = builder.get_object("editor_text")
|
||||
self.editorItems = list()
|
||||
|
||||
self.editorTextBuffer = builder.get_object("editor_text")
|
||||
self.editorFlowbox = builder.get_object("editor_flowbox")
|
||||
self.loadEditorData(None)
|
||||
|
||||
self.editorFlowbox.connect("child-activated", self.editorFlowboxChildActivated)
|
||||
|
||||
self.upButtons = [
|
||||
builder.get_object("up"),
|
||||
builder.get_object("up_")
|
||||
]
|
||||
|
||||
for button in self.upButtons:
|
||||
button.connect("clicked", self.upButtonClicked)
|
||||
|
||||
self.unloadOutlineData()
|
||||
|
||||
def refreshLabelStore(self):
|
||||
self.labelStore.clear()
|
||||
|
@ -60,15 +74,6 @@ class EditorView:
|
|||
|
||||
self.statusStore.set_value(tree_iter, 0, validString(status.name))
|
||||
|
||||
@classmethod
|
||||
def __getIconByOutlineType(cls, outlineItem: OutlineItem):
|
||||
if type(outlineItem) is OutlineFolder:
|
||||
return "folder-symbolic"
|
||||
elif type(outlineItem) is OutlineText:
|
||||
return "emblem-documents-symbolic"
|
||||
else:
|
||||
return "folder-documents-symbolic"
|
||||
|
||||
def __appendOutlineItem(self, outlineItem: OutlineItem, parent_iter=None):
|
||||
tree_iter = self.outlineStore.append(parent_iter)
|
||||
|
||||
|
@ -78,7 +83,7 @@ class EditorView:
|
|||
if outlineItem.state != OutlineState.COMPLETE:
|
||||
outlineItem.load(False)
|
||||
|
||||
icon = EditorView.__getIconByOutlineType(outlineItem)
|
||||
icon = iconByOutlineItemType(outlineItem)
|
||||
|
||||
if type(outlineItem) is OutlineFolder:
|
||||
for item in outlineItem:
|
||||
|
@ -109,6 +114,18 @@ class EditorView:
|
|||
for item in self.project.outline.items:
|
||||
self.__appendOutlineItem(item)
|
||||
|
||||
def loadOutlineData(self, outlineItem: OutlineItem):
|
||||
self.outlineItem = None
|
||||
|
||||
self.loadEditorData(outlineItem)
|
||||
|
||||
self.outlineItem = outlineItem
|
||||
|
||||
def unloadOutlineData(self):
|
||||
self.outlineItem = None
|
||||
|
||||
self.loadEditorData(None)
|
||||
|
||||
def __appendOutlineItemText(self, outlineItem: OutlineItem):
|
||||
end_iter = self.editorTextBuffer.get_end_iter()
|
||||
|
||||
|
@ -136,38 +153,47 @@ class EditorView:
|
|||
return False
|
||||
|
||||
def loadEditorData(self, outlineItem: OutlineItem | None):
|
||||
self.editorTextBuffer.set_text("")
|
||||
self.editorItems = list()
|
||||
self.outlineItem = None
|
||||
|
||||
for item in self.project.outline.items:
|
||||
start_iter, end_iter = self.editorTextBuffer.get_bounds()
|
||||
self.editorTextBuffer.delete(start_iter, end_iter)
|
||||
|
||||
if outlineItem is None:
|
||||
self.editorItems = self.project.outline.items
|
||||
elif type(outlineItem) is OutlineFolder:
|
||||
self.editorItems = outlineItem.items
|
||||
elif type(outlineItem) is OutlineText:
|
||||
self.__appendOutlineItemText(outlineItem)
|
||||
|
||||
self.editorFlowbox.foreach(self.editorFlowbox.remove)
|
||||
if len(self.editorItems) <= 0:
|
||||
self.outlineItem = outlineItem
|
||||
return
|
||||
|
||||
for item in self.editorItems:
|
||||
self.__appendOutlineItemText(item)
|
||||
|
||||
for item in self.project.outline.items:
|
||||
child = Gtk.FlowBoxChild()
|
||||
for item in self.editorItems:
|
||||
self.editorFlowbox.insert(GridItem(item).widget, -1)
|
||||
|
||||
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
self.outlineItem = outlineItem
|
||||
|
||||
icon = EditorView.__getIconByOutlineType(item)
|
||||
def editorFlowboxChildActivated(self, box: Gtk.FlowBox, child: Gtk.FlowBoxChild):
|
||||
if child is None:
|
||||
return
|
||||
|
||||
iconImage = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.MENU)
|
||||
titleLabel = Gtk.Label(item.title)
|
||||
summaryLabel = Gtk.Label(item.summaryFull)
|
||||
index = child.get_index()
|
||||
if (index < 0) or (index >= len(self.editorItems)):
|
||||
return
|
||||
|
||||
titleLabel.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
summaryLabel.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
summaryLabel.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
|
||||
summaryLabel.set_line_wrap(True)
|
||||
summaryLabel.set_max_width_chars(20)
|
||||
self.loadEditorData(self.editorItems[index])
|
||||
|
||||
hbox.pack_start(iconImage, False, True, 4)
|
||||
hbox.pack_start(titleLabel, False, True, 4)
|
||||
def upButtonClicked(self, button: Gtk.Button):
|
||||
if self.outlineItem is None:
|
||||
return
|
||||
|
||||
vbox.pack_start(hbox, False, True, 4)
|
||||
vbox.pack_start(summaryLabel, False, True, 4)
|
||||
|
||||
child.add(vbox)
|
||||
|
||||
self.editorFlowbox.add(child)
|
||||
self.loadOutlineData(self.outlineItem.parentItem())
|
||||
|
||||
def show(self):
|
||||
self.widget.show_all()
|
||||
|
|
|
@ -374,6 +374,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<property name="can-focus">True</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="buffer">editor_text</property>
|
||||
<property name="input-hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_NONE</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -569,7 +570,7 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<property name="margin-bottom">2</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkButton" id="up">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
@ -678,15 +679,13 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">2</property>
|
||||
<property name="margin-right">2</property>
|
||||
<property name="margin-start">2</property>
|
||||
<property name="margin-end">2</property>
|
||||
<property name="margin-top">2</property>
|
||||
<property name="margin-bottom">2</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkButton" id="up_">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
|
@ -728,8 +727,6 @@ along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
|||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">8</property>
|
||||
<property name="margin-right">8</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="label" translatable="yes">0 words</property>
|
||||
|
|
108
ui/editor/grid-item.glade
Normal file
108
ui/editor/grid-item.glade
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0
|
||||
|
||||
Copyright (C) 2015-2021 Olivier Keshavjee et al.
|
||||
|
||||
This file is part of Manuskript.
|
||||
|
||||
Manuskript is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Manuskript is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Manuskript. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<!-- interface-license-type gplv3 -->
|
||||
<!-- interface-name Manuskript -->
|
||||
<!-- interface-description Manuskript is an open-source tool for writers. -->
|
||||
<!-- interface-copyright 2015-2021 Olivier Keshavjee et al. -->
|
||||
<object class="GtkFrame" id="grid_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">2</property>
|
||||
<property name="label-xalign">0</property>
|
||||
<property name="label-yalign">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="icon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">info-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="single-line-mode">True</property>
|
||||
<property name="max-width-chars">15</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="summary">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="max-width-chars">15</property>
|
||||
<property name="lines">3</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
Loading…
Reference in a new issue