C/C++ - *QT* | Как сделать свой QAbstractItemModel

Ответить
Аватара пользователя
pva

C/C++ - *QT* | Как сделать свой QAbstractItemModel

Сообщение pva »

Вопрос знатокам 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(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(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(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(rc, Node(parent));
    QVector *v = parent ? parent->children : tree;
    return const_cast(&(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

Re: C/C++ - *QT* | Как сделать свой QAbstractItemModel

Сообщение usvad »

// Получение индекса класса 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(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(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

//

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(rc, Node(parent));

QVector *v = parent ? parent->children : tree;

return const_cast(&(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

Re: C/C++ - *QT* | Как сделать свой QAbstractItemModel

Сообщение pva »

Как можно эту штуку скрестить с SQL-запросом?
Вложения
treemodels.tar.gz
(3.79 КБ) 0 скачиваний
treemodels.tar.gz
(3.79 КБ) 0 скачиваний
Ответить

Вернуться в «Программирование и базы данных»