diff options
Diffstat (limited to 'external/plyer/platforms/linux/filechooser.py')
-rw-r--r-- | external/plyer/platforms/linux/filechooser.py | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/external/plyer/platforms/linux/filechooser.py b/external/plyer/platforms/linux/filechooser.py new file mode 100644 index 0000000..545487b --- /dev/null +++ b/external/plyer/platforms/linux/filechooser.py @@ -0,0 +1,249 @@ +''' +Linux file chooser +------------------ +''' + +from plyer.facades import FileChooser +from distutils.spawn import find_executable as which +import os +import subprocess as sp +import time + + +class SubprocessFileChooser(object): + '''A file chooser implementation that allows using + subprocess back-ends. + Normally you only need to override _gen_cmdline, executable, + separator and successretcode. + ''' + + executable = "" + '''The name of the executable of the back-end. + ''' + + separator = "|" + '''The separator used by the back-end. Override this for automatic + splitting, or override _split_output. + ''' + + successretcode = 0 + '''The return code which is returned when the user doesn't close the + dialog without choosing anything, or when the app doesn't crash. + ''' + + path = None + multiple = False + filters = [] + preview = False + title = None + icon = None + show_hidden = False + + def __init__(self, **kwargs): + # Simulate Kivy's behavior + for i in kwargs: + setattr(self, i, kwargs[i]) + + _process = None + + def _run_command(self, cmd): + self._process = sp.Popen(cmd, stdout=sp.PIPE) + while True: + ret = self._process.poll() + if ret is not None: + if ret == self.successretcode: + out = self._process.communicate()[0].strip() + self.selection = self._split_output(out) + return self.selection + else: + return None + time.sleep(0.1) + + def _split_output(self, out): + '''This methods receives the output of the back-end and turns + it into a list of paths. + ''' + return out.split(self.separator) + + def _gen_cmdline(self): + '''Returns the command line of the back-end, based on the current + properties. You need to override this. + ''' + raise NotImplementedError() + + def run(self): + return self._run_command(self._gen_cmdline()) + + +class ZenityFileChooser(SubprocessFileChooser): + '''A FileChooser implementation using Zenity (on GNU/Linux). + + Not implemented features: + * show_hidden + * preview + ''' + + executable = "zenity" + separator = "|" + successretcode = 0 + + def _gen_cmdline(self): + cmdline = [ + which(self.executable), + "--file-selection", + "--confirm-overwrite" + ] + if self.multiple: + cmdline += ["--multiple"] + if self.mode == "save": + cmdline += ["--save"] + elif self.mode == "dir": + cmdline += ["--directory"] + if self.path: + cmdline += ["--filename", self.path] + if self.title: + cmdline += ["--name", self.title] + if self.icon: + cmdline += ["--window-icon", self.icon] + for f in self.filters: + if type(f) == str: + cmdline += ["--file-filter", f] + else: + cmdline += [ + "--file-filter", + "{name} | {flt}".format(name=f[0], flt=" ".join(f[1:])) + ] + return cmdline + + +class KDialogFileChooser(SubprocessFileChooser): + '''A FileChooser implementation using KDialog (on GNU/Linux). + + Not implemented features: + * show_hidden + * preview + ''' + + executable = "kdialog" + separator = "\n" + successretcode = 0 + + def _gen_cmdline(self): + cmdline = [which(self.executable)] + + filt = [] + + for f in self.filters: + if type(f) == str: + filt += [f] + else: + filt += list(f[1:]) + + if self.mode == "dir": + cmdline += [ + "--getexistingdirectory", + (self.path if self.path else os.path.expanduser("~")) + ] + elif self.mode == "save": + cmdline += [ + "--getopenfilename", + (self.path if self.path else os.path.expanduser("~")), + " ".join(filt) + ] + else: + cmdline += [ + "--getopenfilename", + (self.path if self.path else os.path.expanduser("~")), + " ".join(filt) + ] + if self.multiple: + cmdline += ["--multiple", "--separate-output"] + if self.title: + cmdline += ["--title", self.title] + if self.icon: + cmdline += ["--icon", self.icon] + return cmdline + + +class YADFileChooser(SubprocessFileChooser): + '''A NativeFileChooser implementation using YAD (on GNU/Linux). + + Not implemented features: + * show_hidden + ''' + + executable = "yad" + separator = "|?|" + successretcode = 0 + + def _gen_cmdline(self): + cmdline = [ + which(self.executable), + "--file-selection", + "--confirm-overwrite", + "--geometry", + "800x600+150+150" + ] + if self.multiple: + cmdline += ["--multiple", "--separator", self.separator] + if self.mode == "save": + cmdline += ["--save"] + elif self.mode == "dir": + cmdline += ["--directory"] + if self.preview: + cmdline += ["--add-preview"] + if self.path: + cmdline += ["--filename", self.path] + if self.title: + cmdline += ["--name", self.title] + if self.icon: + cmdline += ["--window-icon", self.icon] + for f in self.filters: + if type(f) == str: + cmdline += ["--file-filter", f] + else: + cmdline += [ + "--file-filter", + "{name} | {flt}".format(name=f[0], flt=" ".join(f[1:])) + ] + return cmdline + +CHOOSERS = { + "gnome": ZenityFileChooser, + "kde": KDialogFileChooser, + "yad": YADFileChooser +} + + +class LinuxFileChooser(FileChooser): + '''FileChooser implementation for GNu/Linux. Accepts one additional + keyword argument, *desktop_override*, which, if set, overrides the + back-end that will be used. Set it to "gnome" for Zenity, to "kde" + for KDialog and to "yad" for YAD (Yet Another Dialog). + If set to None or not set, a default one will be picked based on + the running desktop environment and installed back-ends. + ''' + + desktop = None + if str(os.environ.get("XDG_CURRENT_DESKTOP")).lower() == "kde" \ + and which("kdialog"): + desktop = "kde" + elif which("yad"): + desktop = "yad" + elif which("zenity"): + desktop = "gnome" + + def _file_selection_dialog(self, desktop_override=desktop, **kwargs): + if not desktop_override: + desktop_override = desktop + # This means we couldn't find any back-end + if not desktop_override: + raise OSError("No back-end available. Please install one.") + + chooser = CHOOSERS[desktop_override] + c = chooser(**kwargs) + return c.run() + + +def instance(): + return LinuxFileChooser() |