summaryrefslogtreecommitdiff
path: root/external/plyer/platforms/linux/filechooser.py
diff options
context:
space:
mode:
Diffstat (limited to 'external/plyer/platforms/linux/filechooser.py')
-rw-r--r--external/plyer/platforms/linux/filechooser.py249
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()