]> git.zarvox.org Git - wp3.git/blob - mainapp.py
Added Python docstrings for all classes.
[wp3.git] / mainapp.py
1 from PyQt4.QtCore import *
2 from PyQt4.QtGui import *
3 from PyQt4.QtSql import *
4
5 from chooseaction import ChooseAction
6 from editperson import EditPerson
7 from mergephotos import MergePhotos
8 from odtwriter import ODTWriter
9 from analytics import Analytics
10
11 class MainApp (QMainWindow):
12         schema = "CREATE TABLE people ( id INTEGER PRIMARY KEY AUTOINCREMENT, forename TEXT NOT NULL, surname TEXT NOT NULL, netid TEXT NOT NULL, email TEXT, birthday TEXT, phone TEXT, major TEXT, dorm TEXT, room INTEGER, photo BLOB, createtime TEXT NOT NULL, mtime TEXT NOT NULL);"
13         def __init__(self, Parent=None):
14                 """Set up the main view, load the default database and schema, and set the widgets visible."""
15                 QMainWindow.__init__(self, Parent)
16                 self.setWindowTitle("Whitepages V3")
17
18                 self.db = QSqlDatabase.addDatabase("QSQLITE")
19                 self.db.setDatabaseName("families.db")
20                 self.db.open()
21                 q = QSqlQuery(self.db)
22                 q.exec_(MainApp.schema)
23
24                 self.center = QStackedWidget()
25                 self.chooseaction = ChooseAction(self,self.db)
26                 self.editperson = EditPerson(self,self.db)
27                 self.mergephotos = MergePhotos(self,self.db)
28                 self.analytics = Analytics(self,self.db)
29                 self.center.addWidget(self.chooseaction)
30                 self.center.addWidget(self.editperson)
31                 self.center.addWidget(self.mergephotos)
32                 self.center.addWidget(self.analytics)
33                 self.setCentralWidget(self.center)
34
35                 self.createActions()
36                 self.createMenus()
37
38                 self.statusBar().showMessage("Ready")
39                 self.setUnifiedTitleAndToolBarOnMac(True);
40                 self.resize(800,600)
41                 self.show()
42
43         def createActions(self):
44                 """Create actions and connect signals and slots."""
45                 self.fileNewAction = QAction("&New Database",self)
46                 QObject.connect( self.fileNewAction, SIGNAL("triggered()"), self.newFile)
47                 self.fileOpenAction = QAction("&Open Database",self)
48                 QObject.connect( self.fileOpenAction, SIGNAL("triggered()"), self.openFile)
49                 self.fileImportAction = QAction("&Import (Merge)", self)
50                 QObject.connect( self.fileImportAction, SIGNAL("triggered()"), self.mergeWizard)
51                 self.fileQuitAction = QAction("&Quit",self)
52                 QObject.connect( self.fileQuitAction, SIGNAL("triggered()"), self.quit)
53                 QObject.connect( self.chooseaction, SIGNAL("editPerson()"), self.editPersonSlot)
54                 QObject.connect( self.chooseaction, SIGNAL("mergePhotos()"), self.mergePhotosSlot)
55                 QObject.connect( self.chooseaction, SIGNAL("exportDocument(QString)"), self.exportDocumentSlot)
56                 QObject.connect( self.chooseaction, SIGNAL("runAnalytics()"), self.runAnalyticsSlot)
57                 QObject.connect( self.editperson, SIGNAL("done()"), self.returnToMainMenu)
58                 QObject.connect( self.mergephotos, SIGNAL("done()"), self.returnToMainMenu)
59                 QObject.connect( self.analytics, SIGNAL("done()"), self.returnToMainMenu)
60                 QObject.connect( self, SIGNAL("databaseChanged(QString)"), self.editperson.updateDB)
61                 QObject.connect( self, SIGNAL("databaseChanged(QString)"), self.analytics.updateDB)
62                 QObject.connect( self, SIGNAL("mergeDone()"), self.editperson.reselect )
63                 
64         
65         def createMenus(self):
66                 """Create the drop-down File menu."""
67                 self.fileMenu = self.menuBar().addMenu("&File")
68                 self.fileMenu.addAction(self.fileNewAction)
69                 self.fileMenu.addAction(self.fileOpenAction)
70                 self.fileMenu.addAction(self.fileImportAction)
71                 self.fileMenu.addSeparator()
72                 self.fileMenu.addAction(self.fileQuitAction)
73
74
75         def newFile(self):
76                 """Allow user to specify a new SQLite database to work with."""
77                 fileName = QFileDialog.getSaveFileName(self, "Save new file as:", ".", "Databases (*.db)")
78                 if not fileName.isEmpty(): # If they cancelled, do nothing
79                         if not fileName.endsWith(".db"): # if they leave off the extension, add it
80                                 fileName = fileName.append(".db")
81                         self.db.close()
82                         self.db.setDatabaseName(fileName)
83                         self.db.open()
84                         q = QSqlQuery(self.db)
85                         q.exec_(MainApp.schema)
86                         self.statusBar().showMessage("Closed the existing database, created " + fileName)
87                         self.emit(SIGNAL("databaseChanged(QString)"),self.db.databaseName())
88                 else:
89                         self.statusBar().showMessage("Cancelled creating new database")
90         def openFile(self):
91                 """Load user-specified SQLite database for editing."""
92                 fileName = QFileDialog.getOpenFileName(self, "Open dataset", ".", "Databases (*.db)")
93                 if not fileName.isEmpty():
94                         self.db.close()
95                         self.db.setDatabaseName(fileName)
96                         self.db.open()
97                         self.statusBar().showMessage("Successfully loaded database " + fileName)
98                         self.returnToMainMenu()
99                         self.emit(SIGNAL("databaseChanged(QString)"),self.db.databaseName())
100                 else:
101                         self.statusBar().showMessage("Canceled loading database")
102         def mergeWizard(self):
103                 """Import user-specified SQLite database into this database, with intelligent merge heuristics.  NetID conflicts are resolved by ignoring the to-be-imported record and keeping the one in the currently-open database."""
104                 fileName = QFileDialog.getOpenFileName(self, "Import which dataset?", ".", "Databases (*.db)" )
105                 if not fileName.isEmpty():
106                         tempdb = QSqlDatabase.addDatabase("QSQLITE","tempdb")
107                         tempdb.setDatabaseName(fileName)
108                         tempdb.open()
109                         q = QSqlQuery(self.db)
110                         import_q = QSqlQuery(tempdb)
111                         import_q.exec_("SELECT * FROM people;")
112                         rec = import_q.record()
113                         col_id = rec.indexOf("id")
114                         col_forename = rec.indexOf("forename")
115                         col_surname = rec.indexOf("surname")
116                         col_netid = rec.indexOf("netid")
117                         col_email = rec.indexOf("email")
118                         col_birthday = rec.indexOf("birthday")
119                         col_phone = rec.indexOf("phone")
120                         col_major = rec.indexOf("major")
121                         col_dorm = rec.indexOf("dorm")
122                         col_room = rec.indexOf("room")
123                         col_photo = rec.indexOf("photo")
124                         col_createtime = rec.indexOf("createtime")
125                         col_mtime = rec.indexOf("mtime")
126                         #print "Number of columns:",rec.count()
127                         records_merged = 0
128                         while import_q.next():
129                                 qtestnewnetid = QSqlQuery(self.db)
130                                 qtestnewnetid.prepare("SELECT * FROM people WHERE netid = :netid")
131                                 qtestnewnetid.bindValue(":netid", import_q.value(col_netid) )
132                                 qtestnewnetid.exec_()
133                                 if qtestnewnetid.next(): # if the person's already in the DB, keep the old data
134                                         continue
135                                 q.prepare("INSERT INTO people (netid, forename, surname, email, birthday, phone, major, dorm, room, createtime, mtime, photo )"
136                                                                 "VALUES (:netid, :forename, :surname, :email, :birthday, :phone, :major, :dorm, :room, :createtime, :mtime, :photo )" )
137                                 q.bindValue(":netid", import_q.value(col_netid) )
138                                 q.bindValue(":forename", import_q.value(col_forename) )
139                                 q.bindValue(":surname", import_q.value(col_surname) )
140                                 q.bindValue(":email", import_q.value(col_email) )
141                                 q.bindValue(":birthday", import_q.value(col_birthday) )
142                                 q.bindValue(":phone", import_q.value(col_phone) )
143                                 q.bindValue(":major", import_q.value(col_major) )
144                                 q.bindValue(":dorm", import_q.value(col_dorm) )
145                                 q.bindValue(":room", import_q.value(col_room) )
146                                 q.bindValue(":createtime", import_q.value(col_createtime) )
147                                 q.bindValue(":mtime", import_q.value(col_mtime) )
148                                 q.bindValue(":photo", import_q.value(col_photo) )
149                                 q.exec_()
150                                 print "Inserted", import_q.value(col_forename).toString(), import_q.value(col_surname).toString(), "into DB"
151                                 records_merged = records_merged + 1
152                         self.statusBar().showMessage(QString("Successfully merged %1 records from %2").arg(QString(str(records_merged))).arg(fileName))
153                         tempdb.close()
154                         self.emit(SIGNAL("mergeDone()"))
155                 else:
156                         self.statusBar().showMessage("Canceled merging databases")
157         def quit(self):
158                 """Exit program."""
159                 # You could do cleanup, like closing/flushing the database, an "Are you sure you want to quit?"
160                 # modal dialog, or saving the window layout/state.
161                 qApp.quit()
162         def returnToMainMenu(self):
163                 """Switch to ChooseAction widget."""
164                 self.center.setCurrentWidget(self.chooseaction)
165         def editPersonSlot(self):
166                 """Switch to EditPerson widget."""
167                 self.editperson.model.select() # update the table
168                 self.center.setCurrentWidget(self.editperson)
169         def mergePhotosSlot(self):
170                 """Switch to MergePhotos widget."""
171                 print "beginning photo merge"
172                 self.center.setCurrentWidget(self.mergephotos)
173                 #self.mergephotos.beginMerge()
174         def exportDocumentSlot(self, filename):
175                 """Export current database to ODT file <filename>."""
176                 writer = ODTWriter(self.db)
177                 success = writer.write(filename)
178                 if success:
179                         self.statusBar().showMessage(QString("Successfully exported to %1").arg(filename))
180                 else:
181                         self.statusBar().showMessage(QString("Document export cancelled or failed"))
182         def runAnalyticsSlot(self):
183                 """Switch to Analytics widget."""
184                 print "Running analytics"
185                 self.analytics.generateReport()
186                 self.center.setCurrentWidget(self.analytics)
187
188
189 if __name__ == "__main__" :
190         app = QApplication([""])
191         widget = MainApp()
192         app.exec_()
193