What I have is a listview, to show list of contacts. Also, there is a search box and a label. Based on the text typed in the search box, the contact list will be filtered.
Here is my code:
import QtQuick 1.1
import com.nokia.symbian 1.1
import com.nokia.extras 1.1
import QtMobility.contacts 1.1
Window {
id: window
StatusBar {
id: statusBar
anchors.top: window.top
Text {
id: statusBarTitle
text: "Contacts"
color: "#ffffff"
}
}
ContactModel {
id: contactModel
filter:
IntersectionFilter {
DetailFilter {
detail: ContactDetail.PhoneNumber
field: PhoneNumber.PhoneNumber
value: PhoneNumber.Mobile
}
UnionFilter {
DetailFilter {
detail: ContactDetail.Name
field: Name.FirstName
value: searchbox.searchText
matchFlags: Filter.MatchStartsWith
}
DetailFilter {
detail: ContactDetail.Name
field: Name.LastName
value: searchbox.searchText
matchFlags: Filter.MatchStartsWith
}
DetailFilter {
detail: ContactDetail.DisplayLabel
field: DisplayLabel.Label
value: searchbox.searchText
matchFlags: Filter.MatchStartsWith
}
}
}
sortOrders:
SortOrder {
detail: ContactDetail.Name
field: Name.FirstName
direction: Qt.AscendingOrder
}
}
Component {
id: contactListDelegate
ListItem {
id: listItem
Image {
id: avatar
source: contact.thumbnail
sourceSize.width: 60
sourceSize.height: 60
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
}
ListItemText {
id: nameText
text: contact.name.firstName + " " + contact.name.lastName
color: "white"
anchors.left: avatar.right
anchors.leftMargin: 10
font.family: "Helvetica"
anchors.verticalCenter: parent.verticalCenter
}
}
}
ListView {
id: listView
anchors.top: searchbox.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: toolBar.top
clip: true
model: contactModel
delegate: contactListDelegate
visible: true
}
SearchBox {
id: searchbox
anchors.top: statusBar.bottom
placeHolderText: "Search Contact"
onSearchTextChanged: {
searchingBusyIndicator.running = true
searchingBusyIndicator.visible = true
searchTimeoutTimer.restart()
}
}
Label {
id: noMatchesLabel
anchors.centerIn: listView
visible: false
text: "No matches"
}
BusyIndicator{
id: searchingBusyIndicator
anchors.centerIn: parent
platformInverted: window.platformInverted
width: 80
height: 80
visible: false
}
Timer{
id: searchTimeoutTimer
interval: 1000
onTriggered: {
searchingBusyIndicator.running = false
searchingBusyIndicator.visible = false
}
}
ToolBar {
id: toolBar
anchors.bottom: window.bottom
tools: ToolBarLayout {
id: toolBarLayout
ToolButton {
flat: true
iconSource: "toolbar-back"
onClicked: {
Qt.quit()
}
}
ToolButton {
flat: true
iconSource: "toolbar-search"
}
}
}
}
}
Now I need to change the visible property of the list view to false & the label property to true, when there is no matches in the list. How to achieve that.?
What's happening now is, the application crashes and terminates when there is no matches.
I spent 2 days while find solution of this problem...
here is my fix:
ContactModel {
...........
onRowsInserted: {
if(last === 0)
{
noMatchesLabel.visible = true;
listView.model = {};
}
else
{
noMatchesLabel.visible = false;
listView.model = contactModel;
}
}
While the contactModel haven't contacts because of using filters, we swap the model of listView to empty one. In that way the app doesn't crash
Related
I'm trying to create a Combobox in QML with custom items in it.
Each item must have two Labels/text.
I'm trying to customize it, changing the background etc. but the Items in the popup are rendering outside of its borders
How can I contain the items inside the popup?
This is the closest sample code I could get:
import QtQuick 2.13
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.15
ComboBox {
ListModel {
id: _dataModel
ListElement {
name: "Account1"
numbers: "12345"
}
ListElement {
name: "Account2"
numbers: "12346"
}
ListElement {
name: "Account3"
numbers: "12346"
}
ListElement {
name: "Account4"
numbers: "12346"
}
ListElement {
name: "Account5"
numbers: "12346"
}
ListElement {
name: "Account6"
numbers: "12346"
}
}
id:equipmentList
anchors.verticalCenter: parent.verticalCenter
width: 400
height: 50
model: _dataModel
background: Rectangle {
color: "#95A4A8"
border.color: "white"
}
delegate: ItemDelegate {
id:itemDlgt
width: equipmentList.width
height: 80
contentItem: Column {
id:rectDlgt
width:parent.implicitWidth
spacing: 2
Text {
id: _firstLabel
Layout.preferredHeight: 20
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
color: "black"
font.pixelSize: 16
text: name
}
Text {
Layout.preferredHeight: 16
color: "grey"
font.pixelSize: 14
text: numbers
}
}
}
contentItem: Text {
leftPadding: 20
rightPadding: equipmentList.indicator.width + equipmentList.spacing
text: "This doesnt work either"
font: equipmentList.font
color: "white"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
}
popup: Popup {
id:comboPopup
visible: true
y: equipmentList.height - 50
width: equipmentList.width
height:contentItem.implicitHeigh
padding: 1
contentItem: ListView {
id:listView
implicitHeight: 150
model: equipmentList.popup.visible ? equipmentList.delegateModel : null
ScrollIndicator.vertical: ScrollIndicator {}
}
background: Rectangle {
radius: 7
border.width: 1
}
}
}
I have bad problem on my qml code performance, laggy when swiping between "Inbox" and "MyBoxes", code is simple but...
Ok, here is my code, main:
Loader {
id: loader
anchors.fill: parent
sourceComponent: splash
}
Component {
id: splash
Splash {
percent: l_i.load
fin: ()=>{
loader.sourceComponent = swip_cmp
}
}
}
Component {
id: swip_cmp
Swip {
}
}
Swip.qml:
Page {
SwipeView {
id: swipeView
topPadding: 10
anchors.fill: parent
currentIndex: tabBar.currentIndex
Inbox {
title: "Inbox"
}
MyBoxes {
title: "MyBoxes"
}
}
header: Navigation {
id: tabBar
pageIndex: swipeView.currentIndex
implicitHeight: 50
width: parent.width
anchors.top: head.bottom
anchors.topMargin: 0
tabs:[
NavButton { text: "Inbox"; icon.source: "../assets/Inbox.png" },
NavButton { text: "MyBoxes"; icon.source: "../assets/Box.png" },
NavButton { text: "Leitners"; icon.source: "../assets/Cards.png" }
]
}
}
MyBoxes.ui.qml:
Page {
Rectangle{
id: page
width: parent.width * .9
anchors.horizontalCenter: parent.horizontalCenter
Column {
spacing: 5
Box {
width: page.width
active: true
title: "504"
totalwords: "504"
details: "Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups."
}
Box {
width: page.width
title: "504"
totalwords: "504"
details: "Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups."
}
}
}
}
Box.qml:
Item {
id: item2
property string title: "title"
property string totalwords: "totalwords"
property string details: "details"
property string src: "src"
property bool online: false
property bool active: false
height: head.contentHeight+det.contentHeight + 50
Rectangle {
id: bodybg
anchors.fill: parent
color: "#FFFFFF"
Text {
id: head
color: "#373737"
text: title
font.bold: true
font.pointSize: 14
anchors.leftMargin: 5
anchors.topMargin: 5
anchors.left: parent.left
anchors.top: parent.top
}
Text {
id: tw
color: "#777777"
text: totalwords
font.bold: true
font.pointSize: 10
anchors.top: parent.top
anchors.topMargin: 5
anchors.right: parent.right
anchors.rightMargin: 5
}
Rectangle {
id: hr
width: parent.width * .9
height: 1
color: "#707070"
anchors.top: head.bottom
anchors.topMargin: 5
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
id: det
width: parent.width
color: "#222222"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: details
anchors.margins: 5
anchors.top: hr.bottom
anchors.right: parent.right
anchors.left: parent.left
}
Button {
id: add
width: 64
height: 26
text: online ? "Download" : (active ? "Deactive" : "Active")
anchors.right: parent.right
anchors.top: det.bottom
anchors.rightMargin: 5
anchors.bottomMargin: 5
contentItem: Rectangle {
id: rectangle
anchors.fill: parent
color: (active ? "#BC0C52" : "#00C193")
Text {
text: add.text
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: "#FFFFFF"
}
}
}
Text {
id: delt
visible: !online
color: "#BC0C52"
text: "Delete"
anchors.verticalCenter: add.verticalCenter
anchors.right: add.left
anchors.rightMargin: 10
font.underline: true
}
}
DropShadow {
anchors.fill: bodybg
samples: 17
color: "#80000000"
source: bodybg
}
}
I have no matter cpp code yet!
It's mostly code:|
I think Box.qml must optimize, or may problem be because of long texts in MyBoxes.ui.qml
Or maybe I should change compile configuration, here is qmake:
-spec android-clang "CONFIG+=debug" "CONFIG+=qml_debug" ANDROID_ABIS="armeabi-v7a" && D:/Android/SDK/ndk/21.1.6352462/prebuilt/windows-x86_64/bin/make.exe qmake_all
You can try setting cached: true on the DropShadow:
This property allows the effect output pixels to be cached in order to improve the rendering performance. Every time the source or effect properties are changed, the pixels in the cache must be updated. Memory consumption is increased, because an extra buffer of memory is required for storing the effect output.
It is recommended to disable the cache when the source or the effect properties are animated.
By default, the property is set to false.
https://doc.qt.io/qt-5/qml-qtgraphicaleffects-dropshadow.html#cached-prop
I have a TreeViewand I have an image with a MouseArea in one of the columns. By clicking on it, the focus (selection, highlighting?) doesn't move to the string because the MouseArea is above the TreeView (as far as I understand)
Here is the code:
TreeView
{
clip: true id: mapsTreeView
objectName: "mapsTreeView"
model: theModel
TableViewColumn {
width: 100
role: "name_role"
title: "Map"
}
TableViewColumn {
width: 50
role: "description_role"
}
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
mapsTreeView.sigChangeState()
}
}
Image {
anchors.fill: parent
width: 5
source: "icon" + styleData.value + ".png"
}
}
}
signal sigChangeState()
}
}
The same story applies to the button:
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Button {
iconSource: "icon" + styleData.value + ".png"
onClicked: mapsTreeView.sigChangeState()
}
}
When I click on the button, the focus doesn't moves to the string that contains button.
So the question is, how to make the image/button delegate so that by clicking on it focus will move to the string that contains this object, and some signal is emitted.
In ListView, all I had to do was simply the following:
onClicked:{
mapsView.currentIndex=model.index
mapsState.sigChangeState()
}
But TreeView doesn't allow one to write CurrentIndex
I would like to add a MouseArea/Button to a TableViewColumn to perform specific tasks. However, if I add one of the above type, it overrides the "click" event of TableViewColumn so that I lose row selection.
Here is an example code. The row is not switching when I click it in the area of the last column:
TreeView {
clip: true id: mapsTreeView
objectName: "mapsTreeView"
model: theModel
TableViewColumn {
width: 100
role: "name_role"
title: "Map"
}
TableViewColumn {
width: 50
role: "description_role"
}
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
mapsTreeView.sigChangeState()
}
}
Image {
anchors.fill: parent
width: 5
source: "icon" + styleData.value + ".png"
}
}
}
signal sigChangeState()
}
Maybe there is a better solution, but this works for me:
MouseArea {
anchors.fill: parent
onContainsPressChanged: {
if(containsPress)
{
console.log("PRESSED")
}
}
onPressed: {
mouse.accepted = false
}
}
I'm trying to get data from a specific column when the row is selected.
For exemple, when the user selects the first row, I need to retrieve the value of the column "Image source". Many thanks!!
main.qml
TableView {
onClicked: {
console.log("value "+ column2.value )
}
id:tablev
model: mySQLmodel
anchors.margins: 12
anchors.fill: parent
TableViewColumn {
id: column1
role: "Title"
title: "Title"
width: 120
}
TableViewColumn {
id: column2
role: "Credit"
title: "Credit"
width: 120
}
TableViewColumn {
id: column14
role: "Image"
title: "Image source"
width: 120
}
itemDelegate: Text
{
text: styleData.value
elide: Text.ElideRight
} }}}
Assume you are using TableView with model.
ListModel {
id: libraryModel
ListElement{ title: "A title 1" ; credit: "N/A"; source: "http://someurl.com" }
ListElement{ title: "A title 2" ; credit: "N/A"; source: "http://someurl.com" }
ListElement{ title: "A title 3" ; credit: "N/A"; source: "http://someurl.com" }
}
TableView {
TableViewColumn{ role: "title" ; title: "Title" ; width: 100 }
TableViewColumn{ role: "credit" ; title: "Credit" ; width: 200 }
TableViewColumn{ role: "source" ; title: "Image source" ; width: 200 }
model: libraryModel
}
So you can add onClick event to the view in that way:
onClicked: {
console.log(libraryModel.get(row).source);
}
when row is the selected row passed to onClicked by engine
[Solved]
I use the function bellow and works great:
QVariantMap Model::get(int idx) const {
QVariantMap map;
foreach(int k, roleNames().keys()) {
map[roleNames().value(k)] = data(index(idx, 0), k);
}
return map;
}
Happy codding :)
You could add something like:
`
TableView {
itemDelegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
console.log("row: " + styleData.row + " column: " + styleData.column + " value: " + styleData.value)
}
}
}
}
`