From 13d0f27d7db4dba85ddbedb8ff3072da05bfacd7 Mon Sep 17 00:00:00 2001 From: Suzanne Soy Date: Thu, 21 Jan 2021 21:58:20 +0000 Subject: [PATCH] 02021-01-20 stream --- .gitignore | 1 + GIMPCommand.py | 184 +++++++ Init.py | 0 InitGui.py | 72 +++ LICENSE | 1 + Resources2.py | 1406 ++++++++++++++++++++++++++++++++++++++++++++++++ Resources3.py | 1406 ++++++++++++++++++++++++++++++++++++++++++++++++ icon.xcf | Bin 0 -> 1400 bytes icons/GIMP.svg | 384 +++++++++++++ 9 files changed, 3454 insertions(+) create mode 100644 .gitignore create mode 100644 GIMPCommand.py create mode 100644 Init.py create mode 100644 InitGui.py create mode 100644 LICENSE create mode 100644 Resources2.py create mode 100644 Resources3.py create mode 100644 icon.xcf create mode 100644 icons/GIMP.svg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/GIMPCommand.py b/GIMPCommand.py new file mode 100644 index 0000000..c027feb --- /dev/null +++ b/GIMPCommand.py @@ -0,0 +1,184 @@ +import FreeCAD +import FreeCADGui as Gui +import subprocess +import PySide +import re +from PySide import QtGui +from PySide import QtCore + +class Tool(): + def __init__(self, name, *, start_command_and_args, xwininfo_filter_re, extra_xprop_filter): + self.name = name + self.start_command_and_args = start_command_and_args + self.xwininfo_filter_re = re.compile(xwininfo_filter_re) + self.extra_xprop_filter = extra_xprop_filter + +class Tools(): + def __init__(self, *tools): + self.__dict__ = {tool.name: tool for tool in tools} + def __getitem__(self, k): return self.__dict__[k] + +# tool-specific infos: +tools = Tools( + Tool('Mousepad', + start_command_and_args = ['mousepad', '--disable-server'], + xwininfo_filter_re = r'mousepad', + extra_xprop_filter = lambda processId, windowId, i: True), + Tool('Inkscape', + start_command_and_args = ['inkscape'], + xwininfo_filter_re = r'inkscape', + extra_xprop_filter = lambda processId, windowId, i: x11prop(windowId, 'WM_STATE', 'WM_STATE') is not None), + Tool('GIMP', + start_command_and_args = ['env', '-i', 'DISPLAY=:0', '/home/suzanne/perso/dotfiles/nix/result/bin/gimp', '--new-instance'], + xwininfo_filter_re = r'gimp', + extra_xprop_filter = lambda processId, windowId, i: x11prop(windowId, 'WM_STATE', 'WM_STATE') is not None)) + +class EmbeddedWindow(QtCore.QObject): + def __init__(self, tool, externalAppInstance, processId, windowId): + super(EmbeddedWindow, self).__init__() + self.tool = tool + self.externalAppInstance = externalAppInstance + self.processId = processId + self.windowId = windowId + self.mdi = Gui.getMainWindow().findChild(QtGui.QMdiArea) + self.xw = QtGui.QWindow.fromWinId(self.windowId) + self.xw.setFlags(QtGui.Qt.FramelessWindowHint) + self.xwd = QtGui.QWidget.createWindowContainer(self.xw) + self.mwx = QtGui.QMainWindow() + self.mwx.layout().addWidget(self.xwd) + self.mdiSub = self.mdi.addSubWindow(self.xwd) + self.xwd.setBaseSize(640,480) + self.mwx.setBaseSize(640,480) + self.mdiSub.setBaseSize(640,480) + self.mdiSub.setWindowTitle(tool.name) + self.mdiSub.show() + #self.xw.installEventFilter(self) + def eventFilter(self, obj, event): + # This doesn't seem to work, some events occur but no the close one. + if event.type() == QtCore.QEvent.Close: + mdiSub.close() + return False + + +# "" : +xwininfo_re = re.compile(r'^\s*([0-9]+)\s*"[^"]*"\s*:.*$') + +def x11stillAlive(windowId): + try: + subprocess.check_output(['xprop', '-id', str(windowId), '_NET_WM_PID']) + return True + except: + return False + +def x11prop(windowId, prop, type): + try: + output = subprocess.check_output(['xprop', '-id', str(windowId), prop]).decode('utf-8', 'ignore').split('\n') + except subprocess.CalledProcessError as e: + output = [] + xprop_re = re.compile(r'^' + re.escape(prop) + r'\(' + re.escape(type) + r'\)((:)| =(.*))$') + for line in output: + trymatch = xprop_re.match(line) + if trymatch: + return trymatch.group(2) or trymatch.group(3) + return None + +def try_pipe_lines(commandAndArguments): + try: + return subprocess.check_output(commandAndArguments).decode('utf-8', 'ignore').split('\n') + except: + return [] + +class ExternalApps(): + def __init__(self): + setattr(FreeCAD, 'ExternalApps', self) + +def deleted(widget): + """Detect RuntimeError: Internal C++ object (PySide2.QtGui.QWindow) already deleted.""" + try: + str(widget) # str fails on already-deleted Qt wrappers. + return False + except: + return True + +class ExternalAppInstance(QtCore.QObject): + def __init__(self, toolName): + super(ExternalAppInstance, self).__init__() + self.tool = tools[toolName] + # Start the application + # TODO: popen_process shouldn't be exposed to in-document scripts, it would allow them to redirect output etc. + print('Starting ' + ' '.join(self.tool.start_command_and_args)) + self.popen_process = subprocess.Popen(self.tool.start_command_and_args) + self.toolProcessIds = [self.popen_process.pid] + self.initWaitForWindow() + self.foundWindows = dict() + setattr(FreeCAD.ExternalApps, self.tool.name, self) + + def initWaitForWindow(self): + self.TimeoutHasOccurred = False # for other scritps to know the status + self.startupTimeout = 10000 + self.elapsed = QtCore.QElapsedTimer() + self.elapsed.start() + self.timer = QtCore.QTimer(self) + self.timer.timeout.connect(self.attemptToFindWindow) + + def waitForWindow(self): + self.timer.start(50) + + @QtCore.Slot() + def attemptToFindWindow(self): + try: + self.attemptToFindWindowWrapped() + except: + self.timer.stop() + raise + + def attemptToFindWindowWrapped(self): + # use decode('utf-8', 'ignore') to use strings instead of byte strings and discard ill-formed unicode in case these tool doesn't sanitize their output + for line in try_pipe_lines(['xwininfo', '-root', '-tree', '-int']): + if self.tool.xwininfo_filter_re.search(line): + windowId = int(xwininfo_re.match(line).group(1)) + # use decode('utf-8', 'ignore') to use strings instead of byte strings and discard ill-formed unicode in case this tool doesn't sanitize their output + xprop_try_process_id = x11prop(windowId, '_NET_WM_PID', 'CARDINAL') + if xprop_try_process_id: + processId = int(xprop_try_process_id) # TODO try parse int and catch failure + if processId in self.toolProcessIds: + if self.tool.extra_xprop_filter(processId, windowId, len(self.foundWindows)): + self.foundWindow(processId, windowId) + + if self.elapsed.elapsed() > self.startupTimeout: + self.timer.stop() + self.TimeoutHasOccurred = True + + def foundWindow(self, processId, windowId): + if windowId not in self.foundWindows.keys(): + self.foundWindows[windowId] = EmbeddedWindow(self.tool, self, processId, windowId) + # TODO: find an event instead of polling + for w in self.foundWindows.values(): + #if not deleted(xw) and not xw.isActive(): + if not x11stillAlive(w.windowId): + w.mdiSub.close() + +# prevent_garbage_collect by binding to a variable??? +#p = ExternalAppInstance('Mousepad') +#p = ExternalAppInstance('Inkscape') +ExternalApps() + +class GIMPCommand(): + def GetResources(self): + return { + 'Pixmap': ':/icons/GIMP.svg', + 'Accel': "Shit+G", + 'MenuText': "Menu text", + 'ToolTip': "Tooltip", + } + + def Activated(self): + print("Command activated") + p = ExternalAppInstance('GIMP') + p.waitForWindow() + + def IsActive(self): + # return false to grey out the command in the menus, toolbars etc. + return True + +Gui.addCommand('GIMPCommand', GIMPCommand()) diff --git a/Init.py b/Init.py new file mode 100644 index 0000000..e69de29 diff --git a/InitGui.py b/InitGui.py new file mode 100644 index 0000000..2cef9a6 --- /dev/null +++ b/InitGui.py @@ -0,0 +1,72 @@ +import sys + +class XternalAppsWorkbench(Workbench): + MenuText = "XternalApps" + ToolTip = "Embeds external Applications in FreeCAD" + Icon = """ + /* XPM */ + static char * icon_xpm[] = { + "16 16 15 1", + " c None", + ". c #FFFFFF", + "+ c #E8E5E5", + "@ c #897578", + "# c #9B8B8D", + "$ c #75575C", + "% c #C9C3C4", + "& c #FF89DA", + "* c #FF96DA", + "= c #FFA2DA", + "- c #FFACDA", + "; c #FFB2DA", + "> c #FFEAF3", + ", c #FFB9DA", + "' c #FF9DDA", + "................", + "..........+@....", + ".........#$%....", + "........$$$.....", + ".......%$$%.....", + ".......&%.......", + "......*&........", + ".....=&.........", + "....-&.....&....", + "...;&>....&&....", + "..,'&.....&&....", + "..&&.....&..&...", + ".........&&&&...", + "........&...&...", + ".......&.....&..", + "................"}; + """ + + def __init__(self): + super(self.__class__, self).__init__() + + def Initialize(self): + print('Initialize') + if sys.version_info[0] == 2: + import Resources2 + else: + import Resources3 + import GIMPCommand + # import commands + self.list = ['GIMPCommand'] + self.appendMenu("ExternalApplications", self.list) + self.appendToolbar("ExternalApplications", self.list) + + def Activated(self): + print('Activated') + pass + + def Deactivated(self): + print('Deactivated') + pass + + def ContextMenu(self): + pass + + def GetClassName(self): + return "Gui::PythonWorkbench" + +Gui.addWorkbench(XternalAppsWorkbench()) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a6f206a --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +The contents of this repository are released under the CC0, with the exception of the GIMP logo which comes from the GIMP project and is therefore under the GPL license. diff --git a/Resources2.py b/Resources2.py new file mode 100644 index 0000000..8af6c01 --- /dev/null +++ b/Resources2.py @@ -0,0 +1,1406 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created: Thu Jan 21 01:44:33 2021 +# by: The Resource Compiler for PySide2 (Qt v5.11.3) +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore + +qt_resource_data = b"\ +\x00\x00U\x5c\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a\ +\x0a \x0a \ +\x0a\ + \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \ +\x0a \x0a \ + \x0a \x0a \ +\x0a \x0a \x0a\ + \x0a \ +\x0a \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a <\ +stop\x0a st\ +yle=\x22stop-color:\ +#857c63;stop-opa\ +city:1\x22\x0a \ + offset=\x220\x22\x0a \ + id=\x22stop650\ +2\x22 />\x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a <\ +linearGradient\x0a \ + id=\x22linear\ +Gradient6452\x22>\x0a \ + \x0a \ +\x0a \x0a <\ +linearGradient\x0a \ + x1=\x226.3051\ +529\x22\x0a y1=\x22\ +23.362427\x22\x0a \ + x2=\x225.9846287\x22\ +\x0a y2=\x2231.5\ +7\x22\x0a id=\x22li\ +nearGradient6458\ +\x22\x0a xlink:h\ +ref=\x22#linearGrad\ +ient6452\x22\x0a \ + gradientUnits=\x22\ +userSpaceOnUse\x22 \ +/>\x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \x0a \x0a <\ +/defs>\x0a \x0a \ + \x0a \x0a \ + \x0a <\ +path\x0a d=\x22M\ + 36.96875,11.843\ +75 C 36.406772,1\ +2.770645 35.5622\ +58,13.876916 34.\ +28125,14.9375 C \ +31.649332,17.116\ +542 27.230687,19\ +.099847 20,19.28\ +125 C 15.775627,\ +19.386299 13.047\ +259,17.347101 11\ +.375,15.53125 L \ +11.25,20 C 11.38\ +6107,20.418802 1\ +1.665455,21.3904\ +98 11.1875,22.71\ +875 C 10.673186,\ +24.148046 9.0329\ +86,25.610113 6.2\ +1875,26.71875 C \ +6.4690804,27.240\ +783 6.7142345,27\ +.76237 7.46875,2\ +8.5 C 8.4967003,\ +29.504945 9.9257\ +833,30.588049 11\ +.625,31.5625 C 1\ +5.023433,33.5114\ +02 19.426583,35.\ +055712 23.53125,\ +35.125 C 27.6359\ +17,35.194288 31.\ +388376,33.89045 \ +33.96875,30.125 \ +C 36.347494,26.6\ +53782 37.651223,\ +20.777057 36.968\ +75,11.84375 z \x22\x0a\ + style=\x22op\ +acity:0.18539327\ +;color:black;fil\ +l:none;fill-opac\ +ity:1;fill-rule:\ +evenodd;stroke:u\ +rl(#linearGradie\ +nt8530);stroke-w\ +idth:0.9999997;s\ +troke-linecap:bu\ +tt;stroke-linejo\ +in:miter;marker:\ +none;marker-star\ +t:none;marker-mi\ +d:none;marker-en\ +d:none;stroke-mi\ +terlimit:10;stro\ +ke-dasharray:non\ +e;stroke-dashoff\ +set:0;stroke-opa\ +city:1;visibilit\ +y:visible;displa\ +y:inline;overflo\ +w:visible\x22\x0a \ + id=\x22path8520\x22 \ +/>\x0a \x0a <\ +path\x0a d=\x22M\ + 10.429825 27.22\ +8739 A 4.3310289\ + 6.0987959 0 1 1\ + 1.767767,27.22\ +8739 A 4.3310289\ + 6.0987959 0 1 1\ + 10.429825 27.2\ +28739 z\x22\x0a \ +transform=\x22matri\ +x(0.810984,-0.58\ +5069,0.585069,0.\ +810984,-14.77791\ +,6.947121)\x22\x0a \ + style=\x22color:\ +black;fill:url(#\ +radialGradient85\ +48);fill-opacity\ +:1;fill-rule:eve\ +nodd;stroke:blac\ +k;stroke-width:0\ +.9999997;stroke-\ +linecap:butt;str\ +oke-linejoin:mit\ +er;marker:none;m\ +arker-start:none\ +;marker-mid:none\ +;marker-end:none\ +;stroke-miterlim\ +it:10;stroke-das\ +harray:none;stro\ +ke-dashoffset:0;\ +stroke-opacity:1\ +;visibility:visi\ +ble;display:inli\ +ne;overflow:visi\ +ble\x22\x0a id=\x22\ +path5198\x22 />\x0a \ + \ +\x0a \x0a \x0a <\ +path\x0a d=\x22M\ + 23.157747 20.95\ +3165 A 1.767767 \ +1.767767 0 1 1 \ +19.622213,20.953\ +165 A 1.767767 1\ +.767767 0 1 1 2\ +3.157747 20.9531\ +65 z\x22\x0a tra\ +nsform=\x22matrix(0\ +.766666,0,0,0.76\ +6666,-2.556414,5\ +.029841)\x22\x0a \ + style=\x22color:bl\ +ack;fill:white;f\ +ill-opacity:1;fi\ +ll-rule:evenodd;\ +stroke:none;stro\ +ke-width:0.99999\ +97;stroke-lineca\ +p:butt;stroke-li\ +nejoin:miter;mar\ +ker:none;marker-\ +start:none;marke\ +r-mid:none;marke\ +r-end:none;strok\ +e-miterlimit:10;\ +stroke-dasharray\ +:none;stroke-das\ +hoffset:0;stroke\ +-opacity:1;visib\ +ility:visible;di\ +splay:inline;ove\ +rflow:visible\x22\x0a \ + id=\x22path43\ +61\x22 />\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \ +\x0a \x0a \x0a \ + \x0a \x0a <\ +path\x0a d=\x22M\ + 23.003067,31.73\ +6544 C 24.500439\ +,31.879636 25.85\ +2696,31.464331 2\ +6.41496,31.26249\ +7 C 26.513185,30\ +.707111 26.95151\ +2,29.64124 28.46\ +1048,29.571029 L\ + 27.930718,28.64\ +2952 C 27.930718\ +,28.642952 25.96\ +4077,29.990873 2\ +3.864854,30.3886\ +21 L 23.003067,3\ +1.736544 z \x22\x0a \ + style=\x22color\ +:black;fill:url(\ +#linearGradient4\ +330);fill-opacit\ +y:1;fill-rule:ev\ +enodd;stroke:non\ +e;stroke-width:0\ +.9999997;stroke-\ +linecap:butt;str\ +oke-linejoin:mit\ +er;marker:none;m\ +arker-start:none\ +;marker-mid:none\ +;marker-end:none\ +;stroke-miterlim\ +it:10;stroke-das\ +harray:none;stro\ +ke-dashoffset:0;\ +stroke-opacity:1\ +;visibility:visi\ +ble;display:inli\ +ne;overflow:visi\ +ble\x22\x0a id=\x22\ +path8532\x22 />\x0a <\ +/g>\x0a\x0a\ +" + +qt_resource_name = b"\ +\x00\x05\ +\x00o\xa6S\ +\x00i\ +\x00c\x00o\x00n\x00s\ +\x00\x08\ +\x0e#S\xa7\ +\x00G\ +\x00I\x00M\x00P\x00.\x00s\x00v\x00g\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/Resources3.py b/Resources3.py new file mode 100644 index 0000000..8af6c01 --- /dev/null +++ b/Resources3.py @@ -0,0 +1,1406 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created: Thu Jan 21 01:44:33 2021 +# by: The Resource Compiler for PySide2 (Qt v5.11.3) +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore + +qt_resource_data = b"\ +\x00\x00U\x5c\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a\ +\x0a \x0a \ +\x0a\ + \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \ +\x0a \x0a \ + \x0a \x0a \ +\x0a \x0a \x0a\ + \x0a \ +\x0a \x0a \x0a \ + \x0a \x0a\ + \x0a \x0a <\ +stop\x0a st\ +yle=\x22stop-color:\ +#857c63;stop-opa\ +city:1\x22\x0a \ + offset=\x220\x22\x0a \ + id=\x22stop650\ +2\x22 />\x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \ + \x0a \x0a \x0a <\ +linearGradient\x0a \ + id=\x22linear\ +Gradient6452\x22>\x0a \ + \x0a \ +\x0a \x0a <\ +linearGradient\x0a \ + x1=\x226.3051\ +529\x22\x0a y1=\x22\ +23.362427\x22\x0a \ + x2=\x225.9846287\x22\ +\x0a y2=\x2231.5\ +7\x22\x0a id=\x22li\ +nearGradient6458\ +\x22\x0a xlink:h\ +ref=\x22#linearGrad\ +ient6452\x22\x0a \ + gradientUnits=\x22\ +userSpaceOnUse\x22 \ +/>\x0a \x0a \x0a \ + \x0a \x0a \x0a \x0a \x0a \x0a <\ +/defs>\x0a \x0a \ + \x0a \x0a \ + \x0a <\ +path\x0a d=\x22M\ + 36.96875,11.843\ +75 C 36.406772,1\ +2.770645 35.5622\ +58,13.876916 34.\ +28125,14.9375 C \ +31.649332,17.116\ +542 27.230687,19\ +.099847 20,19.28\ +125 C 15.775627,\ +19.386299 13.047\ +259,17.347101 11\ +.375,15.53125 L \ +11.25,20 C 11.38\ +6107,20.418802 1\ +1.665455,21.3904\ +98 11.1875,22.71\ +875 C 10.673186,\ +24.148046 9.0329\ +86,25.610113 6.2\ +1875,26.71875 C \ +6.4690804,27.240\ +783 6.7142345,27\ +.76237 7.46875,2\ +8.5 C 8.4967003,\ +29.504945 9.9257\ +833,30.588049 11\ +.625,31.5625 C 1\ +5.023433,33.5114\ +02 19.426583,35.\ +055712 23.53125,\ +35.125 C 27.6359\ +17,35.194288 31.\ +388376,33.89045 \ +33.96875,30.125 \ +C 36.347494,26.6\ +53782 37.651223,\ +20.777057 36.968\ +75,11.84375 z \x22\x0a\ + style=\x22op\ +acity:0.18539327\ +;color:black;fil\ +l:none;fill-opac\ +ity:1;fill-rule:\ +evenodd;stroke:u\ +rl(#linearGradie\ +nt8530);stroke-w\ +idth:0.9999997;s\ +troke-linecap:bu\ +tt;stroke-linejo\ +in:miter;marker:\ +none;marker-star\ +t:none;marker-mi\ +d:none;marker-en\ +d:none;stroke-mi\ +terlimit:10;stro\ +ke-dasharray:non\ +e;stroke-dashoff\ +set:0;stroke-opa\ +city:1;visibilit\ +y:visible;displa\ +y:inline;overflo\ +w:visible\x22\x0a \ + id=\x22path8520\x22 \ +/>\x0a \x0a <\ +path\x0a d=\x22M\ + 10.429825 27.22\ +8739 A 4.3310289\ + 6.0987959 0 1 1\ + 1.767767,27.22\ +8739 A 4.3310289\ + 6.0987959 0 1 1\ + 10.429825 27.2\ +28739 z\x22\x0a \ +transform=\x22matri\ +x(0.810984,-0.58\ +5069,0.585069,0.\ +810984,-14.77791\ +,6.947121)\x22\x0a \ + style=\x22color:\ +black;fill:url(#\ +radialGradient85\ +48);fill-opacity\ +:1;fill-rule:eve\ +nodd;stroke:blac\ +k;stroke-width:0\ +.9999997;stroke-\ +linecap:butt;str\ +oke-linejoin:mit\ +er;marker:none;m\ +arker-start:none\ +;marker-mid:none\ +;marker-end:none\ +;stroke-miterlim\ +it:10;stroke-das\ +harray:none;stro\ +ke-dashoffset:0;\ +stroke-opacity:1\ +;visibility:visi\ +ble;display:inli\ +ne;overflow:visi\ +ble\x22\x0a id=\x22\ +path5198\x22 />\x0a \ + \ +\x0a \x0a \x0a <\ +path\x0a d=\x22M\ + 23.157747 20.95\ +3165 A 1.767767 \ +1.767767 0 1 1 \ +19.622213,20.953\ +165 A 1.767767 1\ +.767767 0 1 1 2\ +3.157747 20.9531\ +65 z\x22\x0a tra\ +nsform=\x22matrix(0\ +.766666,0,0,0.76\ +6666,-2.556414,5\ +.029841)\x22\x0a \ + style=\x22color:bl\ +ack;fill:white;f\ +ill-opacity:1;fi\ +ll-rule:evenodd;\ +stroke:none;stro\ +ke-width:0.99999\ +97;stroke-lineca\ +p:butt;stroke-li\ +nejoin:miter;mar\ +ker:none;marker-\ +start:none;marke\ +r-mid:none;marke\ +r-end:none;strok\ +e-miterlimit:10;\ +stroke-dasharray\ +:none;stroke-das\ +hoffset:0;stroke\ +-opacity:1;visib\ +ility:visible;di\ +splay:inline;ove\ +rflow:visible\x22\x0a \ + id=\x22path43\ +61\x22 />\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \ +\x0a \x0a \x0a \ + \x0a \x0a <\ +path\x0a d=\x22M\ + 23.003067,31.73\ +6544 C 24.500439\ +,31.879636 25.85\ +2696,31.464331 2\ +6.41496,31.26249\ +7 C 26.513185,30\ +.707111 26.95151\ +2,29.64124 28.46\ +1048,29.571029 L\ + 27.930718,28.64\ +2952 C 27.930718\ +,28.642952 25.96\ +4077,29.990873 2\ +3.864854,30.3886\ +21 L 23.003067,3\ +1.736544 z \x22\x0a \ + style=\x22color\ +:black;fill:url(\ +#linearGradient4\ +330);fill-opacit\ +y:1;fill-rule:ev\ +enodd;stroke:non\ +e;stroke-width:0\ +.9999997;stroke-\ +linecap:butt;str\ +oke-linejoin:mit\ +er;marker:none;m\ +arker-start:none\ +;marker-mid:none\ +;marker-end:none\ +;stroke-miterlim\ +it:10;stroke-das\ +harray:none;stro\ +ke-dashoffset:0;\ +stroke-opacity:1\ +;visibility:visi\ +ble;display:inli\ +ne;overflow:visi\ +ble\x22\x0a id=\x22\ +path8532\x22 />\x0a <\ +/g>\x0a\x0a\ +" + +qt_resource_name = b"\ +\x00\x05\ +\x00o\xa6S\ +\x00i\ +\x00c\x00o\x00n\x00s\ +\x00\x08\ +\x0e#S\xa7\ +\x00G\ +\x00I\x00M\x00P\x00.\x00s\x00v\x00g\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/icon.xcf b/icon.xcf new file mode 100644 index 0000000000000000000000000000000000000000..ec4cd93541dab8070e044e8d45214d42a0635482 GIT binary patch literal 1400 zcmcgsJCD;q5Z+zeA+Hn1@sN-x_IOBlMWjSRbO`Av5E4jNktU7LaU6>zJ~{SrDG+J5 zqdJL#hWZ-l?q|^Y7tqs&TfW)Y(nd;&nCSC-^Vk{hc$6rfp33uJB+t6N9)s+bAbtVd z0yxLxHc&tM%oqW32XKKpaIfT)cNh2#>_jNt36kkFoMo^X1@~U2p`V3A`6156^406N z#}wH$sqxg0!cLUNL-JAf<-t5#OhP$NCh_pFc`%BCWRj%vz^G0do%phAe!WA4Pqu`6 z()=iVK0oz?coxZC7uI6KDveG)i!&L|f^j&f6Uk^a4>M`a@N{js&n#y} zX~ug1-LZA#2k)aa$!F%;qRgp5({wekPyEFa&-Jv)Pe&U7agv8X#UEI_X>n=smc`o^ z-?8{jaQeEH+yJ2-RR2lIq1a>M8Up>u;?;&!cS49nd|YeutVU73yZEvtMrXcP{`-vQ zZ6@*-bMmGE*CKB)p*7i>;4rN{qq(I8{El`R2Pn_g4R8U}k?#Wg4AuLn-beL5Dgj)H zeuJ&lg@UnC-;^SCsT7(h5A=t+a*zdj^|hh`QAeQ_;NXC(&`P0|LM!;RGOY$^H9)HY zS^>Ne16-ugWETYVC~y&IZfODADNr4tJhwpg0@Vvthffz&{rdT@Hv98aFI$*Ri>;QL z=(S$9apMYf>l$qR4lOV%Vdmq3yKIH;iGwsMjWKDAYdxlo{|Q>e+8cinnuY(@YfIH7 jP_6d=Tw4!)E%BaO2CXfjd@t{KOAIb=T=_q7rfvKM2qfqn literal 0 HcmV?d00001 diff --git a/icons/GIMP.svg b/icons/GIMP.svg new file mode 100644 index 0000000..7504631 --- /dev/null +++ b/icons/GIMP.svg @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +