PDA

Показать полную графическую версию : *QT* | Как сделать свой QAbstractItemModel


pva
25-03-2008, 13:06
Вопрос знатокам QT4: я хочу изображать группы объектов в виде дерева, для этого в SQL хранится табличка типа

create table person_path
(
id integer identity(1,1) primary key,
path_id integer references person_path(id),
name varchar(30) not null,
comment varchar(255),
constraint unique_person_path unique (path_id, name)
);

как теперь сделать из QSqlQueryModel такую модель, чтобы она отображалась в виде дерева? я вырезал из примеров кусок кода, который делает подобное, но не впираю, что за что отвечает. Растусуйте, пожалуйста.

Model::Model(int rows, int columns, QObject *parent)
: QAbstractItemModel(parent),
rc(rows), cc(columns),
tree(new QVector<Node>(rows, Node(0)))
{

}

Model::~Model()
{
delete tree;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if (row < rc && row >= 0 && column < cc && column >= 0) {
Node *p = static_cast<Node*>(parent.internalPointer());
Node *n = node(row, p);
if (n)
return createIndex(row, column, n);
}
return QModelIndex();
}

QModelIndex Model::parent(const QModelIndex &child) const
{
if (child.isValid()) {
Node *n = static_cast<Node*>(child.internalPointer());
Node *p = parent(n);
if (p)
return createIndex(row(p), 0, p);
}
return QModelIndex();
}

int Model::rowCount(const QModelIndex &parent) const
{
return (parent.isValid() && parent.column() != 0) ? 0 : rc;
}

int Model::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return cc;
}

QVariant Model::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole)
return "Item " + QString::number(index.row()) + ":" + QString::number(index.column());
if (role == Qt::DecorationRole) {
if (index.column() == 0)
return iconProvider.icon(QFileIconProvider::Folder);
return iconProvider.icon(QFileIconProvider::File);
}
return QVariant();
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
static QIcon services(QPixmap(":/images/services.png"));
if (role == Qt::DisplayRole)
return QString::number(section);
if (role == Qt::DecorationRole)
return qVariantFromValue(services);
return QAbstractItemModel::headerData(section, orientation, role);
}

bool Model::hasChildren(const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return false;
return rc > 0 && cc > 0;
}

Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return (Qt::ItemIsDragEnabled|Qt::ItemIsSelectable|Qt::ItemIsEnabled);
}

Model::Node *Model::node(int row, Node *parent) const
{
if (parent && !parent->children)
parent->children = new QVector<Node>(rc, Node(parent));
QVector<Node> *v = parent ? parent->children : tree;
return const_cast<Node*>(&(v->at(row)));
}

Model::Node *Model::parent(Node *child) const
{
return child ? child->parent : 0;
}

int Model::row(Node *node) const
{
const Node *first = node->parent ? &(node->parent->children->at(0)) : &(tree->at(0));
return (node - first);
}

usvad
14-05-2008, 10:29
// Получение индекса класса QModelIndex по номеру строки и номеру колонки для родительского элемента parent
// примечание: данный метод вызывает виджет отображения при обходе модели данных
QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
if (row < rc && row >= 0 && column < cc && column >= 0) {
Node *p = static_cast<Node*>(parent.internalPointer());
Node *n = node(row, p);
if (n)
return createIndex(row, column, n);
}
return QModelIndex();
}

// Получить родительский элемент класса QModelIndex для подчиненного элемента child
QModelIndex Model::parent(const QModelIndex &child) const
{
if (child.isValid()) {
Node *n = static_cast<Node*>(child.internalPointer());
Node *p = parent(n);
if (p)
return createIndex(row(p), 0, p);
}
return QModelIndex();
}

// получить количество подчиненных элементов для узла parent
int Model::rowCount(const QModelIndex &parent) const
{
return (parent.isValid() && parent.column() != 0) ? 0 : rc;
}

// получить количество отображаемых колонок с данными для узла parent
// здесь можно было установить количество данных, которое содержит каждый узел,
// например список строк или количество полей из таблицы
int Model::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return cc;
}

// получить данные узла index для роли данных role
//примечание: именно здесть виджет получает данные из узла
QVariant Model::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole) // отображаемое значение
return "Item " + QString::number(index.row()) + ":" + QString::number(index.column());
if (role == Qt::DecorationRole) { // в данном случае декорация это иконка - а можно что угодно
if (index.column() == 0)
return iconProvider.icon(QFileIconProvider::Folder);
return iconProvider.icon(QFileIconProvider::File);
}
return QVariant(); // для других ролей пустое значение, а лучше вызвать родительский метод
}

// получить данные для заголовка виджета отображения модели с номером колонки или строки section
// ориентацией по колонкам или по строкам и роли получаемых данных role
// примечание: чаще всего имеет значение только для корневого узла. Или выдавать значение заголовков для встраиваемых виджетов
QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
static QIcon services(QPixmap(":/images/services.png"));
if (role == Qt::DisplayRole)
return QString::number(section);
if (role == Qt::DecorationRole)
return qVariantFromValue(services);
return QAbstractItemModel::headerData(section, orientation, role);
}

// Проверка на наличие подчиненных узлов для узла parent
// <Не обязательный метод - достаточно перекрыть rowCount>
bool Model::hasChildren(const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return false;
return rc > 0 && cc > 0;
}

// Установить свойства для узла index
// в данном случае это: может выбираться и может быть активным
Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return (Qt::ItemIsDragEnabled|Qt::ItemIsSelectable|Qt::ItemIsEnabled);
}

//__________________________________________________
// Это, как я понял, методы доступа к данным каждого узла
// которые будут закрепляться за QModelIndex

Model::Node *Model::node(int row, Node *parent) const
{
if (parent && !parent->children)
parent->children = new QVector<Node>(rc, Node(parent));
QVector<Node> *v = parent ? parent->children : tree;
return const_cast<Node*>(&(v->at(row)));
}

Model::Node *Model::parent(Node *child) const
{
return child ? child->parent : 0;
}

int Model::row(Node *node) const
{
const Node *first = node->parent ? &(node->parent->children->at(0)) : &(tree->at(0));
return (node - first)

pva
14-05-2008, 15:06
Как можно эту штуку скрестить с SQL-запросом?

usvad
28-05-2008, 07:10
Например вот так..))

usvad
28-05-2008, 07:11
http://forum.oszone.net/attachment.php?attachmentid=11832&stc=1&d=1211951234




© OSzone.net 2001-2012