BlinCT
BlinCTҚаз. 24, 2019, 12:42 Т.Қ.

Заполнение 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);

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

Спасибо.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

13
Evgenii Legotckoi
  • Қаз. 25, 2019, 3:06 Т.Ж.
  • (өңделген)

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

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

    BlinCT
    • Қаз. 25, 2019, 6:33 Т.Ж.

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

      Evgenii Legotckoi
      • Қаз. 25, 2019, 6:43 Т.Ж.

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

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

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

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

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

        BlinCT
        • Қаз. 25, 2019, 12:36 Т.Қ.

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

          Evgenii Legotckoi
          • Қаз. 25, 2019, 1:45 Т.Қ.

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

          #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
            • Қаз. 25, 2019, 2:29 Т.Қ.

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

              BlinCT
              • Қаз. 25, 2019, 3:11 Т.Қ.

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

                BlinCT
                • Қаз. 26, 2019, 7:54 Т.Ж.

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

                #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
                  • Қаз. 26, 2019, 2:03 Т.Қ.

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

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

                    BlinCT
                    • Қаз. 26, 2019, 2:53 Т.Қ.

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

                    void setObject(IModelObject* object);
                    

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

                      Evgenii Legotckoi
                      • Қаз. 26, 2019, 3:08 Т.Қ.

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

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

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

                        BlinCT
                        • Қаз. 26, 2019, 3:12 Т.Қ.

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

                          Evgenii Legotckoi
                          • Қаз. 26, 2019, 3:16 Т.Қ.
                          • (өңделген)

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

                            Пікірлер

                            Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                            Кіріңіз немесе Тіркеліңіз
                            Г

                            C++ - Тест 001. Первая программа и типы данных

                            • Нәтиже:66ұпай,
                            • Бағалау ұпайлары-1
                            t

                            C++ - Тест 001. Первая программа и типы данных

                            • Нәтиже:33ұпай,
                            • Бағалау ұпайлары-10
                            t

                            Qt - Тест 001. Сигналы и слоты

                            • Нәтиже:52ұпай,
                            • Бағалау ұпайлары-4
                            Соңғы пікірлер
                            G
                            GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
                            Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
                            d
                            dblas5Шілде 5, 2024, 11:02 Т.Ж.
                            QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                            k
                            kmssrАқп. 8, 2024, 6:43 Т.Қ.
                            Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                            АК
                            Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
                            Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                            Енді форумда талқылаңыз
                            Evgenii Legotckoi
                            Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                            добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                            F
                            FynjyШілде 22, 2024, 4:15 Т.Ж.
                            при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
                            BlinCT
                            BlinCTМаусым 25, 2024, 1 Т.Ж.
                            Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
                            BlinCT
                            BlinCTМамыр 5, 2024, 5:46 Т.Ж.
                            Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                            Evgenii Legotckoi
                            Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
                            Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

                            Бізді әлеуметтік желілерде бақылаңыз