]> git.zarvox.org Git - wp3.git/blob - editperson.py
Transparently convert UINs into NetIDs, for people who can't follow instructions...
[wp3.git] / editperson.py
1 from PyQt4.QtCore import *
2 from PyQt4.QtGui import *
3 from PyQt4.QtSql import *
4
5 class EditPerson(QWidget):
6         def __init__(self, parent=None, db=None):
7                 QWidget.__init__(self,parent)
8                 self.db = db
9
10                 self.model = QSqlTableModel(self, self.db)
11                 self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
12                 self.model.setTable("people")
13                 self.model.select()
14                 self.model.setHeaderData(self.model.fieldIndex("forename"), Qt.Horizontal, QVariant("First Name"))
15                 self.model.setHeaderData(self.model.fieldIndex("surname"), Qt.Horizontal, QVariant("Last Name"))
16
17                 self.tableview = QTableView(self)
18                 self.tableview.setSelectionBehavior(QAbstractItemView.SelectRows)
19                 self.tableview.setSelectionMode(QAbstractItemView.SingleSelection)
20                 self.tableview.setEditTriggers(QAbstractItemView.NoEditTriggers)
21                 self.tableview.setModel(self.model)
22
23                 for i in xrange(self.model.columnCount()):
24                         self.tableview.hideColumn(i)
25                 self.tableview.showColumn(self.model.fieldIndex("forename"))
26                 self.tableview.showColumn(self.model.fieldIndex("surname"))
27                 self.tableview.resizeColumnsToContents()
28
29                 self.setWindowTitle("Edit records")
30                 self.toplayout = QHBoxLayout() # Master layout
31                 
32                 self.leftpanel = QVBoxLayout() # Contains user search and select
33                 self.search_label = QLabel("F&ilter by name:")
34                 self.search_bar = QLineEdit()
35                 self.search_label.setBuddy(self.search_bar)
36                 self.searchpair = QHBoxLayout()
37                 self.searchpair.addWidget(self.search_label)
38                 self.searchpair.addWidget(self.search_bar)
39                 self.leftpanel.addLayout(self.searchpair)
40                 self.leftpanel.addWidget(self.tableview)
41                 
42                 self.rightpanel = QVBoxLayout() # Contains fields and buttons
43                 self.setupForm()
44
45
46                 self.rightpanel.addLayout(self.formlayout)
47                 self.rightpanel.addLayout(self.buttonlayout)
48
49                 self.toplayout.addLayout(self.leftpanel)
50                 self.toplayout.addSpacing(10)
51                 self.toplayout.addLayout(self.rightpanel)
52
53                 self.setLayout(self.toplayout)
54                 self.setupActions()
55                 self.resize(800,600)
56                 self.show()
57                 
58
59         def setupForm(self):
60                 self.current_record = QSqlRecord()
61                 self.current_row = -1
62                 # Text labels
63                 self.netid_lab = QLabel("NetID:")
64                 self.year_lab = QLabel("Year:")
65                 self.month_lab = QLabel("Month:")
66                 self.day_lab = QLabel("Day:")
67                 self.firstname_lab = QLabel("Preferred name:")
68                 self.surname_lab = QLabel("Last name:")
69                 self.email_lab = QLabel("Email:")
70                 self.phone_lab = QLabel("Phone:")
71                 self.major_lab = QLabel("Major:")
72                 self.hometown_lab = QLabel("Hometown:")
73                 self.room_lab = QLabel("Room number:")
74                 self.bday_lab = QLabel("Birthday:")
75                 self.dorm_lab = QLabel("Dorm:")
76                 self.photo = QLabel("No record selected")
77                 self.photo.setScaledContents(False)
78                 self.currentimage = QImage()
79                 self.displayimage = QImage()
80                 self.displaypixmap = QPixmap()
81                 self.photo.setAlignment(Qt.AlignCenter)
82                 self.pb_changephoto = QPushButton("Select &photo")
83                 self.pb_changephoto.setEnabled(False)
84                 # Personal info
85                 self.surname = QLineEdit()
86                 self.firstname = QLineEdit()
87                 self.phone = QLineEdit()
88                 self.email = QLineEdit()
89                 self.major = QLineEdit()
90                 self.netid = QLineEdit()
91                 # Birthday
92                 self.year = QComboBox()
93                 self.month = QComboBox()
94                 self.day = QComboBox()
95                 # Residence locations
96                 self.dorm = QComboBox()
97                 self.room = QLineEdit()
98                 # Fill the comboboxes with values, set valid field types
99                 years = QStringList(["1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994"])
100                 months = QStringList(["January","February","March","April","May","June","July","August","September","October","November","December"])
101                 days = QStringList(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"])
102                 dorms = QStringList(["Clements","Lechner","McFadden"])
103                 self.year.addItems(years)
104                 self.month.addItems(months)
105                 self.day.addItems(days)
106                 self.dorm.addItems(dorms)
107                 self.phone.setInputMask("(999)-999-9999")
108                 self.major.setMaxLength(4)
109                 self.room.setMaxLength(3)
110                 # Create and fill the UI
111                 self.formlayout = QGridLayout()
112                 self.bday_layout = QHBoxLayout()
113                 self.bday_layout.addWidget(self.year)
114                 self.bday_layout.addWidget(self.month)
115                 self.bday_layout.addWidget(self.day)
116                 self.formlayout.addWidget(self.netid_lab, 0, 0)
117                 self.formlayout.addWidget(self.netid, 0, 1)
118                 self.formlayout.addWidget(self.firstname_lab, 1, 0)
119                 self.formlayout.addWidget(self.firstname, 1, 1)
120                 self.formlayout.addWidget(self.surname_lab, 2, 0)
121                 self.formlayout.addWidget(self.surname, 2, 1)
122                 self.formlayout.addWidget(self.email_lab, 3, 0)
123                 self.formlayout.addWidget(self.email, 3, 1)
124                 self.formlayout.addWidget(self.phone_lab, 4, 0)
125                 self.formlayout.addWidget(self.phone, 4, 1)
126                 self.formlayout.addWidget(self.bday_lab,5,0)
127                 self.formlayout.addLayout(self.bday_layout,5,1)
128                 self.formlayout.addWidget(self.major_lab, 6, 0)
129                 self.formlayout.addWidget(self.major, 6, 1)
130                 self.formlayout.addWidget(self.dorm_lab, 7, 0)
131                 self.formlayout.addWidget(self.dorm, 7, 1)
132                 self.formlayout.addWidget(self.room_lab, 8, 0)
133                 self.formlayout.addWidget(self.room, 8, 1)
134                 self.formlayout.addWidget(self.photo,9,0,1,2)
135                 self.formlayout.addWidget(self.pb_changephoto,10,0,1,2)
136                 self.buttonlayout = QHBoxLayout()
137                 self.pb_cancel = QPushButton("&Cancel")
138                 self.pb_save = QPushButton("&Save")
139                 self.pb_saveclose = QPushButton("Save && Clos&e")
140                 self.pb_reset = QPushButton("&Reset")
141                 self.pb_save.setEnabled(False)
142                 self.pb_saveclose.setEnabled(False)
143                 self.pb_reset.setEnabled(False)
144                 self.buttonlayout.addWidget(self.pb_reset)
145                 self.buttonlayout.addWidget(self.pb_cancel)
146                 self.buttonlayout.addWidget(self.pb_save)
147                 self.buttonlayout.addWidget(self.pb_saveclose)
148         def setupActions(self):
149                 # Update filtered table
150                 QObject.connect(self.search_bar, SIGNAL("textChanged(QString)"), self.updateTable )
151                 # Selecting a record loads it for editing
152                 QObject.connect(self.tableview.selectionModel(), SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), self.selectionChanged )
153                 # Map buttons to actions
154                 QObject.connect(self.pb_reset, SIGNAL("clicked()"), self.resetPressed )
155                 QObject.connect(self.pb_cancel, SIGNAL("clicked()"), self.closePressed )
156                 QObject.connect(self.pb_saveclose, SIGNAL("clicked()"), self.saveClosePressed )
157                 QObject.connect(self.pb_save, SIGNAL("clicked()"), self.savePressed )
158                 QObject.connect(self.pb_changephoto, SIGNAL("clicked()"), self.changePhoto )
159                 # Changes to the record enable buttons
160                 QObject.connect(self.netid, SIGNAL("textEdited(QString)"), self.formChanged )
161                 QObject.connect(self.firstname, SIGNAL("textEdited(QString)"), self.formChanged )
162                 QObject.connect(self.surname, SIGNAL("textEdited(QString)"), self.formChanged )
163                 QObject.connect(self.email, SIGNAL("textEdited(QString)"), self.formChanged )
164                 QObject.connect(self.phone, SIGNAL("textEdited(QString)"), self.formChanged )
165                 QObject.connect(self.major, SIGNAL("textEdited(QString)"), self.formChanged )
166                 QObject.connect(self.room, SIGNAL("textEdited(QString)"), self.formChanged )
167                 QObject.connect(self.year, SIGNAL("currentIndexChanged(int)"), self.formChanged )
168                 QObject.connect(self.month, SIGNAL("currentIndexChanged(int)"), self.formChanged )
169                 QObject.connect(self.day, SIGNAL("currentIndexChanged(int)"), self.formChanged )
170                 QObject.connect(self.dorm, SIGNAL("currentIndexChanged(int)"), self.formChanged )
171
172         def formChanged(self):
173                 # Do this only if a record has been selected
174                 if not self.current_record.isEmpty():
175                         self.pb_reset.setEnabled(True)
176                         self.pb_save.setEnabled(True)
177                         self.pb_saveclose.setEnabled(True)
178         def selectionChanged(self, selected, deselected):
179                 items = selected.indexes()
180                 if len(items) > 0:
181                         self.current_row = items[0].row() # this is the row of the current selected item
182                         self.current_record = self.model.record(items[0].row())
183                         self.fillForm()
184         def fillForm(self):
185                 # Fill fields with data from selected record
186                 self.netid.setText(self.current_record.field("netid").value().toString())
187                 self.firstname.setText(self.current_record.field("forename").value().toString())
188                 self.surname.setText(self.current_record.field("surname").value().toString())
189                 self.email.setText(self.current_record.field("email").value().toString())
190                 self.phone.setText(self.current_record.field("phone").value().toString())
191                 self.major.setText(self.current_record.field("major").value().toString())
192                 self.room.setText(self.current_record.field("room").value().toString())
193                 bday = str(self.current_record.field("birthday").value().toString()).split("-")
194                 self.year.setCurrentIndex(self.year.findText(bday[0]))
195                 self.month.setCurrentIndex(int(bday[1]) - 1)
196                 self.day.setCurrentIndex(int(bday[2]) - 1)
197                 self.dorm.setCurrentIndex(self.dorm.findText(self.current_record.field("dorm").value().toString()))
198                 self.pb_reset.setEnabled(False)
199                 self.pb_save.setEnabled(False)
200                 self.pb_saveclose.setEnabled(False)
201                 ba = self.current_record.field("photo").value().toByteArray()
202                 if ba.size() > 0:
203                         self.currentimage = QImage()
204                         self.currentimage.loadFromData(ba)
205                         self.displayimage = self.currentimage.scaled(self.photo.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
206                         self.displaypixmap = QPixmap.fromImage(self.displayimage)
207                         self.photo.setPixmap(self.displaypixmap)
208                 else:
209                         self.photo.setText("No photo available")
210                 self.pb_changephoto.setEnabled(True)
211
212         def updateTable(self, text):
213                 if text.isEmpty():
214                         self.model.setFilter("")
215                         self.model.select()
216                         return
217                 t = str(text)
218                 strs = t.split()
219                 patterns = [] # can't use list comprehensions for this one because setValue returns void
220                 for i in strs:
221                         f = QSqlField("input",QVariant.String)
222                         f.setValue(QVariant(QString("%" + i + "%")))
223                         patterns.append(f)
224                 escapedpatterns = [ self.model.database().driver().formatValue(wc, False) for wc in patterns]
225                 filters = [ str(QString("(surname LIKE %1 OR forename LIKE %2)").arg(wc).arg(wc)) for wc in escapedpatterns]
226                 filterString = " AND ".join(filters)
227                 self.model.setFilter(QString(filterString))
228                 self.model.select()
229                 if self.model.rowCount() == 1:
230                         self.tableview.selectRow(0)
231         def resetPressed(self):
232                 self.current_record = self.model.record(self.current_row)
233                 self.fillForm()
234                 self.pb_reset.setEnabled(False)
235                 self.pb_save.setEnabled(False)
236                 self.pb_saveclose.setEnabled(False)
237                 print "Resetting form"
238         def closePressed(self):
239                 print "Closing"
240                 self.model.revertAll()
241                 # Wipe contents of all lineedits, destroy current_record and current_index
242                 self.search_bar.clear()
243                 self.current_record = QSqlRecord()
244                 self.current_index = -1
245                 self.surname.clear()
246                 self.firstname.clear()
247                 self.phone.clear()
248                 self.email.clear()
249                 self.major.clear()
250                 self.netid.clear()
251                 self.year.setCurrentIndex(0)
252                 self.month.setCurrentIndex(0)
253                 self.day.setCurrentIndex(0)
254                 self.dorm.setCurrentIndex(0)
255                 self.room.clear()
256                 self.photo.setText("No record selected")
257                 self.model.select()
258                 self.emit(SIGNAL("done()"))
259         def savePressed(self):
260                 print "Saving"
261                 self.current_record.setValue("netid",QVariant(self.netid.text()))
262                 self.current_record.setValue("forename",QVariant(self.firstname.text()))
263                 self.current_record.setValue("surname",QVariant(self.surname.text()))
264                 self.current_record.setValue("email",QVariant(self.email.text()))
265                 self.current_record.setValue("phone",QVariant(self.phone.text()))
266                 self.current_record.setValue("major",QVariant(self.major.text()))
267                 self.current_record.setValue("room",QVariant(self.room.text()))
268                 self.current_record.setValue("dorm",QVariant(self.dorm.currentText()))
269                 y = self.year.currentText().toInt()[0]
270                 m = self.month.currentIndex() + 1
271                 d = self.day.currentText().toInt()[0]
272                 bday = QDate(y,m,d)
273                 self.current_record.setValue("birthday", QVariant(bday.toString(Qt.ISODate)) )
274                 self.current_record.setValue("mtime", QVariant(QDateTime.currentDateTime().toString(Qt.ISODate)) ) # update modification time
275
276                 self.model.setRecord(self.current_row, self.current_record)
277                 self.model.submitAll()
278                 self.updateTable(self.search_bar.text()) # Reselect from the DB
279                 self.pb_reset.setEnabled(False)
280                 self.pb_save.setEnabled(False)
281                 self.pb_saveclose.setEnabled(False)
282         def saveClosePressed(self):
283                 self.savePressed()
284                 self.closePressed()
285         def changePhoto(self):
286                 fileName = QFileDialog.getOpenFileName(self, "Select Photo", ".", "Images (*.jpg *.png)" )
287                 if not fileName.isEmpty():
288                         print "opening", fileName
289                         self.currentimage = QImage()
290                         self.currentimage.load(fileName)
291                         self.displayimage = self.currentimage.scaled(self.photo.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
292                         self.displaypixmap = QPixmap.fromImage(self.displayimage)
293                         self.photo.setPixmap(self.displaypixmap)
294                         ba = QByteArray()
295                         buffer = QBuffer(ba)
296                         buffer.open(QIODevice.WriteOnly)
297                         self.currentimage.save(buffer, "JPG")
298                         buffer.close()
299                         self.current_record.setValue("photo",QVariant(ba))
300                         self.pb_reset.setEnabled(True)
301                         self.pb_save.setEnabled(True)
302                         self.pb_saveclose.setEnabled(True)
303
304
305 if __name__ == "__main__":
306         a = QApplication([""])
307         w = EditPerson()
308         a.exec_()