You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kexi/plugins/scripting/scripts/copycenter/CopyCenterPluginQtSQL.py

496 lines
19 KiB

"""
CopyCenterPlugin to provide 'TQtSQL'.
Description:
This python-script is a plugin for the CopyCenter.py.
Author:
Sebastian Sauer <mail@dipe.org>
Copyright:
GPL v2 or higher.
"""
class CopyCenterPlugin:
""" The CopyCenterPlugin to provide 'TQtSQL' to CopyCenter.py """
name = "TQtSQL 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 Exception("Failed to connect with database.")
if self.database == None or not self.database.isOpen():
raise Exception("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': 'TQMYSQL3', #'TQMYSQL3','TQPSQL7','TQODBC3',...
'hostname': '127.0.0.1',
'port': 3306,
'username': 'root', #'MyUsername',
'password': '', #'MySecretPassword',
'database': '', #'MyTQtSQLDatabase',
'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())
from TQt import tqt
from TQt import tqtsql
self.cursor = tqtsql.TQSqlCursor(tablename,True,self.database)
self.cursor.setFilter(wherestatement)
if not self.cursor.select():
raise Exception("Select on cursor failed.<br>%s<br>%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 Exception("There exists no such field \"%s\" in the table \"%s\"." % (fn,tablename))
self.fieldlist.append(str(field.name()))
if len(self.fieldlist) < 1:
raise Exception("No fields for table \"%s\" defined." % tablename)
copierer.appendProgressMessage("SQL: %s" % str(self.cursor.executedQuery()))
def read(self):
if not next(self.cursor):
return None
record = []
for fieldname in self.fieldlist:
record.append( str(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': 'TQMYSQL3', #'TQMYSQL3','TQPSQL7','TQODBC3',...
'hostname': '127.0.0.1',
'port': 3306,
'username': 'root', #'MyUsername',
'password': '', #'MySecretPassword',
'database': '', #'MyTQtSQLDatabase',
'table': '', #'table2',
'fields': '', #'field1,field2',
'operation': 'Insert', #'Insert','Update'...
'indexfield': '',
}
def init(self,copierer):
self._init(copierer)
from TQt import tqt
from TQt import tqtsql
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 = tqtsql.TQSqlCursor(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 Exception("Select on cursor failed.<br>%s<br>%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 Exception("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)
from TQt import tqt
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 = tqt.TQVariant()
else:
v = tqt.TQVariant(r)
cursorrecord.setValue(self.fieldlist[i], v)
rowcount = self.cursor.insert()
if rowcount < 1:
drv = str(self.cursor.lastError().driverText()).encode("latin-1")
db = str(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 Exception("No index-field defined.")
pkindex = self.cursor.index(self.indexfieldname)
if not pkindex: raise Exception("Invalid index-field defined.")
self.cursor.setPrimaryIndex(pkindex)
#self.cursor.setMode( tqtsql.TQSqlCursor.Insert | tqtsql.TQSqlCursor.Update )
self.copierer.appendProgressMessage("Update SQL: %s" % str(self.cursor.executedQuery()))
def writeUpdate(self, record):
from TQt import tqt
# 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 Exception("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 Exception("Select on cursor failed.<br>%s<br>%s" % ( str(self.cursor.lastError().driverText()),str(self.cursor.lastError().databaseText()) ))
if not next(self.cursor):
#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 = tqt.TQVariant()
else:
v = tqt.TQVariant(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 tqt.TQWidget back to the
CopyCenter.py. The widget will be used to configure our
plugin settings. """
from TQt import tqt
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 = tqt.TQListViewItem(self.listview,table)
else:
item = tqt.TQListViewItem(self.listview,item,table)
if table == text:
self.listview.setSelected(item,True)
self.listview.ensureItemVisible(item)
tqt.TQObject.connect(self.listview, tqt.TQ_SIGNAL("doubleClicked(TQListViewItem*, const TQPoint&, int)"), self.okClicked)
tqt.TQObject.connect(self.okbtn, tqt.TQ_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(tqt.TQListView.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(), tqt.TQVariant.typeToName(fieldinfo.type()), opts),item)
if allfields or fieldinfo.name() in fieldslist:
self.listview.setSelected(item,True)
tqt.TQObject.connect(self.okbtn, tqt.TQ_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(tqt.TQHBox):
def __init__(self,plugin,dialog,parent):
from TQt import tqt
from TQt import tqtsql
tqt.TQHBox.__init__(self,parent)
self.dialog = dialog
self.plugin = plugin
self.connectionbox = tqt.TQVBox(parent)
self.connectionbox.setSpacing(2)
driverbox = tqt.TQHBox(self.connectionbox)
driverlabel = tqt.TQLabel("Driver:",driverbox)
self.driveredit = tqt.TQComboBox(driverbox)
for driver in tqtsql.TQSqlDatabase.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 = tqt.TQHBox(self.connectionbox)
hostlabel = tqt.TQLabel("Hostname:",hostbox)
self.hostedit = tqt.TQLineEdit(self.plugin.options['hostname'],hostbox)
hostlabel.setBuddy(self.hostedit)
hostbox.setStretchFactor(self.hostedit,1)
portbox = tqt.TQHBox(self.connectionbox)
portlabel = tqt.TQLabel("Port:",portbox)
self.portedit = tqt.TQLineEdit(str(self.plugin.options['port']),portbox)
portlabel.setBuddy(self.portedit)
portbox.setStretchFactor(self.portedit,1)
userbox = tqt.TQHBox(self.connectionbox)
userlabel = tqt.TQLabel("Username:",userbox)
self.useredit = tqt.TQLineEdit(self.plugin.options['username'],userbox)
userlabel.setBuddy(self.useredit)
userbox.setStretchFactor(self.useredit,1)
passbox = tqt.TQHBox(self.connectionbox)
passlabel = tqt.TQLabel("Password:",passbox)
self.passedit = tqt.TQLineEdit(self.plugin.options['password'],passbox)
self.passedit.setEchoMode(tqt.TQLineEdit.Password)
passlabel.setBuddy(self.passedit)
passbox.setStretchFactor(self.passedit,1)
dbbox = tqt.TQHBox(self.connectionbox)
dblabel = tqt.TQLabel("Database:",dbbox)
self.dbedit = tqt.TQLineEdit(self.plugin.options['database'],dbbox)
dblabel.setBuddy(self.dbedit)
dbbox.setStretchFactor(self.dbedit,1)
statusbar = tqt.TQHBox(parent)
statusbar.setSpacing(2)
statusbar.setStretchFactor(tqt.TQWidget(statusbar),1)
self.connectbtn = tqt.TQPushButton("Connect",statusbar)
tqt.TQObject.connect(self.connectbtn, tqt.TQ_SIGNAL("clicked()"),self.connectClicked)
self.disconnectbtn = tqt.TQPushButton("Disconnect",statusbar)
self.disconnectbtn.setEnabled(False)
tqt.TQObject.connect(self.disconnectbtn, tqt.TQ_SIGNAL("clicked()"),self.disconnectClicked)
tablebox = tqt.TQHBox(parent)
tablelabel = tqt.TQLabel("Table:",tablebox)
self.tableedit = tqt.TQLineEdit(self.plugin.options['table'],tablebox)
tqt.TQObject.connect(self.tableedit, tqt.TQ_SIGNAL("textChanged(const TQString&)"), self.tableEditChanged)
self.tablebtn = tqt.TQPushButton("...",tablebox)
self.tablebtn.setEnabled(False)
tqt.TQObject.connect(self.tablebtn, tqt.TQ_SIGNAL("clicked()"), self.tableBtnClicked)
tablelabel.setBuddy(self.tableedit)
tablebox.setStretchFactor(self.tableedit,1)
fieldbox = tqt.TQHBox(parent)
fieldlabel = tqt.TQLabel("Fields:",fieldbox)
self.fieldedit = tqt.TQLineEdit(self.plugin.options['fields'],fieldbox)
self.fieldbtn = tqt.TQPushButton("...",fieldbox)
self.fieldbtn.setEnabled(False)
tqt.TQObject.connect(self.fieldbtn, tqt.TQ_SIGNAL("clicked()"), self.fieldBtnClicked)
fieldlabel.setBuddy(self.fieldedit)
fieldbox.setStretchFactor(self.fieldedit,1)
if self.plugin.plugintype == "Source":
box = tqt.TQHBox(parent)
wherelabel = tqt.TQLabel("Where:",box)
self.whereedit = tqt.TQLineEdit(self.plugin.options['where'],box)
wherelabel.setBuddy(self.whereedit)
box.setStretchFactor(self.whereedit,1)
elif self.plugin.plugintype == "Destination":
class OperationBox(tqt.TQVBox):
def __init__(self, mainwidget, parent):
self.mainwidget = mainwidget
tqt.TQVBox.__init__(self, parent)
opbox = tqt.TQHBox(self)
operationlabel = tqt.TQLabel("Operation:",opbox)
self.mainwidget.operationedit = tqt.TQComboBox(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
tqt.TQObject.connect(self.mainwidget.operationedit, tqt.TQ_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 = tqt.TQHBox(self)
indexlabel = tqt.TQLabel("Indexfield:", self.box)
self.mainwidget.indexedit = tqt.TQLineEdit(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...")
from TQt import tqtsql
drivername = str(self.driveredit.currentText())
print("drivername: %s" % drivername)
connectionname = "CopyCenter%s" % self.plugin.plugintype
print("connectionname: %s" % connectionname)
self.plugin.database = tqtsql.TQSqlDatabase.addDatabase(drivername,connectionname)
if not self.plugin.database:
tqt.TQMessageBox.critical(self,"Failed to connect","<qt>Failed to create database for driver \"%s\"</qt>" % 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():
tqt.TQMessageBox.critical(self,"Failed to connect","<qt>%s<br><br>%s</qt>" % (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