Russian Qt Forum
Ноябрь 05, 2024, 22:09 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Прокси модель и удаление строки  (Прочитано 4997 раз)
Kunashir
Гость
« : Июль 06, 2011, 12:39 »

День добрый!

Имеется табличная модель наследник от QAbstractTableModel. Она отображает на QTableView через QSortFilterProxyModel.
Все нормально работает и даже идет удаление, но при этом процессе в Креаторе (в отладочном режиме) выводится QSortFilterProxyModel: inconsistent changes reported by source model.
И удаление 1000 строк идет около минут - ИМХО долго, думаю может из-за этого ошибки.

Подскажите куда копать?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Июль 06, 2011, 12:40 »

Код приложи модели, прокси и как настраиваешь отображение.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Kunashir
Гость
« Ответ #2 : Июль 06, 2011, 12:49 »

Модель:
catalogTableModel.h
Код:
class CatalogTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit CatalogTableModel(TlsPrices *lsItem, QObject *parent);
    ~CatalogTableModel ();
 
    int                   rowCount         (const QModelIndex &parent = QModelIndex ()) const;
    int                   columnCount   (const QModelIndex &parent = QModelIndex ()) const;
    QVariant         headerData     (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags                (const QModelIndex &index) const;
    QVariant         data                  (const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool                 hasChildren    (const QModelIndex &parent = QModelIndex ()) const;
    bool                 setData           (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    bool                 removeRows (int row, int count, const QModelIndex &parent = QModelIndex ());
    bool                removeRowsWithCondition(int column, QString value);
    bool                insertRows     (int row, int count, const QModelIndex &parent = QModelIndex ());
    TlsPrices*      getPointerToData () {   return listItem;}
    void                setHeaderList (QList<QString> ls) { keys = ls;}

private:
    TlsPrices *listItem;                   
    QList <QString> lsNameAttr;     
    QList <QString> keys;                 //списко названий столбцов
};

catalogTableModel.cpp

Код:
#include <QSize>
#include <QFont>
 #include <QFontMetrics>
#include "catalogtablemodel.h"


CatalogTableModel::CatalogTableModel(TlsPrices *lsItem, QObject *parent) :
    QAbstractTableModel(parent)
{
    listItem = lsItem;

}

CatalogTableModel::~CatalogTableModel()
{

}


int CatalogTableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return listItem->count() ;
}

int CatalogTableModel::columnCount(const QModelIndex &parent) const
{
     return   keys.count();//7;//lsNameAttr.count() ;
}

QVariant CatalogTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        return keys.at(section);
    }
    return QAbstractItemModel::headerData(section, orientation, role);
}

Qt::ItemFlags CatalogTableModel::flags(const QModelIndex &index) const
{
     bool isSpec = false;
     if (keys.count() < 6)
            isSpec = true;
     if (index.column() == 6 || (index.column() == 2 && isSpec))
        return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;

    return QAbstractItemModel::flags(index);
}

QVariant CatalogTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || !listItem->count())
        return QVariant ();
    if (role == Qt::FontRole)
    {
        return QFont ("Helvetica");
    }
    if (role == Qt::SizeHintRole)
    {
        //Рассчет наилучшего размера
        //макс длина 200, если больше, то переносим
       QFont f ("Helvetica");
       QFontMetrics fm (f);
        if (index.column() == 0 || index.column() == 1
               || index.column() == 3)
        {
            int w = fm.width (listItem->at(index.row())->getData(index.column()).toString());
            int h = fm.height() - 2;
            if ( (w/200) > 1)
            {
                double ost = w/double (200);
                h = h*ost; //(w/200);
                w = 200;
            }
           return QSize (w, h);
        }
        return QSize (50, 25);
        //QFont
        //listItem->at(index.row())->getData(index.column()).toString().;
    }
    // QList <QString> keys = listItem->keys();
    if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
        bool isSpec = false;
        if (keys.count() < 6)
        {
            isSpec = true;
            if (index.column() == 4)
            {
                double summa = listItem->at(index.row())->getData(2, isSpec).toDouble()*listItem->at(index.row())->getData(3, isSpec).toDouble();
                return summa;
            }
        }
        return listItem->at(index.row())->getData(index.column(), isSpec);

    }
    else if ( role == Qt::UserRole)
    {

    }
    return QVariant ();
}

bool CatalogTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.column() == 6)
    {
        listItem->at(index.row())->order = value.toInt();

        return true;
     }

  // bool isSpec = false;
    if (keys.count() < 6)
    {
        //isSpec = true;
        if (index.column() == 2)
        {
            listItem->at(index.row())->price = value.toDouble();
            reset ();//чтобы обновить вьюхи
            return true;
        }

    }
     return false;
}

bool CatalogTableModel::insertRows (int row, int count, const QModelIndex &parent)
{
//    Q_UNUSED (parent);
//    CATALOG_ITEM newItem ;
//    newItem.id = "0";
//    //newItem.code = "0000002";
//    //for (int i = 0; i < columnCount(QModelIndex()); i++)

//    beginInsertRows(QModelIndex (), row, row + count - 1);
//    //вызов сигнала
//    (*listItem).insert("0", newItem);
//    keys.append("0");

//    endInsertRows();
// //   emit sItemChanged(newItem, true);
    return true;
}

bool CatalogTableModel::removeRows (int row, int count, const QModelIndex &parent)
{
    //TODO:
    Q_UNUSED (parent);
    beginRemoveRows(QModelIndex(), row, row + count - 1);
    //int column = row + count;
    for (int i = 0; i < count; ++i)
    {
        delete listItem->at(row);
        listItem->removeAt(row);
    }
    emit layoutChanged();
    endRemoveRows();
    return true;
}

bool CatalogTableModel::hasChildren(const QModelIndex &parent) const
{
    return !parent.isValid();
}

//Удаление строк модели по условию
//Вход:
//column - колонка условия
//value    - значение для условия
bool CatalogTableModel::removeRowsWithCondition(int column, QString value)
{
    //int i = 0;
    int sizeOfList = listItem->count()-1;
    //while (i < sizeOfList)
    for (int i = sizeOfList; i >= 0; --i)
    {
        if (listItem->at(i)->getData(column).toString() == value)
        {
            removeRows(i, 1);
//            sizeOfList = listItem->count();
//            continue;
        }
        //++i;
    }
}


кусок из mainwindows.cpp

Код:
void MainWindow::setHierarhy()
{

    if (ui->checkBox->isChecked())
    {
        tableProxyModel->setSourceModel(model.getTableModel());//вот с этой моделью работаю
        ui->treeView->setVisible(false);
    }
    else
    {
        tableProxyModel->setSourceModel(&model);
        ui->treeView->setVisible(true);
    }
}

//удаление одной строки

void MainWindow::delRowPrice()
{
    //model.getTableModel()->removeRows( tableProxyModel->mapToSource(ui->tableView->currentIndex()).row(), 1);
    int row = ui->tableView->currentIndex().row();
    if (ui->tableView->currentIndex().isValid())
        tableProxyModel->removeRows(ui->tableView->currentIndex().row(), 1);
    //tableProxyModel->removeRow(ui->tableView->currentIndex().row());
    ui->tableView->setCurrentIndex(tableProxyModel->index(row, 0));
}

Записан
Kunashir
Гость
« Ответ #3 : Июль 07, 2011, 15:32 »

Проблема видимо в синхронизации прокси и исходной модели... но как правильно делать удаления я не нашел.
Пока решил это отключением прокси модели, потом удалением из исходной и новым подключением прокси.
Записан
Kolobok
Гость
« Ответ #4 : Июль 07, 2011, 17:42 »

Убери emit layoutChanged(); из CatalogTableModel::removeRows(). Оно там лишнее. И проблему может решит Улыбающийся
Записан
MoPDoBoPoT
Гость
« Ответ #5 : Июль 07, 2011, 20:19 »

Ещё кое-что в глаза бросилось. Это, конечно, не относиться к проблеме топика, но всё же:
В методе setData() после небольшого изменения ресетиться вся модель, хотя можно было сигналить с помощью dataChanged().
Записан
Kunashir
Гость
« Ответ #6 : Июль 08, 2011, 07:45 »

Убери emit layoutChanged(); из CatalogTableModel::removeRows(). Оно там лишнее. И проблему может решит Улыбающийся

Без него вообще происходит крах где-то в недрах

 endRemoveRows();

У меня впечатление, что я как-то не правильно использую связку с прокси моделью, но только как правильно не пойму.

Павилк: сброс модели поставил, так как при изменение данных не происходило обновление на вьюхи... Попробую с dataChanged().
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.078 секунд. Запросов: 23.