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:
parent
92d67b58b8
commit
66119a07e8
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user