QML ListView and QSqlTableModel
-
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.heightproperty 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; } }
}
@ -
Post 2/2
ContentsPage.qml
@
import QtQuick 2.0Item {
id: mainContentsText { 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 -->" 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.0Item {
id: mainItem
width: 1024FontLoader { 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,
LucijanP.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?
-
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