Алексей Внуков
July 26, 2019, 3:31 a.m.

QML Model & C++Model

qml, qt, model

Доброго времни суток! есть модель на C++,которая берет данные из sqlite базы. в файле QML есть listview, в который должны загружаться данные, с листом очень много действий и в такой ситуации не удобно работать с С++ моделью, поскольку нужно регулярно делать апдейт модели данные в делегатах перезатираются что сильно затрудняет работу, а из самой модели данные нужны только на старте. Собственно вопрос, можно ли при старте програмы С++ модель копировать в QML модель чтоб с ней работать динамично, чтоб только в некоторых ситуациях данные записывались в базу и отобразились только при следующем старте программы.
п.с если не понятно описание задавайте вопросы

2

Do you like it? Share on social networks!

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

Добрый день!

А можно код того, как модель C++ регистрируется в QML и как она добавлена в ListView?

    Алексей Внуков
    • July 26, 2019, 2:32 p.m.
    • (edited)

    main.cpp

    1. PageModel *page_model=new PageModel();
    2. engine.rootContext()->setContextProperty("page_model",page_model);
    3.  

    Pagemodel.h

    1. class PageModel : public QSqlQueryModel
    2. {
    3. Q_OBJECT
    4. public:
    5. explicit PageModel(QObject *parent = nullptr);
    6.  
    7. enum Roles
    8. {
    9. idRole= Qt::UserRole+1,
    10. urlRole,
    11. nameSiteRole,
    12. screenRole
    13. };
    14.  
    15. Q_INVOKABLE QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    16. Q_INVOKABLE QVariantMap get(int idx) const;
    17.  
    18. signals:
    19.  
    20. protected:
    21. QHash<int,QByteArray> roleNames()const;
    22.  
    23. public slots:
    24. void updateModel();
    25. int getId(int row);
    26. };
    27.  

    PageModel.cpp

    1. PageModel::PageModel(QObject *parent) : QSqlQueryModel (parent)
    2. {
    3. this->updateModel();
    4. }
    5.  
    6. QVariant PageModel::data(const QModelIndex &index, int role) const
    7. {
    8. int columnId = role - Qt::UserRole - 1;
    9. // Создаём индекс с помощью новоиспечённого ID колонки
    10. QModelIndex modelIndex = this->index(index.row(), columnId);
    11.  
    12. /* И с помощью уже метода data() базового класса
    13. * вытаскиваем данные для таблицы из модели
    14. * */
    15. return QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
    16. }
    17.  
    18. QVariantMap PageModel::get(int idx) const
    19. {
    20. QVariantMap map;
    21. foreach(int k, roleNames().keys()) {
    22. map[roleNames().value(k)] = data(index(idx, 0), k);
    23. }
    24. return map;
    25. }
    26.  
    27. QHash<int, QByteArray> PageModel::roleNames() const
    28. {
    29. QHash<int, QByteArray> roles;
    30. roles[idRole]="id";
    31. roles[urlRole]="url";
    32. roles[nameSiteRole]="namesite";
    33. roles[screenRole]="screen";
    34. return roles;
    35. }
    36.  
    37. void PageModel::updateModel()
    38. {
    39. this->setQuery("select id, url, namesite, screen from openTabTable");
    40. }
    41.  
    42. int PageModel::getId(int row)
    43. {
    44. return this->data(this->index(row, 0), idRole).toInt();
    45. }
    46.  

    QML

    1. import QtQuick 2.12
    2. import QtQuick.Controls 2.12
    3. import QtWebView 1.13
    4.  
    5. Item {
    6. id: idListView1Form
    7. width: 400
    8. height: 700
    9.  
    10. Rectangle{
    11. id: rectangleForListView
    12. y: parent.height * 0.15
    13. height: parent.height * 0.7
    14. anchors.left: parent.left
    15. anchors.right: parent.right
    16.  
    17. ListView
    18. {
    19. id: myListView1
    20. highlightRangeMode: ListView.StrictlyEnforceRange
    21. anchors.fill: parent
    22. orientation : ListView.Horizontal
    23. snapMode: ListView.NoSnap
    24. contentX: 100
    25. contentWidth: 100
    26. model: page_model
    27.  
    28. delegate:ItemDelegate
    29. {
    30. id: itemDelegate
    31. width : myListView1.width < myListView1.height ? myListView1.width * 0.7 : myListView1.height * 1
    32. height: myListView1.width < myListView1.height ? myListView1.width * 1 : myListView1.height * 0.7
    33. Rectangle
    34. {
    35.  
    36. WebView1
    37. {
    38. id:webView
    39. }
    40.  
    41. anchors.fill: parent
    42. anchors.leftMargin: myListView1.width * 0.06
    43. Label
    44. {
    45. id:site_name
    46. anchors.top: parent.top
    47. anchors.centerIn: parent
    48. text: namesite
    49. }
    50.  
    51. Rectangle {
    52. id: rec1
    53. color: "grey"
    54. anchors
    55. {
    56. top:site_name.bottom
    57. left: parent.left
    58. right:parent.right
    59. bottom:parent.bottom
    60. }
    61. Label
    62. {
    63. anchors.centerIn: parent
    64. text: url
    65. }
    66. }
    67.  
    68.  
    69. }
    70. MouseArea
    71. {
    72. id: ma_click
    73. anchors.fill: parent
    74. onClicked:
    75. {
    76. webView.url=url
    77. stack.push(webView)
    78. }
    79. }
    80. }
    81. }
    82. }
    83. }
    84.  
      Evgenii Legotckoi
      • July 26, 2019, 3:10 p.m.
      • The answer was marked as a solution.

      Я не уверен, но думаю. что можно ещё переписать метод setData в QSqlQueryModel, в котором записывать данные в базу данных и сразу делать апдейт модели после записи данных в базу данных. Тогда проблема с перезатиранием данных в делегатах будет уже менее актуальна.

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

      Ещё можно попробовать с помощью QVariantMap протолкнуть данные до QML и там уже записать в QML модель данных.

      Ещё можно попробовать взять данные из базы данных прямо в QML

      1. import QtQuick 2.0
      2.  
      3. Rectangle {
      4. color: "white"
      5. width: 200
      6. height: 100
      7.  
      8. Text {
      9. text: "?"
      10. anchors.horizontalCenter: parent.horizontalCenter
      11. function findGreetings() {
      12. var db = openDatabaseSync("QDeclarativeExampleDB", "1.0", "The Example QML SQL!", 1000000);
      13.  
      14. db.transaction(
      15. function(tx) {
      16. // Create the database if it doesn't already exist
      17. tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)');
      18.  
      19. // Add (another) greeting row
      20. tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
      21.  
      22. // Show all added greetings
      23. var rs = tx.executeSql('SELECT * FROM Greeting');
      24.  
      25. var r = ""
      26. for (var i = 0; i < rs.rows.length; i++) {
      27. r += rs.rows.item(i).salutation + ", " + rs.rows.item(i).salutee + "\n"
      28. }
      29. text = r
      30. }
      31. )
      32. }
      33. Component.onCompleted: findGreetings()
      34. }
      35. }

      Тогда манипуляций в C++ делать не нужно будет.

        Алексей Внуков
        • July 26, 2019, 3:59 p.m.

        благодарю, интересное решение

          Comments

          Only authorized users can post comments.
          Please, Log in or Sign up
          • Last comments
          • AK
            April 1, 2025, 11:41 a.m.
            Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
          • 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