summaryrefslogtreecommitdiff
path: root/plugins/python/scripting/core.py
blob: 7aff55165ab6279453c7974cf50e8987e849c955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

from gi.repository import Gtk

from pychrysalide import PluginModule
from pychrysalide import core
from pychrysalide.gui import core as gcore
from pychrysalide.gtkext import EasyGtk


class ScriptingEngine(PluginModule):
    """Extend the GUI to run external Python scripts."""

    _name = 'ScriptingEngine'
    _desc = 'Run external Python scripts on demand'
    _version = '0.1'
    _url = 'https://www.chrysalide.re/'

    _actions = ( )


    def __init__(self):
        """Initialize the plugin for Chrysalide."""

        super(ScriptingEngine, self).__init__()

        # Insert the new menu item into 'File' submenu

        bar = gcore.find_editor_item_by_key('menubar')

        builder = gcore.get_editor_builder()

        file_menu = builder.get_object('file').get_submenu()
        sep_item = builder.get_object('file_sep_1')
        save_item = builder.get_object('file_save_project')

        index = EasyGtk.find_contained_child_index(file_menu, save_item)

        if index == -1:
            raise RuntimeError('file menu not found')

        prev = EasyGtk.get_nth_contained_child(file_menu, index - 1)

        if sep_item == prev:

            sep = Gtk.SeparatorMenuItem()
            sep.show()

            file_menu.insert(sep, index)

        item = Gtk.MenuItem(label='Run Python script...')
        item.connect("activate", self._on_file_run_script_activate)
        item.show()

        file_menu.insert(item, index)


    def _on_file_run_script_activate(self, widget):
        """Look for a new script to run."""

        dialog = Gtk.FileChooserDialog(title='Please choose a Python script to execute',
                                       transient_for=gcore.get_editor_window(),
                                       action=Gtk.FileChooserAction.OPEN)

        dialog.add_buttons(Gtk.STOCK_CANCEL,
                           Gtk.ResponseType.CANCEL,
                           Gtk.STOCK_OPEN,
                           Gtk.ResponseType.OK)

        ffilter = Gtk.FileFilter()
        ffilter.set_name('Python files')
        ffilter.add_mime_type('text/x-python')
        dialog.add_filter(ffilter)

        response = dialog.run()

        if response == Gtk.ResponseType.OK:
            filename = dialog.get_filename()
        else:
            filename = None

        dialog.destroy()

        if filename:
            self._run_script_file(filename)


    def _run_script_file(self, filename):
        """Run a given script file."""

        core.log_message(core.LogMessageType.INFO, 'Execute the script file \'%s\'' % filename)

        try:
            with open(filename, 'r') as fd:
                content = fd.read()

            code = compile(content, '<string>', 'exec')

            eval(code)

        except Exception as e:
            core.log_message(core.LogMessageType.EXT_ERROR, 'Error while running the script: %s' % str(e))