Implement grid view with navigation

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
TheJackiMonster 2022-11-20 00:13:41 +01:00
parent cc001aba9f
commit 7fd205cd7f
No known key found for this signature in database
GPG key ID: D850A5F772E880F9
8 changed files with 240 additions and 46 deletions

View file

@ -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()

View file

@ -0,0 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from manuskript.ui.editor.gridItem import GridItem

View 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()

View file

@ -66,4 +66,3 @@ class TemplateEntry:
def show(self):
self.widget.show_all()

View file

@ -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"

View file

@ -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()

View file

@ -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
View 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>