Address Book example: Replace QPair by struct

Introduce Contact struct to store contact data and use it
instead of QPair<QString, QString>. Proper naming really
clarifies the code.

Task-number: QTBUG-60635
Change-Id: Ibfb421dfc854accc382212b0da46e7aafc0d528a
Reviewed-by: Jesus Fernandez <Jesus.Fernandez@qt.io>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
Alexander Volkov 2017-09-04 18:09:52 +03:00
parent 92d67b58b8
commit 66119a07e8
4 changed files with 64 additions and 54 deletions

View File

@ -60,8 +60,8 @@
the address book.
\c TableModel is a subclass of QAbstractTableModel that provides
the standard model/view API to access data. It also holds a
QList of \l{QPair}s corresponding to the contacts added.
the standard model/view API to access data. It holds a list of
added contacts.
However, this data is not all visible in a single tab. Instead,
QTableView is used to provide 9 different views of the same
data, according to the alphabet groups.
@ -80,7 +80,7 @@
\section1 TableModel Class Definition
The \c TableModel class provides standard API to access data in
its QList of \l{QPair}s by subclassing QAbstractTableModel. The
its list of contacts by subclassing QAbstractTableModel. The
basic functions that must be implemented in order to do so are:
\c rowCount(), \c columnCount(), \c data(), \c headerData().
For TableModel to be editable, it has to provide implementations
@ -90,15 +90,14 @@
\snippet itemviews/addressbook/tablemodel.h 0
Two constructors are used, a default constructor which uses
\c TableModel's own \c {QList<QPair<QString, QString>>} and one
that takes \c {QList<QPair<QString, QString>} as an argument,
for convenience.
\c TableModel's own \c {QList<Contact>} and one that takes
\c {QList<Contact>} as an argument, for convenience.
\section1 TableModel Class Implementation
We implement the two constructors as defined in the header file.
The second constructor initializes the list of pairs in the
The second constructor initializes the list of contacts in the
model, with the parameter value.
\snippet itemviews/addressbook/tablemodel.cpp 0
@ -117,7 +116,7 @@
The \c data() function returns either a \b Name or
\b {Address}, based on the contents of the model index
supplied. The row number stored in the model index is used to
reference an item in the list of pairs. Selection is handled
reference an item in the list of contacts. Selection is handled
by the QItemSelectionModel, which will be explained with
\c AddressWidget.
@ -164,12 +163,11 @@
use the editing features of the QTableView object, we enable
them here so that we can reuse the model in other programs.
The last function in \c {TableModel}, \c getList() returns the
QList<QPair<QString, QString>> object that holds all the
contacts in the address book. We use this function later to
obtain the list of contacts to check for existing entries, write
the contacts to a file and read them back. Further explanation is
given with \c AddressWidget.
The last function in \c {TableModel}, \c getContacts() returns the
QList<Contact> object that holds all the contacts in the address
book. We use this function later to obtain the list of contacts to
check for existing entries, write the contacts to a file and read
them back. Further explanation is given with \c AddressWidget.
\snippet itemviews/addressbook/tablemodel.cpp 8
@ -250,7 +248,7 @@
Basic validation is done in the second \c addEntry() function to
prevent duplicate entries in the address book. As mentioned with
\c TableModel, this is part of the reason why we require the
getter method \c getList().
getter method \c getContacts().
\snippet itemviews/addressbook/addresswidget.cpp 3
@ -292,7 +290,7 @@
The \c writeToFile() function is used to save a file containing
all the contacts in the address book. The file is saved in a
custom \c{.dat} format. The contents of the QList of \l{QPair}s
custom \c{.dat} format. The contents of the list of contacts
are written to \c file using QDataStream. If the file cannot be
opened, a QMessageBox is displayed with the related error message.
@ -301,7 +299,7 @@
The \c readFromFile() function loads a file containing all the
contacts in the address book, previously saved using
\c writeToFile(). QDataStream is used to read the contents of a
\c{.dat} file into a list of pairs and each of these is added
\c{.dat} file into a list of contacts and each of these is added
using \c addEntry().
\snippet itemviews/addressbook/addresswidget.cpp 7

View File

@ -85,10 +85,7 @@ void AddressWidget::showAddEntryDialog()
//! [3]
void AddressWidget::addEntry(QString name, QString address)
{
QList<QPair<QString, QString> >list = table->getList();
QPair<QString, QString> pair(name, address);
if (!list.contains(pair)) {
if (!table->getContacts().contains({ name, address })) {
table->insertRows(0, 1, QModelIndex());
QModelIndex index = table->index(0, 0, QModelIndex());
@ -211,18 +208,16 @@ void AddressWidget::readFromFile(const QString &fileName)
return;
}
QList<QPair<QString, QString> > pairs = table->getList();
QList<Contact> contacts;
QDataStream in(&file);
in >> pairs;
in >> contacts;
if (pairs.isEmpty()) {
if (contacts.isEmpty()) {
QMessageBox::information(this, tr("No contacts in file"),
tr("The file you are attempting to open contains no contacts."));
} else {
for (int i=0; i<pairs.size(); ++i) {
QPair<QString, QString> p = pairs.at(i);
addEntry(p.first, p.second);
}
for (const auto &contact: qAsConst(contacts))
addEntry(contact.name, contact.address);
}
}
//! [7]
@ -237,8 +232,7 @@ void AddressWidget::writeToFile(const QString &fileName)
return;
}
QList<QPair<QString, QString> > pairs = table->getList();
QDataStream out(&file);
out << pairs;
out << table->getContacts();
}
//! [6]

View File

@ -56,10 +56,10 @@ TableModel::TableModel(QObject *parent)
{
}
TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
TableModel::TableModel(QList<Contact> contacts, QObject *parent)
: QAbstractTableModel(parent)
, contacts(contacts)
{
listOfPairs = pairs;
}
//! [0]
@ -67,7 +67,7 @@ TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
int TableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return listOfPairs.size();
return contacts.size();
}
int TableModel::columnCount(const QModelIndex &parent) const
@ -83,16 +83,16 @@ QVariant TableModel::data(const QModelIndex &index, int role) const
if (!index.isValid())
return QVariant();
if (index.row() >= listOfPairs.size() || index.row() < 0)
if (index.row() >= contacts.size() || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QPair<QString, QString> pair = listOfPairs.at(index.row());
const auto &contact = contacts.at(index.row());
if (index.column() == 0)
return pair.first;
return contact.name;
else if (index.column() == 1)
return pair.second;
return contact.address;
}
return QVariant();
}
@ -126,10 +126,8 @@ bool TableModel::insertRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
QPair<QString, QString> pair(" ", " ");
listOfPairs.insert(position, pair);
}
for (int row = 0; row < rows; ++row)
contacts.insert(position, { QString(), QString() });
endInsertRows();
return true;
@ -142,9 +140,8 @@ bool TableModel::removeRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
listOfPairs.removeAt(position);
}
for (int row = 0; row < rows; ++row)
contacts.removeAt(position);
endRemoveRows();
return true;
@ -157,16 +154,16 @@ bool TableModel::setData(const QModelIndex &index, const QVariant &value, int ro
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
QPair<QString, QString> p = listOfPairs.value(row);
auto contact = contacts.value(row);
if (index.column() == 0)
p.first = value.toString();
contact.name = value.toString();
else if (index.column() == 1)
p.second = value.toString();
contact.address = value.toString();
else
return false;
listOfPairs.replace(row, p);
contacts.replace(row, contact);
emit(dataChanged(index, index));
return true;
@ -187,8 +184,8 @@ Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
//! [7]
//! [8]
QList< QPair<QString, QString> > TableModel::getList()
QList<Contact> TableModel::getContacts() const
{
return listOfPairs;
return contacts;
}
//! [8]

View File

@ -53,16 +53,37 @@
#include <QAbstractTableModel>
#include <QList>
#include <QPair>
//! [0]
struct Contact
{
QString name;
QString address;
bool operator==(const Contact &other) const
{
return name == other.name && address == other.address;
}
};
inline QDataStream &operator<<(QDataStream &stream, const Contact &contact)
{
return stream << contact.name << contact.address;
}
inline QDataStream &operator>>(QDataStream &stream, Contact &contact)
{
return stream >> contact.name >> contact.address;
}
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel(QObject *parent = 0);
TableModel(QList<QPair<QString, QString> > listofPairs, QObject *parent = 0);
TableModel(QList<Contact> contacts, QObject *parent = 0);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
@ -72,10 +93,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
QList<QPair<QString, QString> > getList();
QList<Contact> getContacts() const;
private:
QList<QPair<QString, QString> > listOfPairs;
QList<Contact> contacts;
};
//! [0]