1#!/usr/bin/env python 2 3 4############################################################################# 5## 6## Copyright (C) 2013 Riverbank Computing Limited. 7## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 8## All rights reserved. 9## 10## This file is part of the examples of PyQt. 11## 12## $QT_BEGIN_LICENSE:BSD$ 13## You may use this file under the terms of the BSD license as follows: 14## 15## "Redistribution and use in source and binary forms, with or without 16## modification, are permitted provided that the following conditions are 17## met: 18## * Redistributions of source code must retain the above copyright 19## notice, this list of conditions and the following disclaimer. 20## * Redistributions in binary form must reproduce the above copyright 21## notice, this list of conditions and the following disclaimer in 22## the documentation and/or other materials provided with the 23## distribution. 24## * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 25## the names of its contributors may be used to endorse or promote 26## products derived from this software without specific prior written 27## permission. 28## 29## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 40## $QT_END_LICENSE$ 41## 42############################################################################# 43 44 45from PyQt5.QtCore import Qt 46from PyQt5.QtWidgets import QGridLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QTextEdit, QVBoxLayout, QWidget 47 48 49class SortedDict(dict): 50 class Iterator(object): 51 def __init__(self, sorted_dict): 52 self._dict = sorted_dict 53 self._keys = sorted(self._dict.keys()) 54 self._nr_items = len(self._keys) 55 self._idx = 0 56 57 def __iter__(self): 58 return self 59 60 def next(self): 61 if self._idx >= self._nr_items: 62 raise StopIteration 63 64 key = self._keys[self._idx] 65 value = self._dict[key] 66 self._idx += 1 67 68 return key, value 69 70 __next__ = next 71 72 def __iter__(self): 73 return SortedDict.Iterator(self) 74 75 iterkeys = __iter__ 76 77 78class AddressBook(QWidget): 79 def __init__(self, parent=None): 80 super(AddressBook, self).__init__(parent) 81 82 self.contacts = SortedDict() 83 self.oldName = '' 84 self.oldAddress = '' 85 86 nameLabel = QLabel("Name:") 87 self.nameLine = QLineEdit() 88 self.nameLine.setReadOnly(True) 89 90 addressLabel = QLabel("Address:") 91 self.addressText = QTextEdit() 92 self.addressText.setReadOnly(True) 93 94 self.addButton = QPushButton("&Add") 95 self.addButton.show() 96 self.submitButton = QPushButton("&Submit") 97 self.submitButton.hide() 98 self.cancelButton = QPushButton("&Cancel") 99 self.cancelButton.hide() 100 101 self.addButton.clicked.connect(self.addContact) 102 self.submitButton.clicked.connect(self.submitContact) 103 self.cancelButton.clicked.connect(self.cancel) 104 105 buttonLayout1 = QVBoxLayout() 106 buttonLayout1.addWidget(self.addButton, Qt.AlignTop) 107 buttonLayout1.addWidget(self.submitButton) 108 buttonLayout1.addWidget(self.cancelButton) 109 buttonLayout1.addStretch() 110 111 mainLayout = QGridLayout() 112 mainLayout.addWidget(nameLabel, 0, 0) 113 mainLayout.addWidget(self.nameLine, 0, 1) 114 mainLayout.addWidget(addressLabel, 1, 0, Qt.AlignTop) 115 mainLayout.addWidget(self.addressText, 1, 1) 116 mainLayout.addLayout(buttonLayout1, 1, 2) 117 118 self.setLayout(mainLayout) 119 self.setWindowTitle("Simple Address Book") 120 121 def addContact(self): 122 self.oldName = self.nameLine.text() 123 self.oldAddress = self.addressText.toPlainText() 124 125 self.nameLine.clear() 126 self.addressText.clear() 127 128 self.nameLine.setReadOnly(False) 129 self.nameLine.setFocus(Qt.OtherFocusReason) 130 self.addressText.setReadOnly(False) 131 132 self.addButton.setEnabled(False) 133 self.submitButton.show() 134 self.cancelButton.show() 135 136 def submitContact(self): 137 name = self.nameLine.text() 138 address = self.addressText.toPlainText() 139 140 if name == "" or address == "": 141 QMessageBox.information(self, "Empty Field", 142 "Please enter a name and address.") 143 return 144 145 if name not in self.contacts: 146 self.contacts[name] = address 147 QMessageBox.information(self, "Add Successful", 148 "\"%s\" has been added to your address book." % name) 149 else: 150 QMessageBox.information(self, "Add Unsuccessful", 151 "Sorry, \"%s\" is already in your address book." % name) 152 return 153 154 if not self.contacts: 155 self.nameLine.clear() 156 self.addressText.clear() 157 158 self.nameLine.setReadOnly(True) 159 self.addressText.setReadOnly(True) 160 self.addButton.setEnabled(True) 161 self.submitButton.hide() 162 self.cancelButton.hide() 163 164 def cancel(self): 165 self.nameLine.setText(self.oldName) 166 self.nameLine.setReadOnly(True) 167 168 self.addressText.setText(self.oldAddress) 169 self.addressText.setReadOnly(True) 170 171 self.addButton.setEnabled(True) 172 self.submitButton.hide() 173 self.cancelButton.hide() 174 175 176if __name__ == '__main__': 177 import sys 178 179 from PyQt5.QtWidgets import QApplication 180 181 app = QApplication(sys.argv) 182 183 addressBook = AddressBook() 184 addressBook.show() 185 186 sys.exit(app.exec_()) 187