""" CopyCenterPlugin to provide 'QtSQL'. Description: This python-script is a plugin for the CopyCenter.py. Author: Sebastian Sauer Copyright: GPL v2 or higher. """ class CopyCenterPlugin: """ The CopyCenterPlugin to provide 'QtSQL' to CopyCenter.py """ name = "QtSQL Database" """ The name this plugin has. The name should be unique and will be used for displaying a caption. """ class Plugin: def _init_(self,copycenterplugin): self.copycenterplugin = copycenterplugin self.widget = None self.database = None self.cursor = None self.isfinished = True def _init(self,copierer): self.copierer = copierer if not self.widget.connectClicked(): raise "Failed to connect with database." if self.database == None or not self.database.isOpen(): raise "Database is not initialized or not opened." self.copierer.appendProgressMessage("Connected: %s %s@%s:%i %s" % (str(self.database.driverName()),str(self.database.userName()),str(self.database.hostName()),self.database.port(),str(self.database.databaseName())) ) self.isfinished = False def isFinished(self): return self.isfinished def finish(self): self.isfinished = True self.widget.disconnectClicked() def createWidget(self,dialog,parent): return self.copycenterplugin.widget(dialog, self, parent) class Source(Plugin): plugintype = "Source" def __init__(self,copycenterplugin): self._init_(copycenterplugin) self.options = { 'driver': 'QMYSQL3', #'QMYSQL3','QPSQL7','QODBC3',... 'hostname': '127.0.0.1', 'port': 3306, 'username': 'root', #'MyUsername', 'password': '', #'MySecretPassword', 'database': '', #'MyQtSQLDatabase', 'table': '', #'table1', 'fields': '', #'f1,f2', 'where': '', } def init(self,copierer): self._init(copierer) tablename = str(self.widget.tableedit.text()) wherestatement = str(self.widget.whereedit.text()) import qt import qtsql self.cursor = qtsql.QSqlCursor(tablename,True,self.database) self.cursor.setFilter(wherestatement) if not self.cursor.select(): raise "Select on cursor failed.
%s
%s" % ( str(self.cursor.lastError().driverText()),str(self.cursor.lastError().databaseText()) ) self.fieldlist = [] for fieldname in str(self.widget.fieldedit.text()).split(","): fn = fieldname.strip() if fn != "": field = self.cursor.field(fn) if not field: raise "There exists no such field \"%s\" in the table \"%s\"." % (fn,tablename) self.fieldlist.append(str(field.name())) if len(self.fieldlist) < 1: raise "No fields for table \"%s\" defined." % tablename copierer.appendProgressMessage("SQL: %s" % str(self.cursor.executedQuery())) def read(self): if not self.cursor.next(): return None record = [] for fieldname in self.fieldlist: record.append( unicode(self.cursor.value(fieldname).toString()).encode("latin-1") ) #print "read record: %s" % record return record class Destination(Plugin): plugintype = "Destination" def __init__(self,copycenterplugin): self._init_(copycenterplugin) self.options = { 'driver': 'QMYSQL3', #'QMYSQL3','QPSQL7','QODBC3',... 'hostname': '127.0.0.1', 'port': 3306, 'username': 'root', #'MyUsername', 'password': '', #'MySecretPassword', 'database': '', #'MyQtSQLDatabase', 'table': '', #'table2', 'fields': '', #'field1,field2', 'operation': 'Insert', #'Insert','Update'... 'indexfield': '', } def init(self,copierer): self._init(copierer) import qt import qtsql self.fieldlist = [] for fieldname in str(self.widget.fieldedit.text()).split(","): fn = fieldname.strip() if fn != "": self.fieldlist.append(fn) tablename = str(self.widget.tableedit.text()) self.cursor = qtsql.QSqlCursor(tablename,True,self.database) { 0: self.initInsert, 1: self.initUpdate }[ self.widget.operationedit.currentItem() ]() def initInsert(self): self.write = self.writeInsert if not self.cursor.select(): raise "Select on cursor failed.
%s
%s" % ( str(self.cursor.lastError().driverText()),str(self.cursor.lastError().databaseText()) ) for fieldname in self.fieldlist: # check fieldlist field = self.cursor.field(fieldname) if not field: raise "There exists no such field \"%s\" in the table \"%s\"." % (fieldname, self.cursor.name()) self.copierer.appendProgressMessage("Insert SQL: %s" % str(self.cursor.executedQuery())) def writeInsert(self, record): print "insert record: %s" % record import qt cursorrecord = self.cursor.primeInsert() count = len(record) for i in range(len(self.fieldlist)): if i == count: break r = record[i] if r == None: v = qt.QVariant() else: v = qt.QVariant(r) cursorrecord.setValue(self.fieldlist[i], v) rowcount = self.cursor.insert() if rowcount < 1: drv = unicode(self.cursor.lastError().driverText()).encode("latin-1") db = unicode(self.cursor.lastError().databaseText()).encode("latin-1") print "failed: %s %s" % (drv,db) self.copierer.writeFailed(record) else: self.copierer.writeSuccess(record,rowcount) #import time #time.sleep(1) return True def initUpdate(self): self.write = self.writeUpdate self.indexfieldname = str(self.widget.indexedit.text()).strip() if self.indexfieldname == "": raise "No index-field defined." pkindex = self.cursor.index(self.indexfieldname) if not pkindex: raise "Invalid index-field defined." self.cursor.setPrimaryIndex(pkindex) #self.cursor.setMode( qtsql.QSqlCursor.Insert | qtsql.QSqlCursor.Update ) self.copierer.appendProgressMessage("Update SQL: %s" % str(self.cursor.executedQuery())) def writeUpdate(self, record): import qt # determinate the primary-index try: idx = self.fieldlist.index(self.indexfieldname) indexvalue = record[idx] except: import traceback print "".join( traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) ) raise "Failed to determinate the value for the primary key." # select cursor and go to matching record. wherestatement = "%s = \"%s\"" % (self.indexfieldname, indexvalue) if not self.cursor.select(wherestatement): raise "Select on cursor failed.
%s
%s" % ( str(self.cursor.lastError().driverText()),str(self.cursor.lastError().databaseText()) ) if not self.cursor.next(): #print "No such record to update !" return False # Prepare updating the record. cursorrecord = self.cursor.primeUpdate() # Update the fields in the record. count = len(record) for i in range(len(self.fieldlist)): if i == count: break fieldname = self.fieldlist[i] if self.indexfieldname != fieldname: # don't update the indexfield! r = record[i] if r == None: v = qt.QVariant() else: v = qt.QVariant(r) cursorrecord.setValue(fieldname, v) # Write updated record. rowcount = self.cursor.update() if rowcount < 1: self.copierer.writeFailed(record) else: self.copierer.writeSuccess(record,rowcount) print "updated record (rowcount %s): %s" % (rowcount,record) return True def __init__(self, copycenter): """ Constructor. """ pass def widget(self,dialog,plugin,parent): """ Each plugin may provide a qt.QWidget back to the CopyCenter.py. The widget will be used to configure our plugin settings. """ import qt import os self.dialog = dialog ListViewDialog = self.dialog.ListViewDialog class TableDialog(ListViewDialog): def __init__(self, mainwidget): ListViewDialog.__init__(self,mainwidget,"Tables") self.mainwidget = mainwidget self.listview.addColumn("Name") text = str(self.mainwidget.tableedit.text()) item = None for table in self.mainwidget.plugin.database.tables(): if item == None: item = qt.QListViewItem(self.listview,table) else: item = qt.QListViewItem(self.listview,item,table) if table == text: self.listview.setSelected(item,True) self.listview.ensureItemVisible(item) qt.QObject.connect(self.listview, qt.SIGNAL("doubleClicked(QListViewItem*, const QPoint&, int)"), self.okClicked) qt.QObject.connect(self.okbtn, qt.SIGNAL("clicked()"), self.okClicked) def okClicked(self): item = self.listview.selectedItem() if item == None: self.mainwidget.tableedit.setText("") else: self.mainwidget.tableedit.setText(item.text(0)) self.close() class FieldsDialog(ListViewDialog): def __init__(self, mainwidget): ListViewDialog.__init__(self,parent,"Fields") self.mainwidget = mainwidget self.listview.setSelectionMode(qt.QListView.Multi) self.listview.setSorting(-1) self.listview.header().setClickEnabled(False) self.listview.addColumn("Name") self.listview.addColumn("Type") self.listview.addColumn("Options") tablename = str(self.mainwidget.tableedit.text()) recinfo = self.mainwidget.plugin.database.recordInfo(tablename) if recinfo != None: fieldslist = str(self.mainwidget.fieldedit.text()).split(",") allfields = ("*" in fieldslist) item = None for fieldinfo in recinfo: opts = "" for s in ('Required','Calculated'): #,'Generated'): if getattr(fieldinfo,"is%s" % s)(): opts += "%s " % s item = self.addItem((fieldinfo.name(), qt.QVariant.typeToName(fieldinfo.type()), opts),item) if allfields or fieldinfo.name() in fieldslist: self.listview.setSelected(item,True) qt.QObject.connect(self.okbtn, qt.SIGNAL("clicked()"), self.okClicked) def okClicked(self): selitems = [] item = self.listview.firstChild() while item: if item.isSelected(): selitems.append(str(item.text(0))) item = item.nextSibling() self.mainwidget.fieldedit.setText(",".join(selitems)) self.close() class MainWidget(qt.QHBox): def __init__(self,plugin,dialog,parent): import qt import qtsql qt.QHBox.__init__(self,parent) self.dialog = dialog self.plugin = plugin self.connectionbox = qt.QVBox(parent) self.connectionbox.setSpacing(2) driverbox = qt.QHBox(self.connectionbox) driverlabel = qt.QLabel("Driver:",driverbox) self.driveredit = qt.QComboBox(driverbox) for driver in qtsql.QSqlDatabase.drivers(): self.driveredit.insertItem(driver) if self.plugin.options['driver'] == driver: self.driveredit.setCurrentItem(self.driveredit.count() - 1) driverlabel.setBuddy(self.driveredit) driverbox.setStretchFactor(self.driveredit,1) hostbox = qt.QHBox(self.connectionbox) hostlabel = qt.QLabel("Hostname:",hostbox) self.hostedit = qt.QLineEdit(self.plugin.options['hostname'],hostbox) hostlabel.setBuddy(self.hostedit) hostbox.setStretchFactor(self.hostedit,1) portbox = qt.QHBox(self.connectionbox) portlabel = qt.QLabel("Port:",portbox) self.portedit = qt.QLineEdit(str(self.plugin.options['port']),portbox) portlabel.setBuddy(self.portedit) portbox.setStretchFactor(self.portedit,1) userbox = qt.QHBox(self.connectionbox) userlabel = qt.QLabel("Username:",userbox) self.useredit = qt.QLineEdit(self.plugin.options['username'],userbox) userlabel.setBuddy(self.useredit) userbox.setStretchFactor(self.useredit,1) passbox = qt.QHBox(self.connectionbox) passlabel = qt.QLabel("Password:",passbox) self.passedit = qt.QLineEdit(self.plugin.options['password'],passbox) self.passedit.setEchoMode(qt.QLineEdit.Password) passlabel.setBuddy(self.passedit) passbox.setStretchFactor(self.passedit,1) dbbox = qt.QHBox(self.connectionbox) dblabel = qt.QLabel("Database:",dbbox) self.dbedit = qt.QLineEdit(self.plugin.options['database'],dbbox) dblabel.setBuddy(self.dbedit) dbbox.setStretchFactor(self.dbedit,1) statusbar = qt.QHBox(parent) statusbar.setSpacing(2) statusbar.setStretchFactor(qt.QWidget(statusbar),1) self.connectbtn = qt.QPushButton("Connect",statusbar) qt.QObject.connect(self.connectbtn, qt.SIGNAL("clicked()"),self.connectClicked) self.disconnectbtn = qt.QPushButton("Disconnect",statusbar) self.disconnectbtn.setEnabled(False) qt.QObject.connect(self.disconnectbtn, qt.SIGNAL("clicked()"),self.disconnectClicked) tablebox = qt.QHBox(parent) tablelabel = qt.QLabel("Table:",tablebox) self.tableedit = qt.QLineEdit(self.plugin.options['table'],tablebox) qt.QObject.connect(self.tableedit, qt.SIGNAL("textChanged(const QString&)"), self.tableEditChanged) self.tablebtn = qt.QPushButton("...",tablebox) self.tablebtn.setEnabled(False) qt.QObject.connect(self.tablebtn, qt.SIGNAL("clicked()"), self.tableBtnClicked) tablelabel.setBuddy(self.tableedit) tablebox.setStretchFactor(self.tableedit,1) fieldbox = qt.QHBox(parent) fieldlabel = qt.QLabel("Fields:",fieldbox) self.fieldedit = qt.QLineEdit(self.plugin.options['fields'],fieldbox) self.fieldbtn = qt.QPushButton("...",fieldbox) self.fieldbtn.setEnabled(False) qt.QObject.connect(self.fieldbtn, qt.SIGNAL("clicked()"), self.fieldBtnClicked) fieldlabel.setBuddy(self.fieldedit) fieldbox.setStretchFactor(self.fieldedit,1) if self.plugin.plugintype == "Source": box = qt.QHBox(parent) wherelabel = qt.QLabel("Where:",box) self.whereedit = qt.QLineEdit(self.plugin.options['where'],box) wherelabel.setBuddy(self.whereedit) box.setStretchFactor(self.whereedit,1) elif self.plugin.plugintype == "Destination": class OperationBox(qt.QVBox): def __init__(self, mainwidget, parent): self.mainwidget = mainwidget qt.QVBox.__init__(self, parent) opbox = qt.QHBox(self) operationlabel = qt.QLabel("Operation:",opbox) self.mainwidget.operationedit = qt.QComboBox(opbox) for op in ('Insert','Update'): self.mainwidget.operationedit.insertItem(op) if self.mainwidget.plugin.options['operation'] == op: self.mainwidget.operationedit.setCurrentItem(self.mainwidget.operationedit.count() - 1) operationlabel.setBuddy(self.mainwidget.operationedit) opbox.setStretchFactor(self.mainwidget.operationedit,1) self.box = None qt.QObject.connect(self.mainwidget.operationedit, qt.SIGNAL("activated(int)"), self.operationActivated) self.operationActivated() def operationActivated(self, **args): if self.box: self.box.hide() self.box.destroy() self.box = None def showInsert(self): pass def showUpdate(self): self.box = qt.QHBox(self) indexlabel = qt.QLabel("Indexfield:", self.box) self.mainwidget.indexedit = qt.QLineEdit(self.mainwidget.plugin.options['indexfield'], self.box) indexlabel.setBuddy(self.mainwidget.indexedit) self.box.setStretchFactor(self.mainwidget.indexedit,1) { 0: showInsert, 1: showUpdate, }[ self.mainwidget.operationedit.currentItem() ](self) if self.box != None: self.box.show() OperationBox(self,parent) def tableEditChanged(self,text): if self.plugin.database != None and self.plugin.database.isOpen(): if str(text) in self.plugin.database.tables(): self.fieldbtn.setEnabled(True) return self.fieldbtn.setEnabled(False) def tableBtnClicked(self): dialog = TableDialog(self) dialog.show() def fieldBtnClicked(self): dialog = FieldsDialog(self) dialog.show() def updateConnectState(self): connected = self.plugin.database != None and self.plugin.database.isOpen() self.connectionbox.setEnabled(not connected) self.connectbtn.setEnabled(not connected) self.disconnectbtn.setEnabled(connected) self.tablebtn.setEnabled(connected) self.tableEditChanged(self.tableedit.text()) def getOptionValue(self,optionname): try: if optionname == 'driver': return str(self.driveredit.currentText()) if optionname == 'hostname': return str(self.hostedit.text()) if optionname == 'port': return str(self.portedit.text()) if optionname == 'username': return str(self.useredit.text()) if optionname == 'password': return str(self.passedit.text()) if optionname == 'database': return str(self.dbedit.text()) if optionname == 'table': return str(self.tableedit.text()) if optionname == 'fields': return str(self.fieldedit.text()) if optionname == 'where': return str(self.whereedit.text()) if optionname == 'operation': return str(self.operationedit.currentText()) if optionname == 'indexfield': return str(self.indexedit.text()) except: import traceback print "".join( traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) ) return "" def connectClicked(self): if self.plugin.database != None and self.plugin.database.isOpen(): print "already connected. not needed to reconnect..." self.updateConnectState() return True print "trying to connect..." import qtsql drivername = str(self.driveredit.currentText()) print "drivername: %s" % drivername connectionname = "CopyCenter%s" % self.plugin.plugintype print "connectionname: %s" % connectionname self.plugin.database = qtsql.QSqlDatabase.addDatabase(drivername,connectionname) if not self.plugin.database: qt.QMessageBox.critical(self,"Failed to connect","Failed to create database for driver \"%s\"" % drivername) return False hostname = str(self.hostedit.text()) self.plugin.database.setHostName(hostname) portnumber = int(str(self.portedit.text())) self.plugin.database.setPort(portnumber) username = str(self.useredit.text()) self.plugin.database.setUserName(username) password = str(self.passedit.text()) self.plugin.database.setPassword(password) databasename = str(self.dbedit.text()) self.plugin.database.setDatabaseName(databasename) if not self.plugin.database.open(): qt.QMessageBox.critical(self,"Failed to connect","%s

%s
" % (self.plugin.database.lastError().driverText(),self.plugin.database.lastError().databaseText())) return False print "database is opened now!" self.updateConnectState() return True def disconnectClicked(self): print "trying to disconnect..." if self.plugin.database: self.plugin.database.close() self.plugin.database = None print "database is closed now!" self.updateConnectState() plugin.widget = MainWidget(plugin,self.dialog,parent) return plugin.widget