1#!/usr/local/bin/python3.8
2#-*-indent-tabs-mode: nil-*-
3
4import sys
5import os.path
6
7import gi
8gi.require_version('Gtk', '3.0')
9from gi.repository import Gtk, Gio
10
11SCHEMAS = "org.cinnamon.desklets.launcher"
12LAUNCHER_KEY = "launcher-list"
13
14HOME_DIR = os.path.expanduser("~")+"/"
15CUSTOM_LAUNCHERS_PATH = HOME_DIR + ".cinnamon/panel-launchers/"
16EDITOR_DIALOG_UI_PATH = "/usr/local/share/cinnamon/desklets/launcher@cinnamon.org/editorDialog.ui"
17
18class EditorDialog:
19    def __init__(self, desklet_id=-1):
20        self.launcher_settings = Gio.Settings.new(SCHEMAS)
21        self.launcher_type = "Application"
22        self.name = ""
23        self.desklet_id = desklet_id
24
25        if not desklet_id == -1:
26            launcher_list = self.launcher_settings.get_strv(LAUNCHER_KEY)
27            launcher = ""
28            for item in launcher_list:
29                if item.split(":")[0] == str(self.desklet_id):
30                    launcher = item.split(":")[1][:-8]
31                    break;
32
33            self.name = launcher
34            if self.name[:24] == "cinnamon-custom-launcher":
35                self.launcher_type = "Custom Application"
36
37        self.tree = Gtk.Builder()
38        self.tree.set_translation_domain('cinnamon') # let it translate!
39        self.tree.add_from_file(EDITOR_DIALOG_UI_PATH)
40
41        self.dialog = self.tree.get_object("dialog")
42        self.launcher_type_combo_box = self.tree.get_object("launcher_type_combo_box")
43        self.name_entry = self.tree.get_object("name_entry")
44        self.title_entry = self.tree.get_object("title_entry")
45        self.command_entry = self.tree.get_object("command_entry")
46        self.icon_name_entry = self.tree.get_object("icon_name_entry")
47        self.launcher_icon = self.tree.get_object("launcher_icon")
48
49        self.name_entry.set_text(self.name)
50
51        self.model = self.launcher_type_combo_box.get_model()
52        self.citer = [self.model.get_iter_from_string("0"),self.model.get_iter_from_string("1")]
53
54        self.launcher_type_combo_box.set_active_iter(self.citer[self.launcher_type_to_index(self.launcher_type)])
55        self.update_sensitivity()
56        self.set_fields_by_name()
57        self.on_icon_changed(self.icon_name_entry.get_text())
58
59        self.tree.connect_signals(self)
60
61        self.dialog.show_all()
62        self.dialog.connect("destroy", Gtk.main_quit)
63        self.dialog.connect("key_release_event", self.on_key_release_event)
64        Gtk.main()
65
66    def launcher_type_to_index(self,launcher_type):
67        if launcher_type == "Application":
68            return 0
69        elif launcher_type == "Custom Application":
70            return 1
71
72    def update_sensitivity(self):
73        sensitive = True
74        if (self.launcher_type == "Application"):
75            sensitive = False
76
77        self.name_entry.set_sensitive(not sensitive)
78        self.title_entry.set_sensitive(sensitive)
79        self.command_entry.set_sensitive(sensitive)
80        self.icon_name_entry.set_sensitive(sensitive)
81        if (self.launcher_type == "Application"):
82            self.name_entry.grab_focus()
83        else:
84            self.title_entry.grab_focus()
85
86    def on_launcher_type_combo_box_changed(self, widget):
87        self.launcher_type = self.launcher_type_combo_box.get_active_text()
88        self.update_sensitivity()
89        self.on_name_changed(self.name_entry)
90
91    def on_icon_changed(self, widget):
92        self.launcher_icon.set_from_icon_name(self.icon_name_entry.get_text(), 48)
93
94    def on_name_changed(self, widget):
95        if (self.launcher_type == "Application"):
96            self.set_fields_by_name()
97
98    def set_fields_by_name(self):
99        application = Application(self.name_entry.get_text() + ".desktop")
100        if application.title:
101            self.title_entry.set_text(application.title)
102            self.command_entry.set_text(application.command)
103            self.icon_name_entry.set_text(application.icon_name)
104
105    def on_key_release_event(self, widget, event):
106        if event.keyval == 65293: # Enter button
107            self.on_edit_ok_clicked(widget)
108
109    def on_edit_close_clicked(self, widget):
110        self.dialog.destroy()
111
112    def on_edit_ok_clicked(self, widget):
113        if not self.name_entry.get_text():
114            return None
115
116        if (self.launcher_type == "Application"):
117            launcher_name = self.name_entry.get_text() + ".desktop"
118        elif (self.launcher_type == "Custom Application"):
119            launcher_name = self.write_custom_application()
120
121        enabled_desklets = None
122
123        if self.desklet_id == -1: # Add new launcher
124            settings = Gio.Settings.new("org.cinnamon")
125            self.desklet_id = settings.get_int("next-desklet-id")
126            settings.set_int("next-desklet-id", self.desklet_id + 1)
127
128            enabled_desklets = settings.get_strv("enabled-desklets")
129            enabled_desklets.append("launcher@cinnamon.org:%s:0:100" % self.desklet_id)
130
131        launcher_list = self.launcher_settings.get_strv(LAUNCHER_KEY)
132
133        # If the application is initiall set in the list, remove them all
134        for item in launcher_list:
135            if item.split(":")[0] == str(self.desklet_id):
136                launcher_list.remove(item)
137
138        launcher_list.append(str(self.desklet_id) + ":" + launcher_name)
139        self.launcher_settings.set_strv(LAUNCHER_KEY, launcher_list)
140
141        # Update desklets list now if new desklet is made
142        if enabled_desklets:
143            settings.set_strv("enabled-desklets", enabled_desklets)
144
145        self.dialog.destroy()
146
147    def get_custom_id(self):
148        i = 1
149        directory = Gio.file_new_for_path(CUSTOM_LAUNCHERS_PATH)
150        if not directory.query_exists(None):
151            directory.make_directory_with_parents(None)
152
153        fileRec = Gio.file_parse_name(CUSTOM_LAUNCHERS_PATH + 'cinnamon-custom-launcher-' + str(i) + '.desktop')
154        while fileRec.query_exists(None):
155            i = i + 1
156            fileRec = Gio.file_parse_name(CUSTOM_LAUNCHERS_PATH + 'cinnamon-custom-launcher-' + str(i) + '.desktop')
157
158        return i;
159
160    def write_custom_application(self):
161        i = self.get_custom_id();
162
163        file_name = "cinnamon-custom-launcher-" + str(i) + ".desktop"
164        file_path = CUSTOM_LAUNCHERS_PATH + file_name
165
166        title = self.title_entry.get_text()
167        command = self.command_entry.get_text()
168        icon_name = self.icon_name_entry.get_text()
169        _file = open(file_path,"w+")
170
171        write_list=["[Desktop Entry]\n","Type=Application\n", "Name=" + title + "\n","Exec=" + command + "\n","Icon=" + icon_name + "\n"]
172
173        _file.writelines(write_list)
174        _file.close()
175
176        return file_name
177
178
179class Application:
180    def __init__(self, file_name):
181        self.file_name = file_name
182        self._path = None
183        self.icon_name = None
184        self.title = None
185        self.command = None
186
187        if (os.path.exists(CUSTOM_LAUNCHERS_PATH + file_name)):
188            self._path = CUSTOM_LAUNCHERS_PATH + file_name
189        elif (os.path.exists("/usr/local/share/applications/" + file_name)):
190            self._path = "/usr/local/share/applications/" + file_name
191
192        if self._path:
193            self._file = open(self._path, "r")
194            while self._file:
195                line = self._file.readline()
196                if len(line)==0:
197                    break
198
199                if (line.find("Name") == 0 and (not "[" in line)):
200                    self.title = line.replace("Name","").replace("=","").replace("\n","")
201
202                if (line.find("Icon") == 0):
203                    self.icon_name = line.replace("Icon","").replace(" ","").replace("=","").replace("\n","")
204
205                if (line.find("Exec") == 0):
206                    self.command = line.replace("Exec","").replace("=","").replace("\n","")
207
208                if self.icon_name and self.title and self.command:
209                    break
210
211            if not self.icon_name:
212                self.icon_name = "application-x-executable"
213            if not self.title:
214                self.title = "Application"
215            if not self.command:
216                self.command = ""
217            self._file.close()
218
219if __name__ == "__main__":
220    if len(sys.argv) > 1:
221        dialog = EditorDialog(sys.argv[1])
222    else:
223        dialog = EditorDialog()
224