BlinCT
BlinCTOct. 24, 2019, 12:42 p.m.

Заполнение tableModel из структуры

Всем привет.
Пытаюсь заполнить таблицу из структуры которую передаю обьекту вектором.
Может я где то ошибаюсь, undefind reference получаю. Но почему непонятно.
Ниже кидаю код класса.

#pragma once

#include <QtCore/QAbstractTableModel>
#include <sources/structs/wrappers/nvme/Tables.hpp>

template <typename T>
class TableModel : public QAbstractTableModel
{
public:
    explicit TableModel(QVector<T > vec);

    [[nodiscard]] int rowCount(const QModelIndex &parent) const override;

    [[nodiscard]] int columnCount(const QModelIndex &parent) const override;

    [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;

    [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

private:
    int m_rowCount;
    int m_columnCount;

    QVector<T* > m_vec;

    QVector<QString> m_vecSupPowerState;
};
#include <QDebug>

#include "TableModel.hpp"

template <typename T>
TableModel<T>::TableModel(QVector<T > vec)
    : m_vec(vec)
    , m_rowCount(vec.size())
    , m_columnCount(0)
{
    m_vecSupPowerState.push_back("St");
    m_vecSupPowerState.push_back("Op");
    m_vecSupPowerState.push_back("Max");
    m_vecSupPowerState.push_back("Active");
    m_vecSupPowerState.push_back("Idle");
    m_vecSupPowerState.push_back("RL");
    m_vecSupPowerState.push_back("RT");
    m_vecSupPowerState.push_back("WL");
    m_vecSupPowerState.push_back("WT");
    m_vecSupPowerState.push_back("Ent_Lat");
    m_vecSupPowerState.push_back("Ex_lat");

    if (m_vec == QVector<SupportedPowerStates>())
    {
        qDebug() << "SupportedPowerStates";
    }
}

template <typename T>
int TableModel<T>::rowCount(const QModelIndex &parent) const
{
    return m_vec.size();
}

template <typename T>
int TableModel<T>::columnCount(const QModelIndex &parent) const
{
    return 0;
}

template <typename T>
QVariant TableModel<T>::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
    {
        return QVariant();
    }

    int row = index.row();
    int col = index.column();

    switch (role)
    {
        case Qt::DisplayRole:
            return QString("%1, %2").arg(index.column()).arg(index.row());
        default:
            break;
    }

    return QVariant();
}

template <typename T>
QVariant TableModel<T>::headerData(int section, Qt::Orientation orientation, int role) const
{
    if( role != Qt::DisplayRole )
    {
        return QVariant();
    }

    if( orientation == Qt::Vertical )
    {
        return section;
    }

    switch( section )
    {
        case 0:
            return tr( "St" );
        case 1:
            return tr( "Op" );
        case 2:
            return tr( "Max" );
        case 3:
            return tr( "Active" );
        case 4:
            return tr( "Idle" );
        case 5:
            return tr( "RL" );
        case 6:
            return tr( "RT" );
        case 7:
            return tr( "WL" );
        case 8:
            return tr( "WT" );
        case 9:
            return tr( "Ent_Lat" );
        case 10:
            return tr( "Ex_lat" );

    }

}

Если видите в конструкторе я просто воткнул проверку, только для теста, то есть обьекту могут прилететь разыне структуры, у них разное колличество строк и столбцов.
Так же в конструкторе заполняется вектор который будет использоватся если прилетит SupportedPowerStates которая как раз в конструкторе и проверяется.
Вопрос такой, не знаю как проверять в случаи если данная структура прилетела и дял нее использовать данные поля.
И приму любые советы если есть какие то ошибки в реализации.

В main.cpp я создаю обьект таким способом

auto tableModel = new TableModel<QVector<SupportedPowerStates> >(nvmeIdCtrl->getSupportedPowerStates());
engine.rootContext()->setContextProperty("tableModel", tableModel);

Как раз данный метод и возвращает вектор такой структуры.

Спасибо.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

13
Evgenii Legotckoi
  • Oct. 25, 2019, 3:06 a.m.
  • (edited)

Привет.
Зачем использовать таблицу, когда по факту здесь обрабатывается одна строка? Несмотря на то, что по задумке видимо каждый объект должен прдставлять собой именно строку.
При этом в headerData возвращаешь заголовки для горизонтальной ориентации. section в том случае - это номер колонки.
Почему coulmnCount возвращает 0? в данном случае он возвращать должен как минимум 1, если следовать задумке.

Вообще, вместо того, чтобы шаманить шаблоны. Лучше передавать в таблицу указатель на интерфейсный класс, а передаваемые в вектор объекты должны будут реализовывать этот интерфейс.

    BlinCT
    • Oct. 25, 2019, 6:33 a.m.

    По поводу передачи одной строки это пока просто был тест, туда будет именно таблица лететь, ну то есть вектор векторов.
    В headerData там был просто начальный набросок, и как я написал там будет в зависимости какая структура такая структура с заголовками и будет.
    Там я заготовил одну из них. В coulmnCount возвращение 0 это пока дефолтно.

      Evgenii Legotckoi
      • Oct. 25, 2019, 6:43 a.m.

      Вместо вектора векторов лучше использовать класс или структуру. Или лучше я говорил интерфейсный класс или базовый абстрактный класс. В большинстве случае можно и без шаблона обойтись.

      Полагаю, что undefined reference относится скорее к проблеме внутри main функции, полный текст кода хотелось бы видеть.

      Либо проблема может быть в том, что шаблоны и Q_OBJECT не совместимы. То есть либо пишется шаблонная модель, либо модель с макросом Q_OBJECT.
      Либо можно написать шаблонную модель, от которой наследуется конкретная реализация с Q_OBJECT. Такое тоже работает. Но одновременно в одном классе нет. Тоже самое и где-то в документации написано.

      А конкретно для QML отсутствие макроса Q_OBJECT может быть критично, поскольку не создаётся правильная метаинформация.

      Это лишь мысли, проверять нужно. Но скорее всего так. Лучше уже полиморфизм, чем шаблоны в данном случае.

        BlinCT
        • Oct. 25, 2019, 12:36 p.m.

        Ты бы мог простой набросок скинуть как бы выглядела реализация с таким интерфейсом для разного рода контейнеров со структурами и как бы они определялись в модели для заполнения таблицы?

          Evgenii Legotckoi
          • Oct. 25, 2019, 1:45 p.m.

          Вот пример класса интерфейса и класса потомка

          #ifndef MODELOBJECT_H
          #define MODELOBJECT_H
          
          #include <QVariant>
          
          class IModelObject
          {
          public:
              virtual ~IModelObject() {};
              virtual QVariant getMainInfo() const = 0;
              virtual QString getName() const = 0;
              virtual QVariant getValue() const = 0;
          };
          
          class IntModelObject : public IModelObject
          {
          public:
              IntModelObject() : IModelObject() {}
              virtual ~IntModelObject() {}
          
              virtual QVariant getMainInfo() const override { return QString("IntModelObject %1 %2").arg(m_name).arg(m_value); }
              virtual QString getName() const override { return QString("IntModelObject %1").arg(m_name); }
              virtual QVariant getValue() const override { return m_value; }
          
          private:
              int m_value;
              QString m_name;
          };
          
          #endif // MODELOBJECT_H
          

          Можешь наследоваться от интефейса и определять стандартизированное поведение, например у тебя есть методы:

          • получения основной информации
          • получения имени
          • получения значения в виде QVariant

          А дальше внутри модели хранишь только вектор указатель на интерфейс

          QVector<IModelObject*> m_objects;
          

          Дальше в модель загружаешь через какой-нибудь метод указатели на любые объекты, классы которых наследованы от интерфейса.

          А внутри модели уже крутишь всё как хочешь. Смысл тот же, что у тебя и есть.

          Если же тебе нужно совсем различное поведение в разных таблицах, то имеешь одну базовую таблицу, наследуешься от неё, и переопределяешь только то, что тебе нужно.

            BlinCT
            • Oct. 25, 2019, 2:29 p.m.

            Так, тут в принципе немного ясно становится. Но наследование от QAbstractTableModel идет также на IntModelObject и других потомкой что будут работать со своим типом структур?

              BlinCT
              • Oct. 25, 2019, 3:11 p.m.

              Все, по поводу модели понял.

                BlinCT
                • Oct. 26, 2019, 7:54 a.m.

                Хотел уточнить с тем что я написал и правильно ли понял:

                #pragma once
                
                #include <QVariant>
                
                class IModelObject
                {
                public:
                    virtual ~IModelObject() = default;
                    virtual QVariant getMainInfo() const = 0;
                    virtual QVariant getName() const = 0;
                    virtual QVariant getValue() const = 0;
                };
                
                /////////////////////////////
                
                #pragma once
                
                #include "IModelObject.hpp"
                
                class SupPowerStatesModelObject : public IModelObject
                {
                public:
                    explicit SupPowerStatesModelObject();   // как понимаю туда в конструктор должна прилетать уже готовая структура которая потом станет таблицей
                    ~SupPowerStatesModelObject() override = default;
                
                    QVariant getMainInfo() const override;
                
                    QVariant getName() const override;
                
                    QVariant getValue() const override;
                };
                
                ///////////////////////////////////
                
                #pragma once
                
                #include <QtCore/QAbstractTableModel>
                #include <sources/structs/wrappers/nvme/Tables.hpp>
                #include "IModelObject.hpp"
                
                class TableModel : public QAbstractTableModel
                {
                public:
                    explicit TableModel();
                
                    [[nodiscard]] int rowCount(const QModelIndex &parent) const override;
                
                    [[nodiscard]] int columnCount(const QModelIndex &parent) const override;
                
                    [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
                
                    [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
                
                    void setObject(IModelObject* object) const; // метод через который сюда передаются обьекты со структурами
                
                private:
                    int m_rowCount;
                    int m_columnCount;
                
                    QVector<IModelObject* > m_object;
                };
                

                Правильно ли все в этой реализации и коменты что я подписал?

                И вот так уже я в main.cpp передаю один из обьектов с данными

                    SupPowerStatesModelObject sub;
                    auto tableModel = new TableModel();
                    tableModel->setObject(sub);
                
                  Evgenii Legotckoi
                  • Oct. 26, 2019, 2:03 p.m.

                  Если в конструктор передавать какую-то структуру, которую должен поддерживать тот класс, то в принципе да. в общем-то правильно будет. Конкретная реализация уже покажет ошибки в процессе.

                  Что касается метода setObject, то здесь его лучше переименовать в addObject. Поскольку перевоначальное наименование не отражает сути метода. Ты добавляешь объекты, и их может быть много в этой модели. Тогда как setObject априори подразумевает только один объект, который будет находится в классе, в который добавляется данный объект. Ну и совсем явная ошибка, это наличие модификатора const у метода setObject. Данный метод модифицирует состояние модели данных, а значит никак не может быть константным.

                    BlinCT
                    • Oct. 26, 2019, 2:53 p.m.

                    Спасибо, вроде немного стало более ясно. С ошибкой тоже.
                    Получается что

                    void setObject(IModelObject* object);
                    

                    получая обьект уже определяет что это за обьект из наследников и уже у модели внутри что то с каждым делает?

                      Evgenii Legotckoi
                      • Oct. 26, 2019, 3:08 p.m.

                      Внутри он просто закидывает в вектор этот объект, и всё

                      void aadObject(IModelObject* object)
                      {
                          m_objects.push_back(object);
                      }
                      

                      Дальше в методах модели просто вызываешь методы, которые созданы в абстрактном классе IModelObject.
                      Твоя задача определить рееализацию в классах, которые наследованы от IModelObject. Это класс является интерфейсом.
                      Он формирует унифицированный интерфейс, а задача остальных классов наследников реализовать эти интерфейсы.
                      Если сможешь унифицировать поведение тех различных структур, то сможешь обобщить большую часть и использовать меньшее число моделей, чем по модели на каждый вид структуры

                        BlinCT
                        • Oct. 26, 2019, 3:12 p.m.

                        Хорошо, понял.
                        Вообще разница тех контейнеров что несут в себе структуры только в том что разное колличество столбцов, строк, названий столбцой. Ну и данные само собою.

                          Evgenii Legotckoi
                          • Oct. 26, 2019, 3:16 p.m.
                          • (edited)

                          Количество строк роли не играет, поскольку это всего лишь размер контейнера.
                          А вот количество столбцов - это более сложный вопрос.
                          Из-за разного количества столбцов скорее всего придётся делать наследованные модели и расширять поведение. Одним унифицированным интерфейсом не обойтись.

                            Comments

                            Only authorized users can post comments.
                            Please, Log in or Sign up
                            e
                            • ehot
                            • March 31, 2024, 2:29 p.m.

                            C++ - Тест 003. Условия и циклы

                            • Result:78points,
                            • Rating points2
                            B

                            C++ - Test 002. Constants

                            • Result:16points,
                            • Rating points-10
                            B

                            C++ - Test 001. The first program and data types

                            • Result:46points,
                            • Rating points-6
                            Last comments
                            k
                            kmssrFeb. 8, 2024, 6:43 p.m.
                            Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                            Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                            EVA
                            EVADec. 25, 2023, 10:30 a.m.
                            Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                            J
                            JonnyJoDec. 25, 2023, 8:38 a.m.
                            Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                            G
                            GvozdikDec. 18, 2023, 9:01 p.m.
                            Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                            Now discuss on the forum
                            a
                            a_vlasovApril 14, 2024, 6:41 a.m.
                            Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                            Павел Дорофеев
                            Павел ДорофеевApril 14, 2024, 2:35 a.m.
                            QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                            f
                            fastrexApril 4, 2024, 4:47 a.m.
                            Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
                            AC
                            Alexandru CodreanuJan. 19, 2024, 11:57 a.m.
                            QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

                            Follow us in social networks