Commit 77393433 authored by Fabián Orccón's avatar Fabián Orccón Committed by Alexandru Băluț

plugins: Add support for shortcuts commands in Developer Console

parent c2223e82
Pipeline #23321 passed with stages
in 9 minutes and 44 seconds
...@@ -93,6 +93,35 @@ class PluginManager(Loggable): ...@@ -93,6 +93,35 @@ class PluginManager(Loggable):
return PluginType.SYSTEM return PluginType.SYSTEM
return PluginType.USER return PluginType.USER
def get_extension(self, module_name):
"""Gets the extension identified by the specified name.
Args:
module_name (str): The name of the extension.
Returns:
The extension if exists. Otherwise, `None`.
"""
plugin = self.get_plugin_info(module_name)
if not plugin:
return None
return self.extension_set.get_extension(plugin)
def get_plugin_info(self, module_name):
"""Gets the plugin info for the specified plugin name.
Args:
module_name (str): The name from the .plugin file of the module.
Returns:
Peas.PluginInfo: The plugin info if it exists. Otherwise, `None`.
"""
for plugin in self.plugins:
if plugin.get_module_name() == module_name:
return plugin
return None
def _load_plugins(self): def _load_plugins(self):
"""Loads plugins from settings.""" """Loads plugins from settings."""
plugin_names = self.app.settings.ActivePlugins plugin_names = self.app.settings.ActivePlugins
......
...@@ -23,9 +23,42 @@ from gettext import gettext as _ ...@@ -23,9 +23,42 @@ from gettext import gettext as _
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Peas from gi.repository import Peas
from utils import Namespace
from widgets import ConsoleWidget from widgets import ConsoleWidget
class PitiviNamespace(Namespace):
"""Easy to shape Python namespace."""
def __init__(self, app):
Namespace.__init__(self)
self._app = app
@property
@Namespace.shortcut
def app(self):
"""The Pitivi instance."""
return self._app
@property
@Namespace.shortcut
def plugin_manager(self):
"""The Plugin Manager instance."""
return self._app.plugin_manager
@property
@Namespace.shortcut
def project(self):
"""The current project."""
return self._app.project_manager.current_project
@property
@Namespace.shortcut
def timeline(self):
"""The GES.Timeline of the current project."""
return self._app.gui.editor.timeline_ui.timeline.ges_timeline
class Console(GObject.GObject, Peas.Activatable): class Console(GObject.GObject, Peas.Activatable):
"""Plugin which adds a Python console for development purposes.""" """Plugin which adds a Python console for development purposes."""
...@@ -72,9 +105,10 @@ class Console(GObject.GObject, Peas.Activatable): ...@@ -72,9 +105,10 @@ class Console(GObject.GObject, Peas.Activatable):
self.menu_item = None self.menu_item = None
def _setup_dialog(self): def _setup_dialog(self):
namespace = {"app": self.app} namespace = PitiviNamespace(self.app)
self.window = Gtk.Window() self.window = Gtk.Window()
self.terminal = ConsoleWidget(namespace) welcome_message = "".join(self.create_welcome_message(namespace))
self.terminal = ConsoleWidget(namespace, welcome_message)
self.terminal.connect("eof", self.__eof_cb) self.terminal.connect("eof", self.__eof_cb)
self.window.set_default_size(600, 400) self.window.set_default_size(600, 400)
...@@ -82,6 +116,21 @@ class Console(GObject.GObject, Peas.Activatable): ...@@ -82,6 +116,21 @@ class Console(GObject.GObject, Peas.Activatable):
self.window.connect("delete-event", self.__delete_event_cb) self.window.connect("delete-event", self.__delete_event_cb)
self.window.add(self.terminal) self.window.add(self.terminal)
def create_welcome_message(self, namespace):
console_plugin_info = self.app.plugin_manager.get_plugin_info("console")
name = console_plugin_info.get_name()
version = console_plugin_info.get_version() or ""
yield "%s %s\n\n" % (name, version)
yield console_plugin_info.get_help_uri()
yield "\n\n"
yield _("You can use the following shortcuts:")
yield "\n"
for shortcut in namespace.get_shortcuts():
yield " - %s\n" % shortcut
yield "\n"
yield _("Type \"{help}(<command>)\" for more information.").format(help="help")
yield "\n\n"
def __menu_item_activate_cb(self, unused_data): def __menu_item_activate_cb(self, unused_data):
self.window.show_all() self.window.show_all()
self.window.set_keep_above(True) self.window.set_keep_above(True)
......
...@@ -77,17 +77,19 @@ class ConsoleHistory(GObject.Object): ...@@ -77,17 +77,19 @@ class ConsoleHistory(GObject.Object):
class ConsoleBuffer(Gtk.TextBuffer): class ConsoleBuffer(Gtk.TextBuffer):
def __init__(self, namespace): def __init__(self, namespace, welcome_message=""):
Gtk.TextBuffer.__init__(self) Gtk.TextBuffer.__init__(self)
self.insert_at_cursor(sys.ps1)
self.prompt_mark = self.create_mark("after-prompt", self.get_end_iter(), left_gravity=True)
self.prompt = sys.ps1 self.prompt = sys.ps1
self._stdout = FakeOut(self) self._stdout = FakeOut(self)
self._stderr = FakeOut(self) self._stderr = FakeOut(self)
self._console = code.InteractiveConsole(namespace) self._console = code.InteractiveConsole(namespace)
self.insert(self.get_end_iter(), welcome_message)
self.before_prompt_mark = self.create_mark("before-prompt", self.get_end_iter(), left_gravity=True)
self.insert_at_cursor(sys.ps1)
self.prompt_mark = self.create_mark("after-prompt", self.get_end_iter(), left_gravity=True)
self.history = ConsoleHistory() self.history = ConsoleHistory()
namespace["__history__"] = self.history namespace["__history__"] = self.history
self.history.connect("pos-changed", self.__history_pos_changed_cb) self.history.connect("pos-changed", self.__history_pos_changed_cb)
......
...@@ -17,8 +17,10 @@ ...@@ -17,8 +17,10 @@
# License along with this program; if not, write to the # License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA. # Boston, MA 02110-1301, USA.
import functools
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
from gettext import gettext as _
from io import TextIOBase from io import TextIOBase
...@@ -55,6 +57,52 @@ def display_autocompletion(last_obj, matches, text_buffer, ...@@ -55,6 +57,52 @@ def display_autocompletion(last_obj, matches, text_buffer,
print(match) print(match)
class Namespace(dict):
"""Base for namespaces usable when executing a Python command."""
def __init__(self):
dict.__init__(self)
for key in self.get_shortcuts():
dict.__setitem__(self, key, None)
@staticmethod
def shortcut(func):
"""Decorator to add methods or properties to the namespace."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
setattr(wrapper, "__is_shortcut", True)
return wrapper
def __getitem__(self, key):
if key in self.get_shortcuts():
return getattr(self, key)
return dict.__getitem__(self, key)
def __setitem__(self, key, item):
if key in self.get_shortcuts():
print(_("Not possible to override {key}, because shortcuts "
"commands are read-only.").format(key=key), file=sys.stderr)
return
dict.__setitem__(self, key, item)
def __repr__(self):
return "<%s at %s>" % (self.__class__.__name__, hex(id(self)))
@classmethod
def get_shortcuts(cls):
for attr_name in dir(cls):
attr = getattr(cls, attr_name)
is_shortcut = False
if hasattr(attr, "__is_shortcut"):
is_shortcut = getattr(attr, "__is_shortcut")
elif isinstance(attr, property):
if hasattr(attr.fget, "__is_shortcut"):
is_shortcut = getattr(attr.fget, "__is_shortcut")
if is_shortcut:
yield attr_name
class FakeOut(TextIOBase): class FakeOut(TextIOBase):
"""Replacement for sys.stdout/err which redirects writes.""" """Replacement for sys.stdout/err which redirects writes."""
......
...@@ -38,10 +38,10 @@ class ConsoleWidget(Gtk.ScrolledWindow): ...@@ -38,10 +38,10 @@ class ConsoleWidget(Gtk.ScrolledWindow):
"eof": (GObject.SignalFlags.RUN_LAST, None, ()), "eof": (GObject.SignalFlags.RUN_LAST, None, ()),
} }
def __init__(self, namespace): def __init__(self, namespace, welcome_message=""):
Gtk.ScrolledWindow.__init__(self) Gtk.ScrolledWindow.__init__(self)
self._view = Gtk.TextView() self._view = Gtk.TextView()
buf = ConsoleBuffer(namespace) buf = ConsoleBuffer(namespace, welcome_message)
self._view.set_buffer(buf) self._view.set_buffer(buf)
self._view.set_editable(True) self._view.set_editable(True)
self.add(self._view) self.add(self._view)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment