diff --git a/wacom-gui/custom.json b/wacom-gui/custom.json index bf290e1..91faf73 100644 --- a/wacom-gui/custom.json +++ b/wacom-gui/custom.json @@ -2,6 +2,7 @@ "lhyper z": { "label": "Toggle Screen (Wacom)", "run": "/usr/local/bin/wacom-gui --toggle", - "protected": 1 + "protected": 1, + "dconf": "z" } } diff --git a/wacom-gui/hotkeys.py b/wacom-gui/hotkeys.py index 9389456..29a77e8 100644 --- a/wacom-gui/hotkeys.py +++ b/wacom-gui/hotkeys.py @@ -165,6 +165,9 @@ def get_custom(self): self.custom.addAction("* %s *" % user_custom[cmd]['label'], partial(self.set_value, cmd, user_custom[cmd]['label'])) self.keys_custom_list[cmd] = user_custom[cmd]['label'] + for key in self.keymap_custom.keys(): + if key in user_custom.keys(): + del user_custom[key] self.keymap_custom.update(user_custom) except Exception as e: print (e) @@ -176,7 +179,7 @@ def load_menu(self): self.menu.exec_(QCursor.pos()) def get_keystroke(self, runcmd): - ok, cmdstring, label, run = KeystrokeGui.get_keystrokes(runcmd, self.cmd) + ok, cmdstring, label, run, dconf = KeystrokeGui.get_keystrokes(runcmd, self.cmd) if ok == 1: # update custom keystroke db self.set_value(cmdstring, label) @@ -184,9 +187,12 @@ def get_keystroke(self, runcmd): if label == self.keymap_custom[key]['label'] or key == cmdstring: del self.keymap_custom[key] break + if dconf == False: + dconf = '' self.keymap_custom[cmdstring] = {'label': label, - 'run': run, - 'protected': 0} + 'run': run, + 'protected': 0, + 'dconf': dconf} config = os.path.expanduser("~/.wacom-gui") if not os.path.exists(config): os.mkdir(config) @@ -217,6 +223,8 @@ def xsetcmd_gen(self, cmdstring): xsetcmd = "key %s" % stroke else: xsetcmd = "%s key %s" % (xsetcmd, stroke) + if re.match(r'^button \d+', xsetcmd): + xsetcmd = xsetcmd.split(' ')[1] return xsetcmd def get_button_cmd(self): @@ -239,6 +247,7 @@ def __init__(self, cmd, parent=None): self.setWindowTitle("Define Keystroke") self.keymap = None self.keymap_custom = None + self.dconf = None self.keys_list = {} self.keys_custom_list = {} self.menu = QMenu() @@ -432,7 +441,7 @@ def set_value(self, value): self.keystrokeinput.setText("%s%s" % (blah, cmd)) def get_cmd(self): - return str(self.keystrokeinput.text()), str(self.shortcutinput.text()), str(self.runinput.text()) + return str(self.keystrokeinput.text()), str(self.shortcutinput.text()), str(self.runinput.text()), self.dconf @staticmethod def cmd_path_search(cmd, mode=os.F_OK | os.X_OK, path=None): @@ -529,11 +538,10 @@ def run_hotkey_edit(self): (entry, custom[entry]['action'], custom[entry]['binding'], custom[entry]['name'])) f.close() os.popen("dconf load /org/mate/desktop/keybindings/ < %s" % config) - return True + return xbkbmap except Exception as e: print (e) - def load_keyboard_shortcuts(self): custom = {} p = subprocess.Popen("dconf dump /org/mate/desktop/keybindings/", shell=True, stdout=subprocess.PIPE) @@ -573,7 +581,8 @@ def accept(self): elif ' '.join(strokes) in self.keys_custom_list.keys(): if self.shortcutinput.text() != self.keys_custom_list[' '.join(strokes)]: if self.runinput.text() != '': - if self.run_hotkey_edit(): + self.dconf = self.run_hotkey_edit() + if self.dconf != False: super(KeystrokeGui, self).accept() else: warning = QMessageBox(QMessageBox.Warning, "Something happened...", @@ -584,7 +593,8 @@ def accept(self): # shortcut name used for a different shortcut elif self.shortcutinput.text() in self.keys_custom_list.values(): if self.runinput.text() != '': - if self.run_hotkey_edit(): + self.dconf = self.run_hotkey_edit() + if self.dconf != False: super(KeystrokeGui, self).accept() else: warning = QMessageBox(QMessageBox.Warning, "Something happened...", @@ -605,7 +615,8 @@ def accept(self): if self.runinput.text().__len__() == 0: super(KeystrokeGui, self).accept() elif self.cmd_path_search(runcmd.split(' ')[0]) is not None: - if self.run_hotkey_edit(): + self.dconf = self.run_hotkey_edit() + if self.dconf != False: super(KeystrokeGui, self).accept() else: warning = QMessageBox(QMessageBox.Warning, "Invalid Command", @@ -637,11 +648,11 @@ def get_keystrokes(run, parent=None): dialog.runinput.hide() result = dialog.exec_() if result == 1: - cmd, label, run = dialog.get_cmd() + cmd, label, run, dconf = dialog.get_cmd() cmd = ' '.join(filter(None, re.split('{|}| ', str(cmd)))) - return QDialog.Accepted, cmd, label, run + return QDialog.Accepted, cmd, label, run, dconf else: - return QDialog.Rejected, None, None, None + return QDialog.Rejected, None, None, None, None class HotkeyWidget(QWidget): diff --git a/wacom-gui/pad.py b/wacom-gui/pad.py index 62fc88e..29f49d1 100644 --- a/wacom-gui/pad.py +++ b/wacom-gui/pad.py @@ -12,6 +12,7 @@ import pad_ui import os import json +import subprocess # 880, 560 @@ -19,6 +20,9 @@ class Pad(QTabWidget, pad_ui.Ui_PadWidget): def __init__(self, parent = None): super(Pad, self).__init__(parent) self.setupUi(self) + self.cwd = os.path.dirname(os.path.abspath(__file__)) + if self.cwd == '/usr/local/bin': + self.cwd = '/usr/local/wacom-gui' self.keysLayout.setAlignment(Qt.AlignCenter) self.reset = QPushButton("Set Defaults") self.reset.setMinimumSize(90, 20) @@ -26,6 +30,7 @@ def __init__(self, parent = None): self.reset.clicked.connect(self.set_default) self.buttons = {'left': [], 'right': [], 'top': [], 'bottom': []} self.setFocusPolicy(Qt.NoFocus) + self.load_dconf() def deleteItemsOfLayout(self, layout): if layout is not None: @@ -45,6 +50,70 @@ def boxdelete(self, box): self.vlayout.removeItem(layout_item) break + def load_dconf(self): + with open(os.path.join(self.cwd, 'custom.json'), 'r') as f: + hotkeys = json.load(f) + with open(os.path.expanduser("~/.wacom-gui/custom.json"), 'r') as f: + custom = json.load(f) + for key in hotkeys.keys(): + if key in custom.keys(): + del custom[key] + hotkeys.update(custom) + os_custom = self._load_keyboard_shortcuts() + for key, data in hotkeys.items(): + if data['dconf'] != '': + idx = -1 + found = False + for entry in os_custom.keys(): + if int(entry.split('custom')[1]) > idx: + idx = int(entry.split('custom')[1]) + # name match + if os_custom[entry]['name'] == "'%s'" % data['label'] or \ + os_custom[entry]['binding'] == "'%s'" % data['dconf'] or \ + os_custom[entry]['action'] == "'%s'" % data['run']: + # update entry + os_custom[entry]['name'] = "'%s'" % data['label'] + os_custom[entry]['binding'] = "'%s'" % data['dconf'] + os_custom[entry]['action'] = "'%s'" % data['run'] + found = True + break + if not found: + new_entry = 'custom%d' % (idx + 1) + custom[new_entry] = {'name': "'%s'" % data['label'], + 'binding': "'%s'" % data['dconf'], + 'action': "'%s'" % data['run']} + # generate config file + try: + config = os.path.expanduser("~/.wacom-gui") + if not os.path.isdir(config): + os.mkdir(config) + config = os.path.join(config, "keybind.cfg") + f = open(config, "w") + for entry in os_custom: + f.write("[%s]\naction=%s\nbinding=%s\nname=%s\n\n" % + (entry, os_custom[entry]['action'], os_custom[entry]['binding'], os_custom[entry]['name'])) + f.close() + os.popen("dconf load /org/mate/desktop/keybindings/ < %s" % config) + except Exception as e: + print e + + def _load_keyboard_shortcuts(self): + custom = {} + p = subprocess.Popen("dconf dump /org/mate/desktop/keybindings/", shell=True, stdout=subprocess.PIPE) + p.wait() + output = p.communicate()[0].split('\n') + for line in output: + if '[custom' in line: + entry = line[1:-1] + custom[entry] = {} + elif 'action' in line: + custom[entry]['action'] = line.split('=')[1] + elif 'binding' in line: + custom[entry]['binding'] = line.split('=')[1] + elif 'name' in line: + custom[entry]['name'] = line.split('=')[1] + return custom + def init_keys(self, dev_id, image, buttons, cmds): # remove previous stuff self.deleteItemsOfLayout(self.keysLayout.layout()) diff --git a/wacom-gui/stylus.py b/wacom-gui/stylus.py index 2f3c447..6d27f05 100644 --- a/wacom-gui/stylus.py +++ b/wacom-gui/stylus.py @@ -442,7 +442,7 @@ def __init__(self): self.eid = None self.cid = None self.settings = {} - self.displays = self.get_displays() + self.displays = None self.main = QVBoxLayout() self.lorient = QHBoxLayout() self.orient = QComboBox() @@ -469,9 +469,6 @@ def __init__(self): self.main.addWidget(self.mode_box) self.lscreen = QGridLayout() self.screen = QComboBox() - # get display info - self.screen.addItems(sorted(self.displays.keys())) - self.screen.currentIndexChanged.connect(self.update_screen) self.screen_lbl = QLabel("Screen: ") self.forced = QCheckBox("Force Proportions") self.forced.stateChanged.connect(self.update_forced) @@ -487,6 +484,11 @@ def initUI(self, stylus_id, eraser_id, settings={}): self.eid = eraser_id if 'mapping' in settings.keys(): self.settings = settings['mapping'] + # load displays + self.displays = self.get_displays() + # get display info + self.screen.addItems(sorted(self.displays.keys())) + self.screen.currentIndexChanged.connect(self.update_screen) # set rotation value if 'rotate' in self.settings.keys(): if self.settings['rotate'] == 'False': @@ -526,14 +528,7 @@ def initUI(self, stylus_id, eraser_id, settings={}): if self.settings['maptooutput'] in self.displays.keys(): idx = self.screen.findText(str(self.settings['maptooutput'])) self.screen.setCurrentIndex(idx) - self.update_screen() self.screen.setToolTip('[%s]' % self.displays[self.settings['maptooutput']]['cmd']) - else: - # TODO: check if this is working properly.. - self.displays['Partial...']['cmd'] = self.settings['maptooutput'] - self.screen.setToolTip('[%s]' % self.settings['maptooutput']) - self.screen.setCurrentIndex(self.screen.findText('Partial...')) - self.update_screen() else: self.settings['maptooutput'] = 'Full' # hack note @@ -609,13 +604,15 @@ def update_forced(self): def toggle_next(self): idx = self.screen.currentIndex() - if idx == 3: - idx = 0 - else: + if idx + 1 <= self.screen.__len__(): idx = idx + 1 - self.screen.setCurrentIndex(idx) + self.screen.setCurrentIndex(idx) + # if partial matches full screen, skip it + if str(self.screen.currentText()) == 'Partial...' and \ + self.displays['Full']['cmd'] == self.displays['Partial...']['cmd']: + self.screen.setCurrentIndex(0) self.settings['maptooutput'] = str(self.screen.currentText()) - self.update_screen() + # self.update_screen() def get_displays(self): displays = {} @@ -642,7 +639,11 @@ def get_displays(self): 'y': int(info[3]), 'xoff': int(info[4]), 'yoff': int(info[5])} - displays['Partial...'] = {'cmd': "%sx%s+0+0" % (full[0], full[1]), + if 'partial' in self.settings.keys(): + displays['Partial...'] = {'cmd': self.settings['partial']} + else: + self.settings['partial'] = "%sx%s+0+0" % (full[0], full[1]) + displays['Partial...'] = {'cmd': "%sx%s+0+0" % (full[0], full[1]), 'x': full[0], 'y': full[1], 'xoff': 0, diff --git a/wacom-gui/wacom-gui.py b/wacom-gui/wacom-gui.py index 9b7c371..3b33d09 100644 --- a/wacom-gui/wacom-gui.py +++ b/wacom-gui/wacom-gui.py @@ -626,6 +626,7 @@ def display(parent=None): dialog = About() result = dialog.exec_() + def parseArgs(): parser = argparse.ArgumentParser() parser.add_argument("-l", "--load", help="load configuration for device", action="store_true") @@ -633,7 +634,22 @@ def parseArgs(): return parser.parse_args() +def loadToggleShortcut(): + keys = os.popen("setxkbmap -query | grep options").read() + if keys.__len__() == 0: + os.popen("setxkbmap -option 'altwin:hyper_win'") + else: + keys = keys[8:].strip().split(',') + for idx, key in enumerate(keys): + if key.find('altwin') != -1 and key.find('hyper_win') == -1: + keys[idx] = "altwin:hyper_win" + keys = ",".join(map(str, keys)) + os.popen("setxkbmap -option") + os.popen("setxkbmap -option '" + keys + "'") + + def main(): + loadToggleShortcut() app = QApplication(sys.argv) form = WacomGui() opts = parseArgs() diff --git a/wacom-gui/wacom_data.py b/wacom-gui/wacom_data.py index e871d3f..5a292c5 100644 --- a/wacom-gui/wacom_data.py +++ b/wacom-gui/wacom_data.py @@ -45,7 +45,7 @@ def get_connected_tablets(self): try: for dev in dev_names: dev_attr = dev.rstrip().split("\t") - name = dev.split(' %s' % attr[dev_attr[2]])[0] + name = dev.rsplit(' %s' % attr[dev_attr[2]], 1)[0] if name[-3:] in ["Pen", "Pad"]: name = name[:-4] elif "Finger" == name[-6:]: