#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' PyQt4 conversion of Qt Tutorial 'Address Book' - Part 3 Add the ability to navigate backwards and forwards through the contacts. NOTES: ===== The method name for 'next()' has been changed to 'next_()' as 'next' is a reserved word in Python. The 'next_()' and 'prev()' methods are implemented using sorted lists of the contacts names (keys). As lists in Python use 'pointers' (memory addresses) to objects and not the actual objects themselves the methods should scale reasonably well. last modified: 2012-01-24 jg ref: http://developer.qt.nokia.com/doc/qt-4.8/tutorials-addressbook.html http://developer.qt.nokia.com/doc/qt-4.8/tutorials-addressbook-part3.html ''' import sys from PyQt4.QtGui import (QApplication, QWidget, QLabel, QTextEdit, QLineEdit, QGridLayout, QPushButton, QVBoxLayout, QMessageBox, QHBoxLayout) from PyQt4.QtCore import (Qt, pyqtSlot) class AddressBook(QWidget): def __init__(self, parent=None): super(AddressBook, self).__init__(parent) # create a dictonary to hold contacts self._contacts = {} # create input labels and fields nameLabel = QLabel(self.tr("Name:")) self._nameLine = QLineEdit(self) self._nameLine.setReadOnly(True) addrLabel = QLabel(self.tr("Address:")) self._addrText = QTextEdit(self) self._addrText.setReadOnly(True) # create and populate layout mainLayout = QGridLayout() mainLayout.addWidget(nameLabel, 0, 0) mainLayout.addWidget(self._nameLine, 0, 1) mainLayout.addWidget(addrLabel, 1, 0, Qt.AlignTop) mainLayout.addWidget(self._addrText, 1, 1) mainLayout.addLayout(self._initButtonPanel(), 1, 2) mainLayout.addLayout(self._initNavPanel(), 2, 1) # set this objects layout and window title self.setLayout(mainLayout) self.setWindowTitle(self.tr("Simple Address Book")) def _initNavPanel(self): self._nextBtn = QPushButton(self.tr("&Next")) self._prevBtn = QPushButton(self.tr("&Previous")) self._nextBtn.setEnabled(False) self._prevBtn.setEnabled(False) self._nextBtn.clicked.connect(self.next_) self._prevBtn.clicked.connect(self.previous) layout = QHBoxLayout() layout.addWidget(self._prevBtn) layout.addWidget(self._nextBtn) return layout def _initButtonPanel(self): # create buttons self._addBtn = QPushButton(self.tr("&Add")) self._submitBtn = QPushButton(self.tr("&Submit")) self._cancelBtn = QPushButton(self.tr("&Cancel")) # set button visibility self._addBtn.show() self._submitBtn.hide() self._cancelBtn.hide() # define signal/slot connections for event handling self._addBtn.clicked.connect(self._addContact) self._submitBtn.clicked.connect(self._submitContact) self._cancelBtn.clicked.connect(self._cancel) # layout buttons layout = QVBoxLayout() layout.addWidget(self._addBtn, Qt.AlignTop) layout.addWidget(self._submitBtn) layout.addWidget(self._cancelBtn) layout.addStretch() # force additional space to bottom return layout @pyqtSlot() def _addContact(self): self._oldName = self._nameLine.text() self._oldAddress = self._addrText.toPlainText() self._nameLine.clear() self._addrText.clear() self._nameLine.setReadOnly(False) self._nameLine.setFocus(Qt.OtherFocusReason) self._addrText.setReadOnly(False) self._addBtn.setEnabled(False) self._submitBtn.show() self._cancelBtn.show() self._nextBtn.setEnabled(False) # disable navigationd during 'Add' self._prevBtn.setEnabled(False) @pyqtSlot() def _submitContact(self): name = self._nameLine.text() addr = self._addrText.toPlainText() if not (name or addr): QMessageBox.information(self, self.tr("Empty Field"), self.tr("Please enter a name and address.")) return if name not in self._contacts: self._contacts[name] = addr QMessageBox.information(self, self.tr("Add Successful"), self.tr("{0} has been added to your address book.").format(name)) else: QMessageBox.information(self, self.tr("Add Unsuccessful"), self.tr("Sorry, {0} is already in your address book.").format(name)) # restore buttons num = len(self._contacts) if num == 0: self._nameLine.clear() self._addrText.clear() self._nameLine.setReadOnly(True) self._addrText.setReadOnly(True) self._addBtn.setEnabled(True) self._submitBtn.hide() self._cancelBtn.hide() # enable navigation if more than one contact self._nextBtn.setEnabled(num > 1) self._prevBtn.setEnabled(num > 1) @pyqtSlot() def _cancel(self): self._nameLine.setText(self._oldName) self._nameLine.setReadOnly(True) self._addrText.setText(self._oldAddress) self._addrText.setReadOnly(True) self._addBtn.setEnabled(True) self._submitBtn.hide() self._cancelBtn.hide() # enable navigation if more than one contact num = len(self._contacts) self._nextBtn.setEnabled(num > 1) self._prevBtn.setEnabled(num > 1) @pyqtSlot() def next_(self): name = self._nameLine.text() # current contact's name sKeys = sorted(self._contacts.keys()) # sort names i = sKeys.index(name) + 1 # get index for next name in sorted list if i >= len(sKeys): i = 0 # if we're past the end, go to the beginning nextKey = sKeys[i] # name at new index is key we want self._nameLine.setText(nextKey) self._addrText.setText(self._contacts[nextKey]) @pyqtSlot() def previous(self): name = self._nameLine.text() # current contact's name sKeys = sorted(self._contacts.keys()) # sort names i = sKeys.index(name) - 1 # index for previous name in sorted list if i < 0: i = len(sKeys) - 1 # if below the beginning, go to the end prevKey = sKeys[i] # name at the new index is the key we want self._nameLine.setText(prevKey) self._addrText.setText(self._contacts[prevKey]) def main(): app = QApplication(sys.argv) # required for all GUI applications ab = AddressBook() ab.show() # make me visible sys.exit(app.exec_()) # start main event thread if __name__ == '__main__': main()
Page List
▼
Wednesday, January 25, 2012
Qt 4.8 Address Book Tutorial - Part 3
This code is based on the Qt 4.8 Address Book Tutorial Part 3, Navigating Between Entries.