Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML ListView and QSqlTableModel
Forum Updated to NodeBB v4.3 + New Features

QML ListView and QSqlTableModel

Scheduled Pinned Locked Moved QML and Qt Quick
3 Posts 1 Posters 4.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Lucijan
    wrote on last edited by
    #1

    Post 1/2 (exceeds the 6000 character limit)

    Hello,

    I am still new to QML and I have a problem trying to use a QSqlDatabase and QML ListView. I've searched the forum but can't find a solution.

    The application uses QML for most of the work, but it needs to get data from an MS Access database and show it inside QML elements containing a ListView. To do this, I have made a C++ BaseModel class which inherits from QSqlTableModel. I've made a few test programs and managed to connect the database with the ListView to show the data.

    Here's the problem, though. The QML part of the application uses a Loader in the main file to load different pages. These are loaded when I click certain buttons and they hold most of the content. One of these pages needs to contain ComboBoxes which pull data from the database. To make the ComboBox I have first created a ListBox which contains a ListView and a custom-made ListItem which is the delegate. The model for the ListView comes from the C++ BaseModel class. The problem is that I don't know how to de-couple the ListBox/ComboBox from the model to be able to show different data in each ComboBox I make. Currently, it will work if I specify the name of the column directly in the delegate, but because each ComboBox uses a different column (and a different table), I need to be able to do this outside the ComboBox definition, i.e. something like:

    @
    ComboBox {
    id: topicComboBox
    //...
    model: topicModel
    delegate: Topic //this is the column name
    }

    ComboBox {
    id: keyWordComboBox
    //...
    model: keywordModel
    delegate: KeyWord //this is the column name
    }
    @

    I've tried doing this, but I get the following error:

    bq. ReferenceError: KljucnaRijec is not defined

    Do I even need different models for setting each ComboBox?

    I'll provide as much code as possible.

    ListBox.qml

    @import QtQuick 2.0

    Rectangle {
    id: listBox
    width: 400
    height: 500
    color: "#1a4381"
    border.color: "#ffffff"

    property int selectedIndex: testView.currentIndex
    property string selectedText: ""
    property variant listModel
    property string tableField
    
    signal indexChanged()
    
    Component {
        id: delegateItem
    
        ListItem {
            text: listBox.tableField ? listBox.tableField : ""
            width: parent.width
            anchors.left: parent.left
            anchors.leftMargin: 2
            onListItemClick: {
                listBox.selectedText = text;
                testView.currentIndex = index;
            }
        }
    }
    
    ListView {
        id: testView
        clip: true
        anchors.centerIn: parent
        width: parent.width - 2
        height: parent.height - 2
        model: listBox.listModel
        delegate: delegateItem
    
        currentIndex: -1
        onContentHeightChanged: {
            if (listBox.height < testView.contentHeight)
                vScrollBar.visible = true;
            else
                vScrollBar.visible = false;
        }
    
        onCurrentIndexChanged: indexChanged()
    
        ScrollBar {
            id: vScrollBar
            anchors.right: parent.right
            height: parent.height
            position: testView.visibleArea.yPosition
            pageSize: testView.visibleArea.heightRatio
    
            visible: (testView.height < testView.contentHeight) ? true : false
        }
    }
    

    }
    @

    ComboBox.qml

    @import QtQuick 2.0

    Item {
    id: comboBox
    width: 400
    height: selectedItemRect.height

    property alias imageSource: arrowImage.source
    property color itemColor: "#1a4381"
    property color borderColor: "#ffffff"
    property alias text: selectedItemText.text
    property alias listBoxHeight: comboListBox.height
    property variant model
    property string field
    
    Rectangle {
        id: selectedItemRect
        anchors.left: parent.left
        anchors.top: parent.top
        width: parent.width
        height: 20
        color: comboBox.itemColor
        border.color: comboBox.borderColor
    
        Text {
            id: selectedItemText
            color: "#ffffff"
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.left: parent.left
            anchors.leftMargin: 2
            text: ""
            font.pixelSize: 16
            font.family: "Arial"
    
        }
    
        Rectangle {
            id: arrowImageRect
            color:comboBox.itemColor
            border.color: comboBox.borderColor
            height: parent.height
            width: height //width is the same as height
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
    
            Image {
                id: arrowImage
                source: ""
                anchors.centerIn: parent
            }
        }
    
        MouseArea {
            id: comboMouseArea
            anchors.fill: parent
    
            cursorShape: Qt.PointingHandCursor
    
            onClicked: {
                if (comboListBox.visible)
                    comboListBox.visible = false;
                else
                    comboListBox.visible = true;
            }
        }
    }
    
    ListBox {
        id: comboListBox
        anchors.top: selectedItemRect.bottom
        anchors.left: selectedItemRect.left
        width: selectedItemRect.width
        height: 500
        visible: false
        listModel: comboBox.model
        tableField: comboBox.field
    
        onIndexChanged: {
            comboBox.text = selectedText;
            visible = false;
        }
    }
    

    }
    @

    1 Reply Last reply
    0
    • L Offline
      L Offline
      Lucijan
      wrote on last edited by
      #2

      Post 2/2

      ContentsPage.qml

      @
      import QtQuick 2.0

      Item {
      id: mainContents

      Text {
          id: keywordText
          color: "#ffffff"
          anchors.verticalCenter: keywordComboBox.verticalCenter
          anchors.right: authorsIndexText.right
          wrapMode: Text.WordWrap
          text: "<b>Keyword</b>"
          font.pixelSize: 16
          font.family: "Arial"
      }
      
      ComboBox {
              id: keywordComboBox
              width: 300
              height: 20
              listBoxHeight: 570
              itemColor: "#1a4381"
              borderColor: "#ffffff"
              anchors.top: indexRect.bottom
              anchors.topMargin: 10
              anchors.left: indexRect.left
              text: "Choose a keyword --&gt;"
              imageSource: "images/DownArrow.png"
              model: keywordModel
              field: KljucnaRijec //this is the name of the column
              z: 1
      }
      

      }
      @

      The line "field: KljucnaRijec" is the one that causes the error

      bq. ReferenceError: KljucnaRijec is not defined

      main.qml

      @
      import QtQuick 2.0

      Item {
      id: mainItem
      width: 1024

      FontLoader {
          id: avantGardeBookBT
          source: "qrc:/fonts/fonts/AvantGardeBookBT.ttf"
      }
      
      Rectangle {
          id: headerRectangle
          //width: parent.width
          width: 1024
          height: 80
          color: "#1a4381"
          anchors.horizontalCenter: parent.horizontalCenter
      
          ImageTextButton {
              id: exitButton
              imageSource: "images/X.png"
              anchors.right: parent.right
              anchors.top: parent.top
              anchors.topMargin: 5
              onImageTextButtonClick: exitDialog.visible = true;
              text: "EXIT"
          }
      }
      
      Rectangle {
          id: mainRectangle
          //width: parent.width
          width: 1024
          height: mainItem.height - headerRectangle.height - 1
          color: "#1a4381"
          anchors.bottom: parent.bottom
          anchors.horizontalCenter: parent.horizontalCenter
          Component.onCompleted: pageLoader.setSource("HomePage.qml")
      
          signal loadPage(string pageName)
      
          YesNoDialog {
              id: exitDialog
              anchors.centerIn: parent
              visible: false
              z: 1
      
              titleText: "Question"
              messageText: "Are you sure you want to quit?"
              iconSource: "images/Warning.png"
              xButtonImageSource: "images/X.png"
      
              onYesClick: Qt.quit();
              onNoClick: exitDialog.visible = false;
              onExitClick: exitDialog.visible = false;
          }
      
          Image {
              id: mainBgImage
              source: "images/Background1.png"
              anchors.fill: parent
          }
      
          Loader {
              id: pageLoader
      
              anchors.fill: parent
              //source: "HomePage.qml"
          }
      
          Connections {
              id: pageConnections
              ignoreUnknownSignals: true
              target: pageLoader.item
      
              onLoadPage: {
                  if (pageName == "ContentsPage.qml")
                      keywordModel.setModel("KljucneRijeci"); //this will set data from the table specified in quotes to the model
                  pageLoader.source = pageName;
      
              }
          }
      }
      

      }
      @

      I hope this is clear enough.

      Cheers,
      Lucijan

      P.S. I have a side question: if I try to use this application on Linux or Mac, will I need to install a database driver for MS Access databases or will the program call one of Qt's library files? I need to make the program work without any installation. If not, will it work if I convert the database to SQLite or some other database?

      1 Reply Last reply
      0
      • L Offline
        L Offline
        Lucijan
        wrote on last edited by
        #3

        OK, maybe I should start with easier questions. What kind of QML type is the name of the column that I'm sending to the delegate - variant or string? Also, where is the variable visible - only in the delegate, in the file that contains the delegate and ListView or elsewhere as well? I can't make other files see it and I don't know why. This prevents me from making my ListBox a generalized component. As it stands, I would have to make three different ListBox "classes" with the only difference being the data they pull from the database. There has to be a better way to do this, but how? Could I do it from C++ and how would I go about doing that?

        Any pointers in the right direction would be really welcome.

        Cheers,
        Lucijan

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved