diff --git a/oml/api.py b/oml/api.py index 3253645..32c1363 100644 --- a/oml/api.py +++ b/oml/api.py @@ -35,6 +35,8 @@ def selectFolder(data): cmd = ['./ctl', 'ui', 'folder'] if sys.platform == 'win32': cmd = win32_ui('folder') + if 'base' in data: + cmd += [data['base']] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() path = stdout.decode('utf-8').strip() @@ -53,6 +55,8 @@ def selectFile(data): cmd = ['./ctl', 'ui', 'file'] if sys.platform == 'win32': cmd = win32_ui('file') + if 'base' in data: + cmd += [data['base']] p = subprocess.Popen(cmd, stdout=subprocess.PIPE) stdout, stderr = p.communicate() path = stdout.decode('utf-8').strip() diff --git a/oml/ui.py b/oml/ui.py index e1fb45b..683fddd 100644 --- a/oml/ui.py +++ b/oml/ui.py @@ -3,8 +3,9 @@ import sys import os try: + import gi + gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject - GObject.threads_init() use_Gtk = True except: from tkinter import Tk, PhotoImage @@ -13,13 +14,19 @@ except: DEBUG = False + +def short_home(path): + home = os.path.expanduser('~') + if path and path.startswith(home): + path = path.replace(home, '~') + return path + class GtkUI: def selectFolder(self, data): - dialog = Gtk.FileChooserDialog(data.get("title", "Select Folder"), - None, - Gtk.FileChooserAction.SELECT_FOLDER, - (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, - Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + dialog = Gtk.FileChooserDialog(title=data.get("title", "Select Folder"), + action=Gtk.FileChooserAction.SELECT_FOLDER) + dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) response = dialog.run() @@ -36,14 +43,13 @@ class GtkUI: Gtk.main_iteration() if DEBUG: print("done") - return filename + return short_home(filename) def selectFile(self, data): - dialog = Gtk.FileChooserDialog(data.get("title", "Select File"), - None, - Gtk.FileChooserAction.OPEN, - (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, - Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + dialog = Gtk.FileChooserDialog(title=data.get("title", "Select File"), + action=Gtk.FileChooserAction.OPEN) + dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) response = dialog.run() @@ -60,7 +66,7 @@ class GtkUI: Gtk.main_iteration() if DEBUG: print("done") - return filename + return short_home(filename) class TkUI: @@ -77,10 +83,12 @@ class TkUI: self.root.after_idle(self.root.call, 'wm', 'attributes', '.', '-topmost', False) def selectFolder(self, data): - return tkinter.filedialog.askdirectory(parent=self.root, title=data.get("title", "Select Folder")) + folder = tkinter.filedialog.askdirectory(parent=self.root, title=data.get("title", "Select Folder")) + return short_home(folder) def selectFile(self, data): - return tkinter.filedialog.askopenfilename(parent=self.root, title=data.get("title", "Select File")) + filename = tkinter.filedialog.askopenfilename(parent=self.root, title=data.get("title", "Select File")) + return short_home(filename) if use_Gtk: @@ -89,8 +97,12 @@ else: ui = TkUI() if __name__ == '__main__': - import sys - if len(sys.argv) == 2 and sys.argv[1] == 'folder': + base = '~' + if len(sys.argv) >= 3: + base = sys.argv[2] + base = os.path.expanduser(base) + os.chdir(base) + if len(sys.argv) >= 2 and sys.argv[1] == 'folder': print(ui.selectFolder({})) else: print(ui.selectFile({})) diff --git a/static/js/importExportDialog.js b/static/js/importExportDialog.js index ae7fd55..a9ece40 100644 --- a/static/js/importExportDialog.js +++ b/static/js/importExportDialog.js @@ -217,14 +217,7 @@ oml.ui.importExportDialog = function() { var $element = Ox.Element(), $form = Ox.Form({ items: selected == 'import' ? [ - Ox.Input({ - autocomplete: function(value, callback) { - oml.api.autocompleteFolder({path: value}, function(result) { - callback(result.data.items); - }); - }, - autocompleteSelect: true, - changeOnKeypress: true, + oml.ui.selectFolder({ id: 'path', label: 'Source Path', labelWidth: 128, @@ -256,14 +249,7 @@ oml.ui.importExportDialog = function() { width: 480 }) ] : [ - Ox.Input({ - autocomplete: function(value, callback) { - oml.api.autocompleteFolder({path: value}, function(result) { - callback(result.data.items); - }); - }, - autocompleteSelect: true, - changeOnKeypress: true, + oml.ui.selectFolder({ id: 'path', label: 'Destination Path', labelWidth: 128, @@ -296,6 +282,7 @@ oml.ui.importExportDialog = function() { .bindEvent({ change: function(data) { var values = $form.values(); + console.log(values) $activityButton[selected].options({ disabled: !values.path }); diff --git a/static/js/preferencesPanel.js b/static/js/preferencesPanel.js index e13c566..f599dd7 100644 --- a/static/js/preferencesPanel.js +++ b/static/js/preferencesPanel.js @@ -25,24 +25,14 @@ oml.ui.preferencesPanel = function() { { id: 'libraryPath', title: 'Library Path', - autocomplete: function(value, callback) { - oml.api.autocompleteFolder({path: value}, function(result) { - callback(result.data.items); - }); - }, - autocompleteSelect: true, + type: 'selectfolder', value: preferences.libraryPath, help: 'The directory in which your "Books" folder is located. This is where your media files are stored. It can be on your local machine, but just as well on an external drive or networked volume.' }, { id: 'importPath', title: 'Import Path', - autocomplete: function(value, callback) { - oml.api.autocompleteFolder({path: value}, function(result) { - callback(result.data.items); - }); - }, - autocompleteSelect: true, + type: 'selectfolder', value: preferences.importPath, help: 'Any media files that you put in this folder will be added to your library. Once added, they will be removed from this folder.' } @@ -347,6 +337,15 @@ oml.ui.preferencesPanel = function() { value: item.value, width: 384 }) + : item.type == 'selectfolder' + ? oml.ui.selectFolder({ + label: Ox._(item.title), + labelWidth: 128, + placeholder: item.placeholder || '', + style: 'squared', + title: oml.user.preferences[item.id] || item.value || '', + width: 384 - !!item.unit * 48 + }) : Ox.Input({ autocomplete: item.autocomplete || null, autocompleteSelect: item.autocompleteSelect || false, @@ -357,7 +356,6 @@ oml.ui.preferencesPanel = function() { value: oml.user.preferences[item.id] || item.value || '', width: 384 - !!item.unit * 48 }) - ].concat(item.unit ? [ Ox.Label({ overlap: 'left', diff --git a/static/js/selectFolder.js b/static/js/selectFolder.js new file mode 100644 index 0000000..f6a2cc8 --- /dev/null +++ b/static/js/selectFolder.js @@ -0,0 +1,46 @@ +'use strict'; + +oml.ui.selectFolder = function(options, self) { + options.width = options.width - options.labelWidth + options = Ox.extend({ + title: '...', + textAlign: 'left' + }, options); + var $button = Ox.Button(options, self).bindEvent({ + click: function(event) { + oml.api.selectFolder({ + base: $button.value() + }, function(result) { + if (result.data.path) { + $button.value(result.data.path); + $button.options({ + title: result.data.path + }); + $button.triggerEvent('change', result.data.path); + } + }) + } + }), + that = Ox.FormElementGroup({ + id: options.id, + elements: [ + Ox.Label({ + style: options.style, + textAlign: 'right', + overlap: 'right', + title: options.label, + width: options.labelWidth + }), + $button + ], + }, self); + + that.value = function() { + return $button.value() + } + + if (options.title && options.title != '...') { + $button.value(options.title) + } + return that; +} diff --git a/static/json/js.json b/static/json/js.json index 3a77998..1aabee6 100644 --- a/static/json/js.json +++ b/static/json/js.json @@ -58,6 +58,7 @@ "rightPanel.js", "sectionButtons.js", "sectionbar.js", + "selectFolder.js", "sortElement.js", "statusIcon.js", "statusbar.js",