IscanderChe
June 21, 2019, 4:09 p.m.

QSqlTableModel + QTableView + кастомный делегат QComboBox

Пытаюсь реализовать кастомного делегата на основе QComboBox. Получилось отчасти.
1) При щелчке на ячейке в колонке с делегатом (у меня это колонка 4, status) комбобокс появляется, а хотелось бы, чтобы он был виден всегда.
2) При загрузке виджета, если строк в таблице несколько, только в последней строке заполнена колонка status. Надо, чтоб показывались все.
3) Если щелкнуть на ячейке колонки status, где установлено значение "green", а потом перейти на другую ячейку, то значение предыдущей ячейки сбрасывается на значение "white". Должны сохраняться предыдущие установленные значения.

  1. #include "comboboxdelegate.h"
  2. #include <QComboBox>
  3.  
  4. ComboBoxDelegate::ComboBoxDelegate(QObject* parent)
  5. {
  6.  
  7. }
  8.  
  9. QWidget* ComboBoxDelegate::createEditor(QWidget* parent,
  10. const QStyleOptionViewItem& option, const QModelIndex& index) const
  11. {
  12. if(index.column() == 4)
  13. {
  14. QComboBox* editor = new QComboBox(parent);
  15. editor->insertItem(0, "white");
  16. editor->insertItem(1, "green");
  17. return editor;
  18. }
  19.  
  20. return QStyledItemDelegate::createEditor(parent, option, index);
  21. }
  22.  
  23. void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
  24. {
  25. if(index.column() == 4)
  26. {
  27. QString value = index.model()->data(index, Qt::EditRole).toString();
  28. QComboBox* comboBox = static_cast<QComboBox*>(editor);
  29. if(value == "white")
  30. comboBox->setCurrentIndex(0);
  31. else if(value == "green")
  32. comboBox->setCurrentIndex(1);
  33. }
  34. }
  35.  
  36. void ComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model,
  37. const QModelIndex& index) const
  38. {
  39. if(index.column() == 4)
  40. {
  41. QComboBox* comboBox = static_cast<QComboBox*>(editor);
  42. QString value = comboBox->currentData().toString();
  43. model->setData(index, value, Qt::EditRole);
  44. }
  45. }
  46.  
  47. void ComboBoxDelegate::updateEditorGeometry(QWidget* editor,
  48. const QStyleOptionViewItem& option, const QModelIndex& index) const
  49. {
  50. editor->setGeometry(option.rect);
  51. }
2
31
Evgenii Legotckoi
  • June 24, 2019, 3:41 p.m.

Добрый день!

А можете ещё прикрепить какой-нибудь пробный проект с этим делегатом? Я бы вечером глянул после работы, что там, да как.

    IscanderChe
    • June 24, 2019, 7:19 p.m.
    1. // widget.cpp
    2.  
    3. #include "widget.h"
    4. #include <QTableView>
    5. #include <QVBoxLayout>
    6. #include "checkboxdelegate.h"
    7. #include "comboboxdelegate.h"
    8. #include "mytableview.h"
    9. #include <QSqlDatabase>
    10. #include <QDebug>
    11. #include <QSqlQuery>
    12. #include <QSqlError>
    13. #include <QDate>
    14. #include <QTime>
    15. #include <QSqlRecord>
    16. #include <QApplication>
    17.  
    18. Widget::Widget(QWidget *parent)
    19. : QWidget(parent)
    20. {
    21. // Setup UI
    22. MyTableView* tableView = new MyTableView();
    23. QVBoxLayout* layout = new QVBoxLayout;
    24. layout->addWidget(tableView);
    25. setLayout(layout);
    26.  
    27. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    28. db.setHostName("localhost");
    29. QString dbName = qApp->applicationDirPath() + "/db.db";
    30. db.setDatabaseName(dbName);
    31.  
    32. if(db.open())
    33. qDebug() << "DB opened";
    34. else
    35. qDebug() << "DB don't opened";
    36.  
    37. QSqlQuery query_tbl;
    38. if(!query_tbl.exec( "CREATE TABLE IF NOT EXISTS tbl ("
    39. "id INTEGER PRIMARY KEY AUTOINCREMENT, "
    40. "flag INTEGER, "
    41. "timeone TIME NOT NULL, "
    42. "timetwo TIME NOT NULL, "
    43. "status TEXT"
    44. ")"
    45. )
    46. )
    47. {
    48. qDebug() << "Error of create table";
    49. qDebug() << query_tbl.lastError().text();
    50. }
    51. else
    52. qDebug() << "Created table";
    53.  
    54. QVariantList data;
    55. int flag = 1;
    56. data.append(flag);
    57. data.append(QTime::currentTime());
    58. data.append(QTime::currentTime());
    59. QString status = "green";
    60. data.append(status);
    61. qDebug() << data;
    62.  
    63. QSqlQuery query_ins;
    64. query_ins.prepare("INSERT INTO tbl (flag, timeone, timetwo, status) "
    65. "VALUES (:Flag, :TimeOne, :TimeTwo, :Status)"
    66. );
    67. query_ins.bindValue(":Flag", data.at(0).toInt());
    68. query_ins.bindValue(":TimeOne", data.at(1).toTime());
    69. query_ins.bindValue(":TimeTwo", data.at(2).toTime());
    70. query_ins.bindValue(":Status", data.at(3).toString());
    71.  
    72. if(!query_ins.exec())
    73. {
    74. qDebug() << "error insert into table";
    75. qDebug() << query_ins.lastError().text();
    76. }
    77. else
    78. qDebug() << "inserted row";
    79.  
    80. model = new MySqlTableModel;
    81. model->setTable("tbl");
    82.  
    83. tableView->setModel(model);
    84.  
    85. CheckBoxDelegate* checkBoxDelegate = new CheckBoxDelegate;
    86. tableView->setItemDelegateForColumn(1, checkBoxDelegate);
    87.  
    88. ComboBoxDelegate* comboBoxDelegate = new ComboBoxDelegate;
    89. tableView->setItemDelegateForColumn(4, comboBoxDelegate);
    90.  
    91. tableView->resizeColumnToContents(1);
    92.  
    93. model->select();
    94.  
    95. connect(tableView, SIGNAL(clickToCheck(QModelIndex)), this, SLOT(changeStateCheckBox(QModelIndex)));
    96. }
    97.  
    98. Widget::~Widget()
    99. {
    100.  
    101. }
    102.  
    103. void Widget::changeStateCheckBox(QModelIndex index)
    104. {
    105. int state = index.model()->data(index).toBool();
    106. QVariant value = !state;
    107. model->setData(index, value);
    108. }
    109.  
      Evgenii Legotckoi
      • June 25, 2019, 1:33 p.m.

      1) Насчёт того, чтобы делегат был виден всегда. Можете попробовать переопределить метод paint у делегата

      1. void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
      2. {
      3. if (index.column() == 1) // show combobox only in the second column
      4. {
      5. QStyleOptionComboBox box;
      6. box.state = option.state;
      7.  
      8. box.rect = option.rect;
      9. box.currentText = index.data(Qt::EditRole).toString();
      10.  
      11. QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, 0);
      12. QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &box, painter, 0);
      13. return;
      14. }
      15. QStyledItemDelegate::paint(painter, option, index);
      16. }

      Что-то наподобие такого, только перепишите в рамках вашего делегата.

      2) Немного не понял

      3) Не уверен, но возможно, что нужно поработать ещё немного с самой моделью данных.

        IscanderChe
        • June 25, 2019, 3:26 p.m.

        По пункту 1 - да, всё получилось, спасибо. Я почти дошёл до этого, но переопределял paint не совсем правильно.

        По пункту 2 - картинка в прицепе. Для первых двух комбобоксов значения менялись с их же помощью, для следующих двух значения предустановлены программно.
        По пункту 3 - возможно, что надо задействовать модель, я только пока не понимаю, как. Сейчас у меня там кроме формата отображения дат больше ничего нет.

          IscanderChe
          • June 25, 2019, 4:55 p.m.

          По пункту 3 попытался переписать метод setData. В итоге комбобокс перестал работать.

          1. bool MySqlTableModel::setData(const QModelIndex& index, const QVariant& value, int /* role */)
          2. {
          3. bool ok = true;
          4. if(index.column() == 4)
          5. {
          6. QModelIndex primaryKeyIndex = QSqlTableModel::index(index.row(), 0);
          7. int id = QSqlTableModel::data(primaryKeyIndex).toInt();
          8. QSqlQuery query;
          9. query.prepare("UPDATE tbl SET status = ? WHERE id = ?");
          10. query.addBindValue(value.toString());
          11. query.addBindValue(id);
          12. ok = query.exec();
          13. select();
          14. }
          15.  
          16. return ok;
          17. }
            IscanderChe
            • June 26, 2019, 7:35 p.m.
            • The answer was marked as a solution.

            В общем, полностью переписал код, получилось вот что:

            1. // widget.h
            2.  
            3. #ifndef WIDGET_H
            4. #define WIDGET_H
            5.  
            6. #include <QWidget>
            7. #include <QSqlTableModel>
            8.  
            9. class Widget : public QWidget
            10. {
            11. Q_OBJECT
            12.  
            13. public:
            14. Widget(QWidget *parent = 0);
            15. ~Widget();
            16.  
            17. private:
            18. QSqlTableModel* model;
            19. };
            20.  
            21. #endif // WIDGET_H
            22.  
            23. // widget.cpp
            24.  
            25. #include "widget.h"
            26. #include "comboboxdelegate.h"
            27. #include <QTableView>
            28. #include <QVBoxLayout>
            29. #include <QSqlDatabase>
            30. #include <QDebug>
            31. #include <QSqlQuery>
            32. #include <QSqlError>
            33. #include <QTime>
            34. #include <QSqlRecord>
            35. #include <QApplication>
            36.  
            37. Widget::Widget(QWidget *parent)
            38. : QWidget(parent)
            39. {
            40. QTableView* tableView = new QTableView;
            41. QVBoxLayout* layout = new QVBoxLayout;
            42. layout->addWidget(tableView);
            43. setLayout(layout);
            44.  
            45. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
            46. db.setHostName("localhost");
            47. QString dbName = qApp->applicationDirPath() + "/db.db";
            48. db.setDatabaseName(dbName);
            49.  
            50. if(db.open())
            51. qDebug() << "DB opened";
            52. else
            53. qDebug() << "DB don't opened";
            54.  
            55. QSqlQuery query_tbl;
            56. if(!query_tbl.exec( "CREATE TABLE IF NOT EXISTS tbl ("
            57. "id INTEGER PRIMARY KEY AUTOINCREMENT, "
            58. "timeone TIME NOT NULL, "
            59. "timetwo TIME NOT NULL, "
            60. "status TEXT"
            61. ")"
            62. )
            63. )
            64. {
            65. qDebug() << "Error of create table";
            66. qDebug() << query_tbl.lastError().text();
            67. }
            68. else
            69. qDebug() << "Created table";
            70.  
            71. QVariantList data;
            72. data.append(QTime::currentTime());
            73. data.append(QTime::currentTime());
            74. QString color = "white";
            75. data.append(color);
            76. qDebug() << data;
            77.  
            78. QSqlQuery query_ins;
            79. query_ins.prepare("INSERT INTO tbl (timeone, timetwo, status) "
            80. "VALUES (:TimeOne, :TimeTwo, :Status)"
            81. );
            82. query_ins.bindValue(":TimeOne", data.at(0).toTime());
            83. query_ins.bindValue(":TimeTwo", data.at(1).toTime());
            84. query_ins.bindValue(":Status", data.at(2).toString());
            85.  
            86. if(!query_ins.exec())
            87. {
            88. qDebug() << "error insert into table";
            89. qDebug() << query_ins.lastError().text();
            90. }
            91. else
            92. qDebug() << "inserted row";
            93.  
            94. model = new QSqlTableModel;
            95. model->setTable("tbl");
            96.  
            97. tableView->setModel(model);
            98.  
            99. ComboBoxDelegate* delegate = new ComboBoxDelegate;
            100. tableView->setItemDelegateForColumn(3, delegate);
            101.  
            102. model->select();
            103. }
            104.  
            105. Widget::~Widget()
            106. {
            107.  
            108. }
            109.  
            110. // comboboxdelegate.h
            111.  
            112. #ifndef COMBOBOXDELEGATE_H
            113. #define COMBOBOXDELEGATE_H
            114.  
            115. #include <QStyledItemDelegate>
            116.  
            117. class ComboBoxDelegate : public QStyledItemDelegate
            118. {
            119. Q_OBJECT
            120.  
            121. public:
            122. ComboBoxDelegate();
            123.  
            124. QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
            125. const QModelIndex &index) const override;
            126.  
            127. void setEditorData(QWidget* editor, const QModelIndex& index) const override;
            128.  
            129. void setModelData(QWidget *editor, QAbstractItemModel *model,
            130. const QModelIndex &index) const override;
            131.  
            132. void updateEditorGeometry(QWidget *editor,
            133. const QStyleOptionViewItem &option, const QModelIndex &index) const override;
            134.  
            135. void paint(QPainter* painter,
            136. const QStyleOptionViewItem& option, const QModelIndex& index) const override;
            137. };
            138.  
            139. #endif // COMBOBOXDELEGATE_H
            140.  
            141. // comboboxdelegate.cpp
            142.  
            143. #include "comboboxdelegate.h"
            144. #include <QComboBox>
            145. #include <QApplication>
            146. #include <QSqlQuery>
            147. #include <QSqlTableModel>
            148.  
            149. ComboBoxDelegate::ComboBoxDelegate()
            150. {
            151.  
            152. }
            153.  
            154. QWidget* ComboBoxDelegate::createEditor(QWidget *parent,
            155. const QStyleOptionViewItem &option,
            156. const QModelIndex &index) const
            157. {
            158. QComboBox* comboBox = new QComboBox(parent);
            159. QPair<QString, int> pair;
            160. QList<QPair<QString, int> > dataList;
            161. pair.first = "white";
            162. pair.second = 0;
            163. dataList << pair;
            164. pair.first = "yellow";
            165. pair.second = 1;
            166. dataList << pair;
            167. pair.first = "green";
            168. pair.second = 2;
            169. dataList << pair;
            170.  
            171. for(int i = 0; i < dataList.size(); ++i)
            172. {
            173. QPair<QString, int> item = dataList.at(i);
            174. comboBox->addItem(item.first, item.second);
            175. }
            176.  
            177. comboBox->setCurrentIndex(0);
            178.  
            179. return comboBox;
            180. }
            181.  
            182. void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
            183. {
            184. if(index.column() == 3)
            185. {
            186. QString value = index.model()->data(index, Qt::EditRole).toString();
            187. QComboBox* comboBox = static_cast<QComboBox*>(editor);
            188. if(value == "white")
            189. comboBox->setCurrentIndex(0);
            190. else if(value == "yellow")
            191. comboBox->setCurrentIndex(1);
            192. else if(value == "green")
            193. comboBox->setCurrentIndex(2);
            194. }
            195. }
            196.  
            197. void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
            198. const QModelIndex &index) const
            199. {
            200. QComboBox *edit = static_cast<QComboBox *>(editor);
            201. QSqlTableModel* sqlModel = static_cast<QSqlTableModel*>(model);
            202. QModelIndex primaryKeyIndex = sqlModel->index(index.row(), 0);
            203. int id = sqlModel->data(primaryKeyIndex).toInt();
            204. QString value = edit->currentText();
            205. QSqlQuery query;
            206. query.prepare("UPDATE tbl SET status = ? WHERE id = ?");
            207. query.addBindValue(value);
            208. query.addBindValue(id);
            209. query.exec();
            210. sqlModel->select();
            211. }
            212.  
            213. void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,
            214. const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
            215. {
            216. editor->setGeometry(option.rect);
            217. }
            218.  
            219. void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
            220. const QModelIndex &index) const
            221. {
            222. if(index.column() == 3)
            223. {
            224. QStyleOptionComboBox comboBoxStyleOption;
            225. comboBoxStyleOption.state = option.state;
            226. comboBoxStyleOption.rect = option.rect;
            227. comboBoxStyleOption.currentText = index.data(Qt::EditRole).toString();
            228.  
            229. QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &comboBoxStyleOption, painter, 0);
            230. QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &comboBoxStyleOption, painter, 0);
            231.  
            232. return;
            233. }
            234.  
            235. QStyledItemDelegate::paint(painter,option, index);
            236. }

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

              Evgenii Legotckoi
              • June 27, 2019, 12:10 a.m.

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

              1. tableView->setEditTriggers(QAbstractItemView::AllEditTriggers);
                IscanderChe
                • June 27, 2019, 11:42 a.m.
                • (edited)

                Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком.
                И выделяется первая ячейка для редактирования текста, что совсем не надо. Похоже, надо опять думать в сторону собственной реализации QTableView...

                  IscanderChe
                  • June 27, 2019, 7:55 p.m.

                  "Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком." Это осталось, а вот с редактированием удалось успешно закрыть вопрос. Добавилась собственная реализация QTableView и несколько строк в widget.cpp.

                  1. // mytableview.h
                  2.  
                  3. #ifndef MYTABLEVIEW_H
                  4. #define MYTABLEVIEW_H
                  5.  
                  6. #include <QTableView>
                  7.  
                  8. class MyTableView : public QTableView
                  9. {
                  10. Q_OBJECT
                  11.  
                  12. public:
                  13. MyTableView(QObject* parent = 0);
                  14.  
                  15. void mouseMoveEvent(QMouseEvent* event) override;
                  16.  
                  17. signals:
                  18. void mouseHover(QModelIndex index);
                  19. };
                  20.  
                  21. #endif // MYTABLEVIEW_H
                  22.  
                  23. // mytableview.cpp
                  24.  
                  25. #include "mytableview.h"
                  26. #include <QMouseEvent>
                  27.  
                  28. MyTableView::MyTableView(QObject* /*parent*/)
                  29. {
                  30.  
                  31. }
                  32.  
                  33. void MyTableView::mouseMoveEvent(QMouseEvent* event)
                  34. {
                  35. QPoint position = event->pos();
                  36. QModelIndex index = indexAt(position);
                  37. emit mouseHover(index);
                  38. }
                  39.  
                  40. // widget.h
                  41.  
                  42. #ifndef WIDGET_H
                  43. #define WIDGET_H
                  44.  
                  45. #include "mytableview.h"
                  46. #include <QWidget>
                  47. #include <QSqlTableModel>
                  48. #include <QTableView>
                  49.  
                  50. class Widget : public QWidget
                  51. {
                  52. Q_OBJECT
                  53.  
                  54. public:
                  55. Widget(QWidget *parent = 0);
                  56. ~Widget();
                  57.  
                  58. private:
                  59. QSqlTableModel* model;
                  60. MyTableView* tableView;
                  61.  
                  62. private slots:
                  63. void mouseHover(QModelIndex index);
                  64. };
                  65.  
                  66. #endif // WIDGET_H
                  67.  
                  68. // widget.cpp
                  69. ...
                  70. tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
                  71. tableView->setSelectionMode(QAbstractItemView::SingleSelection);
                  72. tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
                  73. tableView->setSortingEnabled(true);
                  74. tableView->setMouseTracking(true);
                  75.  
                  76. connect(tableView, SIGNAL(mouseHover(QModelIndex)), this, SLOT(mouseHover(QModelIndex)));
                  77. }
                  78.  
                  79. Widget::~Widget()
                  80. {
                  81.  
                  82. }
                  83.  
                  84. void Widget::mouseHover(QModelIndex index)
                  85. {
                  86. if(index.column() != 3)
                  87. tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
                  88. if(index.column() == 3)
                  89. tableView->setEditTriggers(QAbstractItemView::AllEditTriggers);
                  90. }

                  Огромное спасибо за помощь по работе с моделями! Трудновато, но очень интересно.)

                    IscanderChe
                    • June 28, 2019, 5:21 p.m.
                    • (edited)

                    С проблемой редактирования текста разобрался с помощью другого дружественного ресурса путём наследования модели и переписывания метода flags. Получилось более элегантно и без костылей в виде кастомного QTableView:

                    1. Qt::ItemFlags MySqlTableModel::flags(const QModelIndex& index) const
                    2. {
                    3. if(index.column() == 0 || index.column() == 1)
                    4. {
                    5. Qt::ItemFlags flags = QSqlTableModel::flags(index);
                    6. flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
                    7. return flags;
                    8. }
                    9.  
                    10. return QSqlTableModel::flags(index);
                    11. }

                    Но вылезла другая интересная проблема. Как удалось выяснить, при выборе другого значения в комбобоксе данные вносятся в базу данных только после щелчка на другой ячейке или свободном пространстве. Можно это как-то побороть, чтобы данные записывались сразу после выбора значения?

                      Evgenii Legotckoi
                      • July 1, 2019, 12:43 p.m.

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

                        IscanderChe
                        • July 1, 2019, 6:48 p.m.

                        Если напрямую из setEditorData делать так:

                        1. emit commitData(editor);

                        то компилятор выдаёт ошибку: "passing 'const ComboBoxDelegate' as 'this' argument discards qualifiers [-fpermissive]"

                          Evgenii Legotckoi
                          • July 2, 2019, 1:07 p.m.

                          commitData ожидает неконстантный указатель на виджет, а у вас туда передаётся константный указатель.

                            IscanderChe
                            • July 2, 2019, 6:08 p.m.

                            В общем, мозг сломал, но так ничего и не придумал... Слишком тонкие намёки для меня.))
                            Вот если бы чуть более развёрнутое объяснение... И примеров кода не надо! Только объяснение.

                              Evgenii Legotckoi
                              • July 3, 2019, 12:30 p.m.

                              А мне бы наоборот код глянуть )) Можете показать, где у вас emit commitData(editor) используется? А то я всё уже в голове не успеваю держать, детали из памяти истераются.

                                IscanderChe
                                • July 3, 2019, 3:20 p.m.
                                1. void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
                                2. {
                                3. qDebug() << "Work setEditorData";
                                4. if(index.column() == 2)
                                5. {
                                6. QString value = index.model()->data(index, Qt::EditRole).toString();
                                7. QComboBox* comboBox = static_cast<QComboBox*>(editor);
                                8.  
                                9. QSqlQuery querySelect("SELECT status FROM statuses");
                                10. QStringList statusList;
                                11. if(!querySelect.exec())
                                12. {
                                13. qDebug() << "Error select from statuses";
                                14. qDebug() << querySelect.lastError().text();
                                15. }
                                16. else
                                17. {
                                18. while(querySelect.next())
                                19. statusList << querySelect.value(0).toString();
                                20. }
                                21.  
                                22. for(int i = 0; i < statusList.size(); ++i)
                                23. {
                                24. if(value == statusList.at(i))
                                25. {
                                26. comboBox->setCurrentIndex(i);
                                27. emit commitData(editor);
                                28. }
                                29. }
                                30. }
                                31. }
                                  Evgenii Legotckoi
                                  • July 4, 2019, 12:08 a.m.

                                  Придумал. Вот что попробуйте, сделайте в методе createEditor коннект лямбды на изменение текущего индекса. В котором и будете делать commitData.

                                  1. QWidget* ComboBoxDelegate::createEditor(QWidget* parent,
                                  2. const QStyleOptionViewItem& option, const QModelIndex& index) const
                                  3. {
                                  4. if(index.column() == 4)
                                  5. {
                                  6. QComboBox* editor = new QComboBox(parent);
                                  7. editor->insertItem(0, "white");
                                  8. editor->insertItem(1, "green");
                                  9.  
                                  10. connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index)
                                  11. {
                                  12. emit commitData(editor);
                                  13. });
                                  14. return editor;
                                  15. }
                                  16.  
                                  17. return QStyledItemDelegate::createEditor(parent, option, index);
                                  18. }

                                  По идее, когда вы измените значение, тогда сразу и вызовется применение изменений.

                                    IscanderChe
                                    • July 4, 2019, 2:14 a.m.

                                    Спасибо, попробую завтра. На работе у меня стоит 5.11, там QOverload поддерживается. А вот дома стоит 5.5.1, и этого там ещё нет...
                                    Не знаете, как правильно под 32-битный линукс скомпилить одновременно и QtCreator, и свежий Qt? Несколько надоело быть ограниченно годным в домашних условиях.

                                      Evgenii Legotckoi
                                      • July 4, 2019, 2:21 a.m.

                                      Ну я никогда не компилировал сам Qt, просто устанавливал нужные версии через Qt Maintanence Tool и всё. Этого достаточно было.

                                        IscanderChe
                                        • July 4, 2019, 2:51 a.m.

                                        Вот ещё, кстати, вопрос не по теме. В сообщениях указывается время, отличное от моего местного. Это правильно? Особо не мешает, но вопрос есть. :) Хорошо бы настроить возможность определять/задавать часовой пояс в профиле пользователя.

                                          IscanderChe
                                          • July 4, 2019, 12:17 p.m.

                                          Всё равно ругается: "passing 'const ComboBoxDelegate' as 'this' argument discards qualifiers [-fpermissive] emit commitData(comboBox);".

                                          1. QWidget* ComboBoxDelegate::createEditor(QWidget* parent,
                                          2. const QStyleOptionViewItem& /*option*/,
                                          3. const QModelIndex& /*index*/) const
                                          4. {
                                          5. QComboBox* comboBox = new QComboBox(parent);
                                          6. QSqlQuery querySelect("SELECT status FROM statuses");
                                          7. QStringList statusList;
                                          8. if(!querySelect.exec())
                                          9. {
                                          10. qDebug() << "Error select from statuses";
                                          11. qDebug() << querySelect.lastError().text();
                                          12. }
                                          13. else
                                          14. {
                                          15. while(querySelect.next())
                                          16. statusList << querySelect.value(0).toString();
                                          17. }
                                          18.  
                                          19. foreach(QString status, statusList)
                                          20. comboBox->addItem(status);
                                          21.  
                                          22. comboBox->setCurrentIndex(0);
                                          23.  
                                          24. connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index)
                                          25. {
                                          26. emit commitData(comboBox);
                                          27. });
                                          28.  
                                          29. return comboBox;
                                          30. }
                                            Evgenii Legotckoi
                                            • July 4, 2019, 2:38 p.m.

                                            Да надо бы это сделать. Я столкнулся в Django с тем, что довольно трудоёмко реализовать автоматическую детекцию часового пояса. А в официальной документации сказано, что добавляйте у пользователя поле для настройки часового пояся и выбирайте из него данные. Ну наверное да, нужно сделать ))))

                                              Evgenii Legotckoi
                                              • July 4, 2019, 2:42 p.m.

                                              етить колотить. Не обратил внимание на то, что это тоже const метод. Попробуйте тогда написать обычный слот без лямбды и подключиться к нему.

                                                IscanderChe
                                                • July 4, 2019, 3 p.m.

                                                Сигнал работает, сообщение "ComboBox index changed" появляется в момент смены значения, всё как надо. Только как теперь в модель всё это передать? Доступа-то к ней из слота нет.

                                                1. QWidget* ComboBoxDelegate::createEditor(QWidget* parent,
                                                2. const QStyleOptionViewItem& /*option*/,
                                                3. const QModelIndex& /*index*/) const
                                                4. {
                                                5. QComboBox* comboBox = new QComboBox(parent);
                                                6. QSqlQuery querySelect("SELECT status FROM statuses");
                                                7. QStringList statusList;
                                                8. if(!querySelect.exec())
                                                9. {
                                                10. qDebug() << "Error select from statuses";
                                                11. qDebug() << querySelect.lastError().text();
                                                12. }
                                                13. else
                                                14. {
                                                15. while(querySelect.next())
                                                16. statusList << querySelect.value(0).toString();
                                                17. }
                                                18.  
                                                19. foreach(QString status, statusList)
                                                20. comboBox->addItem(status);
                                                21.  
                                                22. comboBox->setCurrentIndex(0);
                                                23.  
                                                24. connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changedComboBox(int)));
                                                25.  
                                                26. return comboBox;
                                                27. }
                                                28.  
                                                29. void ComboBoxDelegate::changedComboBox(int /*index*/)
                                                30. {
                                                31. qDebug() << "ComboBox index changed";
                                                32. }
                                                  Evgenii Legotckoi
                                                  • July 4, 2019, 3:07 p.m.

                                                  Попробуйте так

                                                  1. void ComboBoxDelegate::changedComboBox(int /*index*/)
                                                  2. {
                                                  3. emit commitData(qobject_cast<QComboBox*>(sender()));
                                                  4. }
                                                    IscanderChe
                                                    • July 4, 2019, 3:15 p.m.

                                                    Сработало! Спасибо!!!

                                                      Evgenii Legotckoi
                                                      • July 4, 2019, 3:19 p.m.

                                                      Кстати, скорее всего на новом синтаксисе сигналов и слотов через указатели на методы не получится так сделать. Дело в том, что Макросы кладут болт на некоторые моменты в плане приватности и константности объектов... Но я бы проверил...

                                                      Можете проверить коннект так? Любопытства ради. Если я правильно понимаю, то тогда не сможет скомпилироваться...

                                                      1. connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ComboBoxDelegate::changedComboBox);
                                                        IscanderChe
                                                        • July 4, 2019, 3:36 p.m.

                                                        Скомилировалось и нормально работает.

                                                          Evgenii Legotckoi
                                                          • July 4, 2019, 3:40 p.m.

                                                          Хорошо, значит ошибочная мысль была. Спасибо.

                                                          Оставьте тогда на новом синтаксисе. Уже не комильфо использовать старый синтаксис )))

                                                            IscanderChe
                                                            • April 20, 2023, 12:21 p.m.

                                                            Добрый день.

                                                            Я тут жаловался в посте выше ( тут ), что: "Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком." Т.е. комбобокс в делегате начинал работать только после того, как щёлкнешь на нём: клик, и потом на второй клик уже список значений выпадает.

                                                            Удалось победить с помощью дружественного форума так:

                                                            1. tableView->openPersistentEditor(model->index(row,col));

                                                            где индекс указывает на те ячейки, где размещается делегат.

                                                              Evgenii Legotckoi
                                                              • April 20, 2023, 2:17 p.m.

                                                              Круто, хорошо, что удалось разобраться :-)

                                                                Comments

                                                                Only authorized users can post comments.
                                                                Please, Log in or Sign up
                                                                • Last comments
                                                                • Evgenii Legotckoi
                                                                  March 9, 2025, 9:02 p.m.
                                                                  К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
                                                                • VP
                                                                  March 9, 2025, 4:14 p.m.
                                                                  Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
                                                                • ИМ
                                                                  Nov. 22, 2024, 9:51 p.m.
                                                                  Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                                                • Evgenii Legotckoi
                                                                  Oct. 31, 2024, 11:37 p.m.
                                                                  Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                                                • A
                                                                  Oct. 19, 2024, 5:19 p.m.
                                                                  Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html