SqlBrowser/SqlBrowserWidget.py

changeset 0
de9c2efb9d02
child 7
c679fb30c8f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SqlBrowser/SqlBrowserWidget.py	Mon Dec 28 16:03:33 2009 +0000
@@ -0,0 +1,300 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the SQL Browser widget.
+"""
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4.QtSql import QSqlDatabase, QSqlError, QSqlTableModel, QSqlQueryModel, QSqlQuery
+
+from SqlConnectionDialog import SqlConnectionDialog
+
+from Ui_SqlBrowserWidget import Ui_SqlBrowserWidget
+
+class SqlBrowserWidget(QWidget, Ui_SqlBrowserWidget):
+    """
+    Class implementing the SQL Browser widget.
+    
+    @signal statusMessage(string) emitted to show a status message
+    """
+    cCount = 0
+    
+    def __init__(self, parent = None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        QWidget.__init__(self, parent)
+        self.setupUi(self)
+        
+        self.table.addAction(self.insertRowAction)
+        self.table.addAction(self.deleteRowAction)
+        
+        if len(QSqlDatabase.drivers()) == 0:
+            QMessageBox.information(None,
+                self.trUtf8("No database drivers found"),
+                self.trUtf8("""This tool requires at least one Qt database driver. """
+                """Please check the Qt documentation how to build the """
+                """Qt SQL plugins."""))
+        
+        self.connect(self.connections, SIGNAL("tableActivated(QString)"), 
+                     self.on_connections_tableActivated)
+        self.connect(self.connections, SIGNAL("schemaRequested(QString)"), 
+                     self.on_connections_schemaRequested)
+        self.connect(self.connections, SIGNAL("cleared()"), 
+                     self.on_connections_cleared)
+        
+        self.emit(SIGNAL("statusMessage(QString)"), self.trUtf8("Ready"))
+    
+    @pyqtSlot()
+    def on_clearButton_clicked(self):
+        """
+        Private slot to clear the SQL entry widget.
+        """
+        self.sqlEdit.clear()
+        self.sqlEdit.setFocus()
+    
+    @pyqtSlot()
+    def on_executeButton_clicked(self):
+        """
+        Private slot to execute the entered SQL query.
+        """
+        self.executeQuery()
+        self.sqlEdit.setFocus()
+    
+    @pyqtSlot()
+    def on_insertRowAction_triggered(self):
+        """
+        Private slot handling the action to insert a new row.
+        """
+        self.__insertRow()
+    
+    @pyqtSlot()
+    def on_deleteRowAction_triggered(self):
+        """
+        Private slot handling the action to delete a row.
+        """
+        self.__deleteRow()
+    
+    @pyqtSlot(str)
+    def on_connections_tableActivated(self, table):
+        """
+        Private slot to show the contents of a table.
+        
+        @param table name of the table for which to show the contents (string)
+        """
+        self.showTable(table)
+    
+    @pyqtSlot(str)
+    def on_connections_schemaRequested(self, table):
+        """
+        Private slot to show the schema of a table.
+        
+        @param table name of the table for which to show the schema (string)
+        """
+        self.showSchema(table)
+    
+    @pyqtSlot()
+    def on_connections_cleared(self):
+        """
+        Private slot to clear the table.
+        """
+        model = QStandardItemModel(self.table)
+        self.table.setModel(model)
+        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
+        
+        self.updateActions()
+    
+    def addConnection(self, driver, dbName, user, password, host, port):
+        """
+        Public method to add a database connection.
+        
+        @param driver name of the Qt database driver (string)
+        @param dbName name of the database (string)
+        @param user user name (string)
+        @param password password (string)
+        @param host host name (string)
+        @param port port number (integer)
+        """
+        err = QSqlError()
+        
+        self.__class__.cCount += 1
+        db = QSqlDatabase.addDatabase(driver.upper(), 
+                                      "Browser%d" % self.__class__.cCount)
+        db.setDatabaseName(dbName)
+        db.setHostName(host)
+        db.setPort(port)
+        if not db.open(user, password):
+            err = db.lastError()
+            db = QSqlDatabase()
+            QSqlDatabase.removeDatabase("Browser%d" % self.__class__.cCount)
+        
+        self.connections.refresh()
+        
+        return err
+    
+    def addConnectionByDialog(self):
+        """
+        Public slot to add a database connection via an input dialog.
+        """
+        dlg = SqlConnectionDialog(self)
+        if dlg.exec_() == QDialog.Accepted:
+            driver, dbName, user, password, host, port = dlg.getData()
+            err = self.addConnection(driver, dbName, user, password, host, port)
+            
+            if err.type() != QSqlError.NoError:
+                QMessageBox.warning(self,
+                    self.trUtf8("Unable to open database"),
+                    self.trUtf8("""An error occurred while opening the connection."""))
+    
+    def showTable(self, table):
+        """
+        Public slot to show the contents of a table.
+        
+        @param table name of the table to be shown (string)
+        """
+        model = QSqlTableModel(self.table, self.connections.currentDatabase())
+        model.setEditStrategy(QSqlTableModel.OnRowChange)
+        model.setTable(table)
+        model.select()
+        if model.lastError().type() != QSqlError.NoError:
+            self.emit(SIGNAL("statusMessage(QString)"), model.lastError().text())
+        self.table.setModel(model)
+        self.table.setEditTriggers(
+            QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed)
+        
+        self.table.resizeColumnsToContents()
+        
+        self.connect(self.table.selectionModel(), 
+                     SIGNAL("currentRowChanged(QModelIndex, QModelIndex)"), 
+                     self.updateActions)
+        
+        self.updateActions()
+    
+    def showSchema(self, table):
+        """
+        Public slot to show the schema of a table.
+        
+        @param table name of the table to be shown (string)
+        """
+        rec = self.connections.currentDatabase().record(table)
+        model = QStandardItemModel(self.table)
+        
+        model.insertRows(0, rec.count())
+        model.insertColumns(0, 7)
+        
+        model.setHeaderData(0, Qt.Horizontal, QVariant("Fieldname"))
+        model.setHeaderData(1, Qt.Horizontal, QVariant("Type"))
+        model.setHeaderData(2, Qt.Horizontal, QVariant("Length"))
+        model.setHeaderData(3, Qt.Horizontal, QVariant("Precision"))
+        model.setHeaderData(4, Qt.Horizontal, QVariant("Required"))
+        model.setHeaderData(5, Qt.Horizontal, QVariant("Auto Value"))
+        model.setHeaderData(6, Qt.Horizontal, QVariant("Default Value"))
+        
+        for i in range(rec.count()):
+            fld = rec.field(i)
+            model.setData(model.index(i, 0), QVariant(fld.name()))
+            if fld.typeID() == -1:
+                model.setData(model.index(i, 1), 
+                              QVariant(QVariant.typeToName(fld.type())))
+            else:
+                model.setData(model.index(i, 1), QVariant("%s1 (%s)" % (\
+                                                 QVariant.typeToName(fld.type()), 
+                                                 fld.typeID())))
+            if fld.length() < 0:
+                model.setData(model.index(i, 2), QVariant("?"))
+            else:
+                model.setData(model.index(i, 2), QVariant(fld.length()))
+            if fld.precision() < 0:
+                model.setData(model.index(i, 3), QVariant("?"))
+            else:
+                model.setData(model.index(i, 3), QVariant(fld.precision()))
+            if fld.requiredStatus() == -1:
+                model.setData(model.index(i, 4), QVariant("?"))
+            else:
+                model.setData(model.index(i, 4), QVariant(bool(fld.requiredStatus())))
+            model.setData(model.index(i, 5), QVariant(fld.isAutoValue()))
+            model.setData(model.index(i, 6), QVariant(fld.defaultValue()))
+        
+        self.table.setModel(model)
+        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
+        
+        self.table.resizeColumnsToContents()
+        
+        self.updateActions()
+    
+    def updateActions(self):
+        """
+        Public slot to update the actions.
+        """
+        enableIns = isinstance(self.table.model(), QSqlTableModel)
+        enableDel = enableIns & self.table.currentIndex().isValid()
+        
+        self.insertRowAction.setEnabled(enableIns)
+        self.deleteRowAction.setEnabled(enableDel)
+    
+    def __insertRow(self):
+        """
+        Privat slot to insert a row into the database table.
+        """
+        model = self.table.model()
+        if not isinstance(model, QSqlTableModel):
+            return
+        
+        insertIndex = self.table.currentIndex()
+        if insertIndex.row() == -1:
+            row = 0
+        else:
+            row = insertIndex.row()
+        model.insertRow(row)
+        insertIndex = model.index(row, 0)
+        self.table.setCurrentIndex(insertIndex)
+        self.table.edit(insertIndex)
+    
+    def __deleteRow(self):
+        """
+        Privat slot to delete a row from the database table.
+        """
+        model = self.table.model()
+        if not isinstance(model, QSqlTableModel):
+            return
+        
+        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
+        
+        currentSelection = self.table.selectionModel().selectedIndexes()
+        for selectedIndex in currentSelection:
+            if selectedIndex.column() != 0:
+                continue
+            model.removeRow(selectedIndex.row())
+        
+        model.submitAll()
+        model.setEditStrategy(QSqlTableModel.OnRowChange)
+        
+        self.updateActions()
+    
+    def executeQuery(self):
+        """
+        Public slot to execute the entered query.
+        """
+        model = QSqlQueryModel(self.table)
+        model.setQuery(
+            QSqlQuery(self.sqlEdit.toPlainText(), self.connections.currentDatabase()))
+        self.table.setModel(model)
+        
+        if model.lastError().type() != QSqlError.NoError:
+            self.emit(SIGNAL("statusMessage(QString)"), model.lastError().text())
+        elif model.query().isSelect():
+            self.emit(SIGNAL("statusMessage(QString)"), self.trUtf8("Query OK."))
+        else:
+            self.emit(SIGNAL("statusMessage(QString)"), 
+                self.trUtf8("Query OK, number of affected rows: {0}")\
+                    .format(model.query().numRowsAffected()))
+        
+        self.table.resizeColumnsToContents()
+        
+        self.updateActions()

eric ide

mercurial