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