BlinCT
BlinCT24 октября 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 г. 13: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 г. 14:29

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

              BlinCT
              • 25 октября 2019 г. 15: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 г. 14:03

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

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

                    BlinCT
                    • 26 октября 2019 г. 14:53

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

                    void setObject(IModelObject* object);
                    

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

                      Evgenii Legotckoi
                      • 26 октября 2019 г. 15:08

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

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

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

                        BlinCT
                        • 26 октября 2019 г. 15:12

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

                          Evgenii Legotckoi
                          • 26 октября 2019 г. 15:16
                          • (ред.)

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

                            Комментарии

                            Только авторизованные пользователи могут публиковать комментарии.
                            Пожалуйста, авторизуйтесь или зарегистрируйтесь
                            d
                            • dsfs
                            • 26 апреля 2024 г. 14:56

                            C++ - Тест 004. Указатели, Массивы и Циклы

                            • Результат:80баллов,
                            • Очки рейтинга4
                            d
                            • dsfs
                            • 26 апреля 2024 г. 14:45

                            C++ - Тест 002. Константы

                            • Результат:50баллов,
                            • Очки рейтинга-4
                            d
                            • dsfs
                            • 26 апреля 2024 г. 14:35

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

                            • Результат:73баллов,
                            • Очки рейтинга1
                            Последние комментарии
                            k
                            kmssr9 февраля 2024 г. 5:43
                            Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                            АК
                            Анатолий Кононенко5 февраля 2024 г. 12:50
                            Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                            EVA
                            EVA25 декабря 2023 г. 21:30
                            Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                            J
                            JonnyJo25 декабря 2023 г. 19:38
                            Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                            G
                            Gvozdik19 декабря 2023 г. 8:01
                            Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                            Сейчас обсуждают на форуме
                            G
                            Gar22 апреля 2024 г. 15:46
                            Clipboard Как скопировать окно целиком в clipb?
                            DA
                            Dr Gangil Academics20 апреля 2024 г. 17:45
                            Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
                            a
                            a_vlasov14 апреля 2024 г. 16:41
                            Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                            Павел Дорофеев
                            Павел Дорофеев14 апреля 2024 г. 12:35
                            QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                            f
                            fastrex4 апреля 2024 г. 14:47
                            Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

                            Следите за нами в социальных сетях