mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-15 10:22:26 +12:00
Implement recent projects menu
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
parent
988fa62d61
commit
9287e85b7e
|
@ -14,5 +14,6 @@ from manuskript.ui import MainWindow
|
||||||
|
|
||||||
path = os.path.join(os.getcwd(), "sample-projects/book-of-acts")
|
path = os.path.join(os.getcwd(), "sample-projects/book-of-acts")
|
||||||
|
|
||||||
window = MainWindow(path + ".msk")
|
window = MainWindow()
|
||||||
|
window.openProject(path + ".msk")
|
||||||
window.run()
|
window.run()
|
||||||
|
|
|
@ -17,36 +17,14 @@ from manuskript.ui.tools import *
|
||||||
from manuskript.ui.aboutDialog import AboutDialog
|
from manuskript.ui.aboutDialog import AboutDialog
|
||||||
from manuskript.ui.settingsWindow import SettingsWindow
|
from manuskript.ui.settingsWindow import SettingsWindow
|
||||||
from manuskript.ui.startupWindow import StartupWindow
|
from manuskript.ui.startupWindow import StartupWindow
|
||||||
from manuskript.ui.util import bindMenuItem
|
from manuskript.ui.util import bindMenuItem, packViewIntoSlot, unpackFromSlot
|
||||||
from manuskript.util import profileTime
|
from manuskript.util import parseFilenameFromURL
|
||||||
|
|
||||||
|
|
||||||
class MainWindow:
|
class MainWindow:
|
||||||
|
|
||||||
@classmethod
|
def __init__(self):
|
||||||
def packViewIntoSlot(cls, builder, id, view_cls, data=None):
|
self.project = 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()
|
|
||||||
|
|
||||||
builder = Gtk.Builder()
|
builder = Gtk.Builder()
|
||||||
builder.add_from_file("ui/main.glade")
|
builder.add_from_file("ui/main.glade")
|
||||||
|
@ -58,20 +36,25 @@ class MainWindow:
|
||||||
self.leaflet = builder.get_object("leaflet")
|
self.leaflet = builder.get_object("leaflet")
|
||||||
self.viewSwitcherBar = builder.get_object("view_switcher_bar")
|
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.viewSwitcherBar, "reveal", GObject.BindingFlags.SYNC_CREATE)
|
||||||
self.leaflet.bind_property("folded", self.headerBar, "show-close-button", GObject.BindingFlags.SYNC_CREATE |
|
self.leaflet.bind_property("folded", self.headerBar, "show-close-button", GObject.BindingFlags.SYNC_CREATE |
|
||||||
GObject.BindingFlags.INVERT_BOOLEAN)
|
GObject.BindingFlags.INVERT_BOOLEAN)
|
||||||
|
|
||||||
self.generalView = MainWindow.packViewIntoSlot(builder, "general_slot", GeneralView, self.project.info)
|
self.generalSlot = builder.get_object("general_slot")
|
||||||
self.summaryView = MainWindow.packViewIntoSlot(builder, "summary_slot", SummaryView, self.project.summary)
|
self.summarySlot = builder.get_object("summary_slot")
|
||||||
self.charactersView = MainWindow.packViewIntoSlot(builder, "characters_slot", CharactersView,
|
self.charactersSlot = builder.get_object("characters_slot")
|
||||||
self.project.characters)
|
self.plotSlot = builder.get_object("plot_slot")
|
||||||
self.plotView = MainWindow.packViewIntoSlot(builder, "plot_slot", PlotView, self.project.plots)
|
self.worldSlot = builder.get_object("world_slot")
|
||||||
self.worldView = MainWindow.packViewIntoSlot(builder, "world_slot", WorldView, self.project.world)
|
self.outlineSlot = builder.get_object("outline_slot")
|
||||||
self.outlineView = MainWindow.packViewIntoSlot(builder, "outline_slot", OutlineView, self.project.outline)
|
self.editorSlot = builder.get_object("editor_slot")
|
||||||
self.editorView = MainWindow.packViewIntoSlot(builder, "editor_slot", EditorView, self.project)
|
|
||||||
|
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.startupWindow = StartupWindow(self)
|
||||||
self.aboutDialog = AboutDialog(self)
|
self.aboutDialog = AboutDialog(self)
|
||||||
|
@ -85,6 +68,9 @@ class MainWindow:
|
||||||
self.settingsWindow
|
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, "open_menu_item", self._openAction)
|
||||||
bindMenuItem(builder, "save_menu_item", self._saveAction)
|
bindMenuItem(builder, "save_menu_item", self._saveAction)
|
||||||
bindMenuItem(builder, "close_menu_item", self._closeAction)
|
bindMenuItem(builder, "close_menu_item", self._closeAction)
|
||||||
|
@ -94,18 +80,66 @@ class MainWindow:
|
||||||
bindMenuItem(builder, "frequency_menu_item", self._frequencyAction)
|
bindMenuItem(builder, "frequency_menu_item", self._frequencyAction)
|
||||||
bindMenuItem(builder, "about_menu_item", self._aboutAction)
|
bindMenuItem(builder, "about_menu_item", self._aboutAction)
|
||||||
|
|
||||||
|
self.hide()
|
||||||
|
|
||||||
def getProject(self):
|
def getProject(self):
|
||||||
return self.project
|
return self.project
|
||||||
|
|
||||||
def openProject(self):
|
def openProject(self, path=None, dialog=False):
|
||||||
pass
|
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):
|
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.hide()
|
||||||
self.startupWindow.show()
|
self.startupWindow.show()
|
||||||
|
|
||||||
def _openAction(self, menuItem: Gtk.MenuItem):
|
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):
|
def _saveAction(self, menuItem: Gtk.MenuItem):
|
||||||
self.getProject().save()
|
self.getProject().save()
|
||||||
|
|
|
@ -6,8 +6,8 @@ import gi
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import GObject, Gtk, Handy
|
from gi.repository import GObject, Gtk, Handy
|
||||||
|
|
||||||
from manuskript.data import Template, TemplateLevel, TemplateKind
|
from manuskript.data import Template, TemplateKind
|
||||||
from manuskript.util import validInt, validString
|
from manuskript.util import validInt, validString, parseFilenameFromURL
|
||||||
|
|
||||||
from manuskript.ui.abstractDialog import AbstractDialog
|
from manuskript.ui.abstractDialog import AbstractDialog
|
||||||
from manuskript.ui.startup import TemplateEntry
|
from manuskript.ui.startup import TemplateEntry
|
||||||
|
@ -25,6 +25,8 @@ class StartupWindow(AbstractDialog):
|
||||||
self.headerBar = None
|
self.headerBar = None
|
||||||
self.templatesLeaflet = None
|
self.templatesLeaflet = None
|
||||||
|
|
||||||
|
self.recentChooserMenu = None
|
||||||
|
|
||||||
self.templatesStore = None
|
self.templatesStore = None
|
||||||
self.fictionTemplatesStore = None
|
self.fictionTemplatesStore = None
|
||||||
self.nonfictionTemplatesStore = None
|
self.nonfictionTemplatesStore = None
|
||||||
|
@ -45,6 +47,9 @@ class StartupWindow(AbstractDialog):
|
||||||
GObject.BindingFlags.SYNC_CREATE |
|
GObject.BindingFlags.SYNC_CREATE |
|
||||||
GObject.BindingFlags.INVERT_BOOLEAN)
|
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, "open_menu_item", self._openAction)
|
||||||
bindMenuItem(builder, "quit_menu_item", self._quitAction)
|
bindMenuItem(builder, "quit_menu_item", self._quitAction)
|
||||||
|
|
||||||
|
@ -154,6 +159,17 @@ class StartupWindow(AbstractDialog):
|
||||||
def _openAction(self, menuItem: Gtk.MenuItem):
|
def _openAction(self, menuItem: Gtk.MenuItem):
|
||||||
self.mainWindow.openProject()
|
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):
|
def _quitAction(self, menuItem: Gtk.MenuItem):
|
||||||
self.mainWindow.exit(True)
|
self.mainWindow.exit(True)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ gi.require_version('GdkPixbuf', '2.0')
|
||||||
from gi.repository import GdkPixbuf, Gdk
|
from gi.repository import GdkPixbuf, Gdk
|
||||||
|
|
||||||
from manuskript.data import Color, OutlineItem, OutlineText, OutlineFolder
|
from manuskript.data import Color, OutlineItem, OutlineText, OutlineFolder
|
||||||
|
from manuskript.util import profileTime
|
||||||
|
|
||||||
|
|
||||||
def rgbaFromColor(color: Color) -> Gdk.RGBA:
|
def rgbaFromColor(color: Color) -> Gdk.RGBA:
|
||||||
|
@ -34,6 +35,36 @@ def bindMenuItem(builder, id, action):
|
||||||
menuItem.connect("activate", 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:
|
def iconByOutlineItemType(outlineItem: OutlineItem) -> str:
|
||||||
if type(outlineItem) is OutlineFolder:
|
if type(outlineItem) is OutlineFolder:
|
||||||
return "folder-symbolic"
|
return "folder-symbolic"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from manuskript.util.counter import CounterKind, CharCounter, WordCounter, PageCounter
|
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)
|
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):
|
def countText(text: str, kind: CounterKind = CounterKind.WORDS):
|
||||||
if text is None:
|
if text is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -923,20 +923,6 @@ summary</property>
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</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>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
|
Loading…
Reference in a new issue