1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "addresswidget.h"
52#include "adddialog.h"
53
54#include <QtWidgets>
55
56//! [0]
57AddressWidget::AddressWidget(QWidget *parent)
58 : QTabWidget(parent),
59 table(new TableModel(this)),
60 newAddressTab(new NewAddressTab(this))
61{
62 connect(sender: newAddressTab, signal: &NewAddressTab::sendDetails,
63 receiver: this, slot: &AddressWidget::addEntry);
64
65 addTab(widget: newAddressTab, tr(s: "Address Book"));
66
67 setupTabs();
68}
69//! [0]
70
71//! [2]
72void AddressWidget::showAddEntryDialog()
73{
74 AddDialog aDialog;
75
76 if (aDialog.exec())
77 addEntry(name: aDialog.name(), address: aDialog.address());
78}
79//! [2]
80
81//! [3]
82void AddressWidget::addEntry(const QString &name, const QString &address)
83{
84 if (!table->getContacts().contains(t: { .name: name, .address: address })) {
85 table->insertRows(position: 0, rows: 1, index: QModelIndex());
86
87 QModelIndex index = table->index(row: 0, column: 0, parent: QModelIndex());
88 table->setData(index, value: name, role: Qt::EditRole);
89 index = table->index(row: 0, column: 1, parent: QModelIndex());
90 table->setData(index, value: address, role: Qt::EditRole);
91 removeTab(index: indexOf(widget: newAddressTab));
92 } else {
93 QMessageBox::information(parent: this, title: tr(s: "Duplicate Name"),
94 text: tr(s: "The name \"%1\" already exists.").arg(a: name));
95 }
96}
97//! [3]
98
99//! [4a]
100void AddressWidget::editEntry()
101{
102 QTableView *temp = static_cast<QTableView*>(currentWidget());
103 QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
104 QItemSelectionModel *selectionModel = temp->selectionModel();
105
106 const QModelIndexList indexes = selectionModel->selectedRows();
107 QString name;
108 QString address;
109 int row = -1;
110
111 for (const QModelIndex &index : indexes) {
112 row = proxy->mapToSource(proxyIndex: index).row();
113 QModelIndex nameIndex = table->index(row, column: 0, parent: QModelIndex());
114 QVariant varName = table->data(index: nameIndex, role: Qt::DisplayRole);
115 name = varName.toString();
116
117 QModelIndex addressIndex = table->index(row, column: 1, parent: QModelIndex());
118 QVariant varAddr = table->data(index: addressIndex, role: Qt::DisplayRole);
119 address = varAddr.toString();
120 }
121//! [4a]
122
123//! [4b]
124 AddDialog aDialog;
125 aDialog.setWindowTitle(tr(s: "Edit a Contact"));
126 aDialog.editAddress(name, address);
127
128 if (aDialog.exec()) {
129 const QString newAddress = aDialog.address();
130 if (newAddress != address) {
131 const QModelIndex index = table->index(row, column: 1, parent: QModelIndex());
132 table->setData(index, value: newAddress, role: Qt::EditRole);
133 }
134 }
135}
136//! [4b]
137
138//! [5]
139void AddressWidget::removeEntry()
140{
141 QTableView *temp = static_cast<QTableView*>(currentWidget());
142 QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
143 QItemSelectionModel *selectionModel = temp->selectionModel();
144
145 const QModelIndexList indexes = selectionModel->selectedRows();
146
147 for (QModelIndex index : indexes) {
148 int row = proxy->mapToSource(proxyIndex: index).row();
149 table->removeRows(position: row, rows: 1, index: QModelIndex());
150 }
151
152 if (table->rowCount(parent: QModelIndex()) == 0)
153 insertTab(index: 0, widget: newAddressTab, tr(s: "Address Book"));
154}
155//! [5]
156
157//! [1]
158void AddressWidget::setupTabs()
159{
160 const auto groups = { "ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ" };
161
162 for (const QString &str : groups) {
163 const auto regExp = QRegularExpression(QString("^[%1].*").arg(a: str),
164 QRegularExpression::CaseInsensitiveOption);
165
166 auto proxyModel = new QSortFilterProxyModel(this);
167 proxyModel->setSourceModel(table);
168 proxyModel->setFilterRegularExpression(regExp);
169 proxyModel->setFilterKeyColumn(0);
170
171 QTableView *tableView = new QTableView;
172 tableView->setModel(proxyModel);
173 tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
174 tableView->horizontalHeader()->setStretchLastSection(true);
175 tableView->verticalHeader()->hide();
176 tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
177 tableView->setSelectionMode(QAbstractItemView::SingleSelection);
178 tableView->setSortingEnabled(true);
179
180 connect(sender: tableView->selectionModel(), signal: &QItemSelectionModel::selectionChanged,
181 receiver: this, slot: &AddressWidget::selectionChanged);
182
183 connect(sender: this, signal: &QTabWidget::currentChanged, context: this, slot: [this, tableView](int tabIndex) {
184 if (widget(index: tabIndex) == tableView)
185 emit selectionChanged(selected: tableView->selectionModel()->selection());
186 });
187
188 addTab(widget: tableView, str);
189 }
190}
191//! [1]
192
193//! [7]
194void AddressWidget::readFromFile(const QString &fileName)
195{
196 QFile file(fileName);
197
198 if (!file.open(flags: QIODevice::ReadOnly)) {
199 QMessageBox::information(parent: this, title: tr(s: "Unable to open file"),
200 text: file.errorString());
201 return;
202 }
203
204 QVector<Contact> contacts;
205 QDataStream in(&file);
206 in >> contacts;
207
208 if (contacts.isEmpty()) {
209 QMessageBox::information(parent: this, title: tr(s: "No contacts in file"),
210 text: tr(s: "The file you are attempting to open contains no contacts."));
211 } else {
212 for (const auto &contact: qAsConst(t&: contacts))
213 addEntry(name: contact.name, address: contact.address);
214 }
215}
216//! [7]
217
218//! [6]
219void AddressWidget::writeToFile(const QString &fileName)
220{
221 QFile file(fileName);
222
223 if (!file.open(flags: QIODevice::WriteOnly)) {
224 QMessageBox::information(parent: this, title: tr(s: "Unable to open file"), text: file.errorString());
225 return;
226 }
227
228 QDataStream out(&file);
229 out << table->getContacts();
230}
231//! [6]
232

source code of qtbase/examples/widgets/itemviews/addressbook/addresswidget.cpp