[gedit-plugins/sessionsaver] Upload files
- From: Jordi Mas <jmas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit-plugins/sessionsaver] Upload files
- Date: Mon, 24 Jun 2019 17:55:05 +0000 (UTC)
commit 30e8e1e8505f70cac7ed60e8f3241082594640c5
Author: Jordi Mas <jmas softcatala org>
Date: Mon Jun 24 09:10:16 2019 +0200
Upload files
meson.build | 1 +
meson_options.txt | 1 +
plugins/sessionsaver/meson.build | 28 +++
.../sessionsaver/sessionsaver.plugin.desktop.in.in | 10 +
plugins/sessionsaver/sessionsaver/__init__.py | 169 ++++++++++++++++
plugins/sessionsaver/sessionsaver/dialogs.py | 167 ++++++++++++++++
plugins/sessionsaver/sessionsaver/gpdefs.py | 5 +
plugins/sessionsaver/sessionsaver/sessionsaver.ui | 213 +++++++++++++++++++++
plugins/sessionsaver/sessionsaver/store.py | 161 ++++++++++++++++
9 files changed, 755 insertions(+)
---
diff --git a/meson.build b/meson.build
index b1c295e..6f07951 100644
--- a/meson.build
+++ b/meson.build
@@ -91,6 +91,7 @@ all_plugins = {
'git': {'language': 'python'},
'joinlines': {'language': 'python'},
'multiedit': {'language': 'python'},
+ 'sessionsaver': {'language': 'python'},
'smartspaces': {'language': 'python'},
'terminal': {'language': 'python'},
'textsize': {'language': 'python'},
diff --git a/meson_options.txt b/meson_options.txt
index d2770b7..a7a578f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,6 +10,7 @@ option('plugin_findinfiles', type: 'boolean', value: false)
option('plugin_git', type: 'boolean')
option('plugin_joinlines', type: 'boolean')
option('plugin_multiedit', type: 'boolean')
+option('plugin_sessionsaver', type: 'boolean')
option('plugin_smartspaces', type: 'boolean')
option('plugin_terminal', type: 'boolean')
option('plugin_textsize', type: 'boolean')
diff --git a/plugins/sessionsaver/meson.build b/plugins/sessionsaver/meson.build
new file mode 100644
index 0000000..3f4ef18
--- /dev/null
+++ b/plugins/sessionsaver/meson.build
@@ -0,0 +1,28 @@
+install_subdir(
+ 'sessionsaver',
+ install_dir: join_paths(
+ pkglibdir,
+ 'plugins',
+ )
+)
+
+sessionsaver_plugin_in = configure_file(
+ input: 'sessionsaver.plugin.desktop.in.in',
+ output: 'sessionsaver.plugin.desktop.in',
+ configuration: plugin_in,
+ install: false,
+)
+
+sessionsaver_plugin = custom_target(
+ 'sessionsaver.plugin',
+ input: sessionsaver_plugin_in,
+ output: 'sessionsaver.plugin',
+ command: msgfmt_plugin_cmd,
+ install: true,
+ install_dir: join_paths(
+ pkglibdir,
+ 'plugins',
+ )
+)
+
+
diff --git a/plugins/sessionsaver/sessionsaver.plugin.desktop.in.in
b/plugins/sessionsaver/sessionsaver.plugin.desktop.in.in
new file mode 100644
index 0000000..aee31e3
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver.plugin.desktop.in.in
@@ -0,0 +1,10 @@
+[Plugin]
+Loader=python3
+Module=sessionsaver
+IAge=3
+Name=Session Saver
+Description=Save and restore your working sessions
+Authors=Steve Frécinaux
+Copyright=Copyright © 2006 Steve Frécinaux
+Website=http://www.gedit.org
+Version=@VERSION@
diff --git a/plugins/sessionsaver/sessionsaver/__init__.py b/plugins/sessionsaver/sessionsaver/__init__.py
new file mode 100644
index 0000000..b1f9ac5
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver/__init__.py
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+# __init__.py
+# This file is part of gedit Session Saver Plugin
+#
+# Copyright (C) 2006-2007 - Steve Frécinaux <code istique net>
+# Copyright (C) 2010 - Kenny Meyer <knny myer gmail com>
+#
+# gedit Session Saver Plugin 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 2 of the License, or
+# (at your option) any later version.
+#
+# gedit Session Saver Plugin 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 gedit Session Saver Plugin; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA
+
+from gi.repository import GObject, Gtk, Gedit
+import gettext
+from .store import XMLSessionStore
+from .dialogs import SaveSessionDialog, SessionManagerDialog
+from .gpdefs import *
+
+try:
+ gettext.bindtextdomain(GETTEXT_PACKAGE, GP_LOCALEDIR)
+ _ = lambda s: gettext.dgettext(GETTEXT_PACKAGE, s);
+except:
+ _ = lambda s: s
+
+ui_string = """
+<ui>
+ <menubar name="MenuBar">
+ <menu name="FileMenu" action="File">
+ <placeholder name="FileOps_2">
+ <separator/>
+ <menu name="FileSessionMenu" action="FileSession">
+ <placeholder name="SessionPluginPlaceHolder"/>
+ <separator/>
+ <menuitem name="FileSessionSaveMenu" action="FileSessionSave"/>
+ <menuitem name="FileSessionManageMenu" action="FileSessionManage"/>
+ </menu>
+ </placeholder>
+ </menu>
+ </menubar>
+</ui>
+"""
+
+class SessionSaverPlugin(GObject.Object, Gedit.WindowActivatable):
+ __gtype_name__ = "SessionSaverPlugin"
+
+ window = GObject.property(type=Gedit.Window)
+
+ SESSION_MENU_PATH = '/MenuBar/FileMenu/FileOps_2/FileSessionMenu/SessionPluginPlaceHolder'
+
+ def __init__(self):
+ GObject.Object.__init__(self)
+ self.sessions = XMLSessionStore()
+
+ def do_activate(self):
+ self._insert_menu()
+
+ def do_deactivate(self):
+ self._remove_menu()
+
+ def do_update_state(self):
+ self._action_group.get_action("FileSessionSave").set_sensitive(self.window.get_active_document() !=
None)
+
+ def _insert_menu(self):
+ ui_manager = self.window.get_ui_manager()
+
+ self._action_group = Gtk.ActionGroup("SessionSaverPluginActions")
+ self._action_group.add_actions(
+ [("FileSession", None, _("Sa_ved sessions"), None, None),
+ ("FileSessionSave", Gtk.STOCK_SAVE_AS,
+ _("_Save current session"), None,
+ _("Save the current document list as a new session"),
+ self.on_save_session_action),
+ ("FileSessionManage", None,
+ _("_Manage saved sessions..."), None,
+ _("Open the saved session manager"),
+ self.on_manage_sessions_action)
+ ])
+ ui_manager.insert_action_group(self._action_group)
+
+ self._ui_id = ui_manager.add_ui_from_string(ui_string)
+
+ self._insert_session_menu()
+
+ ui_manager.ensure_update()
+
+ def _remove_menu(self):
+ ui_manager = self.window.get_ui_manager()
+
+ self._remove_session_menu()
+
+ ui_manager.remove_ui(self._ui_id)
+ ui_manager.remove_action_group(self._action_group)
+
+ ui_manager.ensure_update()
+
+ def _insert_session_menu(self):
+ ui_manager = self.window.get_ui_manager()
+
+ self._merge_id = ui_manager.new_merge_id()
+
+ self._session_action_group = Gtk.ActionGroup(name="SessionSaverPluginSessionActions")
+ ui_manager.insert_action_group(self._session_action_group)
+
+ for i, session in enumerate(self.sessions):
+ action_name = 'SessionSaver%X' % i
+ action = Gtk.Action(action_name,
+ session.name,
+ _("Recover '%s' session") % session.name,
+ None)
+ handler = action.connect("activate", self.session_menu_action, session)
+
+ self._session_action_group.add_action(action)
+
+ ui_manager.add_ui(self._merge_id,
+ self.SESSION_MENU_PATH,
+ action_name,
+ action_name,
+ Gtk.UIManagerItemType.MENUITEM,
+ False)
+
+ def _remove_session_menu(self):
+ ui_manager = self.window.get_ui_manager()
+
+ for action in self._session_action_group.list_actions():
+ action.disconnect_by_func(self.session_menu_action)
+
+ ui_manager.remove_ui(self._merge_id)
+ ui_manager.remove_action_group(self._session_action_group)
+
+ ui_manager.ensure_update()
+
+ def _update_session_menu(self):
+ self._remove_session_menu()
+ self._insert_session_menu()
+
+ def _load_session(self, session):
+ # Note: a session has to stand on its own window.
+ tab = self.window.get_active_tab()
+ if tab is not None and \
+ not (tab.get_document().is_untouched() and \
+ tab.get_state() == Gedit.TabState.STATE_NORMAL):
+ # Create a new gedit window
+ window = Gedit.App.get_default().create_window(None)
+ window.show()
+ else:
+ window = self.window
+
+ Gedit.commands_load_locations(window, session.files, None, 0, 0)
+
+ def on_save_session_action(self, action):
+ SaveSessionDialog(self.window, self, self.sessions).run()
+
+ def on_manage_sessions_action(self, action):
+ SessionManagerDialog(self, self.sessions).run()
+
+ def session_menu_action(self, action, session):
+ self._load_session(session)
+
+# ex:ts=4:et:
diff --git a/plugins/sessionsaver/sessionsaver/dialogs.py b/plugins/sessionsaver/sessionsaver/dialogs.py
new file mode 100644
index 0000000..b45dade
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver/dialogs.py
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2007 - Steve Frécinaux <code istique net>
+# Copyright (c) 2010 - Kenny Meyer <knny myer gmail com>
+# Licence: GPL2 or later
+
+from gi.repository import GObject, Gtk, Gedit
+import os.path
+import gettext
+
+from .store import Session
+
+try:
+ from .gpdefs import *
+ gettext.bindtextdomain(GETTEXT_PACKAGE, GP_LOCALEDIR)
+ _ = lambda s: gettext.dgettext(GETTEXT_PACKAGE, s);
+except:
+ _ = lambda s: s
+
+class SessionModel(Gtk.ListStore):
+ OBJECT_COLUMN = 0
+ NAME_COLUMN = 1
+ N_COLUMNS = 2
+
+ def __init__(self, store):
+ super(SessionModel, self).__init__(GObject.TYPE_PYOBJECT, str)
+ self.store = store
+ for session in store:
+ row = { self.OBJECT_COLUMN : session,
+ self.NAME_COLUMN: session.name }
+ self.append(row.values())
+ self.store.connect_after('session-added', self.on_session_added)
+ self.store.connect('session-removed', self.on_session_removed)
+
+ def on_session_added(self, store, session):
+ row = { self.OBJECT_COLUMN : session,
+ self.NAME_COLUMN: session.name }
+ self.append(row.values())
+
+ def on_session_removed(self, store, session):
+ it = self.get_iter_first()
+ if it is not None:
+ while True:
+ stored_session = self.get_value(it, self.OBJECT_COLUMN)
+ if stored_session == session:
+ self.remove(it)
+ break
+ it = self.iter_next(it)
+ if not it:
+ break
+
+class Dialog(object):
+ UI_FILE = "sessionsaver.ui"
+
+ def __new__(cls):
+ if not ('_instance' in cls.__dict__) or cls._instance is None:
+ cls._instance = object.__new__(cls)
+ return cls._instance
+
+ def __init__(self, main_widget, datadir, parent_window = None):
+ super(Dialog, self).__init__()
+
+ if parent_window is None:
+ parent_window = Gedit.App.get_default().get_active_window()
+ self.parent = parent_window
+
+ self.ui = Gtk.Builder()
+ self.ui.set_translation_domain(GETTEXT_PACKAGE)
+ self.ui.add_from_file(os.path.join(datadir, self.UI_FILE))
+ self.dialog = self.ui.get_object(main_widget)
+ self.dialog.connect('delete-event', self.on_delete_event)
+
+ def __getitem__(self, item):
+ return self.ui.get_object(item)
+
+ def on_delete_event(self, dialog, event):
+ dialog.hide()
+ return True
+
+ def __del__(self):
+ self.__class__._instance = None
+
+ def run(self):
+ self.dialog.set_transient_for(self.parent)
+ self.dialog.show()
+
+ def destroy(self):
+ self.dialog.destroy()
+ self.__del__()
+
+class SaveSessionDialog(Dialog):
+ def __init__(self, window, plugin, sessions):
+ super(SaveSessionDialog, self).__init__('save-session-dialog',
+ plugin.plugin_info.get_data_dir(),
+ window)
+ self.plugin = plugin
+ self.sessions = sessions
+ self.sessionsaver = plugin
+
+ model = SessionModel(sessions)
+
+ combobox = self['session-name']
+ combobox.set_model(model)
+ combobox.set_entry_text_column(1)
+
+ self.dialog.connect('response', self.on_response)
+
+ def on_response(self, dialog, response_id):
+ if response_id == Gtk.ResponseType.OK:
+ files = [doc.get_location()
+ for doc in self.parent.get_documents()
+ if doc.get_location() is not None]
+ name = self['session-name'].get_child().get_text()
+ self.sessions.add(Session(name, files))
+ self.sessions.save()
+ self.sessionsaver.sessions = self.sessions
+ self.sessionsaver._update_session_menu()
+ self.destroy()
+
+class SessionManagerDialog(Dialog):
+ def __init__(self, plugin, sessions):
+ super(SessionManagerDialog, self).__init__('session-manager-dialog',
+ plugin.plugin_info.get_data_dir())
+ self.plugin = plugin
+ self.sessions = sessions
+
+ model = SessionModel(sessions)
+
+ self.view = self['session-view']
+ self.view.set_model(model)
+
+ renderer = Gtk.CellRendererText()
+ column = Gtk.TreeViewColumn(_("Session Name"), renderer, text = model.NAME_COLUMN)
+ self.view.append_column(column)
+
+ handlers = {
+ 'on_close_button_clicked': self.on_close_button_clicked,
+ 'on_open_button_clicked': self.on_open_button_clicked,
+ 'on_delete_button_clicked': self.on_delete_button_clicked
+ }
+ self.ui.connect_signals(handlers)
+
+ def on_delete_event(self, dialog, event):
+ dialog.hide()
+ self.sessions.save()
+ return True
+
+ def get_current_session(self):
+ (model, selected) = self.view.get_selection().get_selected()
+ if selected is None:
+ return None
+ return model.get_value(selected, SessionModel.OBJECT_COLUMN)
+
+ def on_open_button_clicked(self, button):
+ session = self.get_current_session()
+ if session is not None:
+ self.plugin._load_session(session)
+
+ def on_delete_button_clicked(self, button):
+ session = self.get_current_session()
+ self.sessions.remove(session)
+ self.plugin._update_session_menu()
+
+ def on_close_button_clicked(self, button):
+ self.sessions.save()
+ self.destroy()
+
+# ex:ts=4:et:
diff --git a/plugins/sessionsaver/sessionsaver/gpdefs.py b/plugins/sessionsaver/sessionsaver/gpdefs.py
new file mode 100644
index 0000000..d63bfd3
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver/gpdefs.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+PACKAGE = "gedit-plugins"
+GETTEXT_PACKAGE = "gedit-plugins"
+GP_LOCALEDIR = "/usr/share/locale"
diff --git a/plugins/sessionsaver/sessionsaver/sessionsaver.ui
b/plugins/sessionsaver/sessionsaver/sessionsaver.ui
new file mode 100644
index 0000000..7e333df
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver/sessionsaver.ui
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <object class="GtkDialog" id="save-session-dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes">Save session</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox1">
+ <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">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Session name:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="session-name">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="combobox-entry2">
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button2</action-widget>
+ <action-widget response="-5">button1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkWindow" id="session-manager-dialog">
+ <property name="width_request">400</property>
+ <property name="height_request">200</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Saved Sessions</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <object class="GtkBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="session-view">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="headers_visible">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="open-button">
+ <property name="label">gtk-open</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_open_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="delete-button">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_delete_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close-button">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_close_button_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/sessionsaver/sessionsaver/store.py b/plugins/sessionsaver/sessionsaver/store.py
new file mode 100644
index 0000000..3348441
--- /dev/null
+++ b/plugins/sessionsaver/sessionsaver/store.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+# store.py
+# This file is part of gedit Session Saver Plugin
+#
+# Copyright (C) 2006-2007 - Steve Frécinaux <code istique net>
+# Copyright (C) 2010 - Kenny Meyer <knny myer gmail com>
+#
+# gedit Session Saver Plugin 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 2 of the License, or
+# (at your option) any later version.
+#
+# gedit Session Saver Plugin 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 gedit Session Saver Plugin; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA
+
+import os.path
+from xml.parsers import expat
+from gi.repository import GObject, GLib, Gio
+
+class Session(object):
+ def __init__(self, name, files = None):
+ super(Session, self).__init__()
+ self.name = name
+ if files is None:
+ files = []
+ self.files = files
+
+ def __lt__(self, session):
+ return (self.name.lower() < session.name.lower())
+
+ def add_file(self, filename):
+ self.files.append(Gio.file_new_for_uri(filename))
+
+class SessionStore(GObject.Object):
+ __gsignals__ = {
+ "session-added": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE,
+ (GObject.TYPE_PYOBJECT,)),
+ "session-changed": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE,
+ (GObject.TYPE_PYOBJECT,)),
+ "session-removed": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE,
+ (GObject.TYPE_PYOBJECT,))
+ }
+
+ _instance = None
+ def __new__(cls):
+ if cls._instance is None:
+ cls._instance = GObject.Object.__new__(cls)
+ return cls._instance
+
+ def __init__(self):
+ super(SessionStore, self).__init__()
+ self._sessions = []
+
+ def __iter__(self):
+ return iter(self._sessions)
+
+ def __getitem__(self, index):
+ return self._sessions[index]
+
+ def __getslice__(self, i, j):
+ return self._sessions[i:j]
+
+ def __len__(self):
+ return len(self._sessions)
+
+ def do_session_added(self, session):
+ self._sessions.append(session)
+ self._sessions.sort()
+
+ def do_session_changed(self, session):
+ index = self._sessions.index(session)
+ self._sessions[index] = session
+
+ def add(self, session):
+ assert isinstance(session, Session)
+
+ if session in self:
+ self.emit('session-changed', session)
+ else:
+ self.emit('session-added', session)
+
+ def do_session_removed(self, session):
+ self._sessions.remove(session)
+
+ def remove(self, session):
+ assert isinstance(session, Session)
+ if session in self:
+ self.emit('session-removed', session)
+
+ def index(self, session):
+ return self._sessions.index(session)
+
+class XMLSessionStore(SessionStore):
+ def __init__(self):
+ super(XMLSessionStore, self).__init__()
+ self.filename = os.path.join(GLib.get_user_config_dir(), 'gedit/saved-sessions.xml')
+ self.load()
+
+ def _escape(self, string):
+ return string.replace('&', '&') \
+ .replace('<', '<') \
+ .replace('>', '>') \
+ .replace('"', '"')
+
+ def _dump_session(self, session):
+ files = ''.join([' <file path="%s"/>\n' % self._escape(location.get_uri())
+ for location in session.files])
+ session_name = self._escape(str(session.name))
+ return '<session name="%s">\n%s</session>\n' % (session_name, files)
+
+ def dump(self):
+ dump = [self._dump_session(session) for session in self]
+ return '<saved-sessions>\n%s</saved-sessions>\n' % ''.join(dump)
+
+ def save(self):
+ dirname = os.path.dirname(self.filename)
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+
+ fp = open(self.filename, "wb")
+ fp.write(bytes('<?xml version="1.0" encoding="UTF-8"?>\n','UTF-8'))
+ fp.write(bytes(self.dump(),'UTF-8'))
+ fp.close()
+
+ def load(self):
+ if not os.path.isfile(self.filename):
+ return
+
+ parser = expat.ParserCreate('UTF-8')
+ parser.buffer_text = True
+ parser.StartElementHandler = self._expat_start_handler
+ parser.EndElementHandler = self._expat_end_handler
+
+ self._current_session = None
+ try:
+ parser.ParseFile(open(self.filename, 'rb'))
+ except:
+ return
+ del self._current_session
+
+ def _expat_start_handler(self, tag, attr):
+ if tag == 'file':
+ assert self._current_session is not None
+ self._current_session.add_file(str(attr['path']))
+ elif tag == 'session':
+ assert self._current_session is None
+ self._current_session = Session(attr['name'])
+
+ def _expat_end_handler(self, tag):
+ if tag == 'session':
+ self.add(self._current_session)
+ self._current_session = None
+
+# ex:ts=4:et:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]