#!/usr/bin/env python # -*- coding: utf-8 -*- # # $Id: dassmodus.py 11432 2010-11-01 19:20:55Z pstorz $ from PyQt4 import QtGui, QtCore from PyQt4.QtCore import * from PyQt4.QtGui import * from functools import partial import dassmodus.ui.schedule import dassmodus.ui.onlinehelpdialog import dassmodus.ui.messagesdialog import dassmodus.ui.listselectdialog import dassmodus.ui.baseconfwizard import dassmodus.ui.fetchDCdialog import dassmodus.ui.integrityCheckDialog import dassmodus.ui.newdatacenterwizard import dassmodus.ui.deploywizard from nosferatu.bacresources import * from nosferatu.prettynames import PrettyNames #from nosferatu.directive import * #from nosferatu import configrules import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s \t (%(module)s:%(lineno)d) %(message)s ', #filename='vanHelsing.log', filemode='w') import sys import os import re import platform #import glob from dassmodus.ui.mainwindow import Ui_MainWindow as Dlg import re import xmlrpclib import dassmodus.dragndrop import dassmodus.ui.qt_resources # for the icons ''' find where our executable script is called from,as the templates dir is relative to that. As we are running as py2exe on windows, we have to make these efforts: see http://www.py2exe.org/index.cgi/WhereAmI ''' def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located.""" return hasattr(sys, "frozen") def module_path(): """ This will get us the program's directory, even if we are frozen using py2exe""" if we_are_frozen(): return os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( ))) return os.path.dirname(unicode(__file__, sys.getfilesystemencoding( ))) DASSMODUS_PATH = module_path() RXP_DATE = re.compile('.*\((.*)\)') #from nosferatu.directive import * __version__ = 0.1 __revision__ = "$Rev: 11441 $".replace('$','').replace('Rev: ','.') datestring = "$Date: 2011-02-10 15:00:43 +0100 (Do, 10 Feb 2011) $".replace('$','').replace('Date: ','') m = RXP_DATE.match(datestring) __date__ = '(' + m.group(1) + ')' INTERNALLY_REFERENCED_ITEMS = set(['fileset', 'client' , 'catalog', 'messages', 'schedule', 'storage', 'jobdefs', 'pool', 'incrementalbackuppool', 'fullbackuppool', 'differentialbackuppool', 'job', 'basejob', 'device', ]) BOOL_ITEMS = set([ 'store_bool', 'store_runscript_bool', ]) logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s \t (%(module)s:%(lineno)d) %(message)s ', filename='dassModus.log', filemode='w') # create logger logger = logging.getLogger("vanHelsing") logger.setLevel(logging.DEBUG) logger.debug(QApplication.translate('Main','Started Main Program')) OUTPUTDIR = '/etc/bacula/' #INPUTDIR = '/etc/bacula/' INPUTDIR = ':/' #Configurations = [] # global list of configuration objects Datacenters = [] #proxy = xmlrpclib.ServerProxy("http://bacula-devel:8000/") class SafeTransportWithCert(xmlrpclib.SafeTransport): # __cert_file = DFLT_CERTFILE # __key_file = DFLT_KEYFILE __cert_file = 'certs/client-cert.pem' # Replace with your PEM formatted key file __key_file = 'certs/client-cert.pem' # Replace with your PEM formatted certificate file def make_connection(self,host): host_with_cert = (host, { 'key_file' : self.__key_file, 'cert_file' : self.__cert_file } ) return xmlrpclib.SafeTransport.make_connection( self,host_with_cert) #server_url = 'https://bacula-devel:4443' #transport = SafeTransportWithCert() #proxy = xmlrpclib.ServerProxy(server_url, # transport = transport) #print proxy.get_lsscsi() #name = 'bacula-sd.conf' #filename = INPUTDIR + name #outfile = OUTPUTDIR + name #configstring = open(filename).read() #sdconf = StorageDaemonConfig(configstring) #writefile = open(outfile,'w') #writefile.write(str(sdconf)) #name = ('bacula-fd.conf') #filename = INPUTDIR + name #outfile = OUTPUTDIR + name #configstring = open(filename).read() #fdconf = FileDaemonConfig(configstring) #writefile = open(outfile,'w') #writefile.write(str(fdconf)) #name = ('bconsole.conf') #filename = INPUTDIR + name #outfile = OUTPUTDIR + name #readfile = open(filename) #configstring = readfile.read() #conconf = ConsoleConfig(configstring) #readfile.close() #writefile = open(outfile,'w') #writefile.write(str(conconf)) #name = 'bacula-dir.conf' #filename = INPUTDIR + name #outfile = OUTPUTDIR + name #configstring = open(filename).read() #dirconf = DirectorConfig(configstring) #Configurations.append(dirconf) #Configurations.append(sdconf) #Configurations.append(fdconf) #Configurations.append(conconf) #writefile = open(outfile,'w') #writefile.write(str(dirconf)) #print dirconf #def bind(objectName, propertyName, type): # # def getter(self): # return type(self.findChild(QObject, objectName).property(propertyName).toPyObject()) # # def setter(self, value): # self.findChild(QObject, objectName).setProperty(propertyName, QVariant(value)) # # return property(getter, setter) # class StorageItemCheckbox(QCheckBox): def __init__(self, storageItem, label): QCheckBox.__init__(self,label) self.storageItem = storageItem class StorageItemLineEdit(QLineEdit): def __init__(self, parentWidget, storageItem): QCheckBox.__init__(self, parentWidget) self.storageItem = storageItem class StorageItemCombobox(QComboBox): def __init__(self, storageItem): QComboBox.__init__(self) self.storageItem = storageItem class ResourceTreeWidgetItem(QTreeWidgetItem): itemsList = [] # class variable def __init__(self, Resource, headerlist): self.Resource = Resource #print "type:" , type(headerlist),"headerlist:" , headerlist self.itemsList.append(self) QTreeWidgetItem.__init__(self, headerlist) #TODO: Why does the treeview not use the standard fontsize? #col = 0 #f = self.font(col) #f.setPixelSize(14) #self.setFont(col,f) #col=1 #f = self.font(col) #f.setBold(True) #f.setPixelSize(14) #self.setFont(col,f) # fontsize end class ResourceListWidgetItem(QListWidgetItem): def __init__(self, Resource): self.Resource = Resource QListWidgetItem.__init__(self,self.Resource.resourcetype+ ' ' + self.Resource.getName()) #self.Resource.items_dict['name'].storage.value) icon = QtGui.QIcon(":/icons/" + self.Resource.resourcetype + ".png") self.setIcon(icon) class ResItemTableWidgetItem(QTableWidgetItem): def __init__(self, ResItem): self.ResItem = ResItem QTableWidgetItem.__init__(self) class StorageItemPushButton(QPushButton): def __init__(self, storageItem): QPushButton.__init__(self) self.storageItem = storageItem #class VHTreeWidget(QtGui.QTreeWidget): # def __init__(self, parent): # super(VHTreeWidget, self).__init__(parent) #self.treeWidget = QtGui.QTreeWidget(self.verticalLayoutWidget_3) class MeinDialog(QtGui.QMainWindow, Dlg): def __init__(self): QtGui.QDialog.__init__(self) self.setupUi(self) self.gridwidgets = [] self.onlinehelpdialog = dassmodus.ui.onlinehelpdialog.OnlinehelpDialog(self) # restore the applications settings settings = QSettings() #size = settings.value("MainWindows/Size", # QVariant(QSize(600,500))).toSize() # #self.resize(size) ##self.restoreGeometry(settings.value("Geometry").toByteArray()) #position = settings.value("MainWindow/Position", # QVariant(QPoint(0,0))).toPoint() #self.move(position) #self.restoreState(settings.value("Mainwindow/State").toByteArray()) self.restoreGeometry(settings.value("Geometry").toByteArray()) self.onlinehelpdialog.restoreGeometry(settings.value("HelpWindowsGeometry").toByteArray()) # restoring state end # statusbar self.statusLabel = QLabel() self.statusLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.statusBar.setSizeGripEnabled(False) self.statusBar.addPermanentWidget(self.statusLabel) self.statusPB = QProgressBar(self.statusBar) self.statusPB.setMaximumWidth(200) self.statusPB.setTextVisible(True) self.statusBar.addPermanentWidget(self.statusPB) self.statusPB.setMinimum(0) self.statusPB.setMaximum(10) self.statusBar.showMessage(self.tr("Welcome to the bacula configuration program"), 5000) #self.configsToTreeWidget() #self.dirconfRoot = self.addConfigToTreeWidget(dirconf) #self.sdconfRoot = self.addConfigToTreeWidget(sdconf) #self.addConfigToTreeWidget(fdconf) #self.addConfigToTreeWidget(conconf) self.treeWidget.setMouseTracking(True) self.treeWidget.setColumnCount(3) self.treeWidget.resizeColumnToContents(0) self.treeWidget.setAlternatingRowColors(False) self.treeWidget.sortByColumn(0, Qt.AscendingOrder) #self.treeWidget = VHTreeWidget(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.treeWidget) #self.textEdit.setText('hallo') #dassModus v %s

A GUI program to configure Bacula

Copyright © 2010 dass IT GmbH
http://www.dass-it.de

Händelstraße 25-29
50674 Köln
Germany
Phone: +49 221 3 56 56 66-0

Python %s - Qt %s - PyQt %s on %s """ % (str(__version__) + __revision__ + '
' + __date__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system() ) ) def onActionDeployConfig(self, Resource): server_url = 'https://bacula-old:4443' transport = SafeTransportWithCert() proxy = xmlrpclib.ServerProxy(server_url, transport = transport) deploywizard = dassmodus.ui.deploywizard.deploywizard(proxy, str(Resource),Resource.longname, self ) deploywizard.exec_() #server_url = 'https://bacula-old:4443' #transport = SafeTransportWithCert() #proxy = xmlrpclib.ServerProxy(server_url, # transport = transport) #OLD_CONFIG = proxy.get_conf('dir') #proxy.set_conf('dir',str(Resource)) #print proxy.reload_director() def onActionFetch(self): availableDCs = proxy.list_datacenters() DCdialog = dassmodus.ui.fetchDCdialog.FetchDCDialog( datacenterlist = availableDCs ) if DCdialog.exec_(): selectedDC = unicode( DCdialog.listWidget.selectedItems()[0].text() ) DCdata = proxy.get_datacenter(selectedDC).data #TODO: write this to a temporary file, open this file #print availableDCs # configstring = proxy.get_dirdconf() # print "configstring:", configstring # print str(configstring) # dirconf = DirectorConfig(str(configstring)) # Configurations.append(dirconf) # self.rebuildTreeWidget() def onActionCheckIntegrity(self, Resource): ''' call the Datacenters own integrity checks and display the output ''' dc = Resource intcheckdlg = dassmodus.ui.integrityCheckDialog.IntegrityCheckDialog(self,dc.checkFileDaemonsIntegrity()) intcheckdlg.show() #print dc.checkFileDaemonsIntegrity() #print dc.checkStorageDaemonsIntegrity() def onActionNewDatacenter(self): wizard = dassmodus.ui.newdatacenterwizard.newdatacenterwizard(DASSMODUS_PATH) if wizard.exec_(): self.openDatacenterFile(wizard.filename) def onActionCommit(self): #configstring = Configurations[0] #print unicode(configstring) #proxy.set_dirdconf(unicode(configstring)) pass def onRunentryEdit(self): #print "onRunEntryEdi called" #print self.sender().storageItem.runentry rune = self.sender().storageItem.runentry parentcfg = self.sender().storageItem.parentitem.parentresource.parentconfig dialog = dassmodus.ui.schedule.RunentryDialog(self, runentry=rune, parentconfig=parentcfg ) # get parent config to be able to find valid pools, storages, etc. to fill in comboboxes if dialog.exec_(): print "yes" + str(self.sender().storageItem.runentry) #else: # print "no" def onMessageEntryEdit(self): mesgDict = self.sender().storageItem.messageDict dialog = dassmodus.ui.messagesdialog.MessagesDialog(self, messagesTypesDict=mesgDict) if dialog.exec_(): print "yes"# + str(self.sender().storageItem.runentry) else: print "no" def onAclEntryEdit(self): sender = self.sender() aclname = sender.storageItem.parentitem.name if aclname == 'commandacl': for cmd in commands.keys(): if not cmd in sender.storageItem.ACLDict: sender.storageItem.ACLDict[cmd] = False else: parentconfig = self.sender().storageItem.parentitem.parentresource.parentconfig aclresourcename = aclname.lower().replace('acl','') # FilesetACL -> fileset availableresources = parentconfig.getResourcesListByResType(aclresourcename) #cfgdict = {} for res in availableresources: #if not res.items_dict['name'].storage.value in sender.storageItem.ACLDict: if not res.getName() in sender.storageItem.ACLDict: sender.storageItem.ACLDict[res.getName()] = False dialog = dassmodus.ui.listselectdialog.ListSelectDialog(self, configDict = sender.storageItem.ACLDict, title = 'Edit %s' % (aclname) ) #sender.storageItem.setValue(str(sender.storageItem)) #.setValue( unicode(self.sender().text() ) ) if dialog.exec_(): print "yes"# + str(self.sender().storageItem.runentry) sender.storageItem.__ACLDict2value__() else: print "no" def processEventsCallback(self, info = None): QtGui.QApplication.processEvents() if info: self.statusBar.showMessage(info) def onActionOpen(self): #fd = QFileDialog(self) #fd.setFileMode(QFileDialog.Directory) filename = unicode(QFileDialog.getOpenFileName(self ,self.tr('Open Datacenter file') ,'' ,self.tr('dassModus datacenter .dmdz files (*.dmdz)')) ) if filename: self.openDatacenterFile(filename) # self.statusPB.setMinimum(0) # self.statusPB.setMaximum(0) # # dc = DataCenter(filename, self.processEventsCallback ) # Datacenters.append(dc) # # self.statusPB.setMaximum(100) # # self.updateReferenceInformation() # self.rebuildTreeWidget() # self.treeWidget.expandToDepth(0) # self.treeWidget.resizeColumnToContents(0) # self.treeWidget.resizeColumnToContents(1) # # #self.statusPB.setEnabled(False) # #pd.close() # self.statusBar.clearMessage() # self.statusPB.setMaximum(100) # self.statusPB.setMinimum(0) def openDatacenterFile(self,filename): self.statusPB.setMinimum(0) self.statusPB.setMaximum(0) dc = DataCenter(filename, self.processEventsCallback ) Datacenters.append(dc) self.statusPB.setMaximum(100) self.updateReferenceInformation() self.rebuildTreeWidget() self.treeWidget.expandToDepth(0) self.treeWidget.resizeColumnToContents(0) self.treeWidget.resizeColumnToContents(1) #self.statusPB.setEnabled(False) #pd.close() self.statusBar.clearMessage() self.statusPB.setMaximum(100) self.statusPB.setMinimum(0) def datacentersToTreeWidget(self): dcs_to_create = set(Datacenters) dc2treewidgetitem = {} # check if there is already a toplevel item for this dc for dc in Datacenters: count = self.treeWidget.topLevelItemCount() for i in range(count): tli = self.treeWidget.topLevelItem(i) if tli.Resource == dc: dcs_to_create.remove(dc) dc2treewidgetitem[dc] = tli # only add top treewidget for not existing datacenters for dc in Datacenters: #root = self.addDatacenterToTreeWidget(config) if dc in dcs_to_create: dcTWI = QTreeWidgetItem([self.tr('Datacenter'), unicode(dc.name)]) dcTWI.Resource = dc icon = QtGui.QIcon(":/icons/datacenter.png") dcTWI.setIcon(0,icon) # TODO: why does treewidget not use standard fontsize? #col = 0 #f = dcTWI.font(col) #f.setPixelSize(14) #dcTWI.setFont(col,f) #col = 1 #f = dcTWI.font(col) ## f.setBold(True) #f.setPixelSize(14) #dcTWI.setFont(col,f) #font end self.treeWidget.addTopLevelItem(dcTWI) else: dcTWI = dc2treewidgetitem[dc] for config in list(dc.directors) + list(dc.filedaemons) + list(dc.storagedaemons) + list(dc.consoles): self.addConfigToDc(config, dcTWI) def addDatacenterToTreeWidget(self): #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name]) #self.treeWidget.expandAll() pass def menuContextTree(self, point): # Infos about the node selected. index = self.treeWidget.indexAt(point) if not index.isValid(): return item = self.treeWidget.itemAt(point) name = item.text(0) # The text of the node. resource = item.Resource # We build the menu. menu=QtGui.QMenu(self) #action=menu.addAction(name) print "Contextmenu for:" + name + ':' if name == PrettyNames['client']: actionCreateFDConfig = menu.addAction(self.tr("create FiledaemonConfig from ") + name) self.connect(actionCreateFDConfig, SIGNAL("triggered()"), partial(self.onActionCreateFDConfig, resource ) ) if hasattr(resource, 'validitemsset'): for r in resource.validitemsset: if r in MULTIPLE_ALLOWED_ITEMS_SET: icon = QtGui.QIcon(":/icons/" + r + ".png") actionAdd=menu.addAction(icon,'add' + PrettyNames[r]) actionAdd.setObjectName(r) self.connect(actionAdd, SIGNAL("triggered()"), partial( self.onActionAdd, resource, r ) ) elif hasattr(resource, 'validresourcesset'): for r in resource.validresourcesset: if r in MULTIPLE_RESOURCES_IN_DIRD: icon = QtGui.QIcon(":/icons/" + r + ".png") actionAdd=menu.addAction(icon, self.tr('add ') + PrettyNames[r]) actionAdd.setObjectName(r) self.connect(actionAdd, SIGNAL("triggered()"), partial( self.onActionAdd, resource, r ) ) # import a client snippet from the abcd if name == 'DirectorConfig': actionImportSnippet = menu.addAction( icon, 'import client snippet from autoconfiguration' ) self.connect(actionImportSnippet, SIGNAL("triggered()"), partial( self.onImportSnippet, resource) ) # deploy configuration to director actionDeployConfig = menu.addAction( icon, 'deploy configuration....' ) self.connect(actionDeployConfig, SIGNAL("triggered()"), partial( self.onActionDeployConfig, resource) ) if name == 'Datacenter': # TODO: icons for these menu entries actionCheckIntegrity = menu.addAction(self.tr("check integrity of Datacenter")) self.connect(actionCheckIntegrity, SIGNAL("triggered()"), partial(self.onActionCheckIntegrity, resource ) ) actionSaveDatacenter = menu.addAction(self.tr("save Datacenter (") + resource.filename + ')') self.connect(actionSaveDatacenter, SIGNAL("triggered()"), partial(self.onActionSaveDc, resource ) ) actionSaveDatacenterAs = menu.addAction(self.tr("save Datacenter as")) self.connect(actionSaveDatacenterAs, SIGNAL("triggered()"), partial(self.onActionSaveDcAs, resource ) ) menu.addSeparator() actionImportConfigurationFile = menu.addAction(self.tr("Import existing configuration file")) self.connect(actionImportConfigurationFile, SIGNAL("triggered()"), partial(self.onActionImportConfigFile, resource ) ) actionExport = menu.addAction(self.tr("export ") + name) self.connect(actionExport, SIGNAL("triggered()"), partial(self.onActionExport, resource ) ) menu.addSeparator() actionDelete = menu.addAction(self.tr("delete ") + name) self.connect(actionDelete, SIGNAL("triggered()"), partial(self.onActionDelete, resource ) ) menu.exec_(QtGui.QCursor.pos()) def onActionImportConfigFile(self, datacenter): filename = unicode(QFileDialog.getOpenFileName(self ,self.tr('Import bacula configuration file') ,'' ,self.tr('bacula configuration files (*.conf)')) ) if filename: print "open filename" + filename if filename.find('-fd.conf') != -1: datacenter.importConfigurationFile(filename, 'filedaemon') elif filename.find('-sd.conf') != -1: datacenter.importConfigurationFile(filename, 'storagedaemon') elif filename.find('-dir.conf') != -1: datacenter.importConfigurationFile(filename, 'director') elif filename.find('bconsole.conf') != -1: datacenter.importConfigurationFile(filename, 'console') else: # TODO: QMessageBox Error QMessageBox.warning(self, self.tr('Warning'), self.tr('did not recognize the file format of file ' + filename) ) self.datacentersToTreeWidget() ''' TODO: ask for filetype (dir, fd, sd, console) or try all and look if it works? ''' def onActionExport(self, resource): filename = unicode(QFileDialog.getSaveFileName(self ,self.tr('Export configuration file') ,resource.getName().strip('"')+'.conf' ) ) if filename: f = open(filename,'w') f.write(str(resource)) f.close() def onActionSaveDcAs(self ,datacenter): filename = unicode(QFileDialog.getSaveFileName(self ,self.tr('save datacenter file as...') ,datacenter.getName().strip('"')+'.dmdz' ) ) if filename: datacenter.setFileName(filename) datacenter.safeDatacenter() def onActionSaveDc(self ,datacenter): datacenter.safeDatacenter() def onImportSnippet(self, resource): filename = unicode(QFileDialog.getOpenFileName(self ,self.tr('Import bacula client snippet from autoconfiguration daemon') ,'' ,self.tr('bacula client configuration snippets (*.snippet)')) ) if filename: f = open(filename,'r') snippet = f.read() f.close() #newres = resource.createResource('client') resource.parse_configfile(snippet, None) self.rebuildTreeWidget() def onActionAdd(self, resource, resname): newres = resource.createResource(resname) wizard = dassmodus.ui.baseconfwizard.baseconfigwizard(newres,resource) if wizard.exec_(): print "ok" else: resource.deleteResource(newres) self.rebuildTreeWidget() #self.sender().storageItem.setValue( unicode(self.sender().currentText() ) ) def onActionDelete(self, resource): print self.tr("deleting ") , resource if hasattr(resource,'parentconfig'): # resource? resource.parentconfig.deleteResource(resource) del resource elif hasattr(resource,'parentdatacenter'): # resource? resource.parentdatacenter.deleteConfiguration(resource) #del resource else: print "help me" # BaculaConfig TODO! #Configurations.remove(resource) # del resource self.treeWidget.clear() # TODO: better remove the corresponding treewidgetitem self.rebuildTreeWidget() def onActionCreateFDConfig(self, dirClient): print self.tr("creating FD Config from ") , dirClient newFdConfig = FileDaemonConfig('') dirClient.parentconfig.parentdatacenter.filedaemons.add(newFdConfig) newFdConfig.createFdConfigFromDirClient(dirClient) # copy relevant info from dirClient entry #newFdConfig.filename = os.getcwd()+ newFdConfig.name +'-fd.conf' newFdConfig.filename = os.getcwd()+ '/' + newFdConfig.name +'-fd.conf' self.rebuildTreeWidget() #def newClient(self): # newres = dirconf.createResource('client') # newres.items_dict['name'].storage.setValue('newclient') # self.addResourcesToTreeWidget(self.dirconfRoot, [newres]) # #def newJobDefs(self): # newres = dirconf.createResource('jobdefs') # newres.items_dict['name'].storage.setValue('newJobDefs') # self.addResourcesToTreeWidget(self.dirconfRoot, [newres]) # #def newDirector(self): # newres = dirconf.createResource('director') # newres.items_dict['name'].storage.setValue('newDirector') # self.addResourcesToTreeWidget(self.dirconfRoot, [newres]) def onSave(self): for dc in Datacenters: dc.writeDatacenter('/tmp/') #for conf in Configurations:a # print "writing "+ conf.filename # writefile = open(conf.filename,'w') # #writefile = open(outfile,'w') # writefile.write(str(conf)) # #print str(dirconf) # writefile.close() def onTreeItemClick(self, item): #print item.Resource.onlinehelpURL if hasattr(item,'Resource'): if hasattr(item.Resource,'onlinehelpURL'): self.onlinehelpdialog.loadURL(item.Resource.onlinehelpURL) if self.textEdit.isVisible(): # only create the config file if output is visible self.textEdit.setText(unicode(item.Resource)) self.addConfigItemsToItemsGroup(item.Resource) self.updateReferencesItemsList(item.Resource) # TODO: this does not work (why?) #if hasattr(item.Resource,'filename'): # self.statusBar.showMessage(item.Resource.filename, 5000) #def onPushButton(self): # print "PushButton" # self.addConfigToTreeWidget(dirconf,None) # #self.addDictToTreeWidget(myNewResDict,None) def rebuildTreeWidget(self): #self.treeWidget.clear() self.datacentersToTreeWidget() #self.configsToTreeWidget() #self.treeWidget.expandToDepth(0) #self.treeWidget.resizeColumnToContents(0) #self.treeWidget.resizeColumnToContents(1) self.treeWidget.setAlternatingRowColors(False) self.treeWidget.sortByColumn(0, Qt.AscendingOrder) #self.treeWidget.expandAll() def addResourcesToTreeWidget( self, parentTreeItem, Resources ): # check if we already have a treewidgetitem for this resource resources2treewidgetitem = {} resources_to_create = set(Resources) # check if there is already a sibling item for this resource #QtGui.QTreeWidgetItem. count = parentTreeItem.childCount() #print count for res in Resources: # all resources for i in range(count): # iterate over all siblings tli = parentTreeItem.child(i) if tli.Resource == res: # is there already a sibling representing res? resources_to_create.remove(res) resources2treewidgetitem[res]= tli #logger.info(str(resources_to_create)) for res in Resources: # some Resources do not have a name (include, exclude, options...s) try: name = res.getName() #name = res.items_dict['name'].storage.value.strip('"') except: name = ' ' # no name refcount = len(res.reflist) # only add treewidget for not existing resources if res in resources_to_create: mytreeitem = ResourceTreeWidgetItem( res, [ PrettyNames[res.resourcetype], unicode(name), str(refcount)] ) parentTreeItem.addChild(mytreeitem) icon = QtGui.QIcon(":/icons/" + res.resourcetype + ".png") mytreeitem.setIcon(0,icon) else: mytreeitem = resources2treewidgetitem[res] self.addResourcesToTreeWidget(mytreeitem, res.resources) def addConfigToTreeWidget(self,Resource): name = Resource.getName() #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name, Resource.filename]) parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, unicode(name)] ) parent.setStatusTip(0,QtCore.QString(Resource.filename)) #parent.setToolTip(0,QtCore.QString(Resource.filename)) #parent.setWhatsThis(0,QtCore.QString(Resource.filename)) icon = QtGui.QIcon(":/icons/config.png") parent.setIcon(0,icon) #if Resource.__class__.__name__ == 'DirectorConfig': # self.resGroupingTreeItems = {} # which resource types are grouped under DirectorConfig? self.treeWidget.addTopLevelItem(parent) self.addResourcesToTreeWidget(parent, Resource.resources) return parent def addConfigToDc(self, Resource, DcTreeWidgetItem): parent = None count = DcTreeWidgetItem.childCount() #QtGui.QTreeWidgetItem.child(int) for i in range (count): if DcTreeWidgetItem.child(i).Resource == Resource: parent = DcTreeWidgetItem.child(i) if not parent: name = Resource.getName().strip('"') # remove quotation marks #parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, name, Resource.filename]) parent = ResourceTreeWidgetItem(Resource,[Resource.__class__.__name__, unicode(name) ]) parent.setStatusTip(0,QtCore.QString(Resource.filename)) #parent.setToolTip(0,QtCore.QString(Resource.filename)) #parent.setWhatsThis(0,QtCore.QString(Resource.filename)) #icon = QtGui.QIcon(":/icons/config.png") #print Resource.__class__.__name__.replace('Config','').lower() icon = QtGui.QIcon(":/icons/" + Resource.__class__.__name__.replace('Config','').lower() +".png") parent.setIcon(0,icon) #if Resource.__class__.__name__ == 'DirectorConfig': # self.resGroupingTreeItems = {} # which resource types are grouped under DirectorConfig? DcTreeWidgetItem.addChild(parent) #self.treeWidget.addTopLevelItem(parent) self.addResourcesToTreeWidget(parent, Resource.resources) return parent def onCheckboxChecked(self): print "checkbox was checked by:" , self.sender().objectName() , "to:" , self.sender().isChecked() self.sender().storageItem.setValue( self.sender().isChecked() ) def onComboboxChanged(self): print "combobox was changed by:" , self.sender().objectName() , "to:" , self.sender().currentText() self.sender().storageItem.setValue( unicode(self.sender().currentText() ) ) def onLineEditChanged(self): print "LineEdit was changed by:" , self.sender().objectName() , "to:" , self.sender().text() self.sender().storageItem.setValue( unicode(self.sender().text() ) ) def onReferenceItemDoubleClicked(self,item): print "RefItemClicked:" , ":" , item.text(), item.Resource for ResTreeItem in ResourceTreeWidgetItem.itemsList: if ResTreeItem.Resource == item.Resource: self.treeWidget.setCurrentItem(ResTreeItem) #TODO: Find the right TreeWidgetItem and activate it def onFileListItemDoubleClicked(self,item): print "FileItemClicked:" , ":" , item.text() item.editItem(item) #for ResTreeItem in ResourceTreeWidgetItem.itemsList: # if ResTreeItem.Resource == item.Resource: # self.treeWidget.setCurrentItem(ResTreeItem) def updateReferenceInformation(self): """ iterate over all resources and update the reference information accordingly """ for dc in Datacenters: for config in list(dc.directors) + list(dc.filedaemons) + list(dc.storagedaemons) + list(dc.consoles): for res in config.resources: reflist = config.getReferencingResourcesListForResource(res) res.reflist = reflist #print '\n',res.resourcetype, res.items_dict['name'].storage.value,"is referenced", len(reflist),"times:" #for refres in reflist: # print refres.resourcetype, refres.items_dict['name'].storage.value def updateReferencesItemsList(self,Resource): self.referencesListWidget.clear() for r in Resource.reflist: #icon = QtGui.QIcon(":/icons/" + r.resourcetype + ".png") ListWidgetItem = ResourceListWidgetItem(r) #QtGui.QListWidgetItem(r.resourcetype+ ' ' + r.items_dict['name'].storage.value) #ListWidgetItem.setIcon(icon) self.referencesListWidget.addItem(ListWidgetItem) def addConfigItemsToItemsGroup(self,Resource): #cleanup widgets for widget in self.gridwidgets: self.gridLayout_2.removeWidget(widget) widget.setParent(None) self.gridwidgets = [] #TODO: do this depending on the type, ignore for Configs if not hasattr(Resource,'items'): return row = 0 # special treatment of file entries if Resource.shortname == 'include': # is the same as exclude newlabel = QtGui.QLabel(self.scrollAreaWidgetContents) newlabel.setText('Files') self.gridLayout_2.addWidget(newlabel, row, 0, 1, 1) self.gridwidgets.append(newlabel) filelistWidget = dassmodus.dragndrop.DnDListWidget() self.gridwidgets.append(filelistWidget) self.gridLayout_2.addWidget(filelistWidget, row, 1, 1, 1) for f in Resource.getItemsListByItemName('file'): if f.print_item(): fileListWidgetItem = QtGui.QListWidgetItem(unicode(f.storage.value).rstrip('"').lstrip('"')) self.connect( filelistWidget, SIGNAL("itemDoubleClicked(QListWidgetItem *)"), self.onFileListItemDoubleClicked ) #print Resource.items_dict icon = QIcon(":/icons/" + Resource.resourcetype + "file.png") fileListWidgetItem.setIcon(icon) filelistWidget.addItem(fileListWidgetItem) row += 1 #TODO: create a ListWidget on the fileset level containing both include and exclude with +/- icons # in order to view all included and excluded things at once for item in Resource.items: if item.name == 'file': continue # clear # items manually added to horizontallayout if item.print_item() or self.showAllCheckBox.isChecked(): # only print configured or required items newlabel = QtGui.QLabel(self.scrollAreaWidgetContents) labeltext = PrettyNames[item.name] # show job items that are inherited from jobdefs if hasattr(item.parentresource,'shortname') and item.parentresource.shortname == 'job': jobdef = False jobdefname = item.parentresource.getItemValue('jobdefs') #jobdefname = item.parentresource.items_dict['jobdefs'].storage.value if jobdefname is not None: print "jobdefs is set:" + str(jobdefname) jobdef = True else: print "jobdefs is not set:" + str(item.parentresource.items_dict['jobdefs'].storage) jobdef = False if jobdef and item.storage.value == item.defaultvalue: jobdefs = item.parentresource.parentconfig.getResourceByName( jobdefname ) if jobdefs.items_dict[item.name].storage.value != jobdefs.items_dict[item.name].defaultvalue: #print '>' + jobdefs.items_dict[item.name].storage.value + '<' #labeltext = PrettyNames[item.name] + ' (' + jobdefname + '->' + jobdefs.items_dict[item.name].storage.value + ' )' #labeltext = PrettyNames[item.name] + ' (' + jobdefs.items_dict[item.name].storage.value + ')' labeltext = PrettyNames[item.name] + ' (' + jobdefs.getName() + ')' newlabel.setText(labeltext) self.gridLayout_2.addWidget(newlabel, row, 0, 1, 1) self.gridwidgets.append(newlabel) font = QtGui.QFont() # bold means: item will be printed if item.print_item(): font.setWeight(75) font.setBold(True) newlabel.setFont(font) newlabel.setToolTip(self.tr('item will be printed')) # Italic means: item is required if item.required: font.setWeight(50) font.setItalic(True) font.setUnderline(True) newlabel.setFont(font) newlabel.setToolTip(self.tr('item is required')) if item.storage.__class__.__name__ in BOOL_ITEMS: newcheckbox = StorageItemCheckbox(item.storage, unicode(item.storage.value)) #newcheckbox = QtGui.QCheckBox(str(item.storage.value)) self.gridLayout_2.addWidget(newcheckbox, row, 1, 1, 1) newcheckbox.setObjectName(item.name) newcheckbox.setChecked( bool(item.storage.value) ) self.gridwidgets.append(newcheckbox) self.connect( newcheckbox, SIGNAL("toggled(bool)"), self.onCheckboxChecked ) elif item.name == 'run': # Schedule "Run" entries # 'String input' newlineedit = StorageItemLineEdit(self.scrollAreaWidgetContents, item.storage)#QtGui.QLineEdit(self.scrollAreaWidgetContents) newlineedit.setText(unicode(item.storage.value)) self.gridLayout_2.addWidget(newlineedit, row, 1, 1, 1) self.gridwidgets.append(newlineedit) self.connect( newlineedit, SIGNAL("returnPressed()"), self.onLineEditChanged ) self.connect( newlineedit, SIGNAL("editingFinished()"), self.onLineEditChanged ) # add a Button to edit the run entry (with own dialog) newbutton = StorageItemPushButton(item.storage) newbutton.setText(self.tr('Edit...')) self.gridwidgets.append(newbutton) self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1) self.connect( newbutton, SIGNAL("clicked()"), self.onRunentryEdit ) elif item.name in INTERNALLY_REFERENCED_ITEMS: newcombobox = StorageItemCombobox(item.storage) newcombobox.setObjectName(item.name) #QtGui.QComboBox() newcombobox.addItem(unicode(item.storage.value)) #newcombobox.addItem(unicode(item.storage.value.strip('"'))) #QtGui.QComboBox.currentIndexChanged(*types name=str) restype = item.name if restype.endswith('pool'): restype = 'pool' if restype.endswith('job'): restype = 'job' for r in Resource.parentconfig.getResourcesListByResType(restype): if newcombobox.findText(QString(r.getName())) == -1: newcombobox.addItem(r.getName()) #newcombobox.addItem(r.items_dict['name'].storage.value) #newcombobox.setText(str(item.storage.value)) self.gridLayout_2.addWidget(newcombobox, row, 1, 1, 1) self.gridwidgets.append(newcombobox) self.connect( newcombobox, SIGNAL("currentIndexChanged(int)"), self.onComboboxChanged ) elif len(item.storage.possiblevalues) > 0: # do we have predefined possible values? #print item.storage.__class__.__name__ newcombobox = StorageItemCombobox(item.storage)#QtGui.QComboBox() newcombobox.setObjectName(item.name) for v in item.storage.possiblevalues: newcombobox.addItem(PrettyNames[v.lower().replace(' ','')]) self.gridLayout_2.addWidget(newcombobox, row, 1, 1, 1) self.gridwidgets.append(newcombobox) if item.storage.value is None: newcombobox.addItem('unconfigured') newcombobox.setCurrentIndex(newcombobox.findText('unconfigured')) elif item.storage.value is True: #newcombobox.addItem('Yes') newcombobox.setCurrentIndex(newcombobox.findText('Yes')) elif item.storage.value is False: #newcombobox.addItem('No') newcombobox.setCurrentIndex(newcombobox.findText('No')) else: newcombobox.setCurrentIndex( newcombobox.findText(unicode(item.storage.value).lower().replace(' ','') )) self.connect( newcombobox, SIGNAL("currentIndexChanged(int)"), self.onComboboxChanged ) else: # 'String input' newlineedit = StorageItemLineEdit(self.scrollAreaWidgetContents, item.storage)#QtGui.QLineEdit(self.scrollAreaWidgetContents) #newlineedit.setText(str(item.storage.value)) newlineedit.setText(unicode(item.storage)) self.gridLayout_2.addWidget(newlineedit, row, 1, 1, 1) self.gridwidgets.append(newlineedit) self.connect( newlineedit, SIGNAL("returnPressed()"), self.onLineEditChanged ) self.connect( newlineedit, SIGNAL("editingFinished()"), self.onLineEditChanged ) if item.storage.__class__.__name__ == 'store_msgs': # messages items #print "found store_msgs" # add a Button to edit the run entry (with own dialog) newbutton = StorageItemPushButton(item.storage) newbutton.setText('Edit...') self.gridwidgets.append(newbutton) self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1) self.connect( newbutton, SIGNAL("clicked()"), self.onMessageEntryEdit ) elif item.storage.__class__.__name__.endswith('acl'): # acl items #print "found store_msgs" # add a Button to edit the run entry (with own dialog) newbutton = StorageItemPushButton(item.storage) newbutton.setText('Edit...') self.gridwidgets.append(newbutton) self.gridLayout_2.addWidget(newbutton, row, 2, 1, 1) self.connect( newbutton, SIGNAL("clicked()"), self.onAclEntryEdit ) # write the default value after the configured value if item.defaultvalue: requiredlabel = QtGui.QLabel(self.scrollAreaWidgetContents) requiredlabel.setText('('+str(item.defaultvalue)+')') self.gridLayout_2.addWidget(requiredlabel, row, 2, 1, 1) self.gridwidgets.append(requiredlabel) row += 1 # create logger #logger = logging.getLogger("vanHelsing") #print FS_option_kw def main(): print "started in directory " + DASSMODUS_PATH app = QtGui.QApplication(sys.argv) locale = QLocale.system().name() qtTranslator = QTranslator() if qtTranslator.load("qt_" + locale, ":/"): app.installTranslator(qtTranslator) appTranslator = QTranslator() if appTranslator.load("dassModus_" + locale + ":/"): app.installTranslator(appTranslator) app.setOrganizationDomain("dass-it.de") app.setOrganizationName("dassIT GmbH") app.setApplicationName("dassModus") app.setWindowIcon(QIcon(":/icons/DassModusLogo/logo300.png")) dialog = MeinDialog() dialog.show() dialog.onActionAbout() sys.exit(app.exec_()) if __name__ == "__main__": sys.exit(main())