crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Отображение QAbstractItemModel на QSortFilterProxyModel, Забавное поведение
h0x0d9
  опции профиля:
сообщение 3.9.2013, 16:54
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 3.9.2013
Пользователь №: 3923

Спасибо сказали: 0 раз(а)




Репутация:   0  


Добрый вечер.
Возник затык и без посторонней помощи, к сожалению, видимо, не обойдусь.
Есть модель дерева ListsRegisterModel, реализующая QAbstractItemModel.
Есть QSortFilterProxyModel, к которой подключаю источником модель ListsRegisterModel.
Вывожу ListsRegisterModel и прокси-модель в различные QTreeView.
И тут начинается странное. У меня пропали ветки второго уровня во втором отображении, хотя судя по виду, rowCount() отрабатывает правильно.



    ListsRegisterModel *model = new ListsRegisterModel(this);

    QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);


    QTreeView *view = new QTreeView(this);
    view->setModel(model);

    QTreeView *view2 = new QTreeView(this);
    view2->setModel(proxyModel);



Раскрывающийся текст
class ListsRegisterModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    explicit ListsRegisterModel(QObject *parent = 0);
    ~ListsRegisterModel();

    QVariant data(const QModelIndex &index, int role) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const;
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::CheckStateRole);

private:
    enum Columns // нумерованный список колонок
    {
        RamificationColumn,
        ListNameColumn = RamificationColumn,
        ListSubscriberColumn
    };

    TreeItem *rootItem;

    /**
     * @brief parseListsFile разбираем структуру файла с описаниями списков
     * @param path путь к файлу с регистром списков
     * @return QMultiMap<имя_списка, адрес получателя>
     */
    QMultiMap<QString, QString> parseListsFile(QString path);

    /**
     * @brief setupModelData первоначальная настройка модели
     * @param lists multiMap с регистром списков
     * @param parent корневой элемент дерева
     */
    void setupModelData(QMultiMap<QString, QString> lists, TreeItem *parent);
    TreeItem *getItem(const QModelIndex &index) const;
};

#include "listsregistermodel.h"
#include <QtCore>
#include "../treeItem/treeitem.h"

ListsRegisterModel::ListsRegisterModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    QList<QVariant> rootData;
    rootData << tr("Имя") << tr("Абоненты");
    rootItem = new TreeItem(rootData);

    QMultiMap<QString, QString> listsReg = parseListsFile("etc/lists.reg");
    setupModelData(listsReg, rootItem);
}


void ListsRegisterModel::setupModelData(
        QMultiMap<QString, QString> lists, TreeItem *parent)
{
    TreeItem *root = parent;
    QList<TreeItem*> parents;
    parents << root;

    foreach (QString listName, lists.uniqueKeys()) {
        root->appendChild(new TreeItem(listName, root));
        if (root->childCount() > 0) {
            parents << root->child(root->childCount() - 1);
        }
        foreach (QString subscriber, lists.values(listName)) {
            parents.last()->appendChild(
                        new TreeItem(subscriber, parents.last()));
        }
    }
}


QMultiMap<QString, QString> ListsRegisterModel::parseListsFile(QString path)
{
    QMultiMap<QString, QString> listsRegister;
    QRegExp rx("^(\\d{4})\\s+\\{(.+)\\}$");

    QFile file(path);
    if (!file.exists()) {
        qWarning() << "Warning: file " << file.fileName() << " is not exist";
    }

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Warning: file " << file.fileName() << " didn't' open";
    }

    while (!file.atEnd()) {
        // поиск регулярного выражения в следующей строке
        rx.indexIn(file.readLine().trimmed());
        // выбор абонентов выбранного списка
        QStringList subscribers =
                rx.cap(2).simplified().split(",", QString::KeepEmptyParts);
        // заполнение MultiMap контейнера значениями <имя списка, абонент>
        foreach (QString addr, subscribers) {
            listsRegister.insertMulti(rx.cap(1), addr);
        }
    }

    file.close();

    return listsRegister;
}


ListsRegisterModel::~ListsRegisterModel()
{
    delete rootItem;
}


QVariant ListsRegisterModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TreeItem *item = getItem(index);

    switch (role) {
    case Qt::DisplayRole:
        if (item->parent() == rootItem) {
            return item->data(index.column());
        }
        else {
            qDebug() << item->data(index.column() - 1);
            return item->data(index.column() - 1);
        }
        break;
    case Qt::CheckStateRole:
        if (index.column() == RamificationColumn
                && item->parent() == rootItem) {
            return QVariant(item->checkState());
        }
        break;
    default:
        return QVariant();
        break;
    }
    return QVariant();
}


TreeItem *ListsRegisterModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item) return item;
    }
    return rootItem;
}


Qt::ItemFlags ListsRegisterModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    const Qt::ItemFlags f = QAbstractItemModel::flags(index);

    TreeItem * item = getItem(index);

    if (index.column() == RamificationColumn && item->parent() == rootItem) {
        return  f | Qt::ItemIsUserCheckable;
    }
    return f;
}


QVariant ListsRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}


QModelIndex ListsRegisterModel::index(int row, int column, const QModelIndex &parent) const
{
    TreeItem * parentItem;

    if (row < 0 || column < 0)
        return QModelIndex();

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = getItem(parent);

    TreeItem *childItem = parentItem->child(row);

    if (childItem)
        return createIndex(row, column, childItem);

    return QModelIndex();
}


QModelIndex ListsRegisterModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = getItem(index);
    TreeItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}


int ListsRegisterModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}


int ListsRegisterModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}


bool ListsRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::CheckStateRole)
        return false;

    TreeItem *item = getItem(index);

    Qt::CheckState state
            = (value.toInt() == Qt::Checked) ? Qt::Checked : Qt::Unchecked;
    item->setCheckState(state);

    emit dataChanged(index, index);

    return true;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
h0x0d9
  опции профиля:
сообщение 4.9.2013, 18:10
Сообщение #2


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 3.9.2013
Пользователь №: 3923

Спасибо сказали: 0 раз(а)




Репутация:   0  


Добавил исходники: git@bitbucket.org:h0x0d9/myfilterproxymodel.git
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.9.2013, 19:05
Сообщение #3


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


чтобы исключить " хотя судя по виду", сделай так
#include <QDebug>

int ListsRegisterModel::rowCount(const QModelIndex &parent) const
{
TreeItem *parentItem;
if (parent.column() > 0)
return 0;

if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());

qDebug()<<"parentItem->childCount();=="<<parentItem->childCount();

return parentItem->childCount();
}

и проверь, что именно идёт в консоль :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
h0x0d9
  опции профиля:
сообщение 5.9.2013, 13:07
Сообщение #4


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 3.9.2013
Пользователь №: 3923

Спасибо сказали: 0 раз(а)




Репутация:   0  


Решением было переопределить функцию columnCount.

int ListsRegisterModel::columnCount(const QModelIndex &parent) const
{
    return 2;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 18:09