commit 13d0f27d7db4dba85ddbedb8ff3072da05bfacd7 Author: Suzanne Soy Date: Thu Jan 21 21:58:20 2021 +0000 02021-01-20 stream 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 0000000..ec4cd93 Binary files /dev/null and b/icon.xcf differ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +