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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: vector of structs and QAbstractTableModel  (Прочитано 7377 раз)
UVV
Гость
« : Март 27, 2009, 10:29 »

Воспользовавшись поиском, обнаружил, что на эту тему люди задают вопросы в этот раздел, хотя я и не понимаю почему =)

Вопрос в следующем. Допустим есть vector addrSeq структур:
Код:
struct myStruct
{
    int a;
    string b;
    stricg c;
}
Есть офигительное желание натянуть поверх неё QAbstractTableModel =)
Пока не придумал ничего интереснее чем:
Код:
int myModel::columnCount(const QModelIndex &parent) const
{
    return 3;
}

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

    if (index.row() >= addrSeq.size())
        return QVariant();

    if (role == Qt::DisplayRole)
    {
        struct myStruct desc = addrSeq[index.row()];
        switch (index.column())
        {
            case 0:
                return QString("%1").arg(desc.a);
            case 1:
                return QString::fromUtf8(desc.b.c_str());
            case 2:
                return QString::fromUtf8(desc.c.c_str());
        }
    }
    else
        return QVariant();
}

QVariant myTableModel::headerData(int section,
                    Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
        return QString("Column %1").arg(section);
    else
        return QString("Row %1").arg(section);
}


Как бы вы посоветовали реализовать такое более грамотно?
Записан
Barmaglodd
Гость
« Ответ #1 : Март 27, 2009, 11:23 »

Я также делаю.
Записан
UVV
Гость
« Ответ #2 : Март 27, 2009, 12:58 »

Я также делаю.
Т.е. получается под каждую структуру свою модель? =)
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Март 27, 2009, 13:00 »

разве что
Код:
struct myStruct desc = addrSeq[index.row()];
заменить на
Код:
const struct myStruct& desc = addrSeq[index.row()];

чтобы лишний раз не делать копирование структур (будет пошустрее)
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #4 : Март 27, 2009, 13:01 »

Я также делаю.
Т.е. получается под каждую структуру свою модель? =)

Что значит "под каждую структуру свою модель" ?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
UVV
Гость
« Ответ #5 : Март 27, 2009, 13:13 »

Что значит "под каждую структуру свою модель" ?
Это значит, что вектор не один, а их много и они все с разными структурами))
« Последнее редактирование: Март 27, 2009, 13:15 от UVV » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Март 27, 2009, 13:16 »

Тогда передавай его в конструктор модели по поинтеру.
А в модели используй поинтер.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
UVV
Гость
« Ответ #7 : Март 27, 2009, 13:20 »

Тогда передавай его в конструктор модели по поинтеру.
А в модели используй поинтер.

Я говорю вот об этом:
Код:
        switch (index.column())
        {
            case 0:
                return QString("%1").arg(desc.a);
            case 1:
                return QString::fromUtf8(desc.b.c_str());
            case 2:
                return QString::fromUtf8(desc.c.c_str());
        }

Для каждой структуры придётся делать свою модель, где вот этот фрагмент будет отличаться.
Т.е. для структуры myStruct2 модель должна быть уже другой.
Код:
struct myStruct1
{
    int a;
    string b;
    stricg c;
}

struct myStruct2
{
    int d;
    int e;
    stricg f;
}
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #8 : Март 27, 2009, 13:55 »

можно конечно и свою модель, а можно делегаты разные сделать в зависимости от типа структур.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Barmaglodd
Гость
« Ответ #9 : Март 27, 2009, 13:56 »

Да, для каждой структуры своя модель. Если поля интегральных типов и строки, можно сделать функцию, которая конвертирует структуру в массив QVariant'ов, и передавать их в модель, тогда класс модели будет один. Либо сделать интерфейс, который позволяет получить по индексу QVariant c представлением данного поля, и наследников от него - конкретные реализации для каждого класса структур. Либо сделай для каждого класса структур что-то типа type_traits с информацией о полях и их типе, и используй шаблонного наследника от QAbstractItemModel. Наверно можно ещё кучу вариантов придумать.
Записан
Sergeich
Гость
« Ответ #10 : Март 30, 2009, 02:38 »

Либо сделай для каждого класса структур что-то типа type_traits с информацией о полях и их типе, и используй шаблонного наследника от QAbstractItemModel.
При использовании шаблонного наследника от QAbstractItemModel могут возникнуть проблемы, т.к. moc не поддерживает шаблоны в наследниках QObject, лучше использовать абстрактный интерфейс для получения данных из вектора, а в его реализации использовать шаблоны.
 Например, надо построить модель для вектора из трехмерных точек QVector<Point3D>:
В структуру Point3D добавляем метод для получения координаты по индексу и два статических метода для получения числа элементов структуры и названий элементов
Код:
struct Point3D
{
Point3D( float _x = 0, float _y = 0, float _z = 0 ) : x(_x), y(_y), z(_z) {}

float x;
float y;
float z;

QVariant data(int i) const { return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : QVariant(); }
static int count() { return 3; }
static QStringList names() { return QStringList() << "X" << "Y" << "Z"; }
};
Объявляем интерфейс для получения данных:
Код:
class AbstractTableData 
{
public:
virtual QVariant data( int row, int col ) const = 0;
virtual int rowCount() const = 0;
virtual int columnCount() const = 0;
virtual QVariant headerData(int) const { return QVariant(); }
};
Делаем шаблонную реализацию этого интерфейса:
Код:
template <class T>
class TableData : public AbstractTableData, public QVector<T>
{
public:
QVariant data( int row, int col ) const { return value(row).data(col); }
int rowCount() const { return size(); }
int columnCount() const { return T::count(); }
QVariant headerData(int i) const { return T::names().value(i); }
};
Реализуем модель:
Код:
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel( AbstractTableData* data, QObject* parent ) : QAbstractTableModel(parent), m_data(data) {}
int rowCount ( const QModelIndex& ) const { return m_data->rowCount(); }
int columnCount ( const QModelIndex& ) const { return m_data->columnCount(); }
QVariant data ( const QModelIndex& index, int role ) const {
return role ==  Qt::DisplayRole ? m_data->data( index.row(), index.column() ) : QVariant();
  }
QVariant headerData ( int section, Qt::Orientation orientation, int role ) const {
if (role ==  Qt::DisplayRole)
return (orientation == Qt::Horizontal) ? m_data->headerData( section ) : section + 1;
return QVariant();
}
private:
AbstractTableData* m_data;
};
Юзаем:
Код:
int main( int argc, char** argv )
{
QApplication app( argc, argv );

TableData<Point3D> data;
for ( int i = 0; i < 100; i++ )
data << Point3D( i % 10, i / 10, (i % 10) * (i / 10) );

TableModel model( &data, 0 );

QTableView view;
view.setModel( &model );
view.resize( 400, 600 );
view.show();

return app.exec();
}
Записан
Barmaglodd
Гость
« Ответ #11 : Март 30, 2009, 08:23 »

При использовании шаблонного наследника от QAbstractItemModel могут возникнуть проблемы, т.к. moc не поддерживает шаблоны в наследниках QObject, лучше использовать абстрактный интерфейс для получения данных из вектора, а в его реализации использовать шаблоны.
Всё зависит от того, как вы этого наследника будете использовать Подмигивающий
http://doc.trolltech.com/qq/qq15-academic.html
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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