def __init__(self, db, message): QWidget.__init__(self) self.message = message self.setWindowTitle(message.summary) self.db = db self.senderLabel = QLabel(u'Sender: ' + unicode(message.sender)) self.sentLabel = QLabel('Sent: ' + time.strftime('%Y-%m-%d %H:%M:%S', message.sentDate)) recipients = message.getRecipients(db) if len(recipients) == 1: recipientsWidget = QLabel(u'Recipient: ' + unicode(recipients[0])) else: recipients = [(unicode(recipient), recipient) for recipient in recipients] acl = AutoCompleteListBox(self, recipients) acl.getLineEdit().hide() self.recipientsWidget = acl.getListBox() grid = QGridLayout() grid.setSpacing(10) # To be overridden by child classes. self.mainView = QWidget() grid.addWidget(self.senderLabel, 0, 0) grid.addWidget(self.recipientsWidget, 1, 0) grid.addWidget(self.sentLabel, 2, 0) grid.addWidget(self.mainView, 3, 0) self.setLayout(grid)
class EditContact(QWidget): def __init__(self, db, mainWindow, username, contact): QWidget.__init__(self) self.contact = contact self.username = username self.mainWindow = mainWindow self.db = db self.resize(400, 300) self.setWindowTitle('Edit Contact') self.addressListLabel = QLabel('Addresses') addresses = self.contact.getAddresses(self.db) addresses = [("%s: %s" % (address['strAddressType'], address['strAddress']), address['strAddress']) for address in addresses] self.addresses = AutoCompleteListBox(self, addresses) self.addresses.getLineEdit().hide() saveButton = QPushButton('Save') cancelButton = QPushButton('Cancel') self.personRadio = QRadioButton('Contact is a person', self) self.companyRadio = QRadioButton('Contact is an organization', self) self.personWidget = self._getPersonWidget() self.companyWidget = self._getCompanyWidget() self.personRadio.toggled.connect(self.switchToPerson) self.companyRadio.toggled.connect(self.switchToCompany) grid = QGridLayout() grid.setSpacing(10) grid.addWidget(self.addressListLabel, 1, 0) grid.addWidget(self.addresses.getLineEdit(), 0, 1, 1, 2) grid.addWidget(self.addresses.getListBox(), 1, 1, 1, 2) grid.addWidget(self.personRadio, 2, 1, 1, 2) grid.addWidget(self.companyRadio, 3, 1, 1, 2) grid.addWidget(self.personWidget, 4, 0, 1, 3) grid.addWidget(self.companyWidget, 5, 0, 1, 3) grid.addWidget(saveButton, 7, 1) grid.addWidget(cancelButton, 7, 2) self.setLayout(grid) if contact.isPerson == True: self.personRadio.setChecked(True) self.switchToPerson() elif contact.isPerson == False: self.companyRadio.setChecked(True) self.switchToCompany() else: self.personWidget.hide() self.companyWidget.hide() self.connect(cancelButton, SIGNAL('clicked()'), SLOT('close()')) self.connect(saveButton, SIGNAL('clicked()'), self.save) def _getPersonWidget(self): widget = QWidget() grid = QGridLayout() grid.setSpacing(10) self.forenameLabel = QLabel('Forename') self.surnameLabel = QLabel('Surname') self.forenameLineEdit = QLineEdit() self.surnameLineEdit = QLineEdit() if self.contact.forename: self.forenameLineEdit.setText(self.contact.forename) if self.contact.surname: self.surnameLineEdit.setText(self.contact.surname) grid.addWidget(self.forenameLabel, 0, 0) grid.addWidget(self.surnameLabel, 1, 0) grid.addWidget(self.forenameLineEdit, 0, 1) grid.addWidget(self.surnameLineEdit, 1, 1) widget.setLayout(grid) return widget def _getCompanyWidget(self): widget = QWidget() grid = QGridLayout() grid.setSpacing(10) self.companyNameLabel = QLabel('Company Name') self.companyNameLineEdit = QLineEdit() if self.contact.companyName: self.companyNameLineEdit.setText(self.contact.companyName) grid.addWidget(self.companyNameLabel, 0, 0) grid.addWidget(self.companyNameLineEdit, 0, 1) widget.setLayout(grid) return widget def switchToPerson(self): self.companyWidget.hide() self.personWidget.show() def switchToCompany(self): self.personWidget.hide() self.companyWidget.show() def save(self): self.contact.forename = unicode(self.forenameLineEdit.text()) self.contact.surname = unicode(self.surnameLineEdit.text()) self.contact.companyName = unicode(self.companyNameLineEdit.text()) self.contact.isPerson = self.personRadio.isChecked() self.contact.update(self.db) self.mainWindow.refreshLists() self.close()
class MainWindow(QMainWindow): def setupMenus(self): """ Constructs menus and toolbars """ exit = QAction(QIcon("gui/icons/close.png"), "Exit", self) exit.setShortcut("Ctrl+Q") exit.setStatusTip("Exit application") self.connect(exit, SIGNAL("triggered()"), SLOT("close()")) menubar = self.menuBar() file = menubar.addMenu("&File") self.getMessagesMenu = file.addMenu("&Get Messages") file.addAction(exit) toolbar = self.addToolBar("Exit") toolbar.addAction(exit) def __init__(self): """ Initialises the main window of the application. """ QMainWindow.__init__(self) self.setWindowTitle("Owl") self.setGeometry(10, 10, 1100, 800) self.status = self.statusBar() self.status.showMessage("Ready") self.setupMenus() userLabel = QLabel("Contacts") messageLabel = QLabel("Messages") self.userList = AutoCompleteListBox(self, []) self.messageList = MessageListBox(self, []) box = self.userList.getListBox() box.setSelectionMode(QAbstractItemView.ExtendedSelection) box.doubleClicked.connect(self.showEditContact) box.clicked.connect(self.contactListClicked) self.messageList.getListBox().doubleClicked.connect(self.showMessage) frame = QFrame() frame.setFrameStyle(QFrame.VLine | QFrame.Raised) self.mergeButton = QPushButton("Merge") self.mergeButton.setEnabled(False) self.mergeButton.clicked.connect(self.mergeContacts) centralWidget = QWidget() self.setCentralWidget(centralWidget) grid = QGridLayout() grid.setSpacing(10) grid.setColumnStretch(2, 2) grid.addWidget(userLabel, 0, 0) grid.addWidget(messageLabel, 0, 2) grid.addWidget(self.userList.getLineEdit(), 1, 0) grid.addWidget(self.messageList.getLineEdit(), 1, 2) grid.addWidget(self.userList.getListBox(), 2, 0) grid.addWidget(self.messageList.getListBox(), 2, 2) grid.addWidget(frame, 0, 1, 3, 1) grid.addWidget(self.mergeButton, 3, 0) centralWidget.setLayout(grid) def giveCredentials(self, username, password): """ This happens once the user has successfully logged in. We store the username and password for future reference, and refresh the contacts and messages listboxes. """ self.username = username self.password = password message._password = password self.db = Sqlite(username, True) self.gatherData = GatherData(self.username, self.password) self.refreshLists() self.refreshGetMessagesWindow() def refreshLists(self): """ Put locally-stored contact and message lists back into the list boxes. Used if a contact or message has been changed locally. """ contacts = sorted(contact.getContacts(self.db), key=lambda contact: unicode(contact)) messages = sorted(message.getMessages(self.db), key=lambda message: unicode(message)) self.userList.replaceList([(unicode(c), c) for c in contacts]) self.messageList.replaceList([(unicode(m), m) for m in messages]) def refreshGetMessagesWindow(self): self.getMessagesMenu.clear() self.gatherData.refreshNewMessageCounts(self.db) messageCounts = self.gatherData.getAllNewMessageCounts() for count in messageCounts: action = QAction(count["type"] + " (" + str(count["number"]) + ")", self) if count["type"] == "All": tip = "Get all new messages." else: tip = "Get new " + count["type"] + " messages." action.setStatusTip(tip) self.getMessagesMenu.addAction(action) receiver = lambda type=count["type"]: self.downloadNewMessages(type) self.connect(action, SIGNAL("triggered()"), receiver) def updateProgressBar(self, messagesLeft): """ We call this when we’ve downloaded a message. We advance the bar’s progress, and update the label text. """ messagesProcessed = self.progress.maximum() - messagesLeft self.progress.setValue(messagesProcessed) self.progress.setLabelText( "Downloading message %s of %s." % (stringFunctions.formatInt(messagesProcessed + 1), stringFunctions.formatInt(self.progress.maximum())) ) if messagesProcessed >= self.progress.maximum(): self.progress.close() def receiveBroadcastOfDownloadProgress(self, messagesProcessed): """ This method is called from the thread doing the downlaoding. It emits a signal, triggering the progress bar to be updated. """ self.emit(SIGNAL("updateProgressBar(PyQt_PyObject)"), messagesProcessed) def cancelMessageRetrieval(self): """ Stop downloading more messages. """ self.gatherData.stop() def fetchMessagesThread(self, type): self.gatherData.getNewMessages(self.receiveQuestion, type, self.receiveBroadcastOfDownloadProgress) self.emit(SIGNAL("refreshLists()")) def receiveQuestion(self, options, title, text, resultReceiver, multiAnswer=False): self.emit( SIGNAL("askUserAQuestion(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), options, title, text, resultReceiver, multiAnswer, ) def askUserAQuestion(self, options, title, text, resultReceiver, multiAnswer): if multiAnswer: self.dialog = MultiselectionDialogBox(options, title, text, resultReceiver) else: self.dialog = DialogBox(options, title, text, resultReceiver) def downloadNewMessages(self, messageType): """ Starts a thread that downloads all the new messages for the user’s accounts """ newMessageCount = self.gatherData.countNewMessages(messageType) noun = newMessageCount == 1 and "message" or "messages" self.progress = QProgressDialog(str(newMessageCount) + " " + noun + " to download.", "Cancel", 0, 10) self.progress.resize(400, 50) self.progress.setMaximum(newMessageCount) self.progress.show() thread = Thread(target=self.fetchMessagesThread, name="Fetch messages", args=(messageType,)) self.connect(self, SIGNAL("updateProgressBar(PyQt_PyObject)"), self.updateProgressBar) self.connect(self, SIGNAL("refreshLists()"), self.refreshLists) self.connect(self.progress, SIGNAL("canceled()"), self.cancelMessageRetrieval) self.connect( self, SIGNAL("askUserAQuestion(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), self.askUserAQuestion, ) thread.start() def showEditContact(self): """ If a single contact is selected, opens the Edit Contact screen for that contact. """ contacts = self.userList.getSelectedItems() if len(contacts) == 1: self.editContact = EditContact(self.db, self, self.username, contacts[0]) self.editContact.show() def showMessage(self): """ If a message is selected, opens the show message screen for that message. """ messages = self.messageList.getSelectedItems() if len(messages) == 1: if messages[0].type == "email": self.viewMessage = ViewEmail(self.db, emailMessage.getEmailFromId(self.db, messages[0].id)) elif messages[0].type == "SMS": self.viewMessage = ViewSms(self.db, smsMessage.getSmsFromId(self.db, messages[0].id)) elif messages[0].type == "IM": self.viewMessage = ViewConversation( self.db, imConversation.getIMConversationFromId(self.db, messages[0].id) ) self.viewMessage.show() def contactListClicked(self): """ Enables or disables the merge button, depending on whether or not two or more contacts are selected, respectively. """ contacts = self.userList.getSelectedItems() self.mergeButton.setEnabled(contacts != None and len(contacts) > 1) if contacts != None and len(contacts) == 1: self.messageList.filterByContact(contacts[0]) else: self.messageList.removeFilter() def mergeContacts(self): """ Ask the user whether they want to merge the contacts that are selected in the list box. """ self.mergeDialog = MergeDialog(self.db, self.userList.getSelectedItems()) self.mergeDialog.accepted.connect(self.refreshLists) self.mergeDialog.show()