1 | #!/usr/bin/env python
|
---|
2 | # -*- coding: utf-8 -*-
|
---|
3 | #
|
---|
4 | # $Id: dassmodus.py 11432 2010-11-01 19:20:55Z pstorz $
|
---|
5 |
|
---|
6 |
|
---|
7 | from PyQt4 import QtGui, QtCore
|
---|
8 | from PyQt4.QtCore import *
|
---|
9 | from PyQt4.QtGui import *
|
---|
10 | from functools import partial
|
---|
11 |
|
---|
12 | import dassmodus.ui.schedule
|
---|
13 | import dassmodus.ui.onlinehelpdialog
|
---|
14 | import dassmodus.ui.messagesdialog
|
---|
15 | import dassmodus.ui.listselectdialog
|
---|
16 | import dassmodus.ui.baseconfwizard
|
---|
17 | import dassmodus.ui.fetchDCdialog
|
---|
18 | import dassmodus.ui.integrityCheckDialog
|
---|
19 | import dassmodus.ui.newdatacenterwizard
|
---|
20 | import dassmodus.ui.deploywizard
|
---|
21 |
|
---|
22 | from nosferatu.bacresources import *
|
---|
23 | from nosferatu.prettynames import PrettyNames
|
---|
24 | #from nosferatu.directive import *
|
---|
25 | #from nosferatu import configrules
|
---|
26 |
|
---|
27 | import logging
|
---|
28 |
|
---|
29 | logging.basicConfig(level=logging.DEBUG,
|
---|
30 | format='%(asctime)s %(levelname)s \t (%(module)s:%(lineno)d) %(message)s ',
|
---|
31 | #filename='vanHelsing.log',
|
---|
32 | filemode='w')
|
---|
33 |
|
---|
34 |
|
---|
35 | import sys
|
---|
36 | import os
|
---|
37 | import re
|
---|
38 | import platform
|
---|
39 | #import glob
|
---|
40 |
|
---|
41 | from dassmodus.ui.mainwindow import Ui_MainWindow as Dlg
|
---|
42 | import re
|
---|
43 |
|
---|
44 | import xmlrpclib
|
---|
45 |
|
---|
46 | import dassmodus.dragndrop
|
---|
47 |
|
---|
48 | import dassmodus.ui.qt_resources # for the icons
|
---|
49 |
|
---|
50 |
|
---|
51 | '''
|
---|
52 | find where our executable script is called from,as the templates dir is relative to that.
|
---|
53 | As we are running as py2exe on windows, we have to make these efforts:
|
---|
54 | see http://www.py2exe.org/index.cgi/WhereAmI
|
---|
55 | '''
|
---|
56 | def we_are_frozen():
|
---|
57 | """Returns whether we are frozen via py2exe.
|
---|
58 | This will affect how we find out where we are located."""
|
---|
59 |
|
---|
60 | return hasattr(sys, "frozen")
|
---|
61 |
|
---|
62 |
|
---|
63 | def module_path():
|
---|
64 | """ This will get us the program's directory,
|
---|
65 | even if we are frozen using py2exe"""
|
---|
66 |
|
---|
67 | if we_are_frozen():
|
---|
68 | return os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( )))
|
---|
69 | return os.path.dirname(unicode(__file__, sys.getfilesystemencoding( )))
|
---|
70 |
|
---|
71 | DASSMODUS_PATH = module_path()
|
---|
72 |
|
---|
73 | RXP_DATE = re.compile('.*\((.*)\)')
|
---|
74 |
|
---|
75 | #from nosferatu.directive import *
|
---|
76 |
|
---|
77 | __version__ = 0.1
|
---|
78 |
|
---|
79 | __revision__ = "$Rev: 11441 $".replace('$','').replace('Rev: ','.')
|
---|
80 |
|
---|
81 |
|
---|
82 | datestring = "$Date: 2011-02-10 15:00:43 +0100 (Do, 10 Feb 2011) $".replace('$','').replace('Date: ','')
|
---|
83 | m = RXP_DATE.match(datestring)
|
---|
84 | __date__ = '(' + m.group(1) + ')'
|
---|
85 |
|
---|
86 |
|
---|
87 |
|
---|
88 |
|
---|
89 | INTERNALLY_REFERENCED_ITEMS = set(['fileset',
|
---|
90 | 'client' ,
|
---|
91 | 'catalog',
|
---|
92 | 'messages',
|
---|
93 | 'schedule',
|
---|
94 | 'storage',
|
---|
95 | 'jobdefs',
|
---|
96 | 'pool',
|
---|
97 | 'incrementalbackuppool',
|
---|
98 | 'fullbackuppool',
|
---|
99 | 'differentialbackuppool',
|
---|
100 | 'job',
|
---|
101 | 'basejob',
|
---|
102 | 'device',
|
---|
103 | ])
|
---|
104 | BOOL_ITEMS = set([
|
---|
105 | 'store_bool',
|
---|
106 | 'store_runscript_bool',
|
---|
107 | ])
|
---|
108 |
|
---|
109 | logging.basicConfig(level=logging.DEBUG,
|
---|
110 | format='%(asctime)s %(levelname)s \t (%(module)s:%(lineno)d) %(message)s ',
|
---|
111 | filename='dassModus.log',
|
---|
112 | filemode='w')
|
---|
113 |
|
---|
114 | # create logger
|
---|
115 | logger = logging.getLogger("vanHelsing")
|
---|
116 | logger.setLevel(logging.DEBUG)
|
---|
117 |
|
---|
118 |
|
---|
119 |
|
---|
120 | logger.debug(QApplication.translate('Main','Started Main Program'))
|
---|
121 |
|
---|
122 |
|
---|
123 |
|
---|
124 | OUTPUTDIR = '/etc/bacula/'
|
---|
125 | #INPUTDIR = '/etc/bacula/'
|
---|
126 | INPUTDIR = ':/'
|
---|
127 |
|
---|
128 |
|
---|
129 | #Configurations = [] # global list of configuration objects
|
---|
130 | Datacenters = []
|
---|
131 |
|
---|
132 | #proxy = xmlrpclib.ServerProxy("http://bacula-devel:8000/")
|
---|
133 | class SafeTransportWithCert(xmlrpclib.SafeTransport):
|
---|
134 | # __cert_file = DFLT_CERTFILE
|
---|
135 | # __key_file = DFLT_KEYFILE
|
---|
136 | __cert_file = 'certs/client-cert.pem' # Replace with your PEM formatted key file
|
---|
137 | __key_file = 'certs/client-cert.pem' # Replace with your PEM formatted certificate file
|
---|
138 |
|
---|
139 | def make_connection(self,host):
|
---|
140 | host_with_cert = (host, {
|
---|
141 | 'key_file' : self.__key_file,
|
---|
142 | 'cert_file' : self.__cert_file
|
---|
143 | } )
|
---|
144 | return xmlrpclib.SafeTransport.make_connection(
|
---|
145 | self,host_with_cert)
|
---|
146 |
|
---|
147 |
|
---|
148 |
|
---|
149 | #server_url = 'https://bacula-devel:4443'
|
---|
150 | #transport = SafeTransportWithCert()
|
---|
151 | #proxy = xmlrpclib.ServerProxy(server_url,
|
---|
152 | # transport = transport)
|
---|
153 |
|
---|
154 | #print proxy.get_lsscsi()
|
---|
155 |
|
---|
156 | #name = 'bacula-sd.conf'
|
---|
157 | #filename = INPUTDIR + name
|
---|
158 | #outfile = OUTPUTDIR + name
|
---|
159 | #configstring = open(filename).read()
|
---|
160 | #sdconf = StorageDaemonConfig(configstring)
|
---|
161 | #writefile = open(outfile,'w')
|
---|
162 | #writefile.write(str(sdconf))
|
---|
163 |
|
---|
164 |
|
---|
165 | #name = ('bacula-fd.conf')
|
---|
166 | #filename = INPUTDIR + name
|
---|
167 | #outfile = OUTPUTDIR + name
|
---|
168 | #configstring = open(filename).read()
|
---|
169 | #fdconf = FileDaemonConfig(configstring)
|
---|
170 |
|
---|
171 |
|
---|
172 | #writefile = open(outfile,'w')
|
---|
173 | #writefile.write(str(fdconf))
|
---|
174 |
|
---|
175 |
|
---|
176 | #name = ('bconsole.conf')
|
---|
177 | #filename = INPUTDIR + name
|
---|
178 | #outfile = OUTPUTDIR + name
|
---|
179 |
|
---|
180 | #readfile = open(filename)
|
---|
181 | #configstring = readfile.read()
|
---|
182 | #conconf = ConsoleConfig(configstring)
|
---|
183 | #readfile.close()
|
---|
184 |
|
---|
185 | #writefile = open(outfile,'w')
|
---|
186 | #writefile.write(str(conconf))
|
---|
187 |
|
---|
188 |
|
---|
189 |
|
---|
190 | #name = 'bacula-dir.conf'
|
---|
191 | #filename = INPUTDIR + name
|
---|
192 | #outfile = OUTPUTDIR + name
|
---|
193 | #configstring = open(filename).read()
|
---|
194 | #dirconf = DirectorConfig(configstring)
|
---|
195 |
|
---|
196 |
|
---|
197 | #Configurations.append(dirconf)
|
---|
198 | #Configurations.append(sdconf)
|
---|
199 | #Configurations.append(fdconf)
|
---|
200 | #Configurations.append(conconf)
|
---|
201 | #writefile = open(outfile,'w')
|
---|
202 | #writefile.write(str(dirconf))
|
---|
203 |
|
---|
204 | #print dirconf
|
---|
205 |
|
---|
206 |
|
---|
207 |
|
---|
208 | #def bind(objectName, propertyName, type):
|
---|
209 | #
|
---|
210 | # def getter(self):
|
---|
211 | # return type(self.findChild(QObject, objectName).property(propertyName).toPyObject())
|
---|
212 | #
|
---|
213 | # def setter(self, value):
|
---|
214 | # self.findChild(QObject, objectName).setProperty(propertyName, QVariant(value))
|
---|
215 | #
|
---|
216 | # return property(getter, setter)
|
---|
217 | #
|
---|
218 |
|
---|
219 |
|
---|
220 |
|
---|
221 | class StorageItemCheckbox(QCheckBox):
|
---|
222 | def __init__(self, storageItem, label):
|
---|
223 | QCheckBox.__init__(self,label)
|
---|
224 | self.storageItem = storageItem
|
---|
225 |
|
---|
226 | class StorageItemLineEdit(QLineEdit):
|
---|
227 | def __init__(self, parentWidget, storageItem):
|
---|
228 | QCheckBox.__init__(self, parentWidget)
|
---|
229 | self.storageItem = storageItem
|
---|
230 |
|
---|
231 |
|
---|
232 | class StorageItemCombobox(QComboBox):
|
---|
233 | def __init__(self, storageItem):
|
---|
234 | QComboBox.__init__(self)
|
---|
235 | self.storageItem = storageItem
|
---|
236 |
|
---|
237 | class ResourceTreeWidgetItem(QTreeWidgetItem):
|
---|
238 | itemsList = [] # class variable
|
---|
239 | def __init__(self, Resource, headerlist):
|
---|
240 | self.Resource = Resource
|
---|
241 | #print "type:" , type(headerlist),"headerlist:" , headerlist
|
---|
242 |
|
---|
243 | self.itemsList.append(self)
|
---|
244 |
|
---|
245 | QTreeWidgetItem.__init__(self, headerlist)
|
---|
246 |
|
---|
247 | #TODO: Why does the treeview not use the standard fontsize?
|
---|
248 | #col = 0
|
---|
249 | #f = self.font(col)
|
---|
250 | #f.setPixelSize(14)
|
---|
251 | #self.setFont(col,f)
|
---|
252 | #col=1
|
---|
253 | #f = self.font(col)
|
---|
254 | #f.setBold(True)
|
---|
255 | #f.setPixelSize(14)
|
---|
256 | #self.setFont(col,f)
|
---|
257 | # fontsize end
|
---|
258 |
|
---|
259 | class ResourceListWidgetItem(QListWidgetItem):
|
---|
260 | def __init__(self, Resource):
|
---|
261 | self.Resource = Resource
|
---|
262 | QListWidgetItem.__init__(self,self.Resource.resourcetype+ ' ' +
|
---|
263 | self.Resource.getName())
|
---|
264 | #self.Resource.items_dict['name'].storage.value)
|
---|
265 | icon = QtGui.QIcon(":/icons/" + self.Resource.resourcetype + ".png")
|
---|
266 | self.setIcon(icon)
|
---|
267 |
|
---|
268 | class ResItemTableWidgetItem(QTableWidgetItem):
|
---|
269 | def __init__(self, ResItem):
|
---|
270 | self.ResItem = ResItem
|
---|
271 | QTableWidgetItem.__init__(self)
|
---|
272 |
|
---|
273 | class StorageItemPushButton(QPushButton):
|
---|
274 | def __init__(self, storageItem):
|
---|
275 | QPushButton.__init__(self)
|
---|
276 | self.storageItem = storageItem
|
---|
277 |
|
---|
278 | #class VHTreeWidget(QtGui.QTreeWidget):
|
---|
279 | # def __init__(self, parent):
|
---|
280 | # super(VHTreeWidget, self).__init__(parent)
|
---|
281 |
|
---|
282 |
|
---|
283 |
|
---|
284 |
|
---|
285 | #self.treeWidget = QtGui.QTreeWidget(self.verticalLayoutWidget_3)
|
---|
286 |
|
---|
287 | class MeinDialog(QtGui.QMainWindow, Dlg):
|
---|
288 |
|
---|
289 | def __init__(self):
|
---|
290 | QtGui.QDialog.__init__(self)
|
---|
291 | self.setupUi(self)
|
---|
292 | self.gridwidgets = []
|
---|
293 | self.onlinehelpdialog = dassmodus.ui.onlinehelpdialog.OnlinehelpDialog(self)
|
---|
294 |
|
---|
295 | # restore the applications settings
|
---|
296 | settings = QSettings()
|
---|
297 | #size = settings.value("MainWindows/Size",
|
---|
298 | # QVariant(QSize(600,500))).toSize()
|
---|
299 | #
|
---|
300 | #self.resize(size)
|
---|
301 | ##self.restoreGeometry(settings.value("Geometry").toByteArray())
|
---|
302 | #position = settings.value("MainWindow/Position",
|
---|
303 | # QVariant(QPoint(0,0))).toPoint()
|
---|
304 | #self.move(position)
|
---|
305 | #self.restoreState(settings.value("Mainwindow/State").toByteArray())
|
---|
306 |
|
---|
307 |
|
---|
308 | self.restoreGeometry(settings.value("Geometry").toByteArray())
|
---|
309 | self.onlinehelpdialog.restoreGeometry(settings.value("HelpWindowsGeometry").toByteArray())
|
---|
310 |
|
---|
311 | # restoring state end
|
---|
312 |
|
---|
313 |
|
---|
314 |
|
---|
315 |
|
---|
316 |
|
---|
317 |
|
---|
318 |
|
---|
319 | # statusbar
|
---|
320 | self.statusLabel = QLabel()
|
---|
321 | self.statusLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
|
---|
322 | self.statusBar.setSizeGripEnabled(False)
|
---|
323 | self.statusBar.addPermanentWidget(self.statusLabel)
|
---|
324 | self.statusPB = QProgressBar(self.statusBar)
|
---|
325 | self.statusPB.setMaximumWidth(200)
|
---|
326 | self.statusPB.setTextVisible(True)
|
---|
327 | self.statusBar.addPermanentWidget(self.statusPB)
|
---|
328 |
|
---|
329 | self.statusPB.setMinimum(0)
|
---|
330 | self.statusPB.setMaximum(10)
|
---|
331 |
|
---|
332 | self.statusBar.showMessage(self.tr("Welcome to the bacula configuration program"), 5000)
|
---|
333 |
|
---|
334 |
|
---|
335 |
|
---|
336 | #self.configsToTreeWidget()
|
---|
337 | #self.dirconfRoot = self.addConfigToTreeWidget(dirconf)
|
---|
338 | #self.sdconfRoot = self.addConfigToTreeWidget(sdconf)
|
---|
339 | #self.addConfigToTreeWidget(fdconf)
|
---|
340 | #self.addConfigToTreeWidget(conconf)
|
---|
341 | self.treeWidget.setMouseTracking(True)
|
---|
342 | self.treeWidget.setColumnCount(3)
|
---|
343 | self.treeWidget.resizeColumnToContents(0)
|
---|
344 | self.treeWidget.setAlternatingRowColors(False)
|
---|
345 |
|
---|
346 | self.treeWidget.sortByColumn(0, Qt.AscendingOrder)
|
---|
347 |
|
---|
348 |
|
---|
349 |
|
---|
350 | #self.treeWidget = VHTreeWidget(self.verticalLayoutWidget_3)
|
---|
351 | self.verticalLayout_3.addWidget(self.treeWidget)
|
---|
352 |
|
---|
353 |
|
---|
354 |
|
---|
355 |
|
---|
356 | #self.textEdit.setText('hallo')
|
---|
357 | #<print "started"
|
---|
358 | # signale connecten
|
---|
359 |
|
---|
360 | self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
|
---|
361 | self.connect(self.treeWidget,
|
---|
362 | QtCore.SIGNAL("customContextMenuRequested(const QPoint &)")
|
---|
363 | ,self.menuContextTree)
|
---|
364 |
|
---|
365 | self.connect(self.treeWidget,
|
---|
366 | QtCore.SIGNAL("itemClicked(QTreeWidgetItem *,int)"),
|
---|
367 | self.onTreeItemClick)
|
---|
368 | self.connect(self.treeWidget,
|
---|
369 | QtCore.SIGNAL("currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)"),
|
---|
370 | self.onTreeItemClick)
|
---|
371 |
|
---|
372 | self.modifyAction(self.actionSave, None, None, self.tr("save a local configuration file"), False)
|
---|
373 | self.connect(self.actionSave, SIGNAL("triggered()"), self.onSave)
|
---|
374 |
|
---|
375 | self.modifyAction(self.actionOpen, None, 'open', self.tr("load a local datacenter file"), False)
|
---|
376 | self.connect(self.actionOpen, SIGNAL("triggered()"), self.onActionOpen)
|
---|
377 | self.toolBar.addAction(self.actionOpen)
|
---|
378 |
|
---|
379 | self.modifyAction(self.actionFetch, None, 'repository', self.tr("fetch a configuration file from a server"), False)
|
---|
380 | self.connect(self.actionFetch, SIGNAL("triggered()"), self.onActionFetch)
|
---|
381 | self.toolBar.addAction(self.actionFetch)
|
---|
382 |
|
---|
383 | self.modifyAction(self.actionOpenHelp, None, 'help-contextual', self.tr("open the contextsensitive help window"), False)
|
---|
384 | self.connect(self.actionOpenHelp, SIGNAL("triggered()"), self.onOpenHelp)
|
---|
385 | self.toolBar.addAction(self.actionOpenHelp)
|
---|
386 |
|
---|
387 | self.modifyAction(self.actionCommit_to_server, None, None, self.tr("commmit a configuration file on a server"), False)
|
---|
388 | self.connect(self.actionCommit_to_server, SIGNAL("triggered()"), self.onActionCommit)
|
---|
389 |
|
---|
390 | self.modifyAction(self.actionQuit_2, None, None, self.tr("quit program"), False)
|
---|
391 | self.connect(self.actionQuit_2, SIGNAL("triggered()"), self.close)
|
---|
392 |
|
---|
393 | self.modifyAction(self.actionNew_Datacenter, None, 'datacenter_new', self.tr("create new Datacenter"), False)
|
---|
394 | self.connect(self.actionNew_Datacenter, SIGNAL("triggered()"), self.onActionNewDatacenter)
|
---|
395 | self.toolBar.addAction(self.actionNew_Datacenter)
|
---|
396 |
|
---|
397 |
|
---|
398 | self.modifyAction(self.actionAbout, None, None, self.tr("information about the program"), False)
|
---|
399 | self.statusBar.addAction(self.actionAbout)
|
---|
400 | self.toolBar.addAction(self.actionAbout)
|
---|
401 |
|
---|
402 | self.connect(self.actionAbout, SIGNAL("triggered()"), self.onActionAbout)
|
---|
403 |
|
---|
404 | self.treeWidget.setHeaderLabels([self.tr('Resourcetype'),self.tr('Name'),self.tr('Ref.')])
|
---|
405 |
|
---|
406 |
|
---|
407 | self.connect(self.referencesListWidget,
|
---|
408 | SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
|
---|
409 | self.onReferenceItemDoubleClicked
|
---|
410 | )
|
---|
411 | self.onlinehelpdialog.show()
|
---|
412 | # delete widgets from form
|
---|
413 | #self.label.setParent(None)
|
---|
414 | #self.textEdit.setParent(None)
|
---|
415 |
|
---|
416 | def okToQuit(self):
|
---|
417 | reply = QMessageBox.question(self,
|
---|
418 | self.tr("close dassModus"),
|
---|
419 | self.tr("Do you really want to quit"),
|
---|
420 | QMessageBox.Yes|QMessageBox.No | QMessageBox.Cancel)
|
---|
421 | if reply != QMessageBox.Yes:
|
---|
422 | return False
|
---|
423 | else:
|
---|
424 | return True
|
---|
425 |
|
---|
426 | def closeEvent(self, event):
|
---|
427 | if self.okToQuit():
|
---|
428 | settings = QSettings()
|
---|
429 | settings.setValue("Geometry",QVariant(self.saveGeometry()))
|
---|
430 | settings.setValue("HelpWindowsGeometry",QVariant(self.onlinehelpdialog.saveGeometry()))
|
---|
431 | #settings.setValue("MainWindow/Size", QVariant(self.size()))
|
---|
432 | #settings.setValue("MainWindow/Position", QVariant(self.pos()))
|
---|
433 | #settings.setValue("Mainwindow/State", QVariant(self.saveState()))
|
---|
434 | else:
|
---|
435 | event.ignore()
|
---|
436 |
|
---|
437 |
|
---|
438 |
|
---|
439 |
|
---|
440 |
|
---|
441 | def modifyAction(self, action, shortcut=None, icon=None,
|
---|
442 | tip=None, checkable=False ):
|
---|
443 | if icon is not None:
|
---|
444 | action.setIcon(QIcon(":/icons/%s.png" % icon))
|
---|
445 | if shortcut is not None:
|
---|
446 | action.setShortcut(shortcut)
|
---|
447 | if tip is not None:
|
---|
448 | action.setToolTip(tip)
|
---|
449 | action.setStatusTip(tip)
|
---|
450 | if checkable:
|
---|
451 | action.setCheckable(True)
|
---|
452 | return action
|
---|
453 |
|
---|
454 | def onOpenHelp(self):
|
---|
455 | self.onlinehelpdialog.show()
|
---|
456 |
|
---|
457 | def onActionAbout(self):
|
---|
458 | """Show about box"""
|
---|
459 | # TODO: do the Translation for this, maybe use QString (see PyQtBook, Page 515)s
|
---|
460 | QMessageBox.about(self,"About dassModus",
|
---|
461 | u"""
|
---|
462 | <b>dassModus v %s</b>
|
---|
463 | <p>
|
---|
464 | A GUI program to configure Bacula
|
---|
465 | <p>Copyright © 2010 <a href="http://www.dass-it.de/">dass IT GmbH</a><br>
|
---|
466 | <a href="http://www.dass-it.de/">http://www.dass-it.de</a>
|
---|
467 | <p>Händelstraße 25-29<br>
|
---|
468 | 50674 Köln <br>
|
---|
469 | Germany <br>
|
---|
470 | Phone: +49 221 3 56 56 66-0 <br>
|
---|
471 | <p>
|
---|
472 | Python %s - Qt %s - PyQt %s on %s
|
---|
473 | """ % (str(__version__) + __revision__ + '<br>' + __date__, platform.python_version(),
|
---|
474 | QT_VERSION_STR, PYQT_VERSION_STR, platform.system()
|
---|
475 | )
|
---|
476 | )
|
---|
477 |
|
---|
478 | def onActionDeployConfig(self, Resource):
|
---|
479 | server_url = 'https://bacula-old:4443'
|
---|
480 | transport = SafeTransportWithCert()
|
---|
481 | proxy = xmlrpclib.ServerProxy(server_url,
|
---|
482 | transport = transport)
|
---|
483 |
|
---|
484 | deploywizard = dassmodus.ui.deploywizard.deploywizard(proxy, str(Resource),Resource.longname, self )
|
---|
485 | deploywizard.exec_()
|
---|
486 |
|
---|
487 |
|
---|
488 | #server_url = 'https://bacula-old:4443'
|
---|
489 | #transport = SafeTransportWithCert()
|
---|
490 | #proxy = xmlrpclib.ServerProxy(server_url,
|
---|
491 | # transport = transport)
|
---|
492 | #OLD_CONFIG = proxy.get_conf('dir')
|
---|
493 | #proxy.set_conf('dir',str(Resource))
|
---|
494 | #print proxy.reload_director()
|
---|
495 |
|
---|
496 |
|
---|
497 | def onActionFetch(self):
|
---|
498 | availableDCs = proxy.list_datacenters()
|
---|
499 | DCdialog = dassmodus.ui.fetchDCdialog.FetchDCDialog( datacenterlist = availableDCs )
|
---|
500 |
|
---|
501 | if DCdialog.exec_():
|
---|
502 | selectedDC = unicode( DCdialog.listWidget.selectedItems()[0].text() )
|
---|
503 | DCdata = proxy.get_datacenter(selectedDC).data
|
---|
504 |
|
---|
505 | #TODO: write this to a temporary file, open this file
|
---|
506 |
|
---|
507 | #print availableDCs
|
---|
508 | # configstring = proxy.get_dirdconf()
|
---|
509 | # print "configstring:", configstring
|
---|
510 | # print str(configstring)
|
---|
511 | # dirconf = DirectorConfig(str(configstring))
|
---|
512 | # Configurations.append(dirconf)
|
---|
513 | # self.rebuildTreeWidget()
|
---|
514 |
|
---|
515 | def onActionCheckIntegrity(self, Resource):
|
---|
516 | '''
|
---|
517 | call the Datacenters own integrity checks and display the output
|
---|
518 | '''
|
---|
519 | dc = Resource
|
---|
520 | intcheckdlg = dassmodus.ui.integrityCheckDialog.IntegrityCheckDialog(self,dc.checkFileDaemonsIntegrity())
|
---|
521 | intcheckdlg.show()
|
---|
522 | #print dc.checkFileDaemonsIntegrity()
|
---|
523 | #print dc.checkStorageDaemonsIntegrity()
|
---|
524 |
|
---|
525 | def onActionNewDatacenter(self):
|
---|
526 | wizard = dassmodus.ui.newdatacenterwizard.newdatacenterwizard(DASSMODUS_PATH)
|
---|
527 | if wizard.exec_():
|
---|
528 | self.openDatacenterFile(wizard.filename)
|
---|
529 |
|
---|
530 | def onActionCommit(self):
|
---|
531 | #configstring = Configurations[0]
|
---|
532 | #print unicode(configstring)
|
---|
533 | #proxy.set_dirdconf(unicode(configstring))
|
---|
534 | pass
|
---|
535 |
|
---|
536 | def onRunentryEdit(self):
|
---|
537 | #print "onRunEntryEdi called"
|
---|
538 | #print self.sender().storageItem.runentry
|
---|
539 | rune = self.sender().storageItem.runentry
|
---|
540 | parentcfg = self.sender().storageItem.parentitem.parentresource.parentconfig
|
---|
541 |
|
---|
542 | dialog = dassmodus.ui.schedule.RunentryDialog(self,
|
---|
543 | runentry=rune,
|
---|
544 | parentconfig=parentcfg
|
---|
545 | )
|
---|
546 |
|
---|
547 | # get parent config to be able to find valid pools, storages, etc. to fill in comboboxes
|
---|
548 |
|
---|
549 |
|
---|
550 | if dialog.exec_():
|
---|
551 | print "yes" + str(self.sender().storageItem.runentry)
|
---|
552 | #else:
|
---|
553 | # print "no"
|
---|
554 |
|
---|
555 | def onMessageEntryEdit(self):
|
---|
556 | mesgDict = self.sender().storageItem.messageDict
|
---|
557 | dialog = dassmodus.ui.messagesdialog.MessagesDialog(self,
|
---|
558 | messagesTypesDict=mesgDict)
|
---|
559 | if dialog.exec_():
|
---|
560 | print "yes"# + str(self.sender().storageItem.runentry)
|
---|
561 | else:
|
---|
562 | print "no"
|
---|
563 |
|
---|
564 | def onAclEntryEdit(self):
|
---|
565 | sender = self.sender()
|
---|
566 | aclname = sender.storageItem.parentitem.name
|
---|
567 | if aclname == 'commandacl':
|
---|
568 | for cmd in commands.keys():
|
---|
569 | if not cmd in sender.storageItem.ACLDict:
|
---|
570 | sender.storageItem.ACLDict[cmd] = False
|
---|
571 | else:
|
---|
572 | parentconfig = self.sender().storageItem.parentitem.parentresource.parentconfig
|
---|
573 | aclresourcename = aclname.lower().replace('acl','') # FilesetACL -> fileset
|
---|
574 | availableresources = parentconfig.getResourcesListByResType(aclresourcename)
|
---|
575 | #cfgdict = {}
|
---|
576 | for res in availableresources:
|
---|
577 | #if not res.items_dict['name'].storage.value in sender.storageItem.ACLDict:
|
---|
578 | if not res.getName() in sender.storageItem.ACLDict:
|
---|
579 | sender.storageItem.ACLDict[res.getName()] = False
|
---|
580 |
|
---|
581 |
|
---|
582 | dialog = dassmodus.ui.listselectdialog.ListSelectDialog(self,
|
---|
583 | configDict = sender.storageItem.ACLDict,
|
---|
584 | title = 'Edit %s' % (aclname) )
|
---|
585 |
|
---|
586 |
|
---|
587 | #sender.storageItem.setValue(str(sender.storageItem))
|
---|
588 |
|
---|
589 | #.setValue( unicode(self.sender().text() ) )
|
---|
590 |
|
---|
591 | if dialog.exec_():
|
---|
592 | print "yes"# + str(self.sender().storageItem.runentry)
|
---|
593 | sender.storageItem.__ACLDict2value__()
|
---|
594 | else:
|
---|
595 | print "no"
|
---|
596 |
|
---|
597 | def processEventsCallback(self, info = None):
|
---|
598 | QtGui.QApplication.processEvents()
|
---|
599 | if info:
|
---|
600 | self.statusBar.showMessage(info)
|
---|
601 |
|
---|
602 |
|
---|
603 |
|
---|
604 |
|
---|
605 | def onActionOpen(self):
|
---|
606 |
|
---|
607 | #fd = QFileDialog(self)
|
---|
608 | #fd.setFileMode(QFileDialog.Directory)
|
---|
609 | filename = unicode(QFileDialog.getOpenFileName(self
|
---|
610 | ,self.tr('Open Datacenter file')
|
---|
611 | ,''
|
---|
612 | ,self.tr('dassModus datacenter .dmdz files (*.dmdz)'))
|
---|
613 | )
|
---|
614 |
|
---|
615 |
|
---|
616 | if filename:
|
---|
617 | self.openDatacenterFile(filename)
|
---|
618 |
|
---|
619 | # self.statusPB.setMinimum(0)
|
---|
620 | # self.statusPB.setMaximum(0)
|
---|
621 | #
|
---|
622 | # dc = DataCenter(filename, self.processEventsCallback )
|
---|
623 | # Datacenters.append(dc)
|
---|
624 | #
|
---|
625 | # self.statusPB.setMaximum(100)
|
---|
626 | #
|
---|
627 | # self.updateReferenceInformation()
|
---|
628 | # self.rebuildTreeWidget()
|
---|
629 | # self.treeWidget.expandToDepth(0)
|
---|
630 | # self.treeWidget.resizeColumnToContents(0)
|
---|
631 | # self.treeWidget.resizeColumnToContents(1)
|
---|
632 | #
|
---|
633 | # #self.statusPB.setEnabled(False)
|
---|
634 | # #pd.close()
|
---|
635 | # self.statusBar.clearMessage()
|
---|
636 | # self.statusPB.setMaximum(100)
|
---|
637 | # self.statusPB.setMinimum(0)
|
---|
638 |
|
---|
639 | def openDatacenterFile(self,filename):
|
---|
640 |
|
---|
641 | self.statusPB.setMinimum(0)
|
---|
642 | self.statusPB.setMaximum(0)
|
---|
643 |
|
---|
644 | dc = DataCenter(filename, self.processEventsCallback )
|
---|
645 | Datacenters.append(dc)
|
---|
646 |
|
---|
647 | self.statusPB.setMaximum(100)
|
---|
648 |
|
---|
649 | self.updateReferenceInformation()
|
---|
650 | self.rebuildTreeWidget()
|
---|
651 | self.treeWidget.expandToDepth(0)
|
---|
652 | self.treeWidget.resizeColumnToContents(0)
|
---|
653 | self.treeWidget.resizeColumnToContents(1)
|
---|
654 |
|
---|
655 | #self.statusPB.setEnabled(False)
|
---|
656 | #pd.close()
|
---|
657 | self.statusBar.clearMessage()
|
---|
658 | self.statusPB.setMaximum(100)
|
---|
659 | self.statusPB.setMinimum(0)
|
---|
660 |
|
---|
661 |
|
---|
662 | def datacentersToTreeWidget(self):
|
---|
663 |
|
---|
664 | dcs_to_create = set(Datacenters)
|
---|
665 | dc2treewidgetitem = {}
|
---|
666 | # check if there is already a toplevel item for this dc
|
---|
667 | for dc in Datacenters:
|
---|
668 | count = self.treeWidget.topLevelItemCount()
|
---|
669 | for i in range(count):
|
---|
670 | tli = self.treeWidget.topLevelItem(i)
|
---|
671 | if tli.Resource == dc:
|
---|
672 | dcs_to_create.remove(dc)
|
---|
673 | dc2treewidgetitem[dc] = tli
|
---|
674 |
|
---|
675 | # only add top treewidget for not existing datacenters
|
---|
676 | for dc in Datacenters:
|
---|
677 | #root = self.addDatacenterToTreeWidget(config)
|
---|
678 | if dc in dcs_to_create:
|
---|
679 | dcTWI = QTreeWidgetItem([self.tr('Datacenter'), unicode(dc.name)])
|
---|
680 | dcTWI.Resource = dc
|
---|
681 | icon = QtGui.QIcon(":/icons/datacenter.png")
|
---|
682 | dcTWI.setIcon(0,icon)
|
---|
683 | # TODO: why does treewidget not use standard fontsize?
|
---|
684 | #col = 0
|
---|
685 | #f = dcTWI.font(col)
|
---|
686 | #f.setPixelSize(14)
|
---|
687 | #dcTWI.setFont(col,f)
|
---|
688 | #col = 1
|
---|
689 | #f = dcTWI.font(col)
|
---|
690 | ## f.setBold(True)
|
---|
691 | #f.setPixelSize(14)
|
---|
692 | #dcTWI.setFont(col,f)
|
---|
693 | #font end
|
---|
694 | self.treeWidget.addTopLevelItem(dcTWI)
|
---|
695 | else:
|
---|
696 | dcTWI = dc2treewidgetitem[dc]
|
---|
697 |
|
---|
698 | for config in list(dc.directors) + list(dc.filedaemons) + list(dc.storagedaemons) + list(dc.consoles):
|
---|
699 | self.addConfigToDc(config, dcTWI)
|
---|
700 |
|
---|
701 | def addDatacenterToTreeWidget(self):
|
---|
702 | #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name])
|
---|
703 | #self.treeWidget.expandAll()
|
---|
704 | pass
|
---|
705 |
|
---|
706 |
|
---|
707 | def menuContextTree(self, point):
|
---|
708 | # Infos about the node selected.
|
---|
709 | index = self.treeWidget.indexAt(point)
|
---|
710 | if not index.isValid():
|
---|
711 | return
|
---|
712 | item = self.treeWidget.itemAt(point)
|
---|
713 | name = item.text(0) # The text of the node.
|
---|
714 | resource = item.Resource
|
---|
715 | # We build the menu.
|
---|
716 | menu=QtGui.QMenu(self)
|
---|
717 | #action=menu.addAction(name)
|
---|
718 | print "Contextmenu for:" + name + ':'
|
---|
719 |
|
---|
720 | if name == PrettyNames['client']:
|
---|
721 | actionCreateFDConfig = menu.addAction(self.tr("create FiledaemonConfig from ") + name)
|
---|
722 | self.connect(actionCreateFDConfig, SIGNAL("triggered()"),
|
---|
723 | partial(self.onActionCreateFDConfig, resource ) )
|
---|
724 |
|
---|
725 |
|
---|
726 | if hasattr(resource, 'validitemsset'):
|
---|
727 | for r in resource.validitemsset:
|
---|
728 | if r in MULTIPLE_ALLOWED_ITEMS_SET:
|
---|
729 | icon = QtGui.QIcon(":/icons/" + r + ".png")
|
---|
730 | actionAdd=menu.addAction(icon,'add' + PrettyNames[r])
|
---|
731 | actionAdd.setObjectName(r)
|
---|
732 | self.connect(actionAdd, SIGNAL("triggered()"), partial( self.onActionAdd, resource, r ) )
|
---|
733 |
|
---|
734 | elif hasattr(resource, 'validresourcesset'):
|
---|
735 | for r in resource.validresourcesset:
|
---|
736 | if r in MULTIPLE_RESOURCES_IN_DIRD:
|
---|
737 | icon = QtGui.QIcon(":/icons/" + r + ".png")
|
---|
738 | actionAdd=menu.addAction(icon, self.tr('add ') + PrettyNames[r])
|
---|
739 | actionAdd.setObjectName(r)
|
---|
740 | self.connect(actionAdd, SIGNAL("triggered()"), partial( self.onActionAdd, resource, r ) )
|
---|
741 |
|
---|
742 | # import a client snippet from the abcd
|
---|
743 | if name == 'DirectorConfig':
|
---|
744 | actionImportSnippet = menu.addAction( icon, 'import client snippet from autoconfiguration' )
|
---|
745 | self.connect(actionImportSnippet, SIGNAL("triggered()"), partial( self.onImportSnippet, resource) )
|
---|
746 |
|
---|
747 | # deploy configuration to director
|
---|
748 | actionDeployConfig = menu.addAction( icon, 'deploy configuration....' )
|
---|
749 | self.connect(actionDeployConfig, SIGNAL("triggered()"), partial( self.onActionDeployConfig, resource) )
|
---|
750 |
|
---|
751 |
|
---|
752 | if name == 'Datacenter':
|
---|
753 | # TODO: icons for these menu entries
|
---|
754 | actionCheckIntegrity = menu.addAction(self.tr("check integrity of Datacenter"))
|
---|
755 | self.connect(actionCheckIntegrity, SIGNAL("triggered()"),
|
---|
756 | partial(self.onActionCheckIntegrity, resource ) )
|
---|
757 |
|
---|
758 | actionSaveDatacenter = menu.addAction(self.tr("save Datacenter (") + resource.filename + ')')
|
---|
759 | self.connect(actionSaveDatacenter, SIGNAL("triggered()"),
|
---|
760 | partial(self.onActionSaveDc, resource ) )
|
---|
761 |
|
---|
762 | actionSaveDatacenterAs = menu.addAction(self.tr("save Datacenter as"))
|
---|
763 | self.connect(actionSaveDatacenterAs, SIGNAL("triggered()"),
|
---|
764 | partial(self.onActionSaveDcAs, resource ) )
|
---|
765 |
|
---|
766 |
|
---|
767 | menu.addSeparator()
|
---|
768 |
|
---|
769 | actionImportConfigurationFile = menu.addAction(self.tr("Import existing configuration file"))
|
---|
770 | self.connect(actionImportConfigurationFile, SIGNAL("triggered()"),
|
---|
771 | partial(self.onActionImportConfigFile, resource ) )
|
---|
772 |
|
---|
773 | actionExport = menu.addAction(self.tr("export ") + name)
|
---|
774 | self.connect(actionExport, SIGNAL("triggered()"),
|
---|
775 | partial(self.onActionExport, resource ) )
|
---|
776 |
|
---|
777 |
|
---|
778 | menu.addSeparator()
|
---|
779 | actionDelete = menu.addAction(self.tr("delete ") + name)
|
---|
780 | self.connect(actionDelete, SIGNAL("triggered()"),
|
---|
781 | partial(self.onActionDelete, resource ) )
|
---|
782 |
|
---|
783 |
|
---|
784 | menu.exec_(QtGui.QCursor.pos())
|
---|
785 |
|
---|
786 | def onActionImportConfigFile(self, datacenter):
|
---|
787 | filename = unicode(QFileDialog.getOpenFileName(self
|
---|
788 | ,self.tr('Import bacula configuration file')
|
---|
789 | ,''
|
---|
790 | ,self.tr('bacula configuration files (*.conf)'))
|
---|
791 | )
|
---|
792 | if filename:
|
---|
793 | print "open filename" + filename
|
---|
794 |
|
---|
795 | if filename.find('-fd.conf') != -1:
|
---|
796 | datacenter.importConfigurationFile(filename, 'filedaemon')
|
---|
797 |
|
---|
798 | elif filename.find('-sd.conf') != -1:
|
---|
799 | datacenter.importConfigurationFile(filename, 'storagedaemon')
|
---|
800 | elif filename.find('-dir.conf') != -1:
|
---|
801 | datacenter.importConfigurationFile(filename, 'director')
|
---|
802 | elif filename.find('bconsole.conf') != -1:
|
---|
803 | datacenter.importConfigurationFile(filename, 'console')
|
---|
804 | else:
|
---|
805 | # TODO: QMessageBox Error
|
---|
806 | QMessageBox.warning(self,
|
---|
807 | self.tr('Warning'),
|
---|
808 | self.tr('did not recognize the file format of file ' + filename)
|
---|
809 | )
|
---|
810 | self.datacentersToTreeWidget()
|
---|
811 | '''
|
---|
812 | TODO: ask for filetype (dir, fd, sd, console) or try all and look if it works?
|
---|
813 | '''
|
---|
814 |
|
---|
815 |
|
---|
816 |
|
---|
817 | def onActionExport(self, resource):
|
---|
818 | filename = unicode(QFileDialog.getSaveFileName(self
|
---|
819 | ,self.tr('Export configuration file')
|
---|
820 | ,resource.getName().strip('"')+'.conf'
|
---|
821 | )
|
---|
822 | )
|
---|
823 | if filename:
|
---|
824 | f = open(filename,'w')
|
---|
825 | f.write(str(resource))
|
---|
826 | f.close()
|
---|
827 |
|
---|
828 |
|
---|
829 |
|
---|
830 | def onActionSaveDcAs(self ,datacenter):
|
---|
831 | filename = unicode(QFileDialog.getSaveFileName(self
|
---|
832 | ,self.tr('save datacenter file as...')
|
---|
833 | ,datacenter.getName().strip('"')+'.dmdz'
|
---|
834 | )
|
---|
835 | )
|
---|
836 | if filename:
|
---|
837 | datacenter.setFileName(filename)
|
---|
838 | datacenter.safeDatacenter()
|
---|
839 |
|
---|
840 | def onActionSaveDc(self ,datacenter):
|
---|
841 | datacenter.safeDatacenter()
|
---|
842 |
|
---|
843 |
|
---|
844 | def onImportSnippet(self, resource):
|
---|
845 | filename = unicode(QFileDialog.getOpenFileName(self
|
---|
846 | ,self.tr('Import bacula client snippet from autoconfiguration daemon')
|
---|
847 | ,''
|
---|
848 | ,self.tr('bacula client configuration snippets (*.snippet)'))
|
---|
849 | )
|
---|
850 | if filename:
|
---|
851 | f = open(filename,'r')
|
---|
852 | snippet = f.read()
|
---|
853 | f.close()
|
---|
854 | #newres = resource.createResource('client')
|
---|
855 | resource.parse_configfile(snippet, None)
|
---|
856 | self.rebuildTreeWidget()
|
---|
857 |
|
---|
858 | def onActionAdd(self, resource, resname):
|
---|
859 |
|
---|
860 | newres = resource.createResource(resname)
|
---|
861 | wizard = dassmodus.ui.baseconfwizard.baseconfigwizard(newres,resource)
|
---|
862 | if wizard.exec_():
|
---|
863 | print "ok"
|
---|
864 | else:
|
---|
865 | resource.deleteResource(newres)
|
---|
866 | self.rebuildTreeWidget()
|
---|
867 | #self.sender().storageItem.setValue( unicode(self.sender().currentText() ) )
|
---|
868 |
|
---|
869 | def onActionDelete(self, resource):
|
---|
870 | print self.tr("deleting ") , resource
|
---|
871 | if hasattr(resource,'parentconfig'): # resource?
|
---|
872 | resource.parentconfig.deleteResource(resource)
|
---|
873 | del resource
|
---|
874 |
|
---|
875 | elif hasattr(resource,'parentdatacenter'): # resource?
|
---|
876 | resource.parentdatacenter.deleteConfiguration(resource)
|
---|
877 | #del resource
|
---|
878 |
|
---|
879 | else:
|
---|
880 | print "help me"
|
---|
881 | # BaculaConfig TODO!
|
---|
882 | #Configurations.remove(resource)
|
---|
883 | # del resource
|
---|
884 |
|
---|
885 | self.treeWidget.clear() # TODO: better remove the corresponding treewidgetitem
|
---|
886 | self.rebuildTreeWidget()
|
---|
887 |
|
---|
888 | def onActionCreateFDConfig(self, dirClient):
|
---|
889 | print self.tr("creating FD Config from ") , dirClient
|
---|
890 | newFdConfig = FileDaemonConfig('')
|
---|
891 | dirClient.parentconfig.parentdatacenter.filedaemons.add(newFdConfig)
|
---|
892 | newFdConfig.createFdConfigFromDirClient(dirClient) # copy relevant info from dirClient entry
|
---|
893 | #newFdConfig.filename = os.getcwd()+ newFdConfig.name +'-fd.conf'
|
---|
894 | newFdConfig.filename = os.getcwd()+ '/' + newFdConfig.name +'-fd.conf'
|
---|
895 | self.rebuildTreeWidget()
|
---|
896 |
|
---|
897 |
|
---|
898 |
|
---|
899 |
|
---|
900 | #def newClient(self):
|
---|
901 | # newres = dirconf.createResource('client')
|
---|
902 | # newres.items_dict['name'].storage.setValue('newclient')
|
---|
903 | # self.addResourcesToTreeWidget(self.dirconfRoot, [newres])
|
---|
904 | #
|
---|
905 | #def newJobDefs(self):
|
---|
906 | # newres = dirconf.createResource('jobdefs')
|
---|
907 | # newres.items_dict['name'].storage.setValue('newJobDefs')
|
---|
908 | # self.addResourcesToTreeWidget(self.dirconfRoot, [newres])
|
---|
909 | #
|
---|
910 | #def newDirector(self):
|
---|
911 | # newres = dirconf.createResource('director')
|
---|
912 | # newres.items_dict['name'].storage.setValue('newDirector')
|
---|
913 | # self.addResourcesToTreeWidget(self.dirconfRoot, [newres])
|
---|
914 |
|
---|
915 | def onSave(self):
|
---|
916 | for dc in Datacenters:
|
---|
917 | dc.writeDatacenter('/tmp/')
|
---|
918 |
|
---|
919 | #for conf in Configurations:a
|
---|
920 | # print "writing "+ conf.filename
|
---|
921 | # writefile = open(conf.filename,'w')
|
---|
922 | # #writefile = open(outfile,'w')
|
---|
923 | # writefile.write(str(conf))
|
---|
924 | # #print str(dirconf)
|
---|
925 | # writefile.close()
|
---|
926 |
|
---|
927 | def onTreeItemClick(self, item):
|
---|
928 |
|
---|
929 | #print item.Resource.onlinehelpURL
|
---|
930 | if hasattr(item,'Resource'):
|
---|
931 | if hasattr(item.Resource,'onlinehelpURL'):
|
---|
932 | self.onlinehelpdialog.loadURL(item.Resource.onlinehelpURL)
|
---|
933 |
|
---|
934 | if self.textEdit.isVisible(): # only create the config file if output is visible
|
---|
935 | self.textEdit.setText(unicode(item.Resource))
|
---|
936 |
|
---|
937 | self.addConfigItemsToItemsGroup(item.Resource)
|
---|
938 | self.updateReferencesItemsList(item.Resource)
|
---|
939 |
|
---|
940 | # TODO: this does not work (why?)
|
---|
941 | #if hasattr(item.Resource,'filename'):
|
---|
942 | # self.statusBar.showMessage(item.Resource.filename, 5000)
|
---|
943 |
|
---|
944 |
|
---|
945 |
|
---|
946 | #def onPushButton(self):
|
---|
947 | # print "PushButton"
|
---|
948 | # self.addConfigToTreeWidget(dirconf,None)
|
---|
949 | # #self.addDictToTreeWidget(myNewResDict,None)
|
---|
950 |
|
---|
951 | def rebuildTreeWidget(self):
|
---|
952 |
|
---|
953 | #self.treeWidget.clear()
|
---|
954 |
|
---|
955 | self.datacentersToTreeWidget()
|
---|
956 |
|
---|
957 | #self.configsToTreeWidget()
|
---|
958 |
|
---|
959 | #self.treeWidget.expandToDepth(0)
|
---|
960 | #self.treeWidget.resizeColumnToContents(0)
|
---|
961 | #self.treeWidget.resizeColumnToContents(1)
|
---|
962 | self.treeWidget.setAlternatingRowColors(False)
|
---|
963 | self.treeWidget.sortByColumn(0, Qt.AscendingOrder)
|
---|
964 | #self.treeWidget.expandAll()
|
---|
965 |
|
---|
966 | def addResourcesToTreeWidget( self, parentTreeItem, Resources ):
|
---|
967 | # check if we already have a treewidgetitem for this resource
|
---|
968 | resources2treewidgetitem = {}
|
---|
969 | resources_to_create = set(Resources)
|
---|
970 | # check if there is already a sibling item for this resource
|
---|
971 | #QtGui.QTreeWidgetItem.
|
---|
972 | count = parentTreeItem.childCount()
|
---|
973 | #print count
|
---|
974 | for res in Resources: # all resources
|
---|
975 | for i in range(count): # iterate over all siblings
|
---|
976 | tli = parentTreeItem.child(i)
|
---|
977 | if tli.Resource == res: # is there already a sibling representing res?
|
---|
978 | resources_to_create.remove(res)
|
---|
979 | resources2treewidgetitem[res]= tli
|
---|
980 |
|
---|
981 |
|
---|
982 | #logger.info(str(resources_to_create))
|
---|
983 | for res in Resources: # some Resources do not have a name (include, exclude, options...s)
|
---|
984 | try:
|
---|
985 | name = res.getName()
|
---|
986 | #name = res.items_dict['name'].storage.value.strip('"')
|
---|
987 | except:
|
---|
988 | name = ' ' # no name
|
---|
989 |
|
---|
990 | refcount = len(res.reflist)
|
---|
991 | # only add treewidget for not existing resources
|
---|
992 | if res in resources_to_create:
|
---|
993 | mytreeitem = ResourceTreeWidgetItem( res, [ PrettyNames[res.resourcetype], unicode(name), str(refcount)] )
|
---|
994 | parentTreeItem.addChild(mytreeitem)
|
---|
995 | icon = QtGui.QIcon(":/icons/" + res.resourcetype + ".png")
|
---|
996 | mytreeitem.setIcon(0,icon)
|
---|
997 | else:
|
---|
998 | mytreeitem = resources2treewidgetitem[res]
|
---|
999 |
|
---|
1000 | self.addResourcesToTreeWidget(mytreeitem, res.resources)
|
---|
1001 |
|
---|
1002 |
|
---|
1003 |
|
---|
1004 | def addConfigToTreeWidget(self,Resource):
|
---|
1005 | name = Resource.getName()
|
---|
1006 | #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name, Resource.filename])
|
---|
1007 | parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, unicode(name)] )
|
---|
1008 |
|
---|
1009 | parent.setStatusTip(0,QtCore.QString(Resource.filename))
|
---|
1010 | #parent.setToolTip(0,QtCore.QString(Resource.filename))
|
---|
1011 | #parent.setWhatsThis(0,QtCore.QString(Resource.filename))
|
---|
1012 | icon = QtGui.QIcon(":/icons/config.png")
|
---|
1013 | parent.setIcon(0,icon)
|
---|
1014 | #if Resource.__class__.__name__ == 'DirectorConfig':
|
---|
1015 | # self.resGroupingTreeItems = {} # which resource types are grouped under DirectorConfig?
|
---|
1016 |
|
---|
1017 | self.treeWidget.addTopLevelItem(parent)
|
---|
1018 | self.addResourcesToTreeWidget(parent, Resource.resources)
|
---|
1019 | return parent
|
---|
1020 |
|
---|
1021 |
|
---|
1022 | def addConfigToDc(self, Resource, DcTreeWidgetItem):
|
---|
1023 |
|
---|
1024 | parent = None
|
---|
1025 | count = DcTreeWidgetItem.childCount()
|
---|
1026 | #QtGui.QTreeWidgetItem.child(int)
|
---|
1027 | for i in range (count):
|
---|
1028 | if DcTreeWidgetItem.child(i).Resource == Resource:
|
---|
1029 | parent = DcTreeWidgetItem.child(i)
|
---|
1030 |
|
---|
1031 | if not parent:
|
---|
1032 | name = Resource.getName().strip('"') # remove quotation marks
|
---|
1033 | #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name, Resource.filename])
|
---|
1034 | parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, unicode(name) ])
|
---|
1035 |
|
---|
1036 | parent.setStatusTip(0,QtCore.QString(Resource.filename))
|
---|
1037 | #parent.setToolTip(0,QtCore.QString(Resource.filename))
|
---|
1038 | #parent.setWhatsThis(0,QtCore.QString(Resource.filename))
|
---|
1039 | #icon = QtGui.QIcon(":/icons/config.png")
|
---|
1040 | #print Resource.__class__.__name__.replace('Config','').lower()
|
---|
1041 | icon = QtGui.QIcon(":/icons/" + Resource.__class__.__name__.replace('Config','').lower() +".png")
|
---|
1042 |
|
---|
1043 | parent.setIcon(0,icon)
|
---|
1044 | #if Resource.__class__.__name__ == 'DirectorConfig':
|
---|
1045 | # self.resGroupingTreeItems = {} # which resource types are grouped under DirectorConfig?
|
---|
1046 | DcTreeWidgetItem.addChild(parent)
|
---|
1047 | #self.treeWidget.addTopLevelItem(parent)
|
---|
1048 | self.addResourcesToTreeWidget(parent, Resource.resources)
|
---|
1049 | return parent
|
---|
1050 |
|
---|
1051 |
|
---|
1052 |
|
---|
1053 |
|
---|
1054 |
|
---|
1055 |
|
---|
1056 |
|
---|
1057 |
|
---|
1058 |
|
---|
1059 |
|
---|
1060 |
|
---|
1061 | def onCheckboxChecked(self):
|
---|
1062 | print "checkbox was checked by:" , self.sender().objectName() , "to:" , self.sender().isChecked()
|
---|
1063 | self.sender().storageItem.setValue( self.sender().isChecked() )
|
---|
1064 |
|
---|
1065 | def onComboboxChanged(self):
|
---|
1066 | print "combobox was changed by:" , self.sender().objectName() , "to:" , self.sender().currentText()
|
---|
1067 | self.sender().storageItem.setValue( unicode(self.sender().currentText() ) )
|
---|
1068 |
|
---|
1069 | def onLineEditChanged(self):
|
---|
1070 | print "LineEdit was changed by:" , self.sender().objectName() , "to:" , self.sender().text()
|
---|
1071 | self.sender().storageItem.setValue( unicode(self.sender().text() ) )
|
---|
1072 |
|
---|
1073 | def onReferenceItemDoubleClicked(self,item):
|
---|
1074 | print "RefItemClicked:" , ":" , item.text(), item.Resource
|
---|
1075 | for ResTreeItem in ResourceTreeWidgetItem.itemsList:
|
---|
1076 | if ResTreeItem.Resource == item.Resource:
|
---|
1077 | self.treeWidget.setCurrentItem(ResTreeItem)
|
---|
1078 | #TODO: Find the right TreeWidgetItem and activate it
|
---|
1079 |
|
---|
1080 | def onFileListItemDoubleClicked(self,item):
|
---|
1081 | print "FileItemClicked:" , ":" , item.text()
|
---|
1082 | item.editItem(item)
|
---|
1083 |
|
---|
1084 | #for ResTreeItem in ResourceTreeWidgetItem.itemsList:
|
---|
1085 | # if ResTreeItem.Resource == item.Resource:
|
---|
1086 | # self.treeWidget.setCurrentItem(ResTreeItem)
|
---|
1087 |
|
---|
1088 |
|
---|
1089 | def updateReferenceInformation(self):
|
---|
1090 | """
|
---|
1091 | iterate over all resources and update the
|
---|
1092 | reference information accordingly
|
---|
1093 | """
|
---|
1094 | for dc in Datacenters:
|
---|
1095 | for config in list(dc.directors) + list(dc.filedaemons) + list(dc.storagedaemons) + list(dc.consoles):
|
---|
1096 | for res in config.resources:
|
---|
1097 | reflist = config.getReferencingResourcesListForResource(res)
|
---|
1098 | res.reflist = reflist
|
---|
1099 | #print '\n',res.resourcetype, res.items_dict['name'].storage.value,"is referenced", len(reflist),"times:"
|
---|
1100 | #for refres in reflist:
|
---|
1101 | # print refres.resourcetype, refres.items_dict['name'].storage.value
|
---|
1102 |
|
---|
1103 | def updateReferencesItemsList(self,Resource):
|
---|
1104 | self.referencesListWidget.clear()
|
---|
1105 | for r in Resource.reflist:
|
---|
1106 | #icon = QtGui.QIcon(":/icons/" + r.resourcetype + ".png")
|
---|
1107 | ListWidgetItem = ResourceListWidgetItem(r)
|
---|
1108 | #QtGui.QListWidgetItem(r.resourcetype+ ' ' + r.items_dict['name'].storage.value)
|
---|
1109 | #ListWidgetItem.setIcon(icon)
|
---|
1110 | self.referencesListWidget.addItem(ListWidgetItem)
|
---|
1111 |
|
---|
1112 |
|
---|
1113 |
|
---|
1114 | def addConfigItemsToItemsGroup(self,Resource):
|
---|
1115 |
|
---|
1116 | #cleanup widgets
|
---|
1117 | for widget in self.gridwidgets:
|
---|
1118 | self.gridLayout_2.removeWidget(widget)
|
---|
1119 | widget.setParent(None)
|
---|
1120 | self.gridwidgets = []
|
---|
1121 | #TODO: do this depending on the type, ignore for Configs
|
---|
1122 | if not hasattr(Resource,'items'):
|
---|
1123 | return
|
---|
1124 |
|
---|
1125 | row = 0
|
---|
1126 |
|
---|
1127 | # special treatment of file entries
|
---|
1128 | if Resource.shortname == 'include': # is the same as exclude
|
---|
1129 | newlabel = QtGui.QLabel(self.scrollAreaWidgetContents)
|
---|
1130 | newlabel.setText('Files')
|
---|
1131 | self.gridLayout_2.addWidget(newlabel, row, 0, 1, 1)
|
---|
1132 | self.gridwidgets.append(newlabel)
|
---|
1133 |
|
---|
1134 | filelistWidget = dassmodus.dragndrop.DnDListWidget()
|
---|
1135 | self.gridwidgets.append(filelistWidget)
|
---|
1136 | self.gridLayout_2.addWidget(filelistWidget, row, 1, 1, 1)
|
---|
1137 | for f in Resource.getItemsListByItemName('file'):
|
---|
1138 | if f.print_item():
|
---|
1139 | fileListWidgetItem = QtGui.QListWidgetItem(unicode(f.storage.value).rstrip('"').lstrip('"'))
|
---|
1140 |
|
---|
1141 | self.connect( filelistWidget,
|
---|
1142 | SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
|
---|
1143 | self.onFileListItemDoubleClicked
|
---|
1144 | )
|
---|
1145 | #print Resource.items_dict
|
---|
1146 | icon = QIcon(":/icons/" + Resource.resourcetype + "file.png")
|
---|
1147 | fileListWidgetItem.setIcon(icon)
|
---|
1148 | filelistWidget.addItem(fileListWidgetItem)
|
---|
1149 | row += 1
|
---|
1150 |
|
---|
1151 | #TODO: create a ListWidget on the fileset level containing both include and exclude with +/- icons
|
---|
1152 | # in order to view all included and excluded things at once
|
---|
1153 |
|
---|
1154 |
|
---|
1155 |
|
---|
1156 |
|
---|
1157 |
|
---|
1158 | for item in Resource.items:
|
---|
1159 |
|
---|
1160 | if item.name == 'file':
|
---|
1161 | continue
|
---|
1162 | # clear
|
---|
1163 |
|
---|
1164 | # items manually added to horizontallayout
|
---|
1165 |
|
---|
1166 | if item.print_item() or self.showAllCheckBox.isChecked(): # only print configured or required items
|
---|
1167 |
|
---|
1168 | newlabel = QtGui.QLabel(self.scrollAreaWidgetContents)
|
---|
1169 | labeltext = PrettyNames[item.name]
|
---|
1170 | # show job items that are inherited from jobdefs
|
---|
1171 | if hasattr(item.parentresource,'shortname') and item.parentresource.shortname == 'job':
|
---|
1172 | jobdef = False
|
---|
1173 | jobdefname = item.parentresource.getItemValue('jobdefs')
|
---|
1174 | #jobdefname = item.parentresource.items_dict['jobdefs'].storage.value
|
---|
1175 |
|
---|
1176 | if jobdefname is not None:
|
---|
1177 | print "jobdefs is set:" + str(jobdefname)
|
---|
1178 | jobdef = True
|
---|
1179 |
|
---|
1180 | else:
|
---|
1181 | print "jobdefs is not set:" + str(item.parentresource.items_dict['jobdefs'].storage)
|
---|
1182 | jobdef = False
|
---|
1183 |
|
---|
1184 | if jobdef and item.storage.value == item.defaultvalue:
|
---|
1185 | jobdefs = item.parentresource.parentconfig.getResourceByName( jobdefname )
|
---|
1186 | if jobdefs.items_dict[item.name].storage.value != jobdefs.items_dict[item.name].defaultvalue:
|
---|
1187 | #print '>' + jobdefs.items_dict[item.name].storage.value + '<'
|
---|
1188 | #labeltext = PrettyNames[item.name] + ' (' + jobdefname + '->' + jobdefs.items_dict[item.name].storage.value + ' )'
|
---|
1189 | #labeltext = PrettyNames[item.name] + ' (' + jobdefs.items_dict[item.name].storage.value + ')'
|
---|
1190 | labeltext = PrettyNames[item.name] + ' (' + jobdefs.getName() + ')'
|
---|
1191 |
|
---|
1192 | newlabel.setText(labeltext)
|
---|
1193 |
|
---|
1194 | self.gridLayout_2.addWidget(newlabel, row, 0, 1, 1)
|
---|
1195 | self.gridwidgets.append(newlabel)
|
---|
1196 |
|
---|
1197 | font = QtGui.QFont()
|
---|
1198 |
|
---|
1199 | # bold means: item will be printed
|
---|
1200 | if item.print_item():
|
---|
1201 | font.setWeight(75)
|
---|
1202 | font.setBold(True)
|
---|
1203 | newlabel.setFont(font)
|
---|
1204 | newlabel.setToolTip(self.tr('item will be printed'))
|
---|
1205 |
|
---|
1206 | # Italic means: item is required
|
---|
1207 | if item.required:
|
---|
1208 | font.setWeight(50)
|
---|
1209 | font.setItalic(True)
|
---|
1210 | font.setUnderline(True)
|
---|
1211 | newlabel.setFont(font)
|
---|
1212 | newlabel.setToolTip(self.tr('item is required'))
|
---|
1213 |
|
---|
1214 | if item.storage.__class__.__name__ in BOOL_ITEMS:
|
---|
1215 | newcheckbox = StorageItemCheckbox(item.storage, unicode(item.storage.value))
|
---|
1216 |
|
---|
1217 | #newcheckbox = QtGui.QCheckBox(str(item.storage.value))
|
---|
1218 | self.gridLayout_2.addWidget(newcheckbox, row, 1, 1, 1)
|
---|
1219 | newcheckbox.setObjectName(item.name)
|
---|
1220 |
|
---|
1221 | newcheckbox.setChecked( bool(item.storage.value) )
|
---|
1222 | self.gridwidgets.append(newcheckbox)
|
---|
1223 |
|
---|
1224 | self.connect( newcheckbox,
|
---|
1225 | SIGNAL("toggled(bool)"),
|
---|
1226 | self.onCheckboxChecked )
|
---|
1227 |
|
---|
1228 |
|
---|
1229 | elif item.name == 'run': # Schedule "Run" entries
|
---|
1230 | # 'String input'
|
---|
1231 | newlineedit = StorageItemLineEdit(self.scrollAreaWidgetContents,
|
---|
1232 | item.storage)#QtGui.QLineEdit(self.scrollAreaWidgetContents)
|
---|
1233 | newlineedit.setText(unicode(item.storage.value))
|
---|
1234 |
|
---|
1235 | self.gridLayout_2.addWidget(newlineedit, row, 1, 1, 1)
|
---|
1236 | self.gridwidgets.append(newlineedit)
|
---|
1237 | self.connect( newlineedit,
|
---|
1238 | SIGNAL("returnPressed()"),
|
---|
1239 | self.onLineEditChanged )
|
---|
1240 | self.connect( newlineedit,
|
---|
1241 | SIGNAL("editingFinished()"),
|
---|
1242 | self.onLineEditChanged )
|
---|
1243 |
|
---|
1244 | # add a Button to edit the run entry (with own dialog)
|
---|
1245 | newbutton = StorageItemPushButton(item.storage)
|
---|
1246 | newbutton.setText(self.tr('Edit...'))
|
---|
1247 | self.gridwidgets.append(newbutton)
|
---|
1248 |
|
---|
1249 | self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1)
|
---|
1250 | self.connect( newbutton,
|
---|
1251 | SIGNAL("clicked()"),
|
---|
1252 | self.onRunentryEdit )
|
---|
1253 |
|
---|
1254 |
|
---|
1255 |
|
---|
1256 | elif item.name in INTERNALLY_REFERENCED_ITEMS:
|
---|
1257 | newcombobox = StorageItemCombobox(item.storage)
|
---|
1258 | newcombobox.setObjectName(item.name)
|
---|
1259 | #QtGui.QComboBox()
|
---|
1260 |
|
---|
1261 | newcombobox.addItem(unicode(item.storage.value))
|
---|
1262 | #newcombobox.addItem(unicode(item.storage.value.strip('"')))
|
---|
1263 | #QtGui.QComboBox.currentIndexChanged(*types name=str)
|
---|
1264 |
|
---|
1265 | restype = item.name
|
---|
1266 | if restype.endswith('pool'):
|
---|
1267 | restype = 'pool'
|
---|
1268 | if restype.endswith('job'):
|
---|
1269 | restype = 'job'
|
---|
1270 |
|
---|
1271 | for r in Resource.parentconfig.getResourcesListByResType(restype):
|
---|
1272 | if newcombobox.findText(QString(r.getName())) == -1:
|
---|
1273 | newcombobox.addItem(r.getName())
|
---|
1274 | #newcombobox.addItem(r.items_dict['name'].storage.value)
|
---|
1275 | #newcombobox.setText(str(item.storage.value))
|
---|
1276 | self.gridLayout_2.addWidget(newcombobox, row, 1, 1, 1)
|
---|
1277 | self.gridwidgets.append(newcombobox)
|
---|
1278 |
|
---|
1279 | self.connect( newcombobox,
|
---|
1280 | SIGNAL("currentIndexChanged(int)"),
|
---|
1281 | self.onComboboxChanged )
|
---|
1282 |
|
---|
1283 | elif len(item.storage.possiblevalues) > 0: # do we have predefined possible values?
|
---|
1284 | #print item.storage.__class__.__name__
|
---|
1285 | newcombobox = StorageItemCombobox(item.storage)#QtGui.QComboBox()
|
---|
1286 | newcombobox.setObjectName(item.name)
|
---|
1287 |
|
---|
1288 |
|
---|
1289 | for v in item.storage.possiblevalues:
|
---|
1290 | newcombobox.addItem(PrettyNames[v.lower().replace(' ','')])
|
---|
1291 |
|
---|
1292 | self.gridLayout_2.addWidget(newcombobox, row, 1, 1, 1)
|
---|
1293 | self.gridwidgets.append(newcombobox)
|
---|
1294 |
|
---|
1295 | if item.storage.value is None:
|
---|
1296 | newcombobox.addItem('unconfigured')
|
---|
1297 | newcombobox.setCurrentIndex(newcombobox.findText('unconfigured'))
|
---|
1298 |
|
---|
1299 | elif item.storage.value is True:
|
---|
1300 | #newcombobox.addItem('Yes')
|
---|
1301 | newcombobox.setCurrentIndex(newcombobox.findText('Yes'))
|
---|
1302 |
|
---|
1303 | elif item.storage.value is False:
|
---|
1304 | #newcombobox.addItem('No')
|
---|
1305 | newcombobox.setCurrentIndex(newcombobox.findText('No'))
|
---|
1306 |
|
---|
1307 | else:
|
---|
1308 | newcombobox.setCurrentIndex(
|
---|
1309 | newcombobox.findText(unicode(item.storage.value).lower().replace(' ','') ))
|
---|
1310 |
|
---|
1311 |
|
---|
1312 | self.connect( newcombobox,
|
---|
1313 | SIGNAL("currentIndexChanged(int)"),
|
---|
1314 | self.onComboboxChanged )
|
---|
1315 |
|
---|
1316 | else:
|
---|
1317 | # 'String input'
|
---|
1318 | newlineedit = StorageItemLineEdit(self.scrollAreaWidgetContents, item.storage)#QtGui.QLineEdit(self.scrollAreaWidgetContents)
|
---|
1319 |
|
---|
1320 | #newlineedit.setText(str(item.storage.value))
|
---|
1321 | newlineedit.setText(unicode(item.storage))
|
---|
1322 |
|
---|
1323 | self.gridLayout_2.addWidget(newlineedit, row, 1, 1, 1)
|
---|
1324 | self.gridwidgets.append(newlineedit)
|
---|
1325 |
|
---|
1326 | self.connect( newlineedit,
|
---|
1327 | SIGNAL("returnPressed()"),
|
---|
1328 | self.onLineEditChanged )
|
---|
1329 | self.connect( newlineedit,
|
---|
1330 | SIGNAL("editingFinished()"),
|
---|
1331 | self.onLineEditChanged )
|
---|
1332 |
|
---|
1333 |
|
---|
1334 | if item.storage.__class__.__name__ == 'store_msgs': # messages items
|
---|
1335 | #print "found store_msgs"
|
---|
1336 | # add a Button to edit the run entry (with own dialog)
|
---|
1337 | newbutton = StorageItemPushButton(item.storage)
|
---|
1338 | newbutton.setText('Edit...')
|
---|
1339 | self.gridwidgets.append(newbutton)
|
---|
1340 |
|
---|
1341 | self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1)
|
---|
1342 | self.connect( newbutton,
|
---|
1343 | SIGNAL("clicked()"),
|
---|
1344 | self.onMessageEntryEdit )
|
---|
1345 |
|
---|
1346 | elif item.storage.__class__.__name__.endswith('acl'): # acl items
|
---|
1347 | #print "found store_msgs"
|
---|
1348 | # add a Button to edit the run entry (with own dialog)
|
---|
1349 | newbutton = StorageItemPushButton(item.storage)
|
---|
1350 | newbutton.setText('Edit...')
|
---|
1351 | self.gridwidgets.append(newbutton)
|
---|
1352 |
|
---|
1353 | self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1)
|
---|
1354 | self.connect( newbutton,
|
---|
1355 | SIGNAL("clicked()"),
|
---|
1356 | self.onAclEntryEdit )
|
---|
1357 |
|
---|
1358 | # write the default value after the configured value
|
---|
1359 | if item.defaultvalue:
|
---|
1360 | requiredlabel = QtGui.QLabel(self.scrollAreaWidgetContents)
|
---|
1361 | requiredlabel.setText('('+str(item.defaultvalue)+')')
|
---|
1362 | self.gridLayout_2.addWidget(requiredlabel, row, 2, 1, 1)
|
---|
1363 | self.gridwidgets.append(requiredlabel)
|
---|
1364 |
|
---|
1365 |
|
---|
1366 | row += 1
|
---|
1367 |
|
---|
1368 |
|
---|
1369 |
|
---|
1370 |
|
---|
1371 |
|
---|
1372 |
|
---|
1373 | # create logger
|
---|
1374 | #logger = logging.getLogger("vanHelsing")
|
---|
1375 | #print FS_option_kw
|
---|
1376 |
|
---|
1377 |
|
---|
1378 |
|
---|
1379 | def main():
|
---|
1380 |
|
---|
1381 | print "started in directory " + DASSMODUS_PATH
|
---|
1382 | app = QtGui.QApplication(sys.argv)
|
---|
1383 | locale = QLocale.system().name()
|
---|
1384 | qtTranslator = QTranslator()
|
---|
1385 | if qtTranslator.load("qt_" + locale, ":/"):
|
---|
1386 | app.installTranslator(qtTranslator)
|
---|
1387 | appTranslator = QTranslator()
|
---|
1388 | if appTranslator.load("dassModus_" + locale + ":/"):
|
---|
1389 | app.installTranslator(appTranslator)
|
---|
1390 |
|
---|
1391 |
|
---|
1392 | app.setOrganizationDomain("dass-it.de")
|
---|
1393 | app.setOrganizationName("dassIT GmbH")
|
---|
1394 | app.setApplicationName("dassModus")
|
---|
1395 | app.setWindowIcon(QIcon(":/icons/DassModusLogo/logo300.png"))
|
---|
1396 | dialog = MeinDialog()
|
---|
1397 | dialog.show()
|
---|
1398 | dialog.onActionAbout()
|
---|
1399 | sys.exit(app.exec_())
|
---|
1400 |
|
---|
1401 |
|
---|
1402 | if __name__ == "__main__":
|
---|
1403 | sys.exit(main())
|
---|
1404 |
|
---|
1405 |
|
---|