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