Ruslan Polupan
Ruslan PolupanСәуір 24, 2019, 6:07 Т.Ж.

Помогите разобраться с CheckBox delegate в QAbstractTableModel

Delegate, qcheckbox, QAbstractTableModel

Доброго времени суток.
Где то я упустил что-то при изучении делегатов и их использовании.

Отображение работает. Но после того как выбираешь другую строку таблицы, предидущее выделение сбрсывается.
Не получается выбрать несколько объектов.


Файлы реализации делегата CheckBoxDelegate использовал такие же как в этой статье https://evileg.com/ru/post/478/

Реализация модели
modelterminals.h

#ifndef MODELTERMINALS_H
#define MODELTERMINALS_H
#include "terminalclass.h"

#include <QObject>
#include <QAbstractTableModel>

class ModelTerminals : public QAbstractTableModel
{
    Q_OBJECT
    QList<TerminalClass> m_listTerm;
public:
    ModelTerminals(QList<TerminalClass> lsTerm);

    // QAbstractItemModel interface
public:
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;



};

#endif // MODELTERMINALS_H

modelterminals.cpp

#include "modelterminals.h"

ModelTerminals::ModelTerminals(QList<TerminalClass> lsTerm ) :
    m_listTerm(lsTerm)
{

}


int ModelTerminals::rowCount(const QModelIndex &parent) const
{
    return m_listTerm.size();
    Q_UNUSED(parent)
}

int ModelTerminals::columnCount(const QModelIndex &parent) const
{
    return m_listTerm.at(0).colParam();
    Q_UNUSED(parent)
}

QVariant ModelTerminals::data(const QModelIndex &index, int role) const
{
    if(!index.isValid()) { return QVariant();}
    TerminalClass t = m_listTerm[index.row()];
    switch (role) {
    case Qt::DisplayRole:
        switch (index.column()) {
        case 0: return t.isCheced();
        case 1: return t.terminalID();
        case 2: return t.terminalName();
        case 3: return t.regionID();
        case 4: return t.serverName();
        }
        break;
    case Qt::CheckStateRole:
        if(index.column() == 0) {
            return (!t.isCheced()) ? Qt::Checked : Qt::Unchecked;
        }
        break;
    default:
        break;
    }
    return QVariant();
}

bool ModelTerminals::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(!index.isValid()) {return false;}

    TerminalClass t = m_listTerm[index.row()];

    if(role == Qt::CheckStateRole){
        if(value.toInt() == Qt::Checked){
            t.setIsCheced(true);
        } else {
            t.setIsCheced(false);
        }
        emit dataChanged(index,index);
        return true;
    }
    return false;
}

Qt::ItemFlags ModelTerminals::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags = QAbstractTableModel::flags(index);
    if(index.isValid() && index.column() == 0){
        flags |= Qt::ItemIsEditable;
    }
    return flags;
}

QVariant ModelTerminals::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 "";
    case 1: return "АЗС";
    case 2: return "Адрес";
    case 3: return "Регион";
    case 4: return "Сервер";
    default:
        break;
    }
    return QVariant();
}

Получаю данные для модели и создаю модель

#include "fuelnamedialog.h"
#include "ui_fuelnamedialog.h"

FuelNameDialog::FuelNameDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::FuelNameDialog)
{
    ui->setupUi(this);

    createListTerminals();
    createModelterminals();
}

FuelNameDialog::~FuelNameDialog()
{
    delete ui;
}

void FuelNameDialog::createModelterminals()
{
    qInfo(logInfo()) << "Заружено терминалов:" << listTerminals.size();
    CheckBoxDelegate *delegate = new CheckBoxDelegate();
    modelTerminals = new ModelTerminals(listTerminals);

    ui->tableViewTerminals->setModel(modelTerminals);
    ui->tableViewTerminals->setItemDelegateForColumn(0,delegate);

    ui->tableViewTerminals->verticalHeader()->hide();
    ui->tableViewTerminals->resizeColumnsToContents();

}

void FuelNameDialog::createListTerminals()
{
    QSqlQuery q;
    TerminalClass t;
    if(!q.exec("SELECT t.TERMINAL_ID, TRIM(t.name) AS NAME, t.OWNER_ID AS REGION, c.SERVER_NAME  FROM TERMINALS t "
               "LEFT JOIN CONNECTIONS c ON c.TERMINAL_ID = t.TERMINAL_ID "
               "WHERE t.TERMINALTYPE = 3 AND c.CONNECT_ID = 2 "
               "ORDER BY t.TERMINAL_ID")) {
        qInfo(logInfo()) << Q_FUNC_INFO  << "Не возможно получить список терминалов" << q.lastError().text();
        return;
    }
    while(q.next()){
        t.setIsCheced(false);
        t.setTerminalID(q.value(0).toInt());
        t.setTerminalName(q.value(1).toString());
        t.setRegionID(q.value(2).toInt());
        t.setServerName(q.value(3).toString());
        listTerminals.append(t);
    }

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

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

10
Evgenii Legotckoi
  • Сәуір 24, 2019, 7:09 Т.Ж.

Добрый день

А вот этот код

    case Qt::CheckStateRole:
    if(index.column() == 0) {
        return (!t.isCheced()) ? Qt::Checked : Qt::Unchecked;
    }

Не должен быть написан так?

    case Qt::CheckStateRole:
    if(index.column() == 0) {
        return (t.isCheced()) ? Qt::Checked : Qt::Unchecked;
    }
    Ruslan Polupan
    • Сәуір 24, 2019, 7:22 Т.Ж.

    Согласен. но ситуация не поменялась. Такое чуство что данные не записываются в модель.

      Evgenii Legotckoi
      • Сәуір 25, 2019, 3:45 Т.Ж.

      Думаю, что в методе setData нужно в роли Qt::EditRole делать установку значения. Скорее всего у вас просто не заходит в ту ветку кода выполнение программы. Обычно для установки значения используется именно роль Qt::EditRole

        Ruslan Polupan
        • Сәуір 25, 2019, 6:51 Т.Ж.
        • Жауап шешім ретінде белгіленді.

        Изменил функцию
        теперь работает.

        bool ModelTerminals::setData(const QModelIndex &index, const QVariant &value, int role)
        {
            Q_UNUSED(role)
            if(!index.isValid()) {return false;}
        
            m_listTerm[index.row()].setIsCheced(value.toBool());
            emit QAbstractTableModel::dataChanged(index,index);
            return true;
        
        }
        
          Ruslan Polupan
          • Мамыр 7, 2019, 3:36 Т.Ж.

          Продолжаем вопросы... (Сори если что :-)
          Как теперь отловить сигнал checked от делегата?

            Ruslan Polupan
            • Мамыр 7, 2019, 4:09 Т.Ж.

            Пока сделал так:

            connect(ui->tableViewTerminals->model(),&QAbstractTableModel::dataChanged,this,&SelectTerminalPage::terminalChecked);
            

            Где:

            void SelectTerminalPage::terminalChecked()
            {
                const int rowCount = ui->tableViewTerminals->model()->rowCount(QModelIndex());
            
                for(int i =0; i < rowCount; ++i){
                    if(ui->tableViewTerminals->model()->index(i,0).data(Qt::CheckStateRole).toInt() == Qt::Checked)
                        qInfo(logInfo()) << "Выбрана" << i << "строка";
                }
            
            }
            

            но это отрабатывает изменение модели
            А вот сам клик на checkbox бы отловить...

              Evgenii Legotckoi
              • Мамыр 7, 2019, 4:30 Т.Ж.

              Ну по идее есть такой сигнал commitData у делегатов. В данном сигнале высылается указатель на виджет перед записью данных в модель. Можете попробовать на его основе что-то сообразить.

                Ruslan Polupan
                • Мамыр 7, 2019, 6:47 Т.Ж.

                Еще обнаружил такую ситуацию. Оказывается данные в модель записываются, лиш после того как фокус получает любой item TableView.
                Т.е. Состояние CheckBox записывается в модель не при изменении его статуса а лишь тогда когда с него теряется фокус.

                  Evgenii Legotckoi
                  • Мамыр 7, 2019, 6:51 Т.Ж.

                  Ну в общем-то да, есть такая ситуация. Думаю, что это правильное поведение. Дело в том, что если логика под капотом очень сложная и влияет на большое количество компонентов, то апдейт при редактировании может очень сильно уменьшить скорость работы софта, поскольку такие апдейты будут выполняться тогда, когда по факту в 99% случае они вовсе не нужны.

                    Ruslan Polupan
                    • Мамыр 7, 2019, 7:01 Т.Ж.
                    • (өңделген)

                    Реализовать такую ситуацию:
                    Я выбрал несколько строк и не прешел на другую ячейку а нажал кнопку "Выполнить" например.
                    И тогда получается что последняя мною выбранная запись не попадет для дальнейшей обработки.
                    Или есть таки способ принудительно опросить делегаты и записать их состояние в модель?

                      Пікірлер

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

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

                      • Нәтиже:50ұпай,
                      • Бағалау ұпайлары-4
                      m
                      • molni99
                      • Қаз. 26, 2024, 1:37 Т.Ж.

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

                      • Нәтиже:80ұпай,
                      • Бағалау ұпайлары4
                      m
                      • molni99
                      • Қаз. 26, 2024, 1:29 Т.Ж.

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

                      • Нәтиже:20ұпай,
                      • Бағалау ұпайлары-10
                      Соңғы пікірлер
                      ИМ
                      Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
                      Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                      Evgenii Legotckoi
                      Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
                      Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                      A
                      ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
                      Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                      ИМ
                      Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
                      Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                      d
                      dblas5Шілде 5, 2024, 11:02 Т.Ж.
                      QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                      Енді форумда талқылаңыз
                      m
                      moogoҚар. 22, 2024, 7:17 Т.Ж.
                      Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
                      Evgenii Legotckoi
                      Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                      добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                      t
                      tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
                      google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                      NSProject
                      NSProjectМаусым 4, 2022, 3:49 Т.Ж.
                      Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

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