Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   *QT* | Как сделать свой QAbstractItemModel (http://forum.oszone.net/showthread.php?t=103618)

pva 25-03-2008 13:06 767297

*QT* | Как сделать свой QAbstractItemModel
 
Вопрос знатокам 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 802195

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

Как можно эту штуку скрестить с SQL-запросом?

usvad 28-05-2008 07:10 812492

Вложений: 1
Например вот так..))

usvad 28-05-2008 07:11 812493

http://forum.oszone.net/attachment.p...1&d=1211951234


Время: 01:29.

Время: 01:29.
© OSzone.net 2001-