PyQt4 How to send push button signal to another class in Python? - python

I need your advice and help for my code.
I am making a GUI program. Basically the program does the followings:
Gets input from the user
When a certain button is pushed, the program retrieves all the input and saved them in the database
The program does computations.
Shows the output
Here is the simple version of the program, calculator program:
As you can see in the figure, it takes 4 input from user, (1) any integer for var1, (2) any integer for var2, (3) operator (addition or subtraction) and (4) click button.
The GUI was designed using QtDesigner.
And here is my code:
import sys
import sqlite3
from PyQt4 import QtCore, QtGui
from testgui import Ui_MainWindow
class ShowAndInput(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
#connect to the database
self.connect_to_db()
#create table in the database
self.create_table()
#add items to the comboBox
self.add_items()
#calculate button to start calculating, gives signal to the next class Calculate
self.ui.pushButton_3.clicked.connect(self.calculate)
#close button to close the window
QtCore.QObject.connect(self.ui.pushButton,QtCore.SIGNAL("clicked()"), quit)
self.conn.close()
def connect_to_db(self):
self.conn = sqlite3.connect('testguidb.sqlite3')
self.cur = self.conn.cursor()
def create_table(self):
self.cur.execute('''CREATE TABLE IF NOT EXISTS Input (var1 INTEGER, var2 INTEGER)''')
self.conn.commit()
def add_items(self):
lst = ['addition', 'subtraction']
self.ui.comboBox.clear()
self.ui.comboBox.addItems(lst)
def calculate(self):
calculate = Calculate(self)
calculate.exec_()
So the purpose of the first class was to show the GUI and take input from the user. If user clicks the pushbutton named 'Calculate', it should connect to the new class named 'Calculate'.
Here is my code for the Calculate class:
class Calculate(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
#validator to validate that the input is integer or digit
#connect to database
self.connect_to_db()
#get the input values and store them in the database
self.get_the_values()
#print the output
PrintOutcome()
def connect_to_db(self):
self.conn = sqlite3.connect('testguidb.sqlite3')
self.cur = self.conn.cursor()
def get_the_values(self):
dicti = {}
dicti['var1'] = self.ui.lineEdit.text()
dicti['var2'] = self.ui.lineEdit_2.text()
for key, val in sorted(dicti.items()):
key = str(key)
val = int(val)
self.cur.execute('INSERT OR IGNORE INTO Input (?) VALUES (?)',(key,val))
self.conn.commit()
And at the end of this class, it calls another class named 'PrintOutcome' to print out the result in the QTextBrowser. Here is the last piece of the code:
class PrintOutcome(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
#connect to database
self.connect_to_db()
#get the value of the combobox
self.get_combox()
#print the output
if self.operator == 'addition': self.print_add()
elif self.operator == 'subtraction': self.print_sub()
def connect_to_db(self):
self.conn = sqlite3.connect('testguidb.sqlite3')
self.cur = self.conn.cursor()
def get_combox(self):
self.operator = str(self.ui.comboBox.currentText())
def print_add(self):
dicti={}
for i in range(2):
i = i + 1
dicti['var{0}'.format(i)] = self.cur.execute('SELECT var{0} FROM Input'.format(i))
dicti['var{0}'.format(i)] = int(self.cur.fetchone()[0])
text = str(dicti['var{0}'.format(i)])
self.ui.textBrowser.append(text)
result = dicti['var1'] + dicti['var2']
textsep = '-'*25+'(+)'
text = str(result)
self.ui.textBrowser.append(text)
self.ui.textBrowser.append(text)
def print_sub(self):
dicti={}
for i in range(2):
i = i + 1
dicti['var{0}'.format(i)] = self.cur.execute('SELECT var{0} FROM Input'.format(i))
dicti['var{0}'.format(i)] = int(self.cur.fetchone()[0])
text = str(dicti['var{0}'.format(i)])
self.ui.textBrowser.append(text)
result = dicti['var1'] + dicti['var2']
textsep = '-'*25+'(-)'
text = str(result)
self.ui.textBrowser.append(text)
self.ui.textBrowser.append(text)
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
myapp = ShowAndInput()
myapp.show()
sys.exit(app.exec_())
When I ran it, everything was fine. But when I pressed the calculate button, it returned an error message.
Here is the error message: RuntimeError: super-class init() of type Calculate was never called.
Any respond will be much appreciated. Thanks a lot.
Regards,
Arnold

Related

Show completion list when qlineEdit textChanged

I can use the following command to show an auto completion list view if I have a predefined list
wordList =["alpha", "omega", "omicron", "zeta"]
completer = QCompleter(wordList)
ineEdit.setCompleter(completer)
I need a different case:, Type something in lineEdit, when textChanged it connect to a function def searchAction: via lineEdit.textChanged.connect(searchAction). Inside def searchAction: i have an sql query which updates a list (say data_list) for every string I type in the lineEdit . If set wordList as data_list it does not do anything. My question how can I show the data_list as a autocompletion something like in the image.
It is not necessary to create lists since QCompleter supports models so you can filter using QSqlQueryModel as shown below:
import os
import sys
from pathlib import Path
from PyQt5.QtWidgets import QApplication, QCompleter, QLineEdit
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
CURRENT_DIRECTORY = Path(__file__).resolve().parent
def create_connection(path):
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(path)
if not db.open():
print(db.lastError().text())
return False
return True
class SqlQueryCompleter(QCompleter):
def __init__(self, sql_model=None, parent=None):
super().__init__(sql_model, parent)
if sql_model is None:
sql_model = QSqlQueryModel(self)
elif not isinstance(sql_model, QSqlQueryModel):
raise ValueError(f"The {sql_model} must be an instance of QSqlQueryModel")
self.setModel(sql_model)
self.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
def splitPath(self, path):
if isinstance(self.model(), QSqlQueryModel):
self.model().setQuery(self.query(path))
return super().splitPath(path)
def query(self, path):
query = QSqlQuery("SELECT bar FROM 'foo' WHERE bar LIKE ?")
query.addBindValue(f"%{path}%")
if not query.exec_():
print(query.lastError().text())
return query
def main():
app = QApplication(sys.argv)
filename = os.fspath(CURRENT_DIRECTORY / "database.db")
if not create_connection(filename):
sys.exit(-1)
line_edit = QLineEdit()
line_edit.show()
completer = SqlQueryCompleter()
line_edit.setCompleter(completer)
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Program quit with error when using QCompleter

I'm writing a program with pyqt5 and want to make the QlineEdit show history input by using sqlite to store the inputs. I use a signal to catch the cursor when focusInEvent happens and select the history records at that time, then I put the results into QCompleter so it can pop up in QlineEdit. Now I can make the history inputs show in QlineEdit object but when I click on any value, 1s later, the whole program quit automatically with error, which says "Python has stopped".
class FocusLineEdit(QLineEdit):
ac = pyqtSignal(list)
def __init__(self, parent=None):
super(FocusLineEdit, self).__init__(parent)
self.ac.connect(self.addCompleter)
def focusInEvent(self, event):
rtl = call_history(self.objectName())
self.ac.emit(rtl)
def addCompleter(self, rtl):
self.autoCompleter = QCompleter(rtl)
self.autoCompleter.setCompletionMode(1)
self.setCompleter(self.autoCompleter)
def focusOutEvent(self, event):
pass
It is difficult to analyze where the problem is without you provide an MCVE, so my response implements what you require without taking into account your current code for it must meet the following requirements:
You must have 2 tables: objects and history that are related.
The table objects saves the name of the filtering history, it is similar to the use of the objectName that you use, but in general 2 widgets can access the same history if the connection establishes the same name
In the history table the information of the words associated with the id of the objects table is saved.
In my example I use the following instructions to create them:
CREATE TABLE IF NOT EXISTS objects (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE);
CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY AUTOINCREMENT, id_object INTEGER REFERENCES objects (id), word TEXT NOT NULL, UNIQUE (id_object, word));
Also to test it I created a data, if you already have data then you must eliminate the if test: and everything inside.
Finally for a better understanding of my solution I show a QTableView that is changing according to the selection.
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db_path = 'test.db'
db.setDatabaseName(db_path)
if not db.open():
QMessageBox.critical(None, qApp.tr("Cannot open database"),
qApp.tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information "
"how to build it.\n\n"
"Click Cancel to exit."),
QMessageBox.Cancel)
return False
test = True
if test:
query = QtSql.QSqlQuery()
if not query.exec_('CREATE TABLE IF NOT EXISTS objects (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE);'):
return False
if not query.exec_('CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY AUTOINCREMENT, id_object INTEGER REFERENCES objects (id), word TEXT NOT NULL, UNIQUE (id_object, word));'):
return False
for i in range(3):
query.prepare('INSERT INTO objects (name) VALUES (?)')
query.addBindValue("obj{}".format(i))
if not query.exec_():
print(query.lastError().text())
import requests
import random
word_site = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
response = requests.get(word_site)
WORDS = response.content.decode().splitlines()
print(WORDS)
for i in range(3):
for text in random.sample(WORDS, 50):
query.prepare('INSERT INTO history (id_object, word) VALUES (?, ?)')
query.addBindValue(i+1)
query.addBindValue(text)
if not query.exec_():
print(query.lastError().text())
return True
class Completer(QtWidgets.QCompleter):
def __init__(self, parent=None):
super(Completer, self).__init__(parent)
self._last_words = []
def splitPath(self, path):
if path[-1] != ' ':
words = path.split()
self._last_words = words[:-1] if len(words) > 1 else []
return [words[-1]]
else:
QtCore.QTimer.singleShot(0, self.popup().hide)
return []
def pathFromIndex(self, index):
val = super(Completer, self).pathFromIndex(index)
return ' '.join(self._last_words + [val])
class HistoryManager(QtCore.QObject):
nameChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(HistoryManager, self).__init__(parent)
model = QtSql.QSqlRelationalTableModel(self)
model.setTable("history")
model.setRelation(1, QtSql.QSqlRelation("objects", "id", "name"))
model.select()
self._proxy = QtCore.QSortFilterProxyModel(self)
self._proxy.setSourceModel(model)
self._proxy.setFilterKeyColumn(1)
# proxy.setFilterFixedString("obj1")
self._widgets = {}
self._completer = Completer(self)
self._completer.setModel(self._proxy)
self._completer.setCompletionColumn(2)
def register_widget(self, widget, objectname):
# TODO
if callable(getattr(widget, "setCompleter")):
widget.installEventFilter(self)
self._widgets[widget] = objectname
return True
return False
def eventFilter(self, obj, event):
if obj in self._widgets:
if event.type() == QtCore.QEvent.FocusIn:
name = self._widgets[obj]
self._proxy.setFilterFixedString(name)
obj.setCompleter(self._completer)
self.nameChanged.emit(name)
elif event.type() == QtCore.QEvent.FocusOut:
obj.setCompleter(None)
self._proxy.setFilterFixedString("")
self.nameChanged.emit("")
return super(HistoryManager, self).eventFilter(obj, event)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._manager = HistoryManager()
model = QtSql.QSqlRelationalTableModel(self)
model.setTable("history")
model.setRelation(1, QtSql.QSqlRelation("objects", "id", "name"))
model.select()
self._proxy = QtCore.QSortFilterProxyModel(self)
self._proxy.setSourceModel(model)
self._proxy.setFilterKeyColumn(1)
tv = QtWidgets.QTableView()
tv.setModel(self._proxy)
vlay = QtWidgets.QVBoxLayout()
for i in range(3):
le = QtWidgets.QLineEdit()
vlay.addWidget(le)
self._manager.register_widget(le, "obj{}".format(i))
vlay.addStretch()
lay = QtWidgets.QHBoxLayout(self)
lay.addWidget(tv, stretch=1)
lay.addLayout(vlay)
self._manager.nameChanged.connect(self._proxy.setFilterFixedString)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
manager = HistoryManager()
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

PYQT: QTableView. Filter Between Dates

I've created a GUI that allows users to modify, filter update and delete from a sqlite database. Everything is working great except the date range filter. When I run the code, I don't get an error, I only get a blank filtered screen with no data. Does anyone see what's wrong with my code? [Section 1a, subgroup{v} is what I am seeking help on]. Thanks!
from PyQt4 import QtCore, QtGui, QtSql
import sys
import sqlite3
import time
import Search #imported ui.py MainWindow file
import os
try:
from PyQt4.QtCore import QString
except ImportError:
QString = str
class TableEditor(QtGui.QMainWindow, Search.Search_MainWindow):
def __init__(self, tableName, parent=None):
super(self.__class__, self).__init__()
self.setupUi(self)
self.model = QtSql.QSqlTableModel(self)
self.model.setTable('CAUTI')
self.model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
self.model.select()
self.model.setHeaderData(0, QtCore.Qt.Horizontal, "MRN")
self.model.setHeaderData(1, QtCore.Qt.Horizontal, "Last Name")
self.model.setHeaderData(2, QtCore.Qt.Horizontal, "First Name")
self.model.setHeaderData(3, QtCore.Qt.Horizontal, "Date of Event")
self.model.setHeaderData(4, QtCore.Qt.Horizontal, "Facility")
self.model.setHeaderData(5, QtCore.Qt.Horizontal, "Unit")
self.model.setHeaderData(6, QtCore.Qt.Horizontal, "User")
self.tableView.setModel(self.model)
self.setWindowTitle("HAI Table")
self.tableView.setColumnWidth(0,100)
self.tableView.setColumnWidth(1,100)
self.tableView.setColumnWidth(2,100)
self.tableView.setColumnWidth(3,100)
self.tableView.setColumnWidth(4,100)
self.tableView.setColumnWidth(5,100)
self.tableView.setColumnWidth(6,83)
self.submitButton.clicked.connect(self.submit)
self.revertButton.clicked.connect(self.model.revertAll)
self.quitButton.clicked.connect(self.close)
current = QtCore.QDateTime.currentDateTime()
self.startDate.setDate(current.date())
self.endDate.setDate(current.date())
self.startDate.setDisplayFormat("M/dd/yyyy")
self.endDate.setDisplayFormat("M/dd/yyyy")
# Section 1: Signals
# {i} Search Fields Button Emitted:
# [1]
self.search_MRN_Button.clicked.connect(self.search_MRN_FilterRecord)
# [2]
self.search_Lname_Button.clicked.connect(self.search_Lname_FilterRecord)
# [3]
self.search_Unit_Button.clicked.connect(self.search_Unit_FilterRecord)
# {ii} Search Clear Buttons Emitted:
# [1]
self.search_MRN_CancelButton.clicked.connect(self.search_MRN_CancelButton_Clicked)
# [2]
self.search_Lname_CancelButton.clicked.connect(self.search_Lname_CancelButton_Clicked)
# [3]
self.search_Unit_CancelButton.clicked.connect(self.search_Unit_CancelButton_Clicked)
# {iii} Search Fields Button Emitted:
# [1]
self.search_MRN.selectionChanged.connect(self.search_MRN_Edit)
# [2]
self.search_Lname.selectionChanged.connect(self.search_Lname_Edit)
# [3]
self.search_Unit.selectionChanged.connect(self.search_Unit_Edit)
# {iv} Search Fields Button Emitted:
# [1]
self.search_MRN.returnPressed.connect(self.search_MRN_Enter)
# [2]
self.search_Lname.returnPressed.connect(self.search_Lname_Enter)
# [3]
self.search_Unit.returnPressed.connect(self.search_Unit_Enter)
#{v} Search Between 2 Dates
self.btnSubmit.clicked.connect(self.FilterBetweenDates)
# Section 1a: Slots from Section 1.
#{i} Search Field Button Slots:
#[1]
def search_MRN_FilterRecord(self):
text = self.search_MRN.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("MRN like'" +self.search_MRN.text()+ "%%'")
#self.model.setFilter("MRN = '%s'" % text)
#[2]
def search_Lname_FilterRecord(self):
text = self.search_Lname.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("Surname like'" +self.search_Lname.text()+ "%'")
#self.model.setFilter("Surname = '%s'" % text) #This line of code will only pull exact matches.
#[3]
def search_Unit_FilterRecord(self):
text = self.search_Unit.text()
if len(text) == 0:
self.model.setFilter("")
else:
self.model.setFilter("Unit like'" +self.search_Unit.text()+ "%'")
#self.model.setFilter("Unit = '%s'" % text) #This line of code will only pull exact matches.
#{ii} Search Field Cancel Button Slots:
#[1]
def search_MRN_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_MRN.setText("MRN Search")
#[2]
def search_Lname_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_Lname.setText("Last Name Search")
#[3]
def search_Unit_CancelButton_Clicked(self):
self.model.setFilter("")
self.search_Unit.setText("Unit Search")
#{iii} Search Text Edited Slots:
#[1]
def search_MRN_Edit(self):
self.search_MRN.setText("")
#[2]
def search_Lname_Edit(self):
self.search_Lname.setText("")
#[3]
def search_Unit_Edit(self):
self.search_Unit.setText("")
#{iv} Search Text Return Pressed (Enter) Slots:
#[1]
def search_MRN_Enter(self):
self.search_MRN_FilterRecord()
#[2]
def search_Lname_Enter(self):
self.search_Lname_FilterRecord()
#[3]
def search_Unit_Enter(self):
self.search_Unit_FilterRecord()
#{v} Filter Between Dates, Slot:
def FilterBetweenDates(self):
start = str(self.startDate.text())
finish = str(self.endDate.text())
self.model.setFilter("EventDate BETWEEN'" + start and finish)
def submit(self):
self.model.database().transaction()
if self.model.submitAll():
self.model.database().commit()
else:
self.model.database().rollback()
QtGui.QMessageBox.warning(self, "HAI Table",
"The database reported an error: %s" % self.model.lastError().text())
def main():
app = QtGui.QApplication(sys.argv)
#app.setStyle( "Plastique" )
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('HAI.db')
editor = TableEditor('CAUTI')
editor.show()
app.exec_()
if __name__ == '__main__':
The and in your filter text should part of the filter string. Now you are taking the logical-and of two strings (which will be the last string unless the first is empty) and append that to the filter string.
So change
self.model.setFilter("EventDate BETWEEN'" + start and finish)
to
filter = "EventDate BETWEEN '{}' AND '{}'".format(start, finish)
print(filter) # for debugging
self.model.setFilter(filter)
During debugging, it's probably a good idea to print the filter string and try it out in an SQL query (directly in the sqlite3 tool) so that you can see it works.

QCheckBox state change PyQt4

I'm trying to implement a system in PyQt4 where unchecking a checkbox would call function disable_mod and checking it would call enable_mod. But even though state is changing the checkboxes call the initial function they started with. For this case if an already checked box was clicked it'd always keep calling the disable_mod function! I don't understand why is this happening? Can you guys help me out here a little bit? Here's my code:
from PyQt4 import QtCore, QtGui
from os import walk
from os.path import join
import sys
def list_files_regex(dir):
l = []
for (root, dirnames, filenames) in walk(dir):
for d in dirnames:
list_files_regex(join(root, d))
l.extend(filenames)
return l
directory = "J:/test_pack"
directory = join(directory, "/mods")
count = 0
for y in list_files_regex(directory):
print y
count += 1
print count
class ModEdit(QtGui.QMainWindow):
def __init__(self, title, icon, x, y, w, h):
super(ModEdit, self).__init__()
self.setWindowTitle(title)
self.setWindowIcon(QtGui.QIcon(icon))
self.setGeometry(x, y, w, h)
self.choices = []
self.init()
def init(self):
scroll_widget = QtGui.QScrollArea()
sub_widget = QtGui.QWidget()
v_layout = QtGui.QVBoxLayout()
for y in list_files_regex(directory):
tmp = QtGui.QCheckBox(y, self)
tmp.resize(tmp.sizeHint())
if tmp.text()[len(tmp.text()) - 8: len(tmp.text())] != 'disabled':
tmp.setChecked(True)
# if tmp.isChecked() == 0:
# tmp.stateChanged.connect(self.enable_mod)
# if tmp.isChecked():
# tmp.stateChanged.connect(self.disable_mod)
# v_layout.addWidget(tmp)
self.choices.append(tmp)
print self.choices
for choice in self.choices:
v_layout.addWidget(choice)
if choice.isChecked():
choice.stateChanged.connect(self.disable_mod)
else:
choice.stateChanged.connect(self.enable_mod)
sub_widget.setLayout(v_layout)
scroll_widget.setWidget(sub_widget)
self.setCentralWidget(scroll_widget)
self.show()
def enable_mod(self):
print "ENABLE_TEST"
print self.choices[1].isChecked()
def disable_mod(self):
print "DISABLE_TEST"
print self.choices[1].isChecked()
def test(self):
print 'test'
for ch in self.choices:
if ch.isChecked():
ch.stateChanged.connect(self.disable_mod)
else:
ch.stateChanged.connect(self.enable_mod)
class Rename(QtCore.QObject):
enable = QtCore.pyqtSignal
disable = QtCore.pyqtSignal
app = QtGui.QApplication(sys.argv)
ex = ModEdit("Minecraft ModEdit", "ModEdit.png", 64, 64, 640, 480)
sys.exit(app.exec_())
The problem is that you're only connecting the checkbox stateChanged signal once during initialization. After the state of the checkbox changes, you're not disconnecting the signal and reconnecting it to the correct slot.
You'll need to connect the stateChanged signal to an intermediary slot that will decide which function to call based on the checkbox state. Since you're using the same slot for multiple checkboxes, it's probably best to also pass the checkbox to the slot as well.
from functools import partial
def init(self):
...
for tmp in list_of_checkboxes:
enable_slot = partial(self.enable_mod, tmp)
disable_slot = partial(self.disable_mod, tmp)
tmp.stateChanged.connect(lambda x: enable_slot() if x else disable_slot())
def enable_mod(self, checkbox):
print "ENABLE_TEST"
print checkbox.isChecked()
def disable_mod(self, checkbox):
print "DISABLE_TEST"
print checkbox.isChecked()
Alternatively, since we are now passing the checkbox to the slots, you could just use a single slot and check the checkbox state inside the slot
def init(self):
...
for tmp in list_of_checkboxes:
slot = partial(self.enable_disable_mod, tmp)
tmp.stateChanged.connect(lambda x: slot())
def enable_disable_mod(self, checkbox):
if checkbox.isChecked():
...
else:
...

pyqt Using QDataWidgetMapper to update row in database

I am trying to use the QDataWidgetmapper to update a row in the database but my issue is when trying to call the update function row is not a global variable and I have tried to use it in the same function that calls the Qdialog for the input int. I cannot get it to work. I have tried many variations but I am now at my wits end. I'm sure there is something simple I am missing but I am still learning python and pyqt.
import sys
from testdbtableform import *
from PyQt4 import QtSql, QtGui
def createConnection():
"""Creates the pyqt connection to the database"""
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('demo.db')
if db.open():
return True
else:
print db.lastError().text()
return False
class MyForm(QtGui.QDialog):
"""Creates the class"""
def __init__(self, parent=None):
"""Initiates the class"""
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.model = QtSql.QSqlRelationalTableModel(self)
self.model.setTable("userlist")
self.model.setSort(0, 0)
self.model.setEditStrategy(2)
self.model.select()
self.mapper = QtGui.QDataWidgetMapper(self)
self.mapper.setSubmitPolicy(1)
self.mapper.setModel(self.model)
self.mapper.addMapping(self.ui.lineEditUser, 0)
self.mapper.addMapping(self.ui.lineEditEmail, 1)
self.ui.tableView.setModel(self.model)
self.ui.pushSearch.clicked.connect(self.dbfilter)
self.ui.Submit.clicked.connect(self.dbinput)
self.ui.pushButton.clicked.connect(self.mapindex)
self.ui.updateButton.clicked.connect(self.updaterow)
self.ui.updateButton.hide()
def mapindex(self):
"""Function called to update a row in the tableview and database"""
i, ok = QtGui.QInputDialog.getInteger(self,
"Update Row", "Row:", 1, 1, 100, 1)
row = "%d" % i
row = int(row) - 1
if ok:
self.ui.Submit.hide()
self.ui.updateButton.show()
self.mapper.setCurrentIndex(row)
def updaterow(self):
"""Function to update data from line edits to the database"""
text1 = self.ui.lineEditUser.text()
text2 = self.ui.lineEditEmail.text()
self.model.setData(self.model.index(row, 0), str(text1).upper())
self.model.setData(self.model.index(row, 1), str(text2))
self.model.submitAll()
self.ui.lineEditUser.clear()
self.ui.lineEditEmail.clear()
self.ui.Submit.show()
self.ui.updateButton.hide()
def dbinput(self):
"""Function to input data from line edits to the database"""
self.model.insertRow(0)
text1 = self.ui.lineEditUser.text()
text2 = self.ui.lineEditEmail.text()
self.model.setData(self.model.index(0, 0), str(text1).upper())
self.model.setData(self.model.index(0, 1), str(text2))
self.model.submitAll()
self.ui.lineEditUser.clear()
self.ui.lineEditEmail.clear()
def dbfilter(self):
"""Function to search through the database for the username"""
self.model.setFilter("USERNAME like '"+self.ui.lineEditSearch.text()+"%'")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
if not createConnection():
sys.exit(1)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
Alright after banging my head against a wall for a few minutes and then just watching random youtube videos on random things davidb from the pyqt irc channel asked me "Is row the same as self.mapper.currentIndex()" so I chanaged row under the update function to row = self.mapper.currentIndex() and it worked. Something simple that I was over looking because I was getting frustrated. Below are the correct functions.
def mapindex(self):
"""Function called to update a row in the tableview and database"""
i, ok = QtGui.QInputDialog.getInteger(self,
"Update Row", "Row:", 1, 1, 100, 1)
row = "%d" % i
row = int(row) - 1
if ok:
self.ui.Submit.hide()
self.ui.updateButton.show()
self.mapper.setCurrentIndex(row)
def updaterow(self):
"""Function to update data from line edits to the database"""
text1 = self.ui.lineEditUser.text()
text2 = self.ui.lineEditEmail.text()
row = self.mapper.currentIndex() #being the missing link
self.model.setData(self.model.index(row, 0), str(text1).upper())
self.model.setData(self.model.index(row, 1), str(text2))
self.model.submitAll()
self.ui.lineEditUser.clear()
self.ui.lineEditEmail.clear()
self.ui.Submit.show()
self.ui.updateButton.hide()

Categories