Package pytsonui
[hide private]
[frames] | no frames]

Source Code for Package pytsonui

  1  import os 
  2   
  3  from PythonQt.QtCore import QFile, QIODevice 
  4  from PythonQt.QtGui import (QIcon, QTabWidget, QSplitterHandle, QButtonGroup, 
  5                              QAction) 
  6   
  7  from PythonQt.QtUiTools import QUiLoader 
  8   
  9  import ts3lib 
 10  import ts3defines 
 11  import pytson 
 12  import ts3client 
 13   
 14   
15 -def ts3print(msg, level, channel, aid):
16 err = ts3lib.logMessage(msg, level, channel, aid) 17 if err != ts3defines.ERROR_ok: 18 print(msg)
19 20
21 -def setIcon(obj, iconpack, pluginicons=None):
22 """ 23 Sets the icon of a QWidget (if it has a property Icon) to an icon in the 24 iconpack represented by a variable which is acquired by the property 25 'pytsonicon' of the object. 26 If the property instead contains a string formated as 27 "octicons:filename.png", the icon is set to filename.png of the octicons 28 pack. 29 If no such property is available, nothing is done. 30 @param obj: the widget 31 @type obj: QWidget 32 @param iconpack: the iconpack 33 @type iconpack: ts3client.IconPack 34 @param pluginicons: callable which gets a string and either returns the 35 path to the image file or returns a QPixmap to set the icon property to; 36 defaults to None 37 @type pluginicons: Callable(str) -> str or QIcon 38 """ 39 if iconpack: 40 if hasattr(obj, "setIcon") and hasattr(obj, "pytsonicon"): 41 var = obj.pytsonicon 42 43 if var.startswith("octicons:"): 44 fname = os.path.join(pytson.getPluginPath("ressources", 45 "octicons", var.split(":")[1])) 46 if os.path.isfile(fname): 47 obj.setIcon(QIcon(fname)) 48 elif var.startswith("plugin:"): 49 if pluginicons: 50 ico = pluginicons(var.split(":")[1]) 51 if type(ico) is str: 52 obj.setIcon(QIcon(ico)) 53 else: 54 obj.setIcon(ico) 55 else: 56 obj.setIcon(QIcon(iconpack.icon(var)))
57 58
59 -def connectSignalSlotsByName(sender, receiver):
60 """ 61 Connects pythonqt signals by name 62 (receiver.on_<sender.objectname>_<signalname>) 63 @param sender: the sender of signals 64 @type sender: QObject 65 @param receiver: the receiver which has slots as callables defined 66 @type receiver: object 67 """ 68 for sig in dir(sender): 69 if type(getattr(sender, sig)).__name__ == "builtin_qt_signal": 70 if hasattr(receiver, 71 "on_%s_%s" % (sender.objectName, sig.split('(')[0])): 72 getattr(sender, sig).connect(getattr(receiver, 73 "on_%s_%s" % (sender.objectName, 74 sig.split('(')[0])))
75 76
77 -def retrieveWidgets(obj, parent, widgets, seticons=True, iconpack=None, 78 pluginicons=None):
79 """ 80 Retrieves widgets from a list and adds them as attribute to another object. 81 If defined, signals from widgets are connected by name to methods in obj. 82 @param obj: the object which will get the attributes added 83 @type obj: object 84 @param parent: the toplevel widget 85 @type parent: QWidget 86 @param widgets: a recursive (parent-relation of widgets) list of tuples, 87 defining which widgets should be added as attributes to obj. 88 The elements must be children of parent. First element of tuple must held 89 the widget's objectname. If second element is True, the widget will be 90 added as property (by objectname) to obj. Third element of the tuple are 91 the child widgets, which should be handled by setupui 92 @type widgets: list[tuple(str, bool, list(...))] 93 @param seticons: if True, icons will be set according to 94 the widgets 'pytsonicon' attribute 95 @type seticons: bool 96 @param iconpack: the iconpack 97 @type iconpack: ts3client.IconPack 98 @param pluginicons: callable which gets a string and either returns the 99 path to the image file or returns a QPixmap to set the icon property to; 100 defaults to None 101 @type pluginicons: Callable(str) -> str or QIcon 102 """ 103 if type(parent) is QTabWidget: 104 childs = [parent.widget(i) for i in range(0, parent.count)] 105 else: 106 childs = parent.children() 107 108 root = False 109 if seticons and not iconpack: 110 try: 111 iconpack = ts3client.IconPack.current() 112 iconpack.open() 113 root = True 114 except Exception as e: 115 iconpack = None 116 seticons = False 117 ts3print(pytson.tr("pytsonui", "Error loading iconpack: " 118 "{exception}").format(exception=e), 119 ts3defines.LogLevel.LogLevel_ERROR, 120 "pytsonui.retrieveWidgets.%s" % obj.objectName, 0) 121 122 names = [w[0] for w in widgets] 123 stores = [w[1] for w in widgets] 124 grchilds = [w[2] for w in widgets] 125 126 for c in childs: 127 if c.objectName in names: 128 i = names.index(c.objectName) 129 if stores[i]: 130 if hasattr(obj, names[i]): 131 raise Exception("Widget objectName %s is not unique" % 132 names[i]) 133 setattr(obj, names[i], c) 134 135 connectSignalSlotsByName(c, obj) 136 137 if seticons: 138 setIcon(c, iconpack, pluginicons) 139 140 retrieveWidgets(obj, c, grchilds[i], seticons, iconpack) 141 142 names.pop(i) 143 stores.pop(i) 144 grchilds.pop(i) 145 146 if len(names) == 0: 147 if root: 148 iconpack.close() 149 return 150 151 if root: 152 iconpack.close() 153 154 if len(names) != 0: 155 raise Exception("Malformed uifile, widgets not found: %s" % names)
156 157
158 -def retrieveAllWidgets(obj, parent, seticons=True, iconpack=None, 159 pluginicons=None):
160 """ 161 Retrieves all child widgets from a parent widget and adds them as attribute 162 to another object. If defined, signals from widgets are connected by name 163 to methods in obj. 164 @param obj: the object which will get the attributes added 165 @type obj: object 166 @param parent: the toplevel widget 167 @type parent: QWidget 168 @param seticons: if True, icons will be set according 169 to the widgets 'pytsonicon' attribute 170 @type seticons: bool 171 @param iconpack: the iconpack 172 @type iconpack: ts3client.IconPack 173 @param pluginicons: callable which gets a string and either returns the 174 path to the image file or returns a QPixmap to set the icon property to; 175 defaults to None 176 @type pluginicons: Callable(str) -> str or QIcon 177 """ 178 root = False 179 if seticons and not iconpack: 180 try: 181 iconpack = ts3client.IconPack.current() 182 iconpack.open() 183 root = True 184 except Exception as e: 185 iconpack = None 186 seticons = False 187 ts3print(pytson.tr("pytsonui", "Error loading iconpack: " 188 "{exception}").format(exception=e), 189 ts3defines.LogLevel.LogLevel_ERROR, 190 "pytsonui.retrieveAllWidgets.%s" % obj.objectName, 0) 191 192 for c in parent.children(): 193 if not c.isWidgetType(): 194 if (not isinstance(c, (QButtonGroup, QAction)) and 195 not c.inherits("QLayout")): 196 continue 197 198 if (c.objectName != "" and type(c) not in [QSplitterHandle] and 199 c.objectName not in ["qt_scrollarea_viewport", 200 "qt_scrollarea_hcontainer", 201 "qt_scrollarea_vcontainer", 202 "qt_spinbox_lineedit", 203 "qt_toolbox_toolboxbutton"]): 204 if not hasattr(obj, c.objectName): 205 setattr(obj, c.objectName, c) 206 207 connectSignalSlotsByName(c, obj) 208 209 if seticons: 210 setIcon(c, iconpack, pluginicons) 211 212 retrieveAllWidgets(obj, c, seticons, iconpack, pluginicons) 213 214 if root: 215 iconpack.close()
216 217
218 -class UiLoader(QUiLoader):
219 """ 220 QUILoader subclass to omit the parent widget from being recreated. 221 """ 222
223 - def __init__(self, main, parent=None, extraWidgets=None):
224 """ 225 Instantiate a new object 226 @param main: parent class which will be omitted 227 @type main: QWidget 228 @param parent: parent class; defaults to None 229 @type parent: QObject 230 @param extraWidgets: list of extra classes to be created, there must 231 be a constructor which takes only the parent object 232 @type extraWidgets: list(QWidget type) 233 """ 234 super().__init__(parent) 235 self.main = main 236 self.extraWidgets = extraWidgets
237
238 - def createWidget(self, clsname, parent=None, name=''):
239 if parent is None: 240 return self.main 241 else: 242 if self.extraWidgets: 243 for w in self.extraWidgets: 244 if w.__name__ == clsname: 245 obj = w(parent) 246 obj.setObjectName(name) 247 return obj 248 249 return QUiLoader.createWidget(self, clsname, parent, name)
250 251
252 -def setupUi(obj, uipath, widgets=None, seticons=True, iconpack=None, 253 pluginicons=None, extraWidgets=None):
254 """ 255 Loads a Qt designer file (.ui), creates the widgets defined in and adds 256 them as property to a given object. This internally calls retrieveWidgets, 257 so signals from widgets are connected by name to obj. 258 @param obj: The object which will act as parent of the loaded ui 259 (this object will receive a new layout) 260 @type obj: QWidget 261 @param uipath: the path to the Qt designer file 262 @type uipath: str 263 @param widgets: optional argument; a recursive (parent-relation of widgets) 264 list of tuples, defining which widgets should be added as attributes to 265 obj. See retrieveWidgets for details. 266 If you omit this or pass None, recursively all child widgets will be stored 267 @type widgets: list[tuple(str, bool, list(...))] or None 268 @param seticons: if True, widgets containing a string-property 269 called 'pytsonicon' will get the icon of a soundpack 270 (value of property = variable in soundpack) 271 @type seticons: bool 272 @param iconpack: if set, the iconpack will be used, if None, the current 273 iconpack is used 274 @type iconpack: ts3client.IconPack 275 @param pluginicons: callable which gets a string and either returns the 276 path to the image file or returns a QPixmap to set the icon property to; 277 defaults to None 278 @type pluginicons: Callable(str) -> str or QIcon 279 @param extraWidgets: list of extra classes to be created, there must be a 280 constructor which takes only the parent object 281 @type extraWidgets: list(QWidget type) 282 """ 283 root = False 284 if seticons and not iconpack: 285 try: 286 iconpack = ts3client.IconPack.current() 287 iconpack.open() 288 root = True 289 except Exception as e: 290 iconpack = None 291 seticons = False 292 ts3print(pytson.tr("pytsonui", "Error loading iconpack: " 293 "{exception}").format(exception=e), 294 ts3defines.LogLevel.LogLevel_ERROR, 295 "pytsonui.setupUi.%s" % obj.objectName, 0) 296 297 if os.path.isfile(uipath): 298 f = QFile(uipath) 299 if f.open(QIODevice.ReadOnly): 300 loader = UiLoader(obj, extraWidgets=extraWidgets) 301 ui = loader.load(f) 302 f.close() 303 304 if not ui: 305 raise Exception("Error creating widget from uifile: %s" % 306 loader.errorString()) 307 else: 308 raise Exception("Could not open uifile") 309 else: 310 raise Exception("Could not find uifile") 311 312 if widgets: 313 retrieveWidgets(obj, ui, widgets, seticons, iconpack, pluginicons) 314 else: 315 retrieveAllWidgets(obj, ui, seticons, iconpack, pluginicons) 316 317 if hasattr(obj, "parent") and obj.parent(): 318 par = obj.parent() 319 obj.move(par.window().frameGeometry.topLeft() + 320 par.window().rect.center() - obj.rect.center()) 321 322 if root: 323 iconpack.close()
324