Implement recent projects menu

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
TheJackiMonster 2023-03-21 20:51:05 +01:00
parent 988fa62d61
commit 9287e85b7e
No known key found for this signature in database
GPG key ID: D850A5F772E880F9
6 changed files with 137 additions and 56 deletions

View file

@ -14,5 +14,6 @@ from manuskript.ui import MainWindow
path = os.path.join(os.getcwd(), "sample-projects/book-of-acts")
window = MainWindow(path + ".msk")
window = MainWindow()
window.openProject(path + ".msk")
window.run()

View file

@ -17,36 +17,14 @@ from manuskript.ui.tools import *
from manuskript.ui.aboutDialog import AboutDialog
from manuskript.ui.settingsWindow import SettingsWindow
from manuskript.ui.startupWindow import StartupWindow
from manuskript.ui.util import bindMenuItem
from manuskript.util import profileTime
from manuskript.ui.util import bindMenuItem, packViewIntoSlot, unpackFromSlot
from manuskript.util import parseFilenameFromURL
class MainWindow:
@classmethod
def packViewIntoSlot(cls, builder, id, view_cls, data=None):
slot = builder.get_object(id)
if slot is None:
return None
try:
if data is None:
view = profileTime(view_cls)
else:
view = profileTime(view_cls, data)
except Exception:
return None
if view.widget is None:
return None
slot.pack_start(view.widget, True, True, 0)
return view
def __init__(self, path):
self.project = Project(path)
self.project.load()
def __init__(self):
self.project = None
builder = Gtk.Builder()
builder.add_from_file("ui/main.glade")
@ -58,20 +36,25 @@ class MainWindow:
self.leaflet = builder.get_object("leaflet")
self.viewSwitcherBar = builder.get_object("view_switcher_bar")
self.headerBar.set_subtitle(self.project.info.title)
self.leaflet.bind_property("folded", self.viewSwitcherBar, "reveal", GObject.BindingFlags.SYNC_CREATE)
self.leaflet.bind_property("folded", self.headerBar, "show-close-button", GObject.BindingFlags.SYNC_CREATE |
GObject.BindingFlags.INVERT_BOOLEAN)
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.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)
self.editorView = MainWindow.packViewIntoSlot(builder, "editor_slot", EditorView, self.project)
self.generalSlot = builder.get_object("general_slot")
self.summarySlot = builder.get_object("summary_slot")
self.charactersSlot = builder.get_object("characters_slot")
self.plotSlot = builder.get_object("plot_slot")
self.worldSlot = builder.get_object("world_slot")
self.outlineSlot = builder.get_object("outline_slot")
self.editorSlot = builder.get_object("editor_slot")
self.generalView = None
self.summaryView = None
self.charactersView = None
self.plotView = None
self.worldView = None
self.outlineView = None
self.editorView = None
self.startupWindow = StartupWindow(self)
self.aboutDialog = AboutDialog(self)
@ -85,6 +68,9 @@ class MainWindow:
self.settingsWindow
]
self.recentChooserMenu = builder.get_object("recent_chooser_menu")
self.recentChooserMenu.connect("item-activated", self._recentAction)
bindMenuItem(builder, "open_menu_item", self._openAction)
bindMenuItem(builder, "save_menu_item", self._saveAction)
bindMenuItem(builder, "close_menu_item", self._closeAction)
@ -94,18 +80,66 @@ class MainWindow:
bindMenuItem(builder, "frequency_menu_item", self._frequencyAction)
bindMenuItem(builder, "about_menu_item", self._aboutAction)
self.hide()
def getProject(self):
return self.project
def openProject(self):
pass
def openProject(self, path=None, dialog=False):
if self.project is not None:
self.closeProject()
if dialog:
return
if path is None:
return
self.project = Project(path)
self.project.load()
self.headerBar.set_subtitle(self.project.info.title)
self.generalView = packViewIntoSlot(self.generalSlot, GeneralView, self.project.info)
self.summaryView = packViewIntoSlot(self.summarySlot, SummaryView, self.project.summary)
self.charactersView = packViewIntoSlot(self.charactersSlot, CharactersView, self.project.characters)
self.plotView = packViewIntoSlot(self.plotSlot, PlotView, self.project.plots)
self.worldView = packViewIntoSlot(self.worldSlot, WorldView, self.project.world)
self.outlineView = packViewIntoSlot(self.outlineSlot, OutlineView, self.project.outline)
self.editorView = packViewIntoSlot(self.editorSlot, EditorView, self.project)
self.startupWindow.hide()
self.show()
def closeProject(self):
if self.project is not None:
self.generalView = unpackFromSlot(self.generalSlot, self.generalView)
self.summaryView = unpackFromSlot(self.summarySlot, self.summaryView)
self.charactersView = unpackFromSlot(self.charactersSlot, self.charactersView)
self.plotView = unpackFromSlot(self.plotSlot, self.plotView)
self.worldView = unpackFromSlot(self.worldSlot, self.worldView)
self.outlineView = unpackFromSlot(self.outlineSlot, self.outlineView)
self.editorView = unpackFromSlot(self.editorSlot, self.editorView)
del self.project
self.project = None
self.hide()
self.startupWindow.show()
def _openAction(self, menuItem: Gtk.MenuItem):
self.openProject()
self.openProject(dialog=True)
def _recentAction(self, recentChooser: Gtk.RecentChooser):
uri = recentChooser.get_current_uri()
if uri is None:
return
path = parseFilenameFromURL(uri)
if path is None:
return
self.openProject(path)
def _saveAction(self, menuItem: Gtk.MenuItem):
self.getProject().save()

View file

@ -6,8 +6,8 @@ import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GObject, Gtk, Handy
from manuskript.data import Template, TemplateLevel, TemplateKind
from manuskript.util import validInt, validString
from manuskript.data import Template, TemplateKind
from manuskript.util import validInt, validString, parseFilenameFromURL
from manuskript.ui.abstractDialog import AbstractDialog
from manuskript.ui.startup import TemplateEntry
@ -25,6 +25,8 @@ class StartupWindow(AbstractDialog):
self.headerBar = None
self.templatesLeaflet = None
self.recentChooserMenu = None
self.templatesStore = None
self.fictionTemplatesStore = None
self.nonfictionTemplatesStore = None
@ -45,6 +47,9 @@ class StartupWindow(AbstractDialog):
GObject.BindingFlags.SYNC_CREATE |
GObject.BindingFlags.INVERT_BOOLEAN)
self.recentChooserMenu = builder.get_object("recent_chooser_menu")
self.recentChooserMenu.connect("item-activated", self._recentAction)
bindMenuItem(builder, "open_menu_item", self._openAction)
bindMenuItem(builder, "quit_menu_item", self._quitAction)
@ -154,6 +159,17 @@ class StartupWindow(AbstractDialog):
def _openAction(self, menuItem: Gtk.MenuItem):
self.mainWindow.openProject()
def _recentAction(self, recentChooser: Gtk.RecentChooser):
uri = recentChooser.get_current_uri()
if uri is None:
return
path = parseFilenameFromURL(uri)
if path is None:
return
self.mainWindow.openProject(path)
def _quitAction(self, menuItem: Gtk.MenuItem):
self.mainWindow.exit(True)

View file

@ -8,6 +8,7 @@ gi.require_version('GdkPixbuf', '2.0')
from gi.repository import GdkPixbuf, Gdk
from manuskript.data import Color, OutlineItem, OutlineText, OutlineFolder
from manuskript.util import profileTime
def rgbaFromColor(color: Color) -> Gdk.RGBA:
@ -34,6 +35,36 @@ def bindMenuItem(builder, id, action):
menuItem.connect("activate", action)
def packViewIntoSlot(slot, view_cls, data=None):
if slot is None:
return None
for child in slot.get_children():
slot.remove(child)
try:
if data is None:
view = profileTime(view_cls)
else:
view = profileTime(view_cls, data)
except Exception:
return None
if view.widget is None:
return None
slot.pack_start(view.widget, True, True, 0)
return view
def unpackFromSlot(slot, view):
if (slot is not None) and (view.widget is not None):
slot.remove(view.widget)
del view
return None
def iconByOutlineItemType(outlineItem: OutlineItem) -> str:
if type(outlineItem) is OutlineFolder:
return "folder-symbolic"

View file

@ -4,6 +4,7 @@
import re
import time
import traceback
import urllib.parse
from manuskript.util.counter import CounterKind, CharCounter, WordCounter, PageCounter
@ -51,6 +52,18 @@ def safeFilename(filename: str, extension: str = None) -> str:
return re.sub(r"[^a-zA-Z0-9._\-+()]", "_", name)
def parseFilenameFromURL(url: str) -> str | None:
result = urllib.parse.urlparse(url)
if result is None:
return None
if result.scheme != "file":
return None
return result.path
def countText(text: str, kind: CounterKind = CounterKind.WORDS):
if text is None:
return 0

View file

@ -923,20 +923,6 @@ summary</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Next</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>