QML onClicked event isn't launched - qt

I create a QML extension, witch work correctly. But now when i try to launched it with onClicked signal that doesn't work correctly, you can see my code here:
QLauncher {
id: qprocess
}
PlasmaComponents.Label {
id: label
visible: showLabel
anchors {
top: icon.bottom
topMargin: units.smallSpacing
left: parent.left
leftMargin: highlightItemSvg.margins.left
right: parent.right
rightMargin: highlightItemSvg.margins.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.NoWrap
font.pointSize: mouseArea.containsMouse ? 26 : 14
text: model.display
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: qprocess.launch('createWaveFromItem "' + model.display + '"')
onExited: qprocess.launch('createWaveFromItem ""');
propagateComposedEvents: true
onClicked: {
mouse.accepted = false;
qprocess.launch('createWaveFromItem "Ouverture"');
}
}
The onClicked is in line number 109.
I see propagateComposedEvents, so i try to add propagateComposedEvents: true and mouse.accepted = false but its don't changed anything.
Why it is never launch and how to do it is working ?
Edit : To see all code go to here https://github.com/handyopensource/dvkbuntu-vocalfly

Related

QML ScrollBar combined with ListView

I'm new to QML and QT so don't blame me if this question is going to sound stupid for most of you but I've search all over the internet without any luck in founding an answer.
What I'm trying to do:
I'm having a ScrollView which has inside of it a ScrollBar and a ListView.
I want that at the moment when I'm scrolling the ListView elements to also move the bar from ScrollBar. In other words, I want to use the ScrollBar as an overall view of your current position, you are not supposed to touch that, its only purpose is for viewing.
My Code:
ScrollView{
implicitHeight: 100
implicitWidth: 50
anchors.fill: parent
ScrollBar.horizontal: ScrollBar{
id: hbar
active: true
policy: ScrollBar.AlwaysOn
anchors {
left: parent.left
top: parent.top
right: parent.right
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 50
opacity: enabled ? 1 : 0.3
color: hbar.down ? "#red" : "black"
}
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: hbar.pressed ? "#81e889" : "#c2f4c6"
}
}
ListView {
id: listViewParent
height: listViewID.height/10*6
contentHeight: height*2
contentWidth: width*2
clip: false
interactive: false
keyNavigationWraps: true
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
enabled: true
scale: 1
transformOrigin: Item.Center
anchors.verticalCenter: parent.verticalCenter
boundsBehavior: Flickable.DragAndOvershootBounds
flickableDirection: Flickable.HorizontalFlick
highlightMoveDuration: 0
cacheBuffer: 300
snapMode: ListView.SnapToItem
layoutDirection: Qt.LeftToRight
orientation: ListView.Vertical
model: 1
delegate:
ListView {
width: parent.width;
height: parent.height;
spacing: listViewID.width/8/9
model: MovieListModel {}
orientation: ListView.Horizontal
id: listid
delegate:
Rectangle {
property int recDynamicHeight: listViewID.height/10*6
property int recOriginalHeight: listViewID.height/10*6
property int recDynamiclWidth: listViewID.width/7
property int recOriginalWidth: listViewID.width/7
id: rectPer
width: recDynamiclWidth
height: recDynamicHeight
Image {
id: image1
anchors.fill: parent;
source: model.imgUrl
}
Text {
property bool isVisible: false
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: textid
text: model.title
font.bold: true
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9
leftPadding: listViewID.width/8/9
}
Text {
anchors.topMargin: listViewID.width/8/9
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: yearId
text: model.year
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9*2
leftPadding: listViewID.width/8/9
}
MouseArea {
anchors.fill: parent
onPressed: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamicHeight += rectPer.recOriginalHeight/10;
rectPer.recDynamiclWidth += rectPer.recOriginalWidth/10;
console.log(textid.isVisible);
textid.isVisible = true;
textid.visible = textid.isVisible;
console.log(sideButtonID.x);
console.log(sideButtonID.y);
console.log(model.year + " clicked");
}
onClicked: {
console.log("INDEX: " + model.id)
load_page(PageType.movie_detailed_view, model.title, model.description, model.imgUrl, model.type, model.year)
}
onReleased: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamiclWidth = rectPer.recOriginalWidth;
textid.isVisible = false;
textid.visible = textid.isVisible;
}
}
}
}
}
}
Layout:
You could try use a Flickable instead of a ScrollView and spawn a ListView there(delegates: Rectangles). Then, spawn the Scrollbar inside the ListView

Line numbers/ line height for a Qml TextArea

We want to implement an embedded code editor in our QtQuick based application. For highlighting we use a QSyntaxHighlighter based on KSyntaxHighlighting. We found no way to determine the line height and line spacing that would allow us to display line numbers next to the code. Supporting dynamic line-wrap would also be a great addition.
Flickable {
id: flickable
flickableDirection: Flickable.VerticalFlick
Layout.preferredWidth: parent.width
Layout.maximumWidth: parent.width
Layout.minimumHeight: 200
Layout.fillHeight: true
Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds
clip: true
ScrollBar.vertical: ScrollBar {
width: 15
active: true
policy: ScrollBar.AlwaysOn
}
property int rowHeight: textArea.font.pixelSize+3
property int marginsTop: 10
property int marginsLeft: 4
property int lineCountWidth: 40
Column {
id: lineNumbers
anchors.left: parent.left
anchors.leftMargin: flickable.marginsLeft
anchors.topMargin: flickable.marginsTop
y: flickable.marginsTop
width: flickable.lineCountWidth
function range(start, end) {
var rangeArray = new Array(end-start);
for(var i = 0; i < rangeArray.length; i++){
rangeArray[i] = start+i;
}
return rangeArray;
}
Repeater {
model: textArea.lineCount
delegate:
Label {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "white" : "#666"
font: textArea.font
width: parent.width
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: flickable.rowHeight
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "red" : "white"
}
}
}
}
Rectangle {
y: 4
height: parent.height
anchors.left: parent.left
anchors.leftMargin: flickable.lineCountWidth + flickable.marginsLeft
width: 1
color: "#ddd"
}
TextArea.flickable: TextArea {
id: textArea
property bool differentFromSavedState: fileManager.textDifferentFromSaved
text: fileManager.textTmpState
textFormat: Qt.PlainText
//dont wrap to allow for easy line annotation wrapMode: TextArea.Wrap
focus: false
selectByMouse: true
leftPadding: flickable.marginsLeft+flickable.lineCountWidth
rightPadding: flickable.marginsLeft
topPadding: flickable.marginsTop
bottomPadding: flickable.marginsTop
background: Rectangle {
color: "white"
border.color: "green"
border.width: 1.5
}
Component.onCompleted: {
fileManager.textEdit = textArea.textDocument
}
onTextChanged: {
fileManager.textTmpState = text
}
function update()
{
text = fileManager.textTmpState
}
}
}
As you can see we use property int rowHeight: textArea.font.pixelSize+3 to guess the line height and line spacing but that of course breaks as soon as DPI or other properties of the system change.
The TextArea type has two properties contentWidth and contentHeight which contains the size of the text content.
So, if you divide the height by the number of lines (which you can get with the property lineCount), you will get the height of a line:
property int rowHeight: textArea.contentHeight / textArea.lineCount
But, if you plan to have multiple line spacing in the same document, you will have to handle each line by manipulating the QTextDocument:
class LineManager: public QObject
{
Q_OBJECT
Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
public:
LineManager(): QObject(), document(nullptr)
{}
Q_INVOKABLE void setDocument(QQuickTextDocument* qdoc)
{
document = qdoc->textDocument();
connect(document, &QTextDocument::blockCountChanged, this, &LineManager::lineCountChanged);
}
Q_INVOKABLE int lineCount() const
{
if (!document)
return 0;
return document->blockCount();
}
Q_INVOKABLE int height(int lineNumber) const
{
return int(document->documentLayout()->blockBoundingRect(document->findBlockByNumber(lineNumber)).height());
}
signals:
void lineCountChanged();
private:
QTextDocument* document;
};
LineManager* mgr = new LineManager();
QQuickView *view = new QQuickView;
view->rootContext()->setContextProperty("lineCounter", mgr);
view->setSource(QUrl("qrc:/main.qml"));
view->show();
Repeater {
model: lineCounter.lineCount
delegate:
Label {
color: "#666"
font: textArea.font
width: parent.width
height: lineCounter.height(index)
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
border.color: "black"
}
}
}
I found a QML only solution:
Use TextEdit instead of TextArea to avoid alignment issues between line numbers and text
Use a 'ListView' to generate the line numbers for the text edit:
Here is an initial solution:
RowLayout {
anchors.fill: parent
ListView {
Layout.preferredWidth: 30
Layout.fillHeight: true
model: textEdit.text.split(/\n/g)
delegate: Text { text: index + 1 }
}
TextEdit {
id: textEdit
Layout.fillWidth: true
Layout.fillHeight: true
}
}
The ListView has a complete copy of each row of text. We can use this copy to compute the line height (taking into account of word wrap). We do this by creating an invisible Text. We can improve the answer further by adding a Flickable to the TextEdit and synchronize the scroll between the ListView and the TextEdit:
Here is a more complete solution:
// NumberedTextEdit.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
Item {
property alias lineNumberFont: lineNumbers.textMetrics.font
property color lineNumberBackground: "#e0e0e0"
property color lineNumberColor: "black"
property alias font: textEdit.font
property alias text: textEdit.text
property color textBackground: "white"
property color textColor: "black"
Rectangle {
anchors.fill: parent
color: textBackground
ListView {
id: lineNumbers
property TextMetrics textMetrics: TextMetrics { text: "99999"; font: textEdit.font }
model: textEdit.text.split(/\n/g)
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
width: textMetrics.boundingRect.width
clip: true
delegate: Rectangle {
width: lineNumbers.width
height: lineText.height
color: lineNumberBackground
Text {
id: lineNumber
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
color: lineNumberColor
font: textMetrics.font
}
Text {
id: lineText
width: flickable.width
text: modelData
font: textEdit.font
visible: false
wrapMode: Text.WordWrap
}
}
onContentYChanged: {
if (!moving) return
flickable.contentY = contentY
}
}
Item {
anchors.left: lineNumbers.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
Flickable {
id: flickable
anchors.fill: parent
clip: true
contentWidth: textEdit.width
contentHeight: textEdit.height
TextEdit {
id: textEdit
width: flickable.width
color: textColor
wrapMode: Text.WordWrap
}
onContentYChanged: {
if (lineNumbers.moving) return
lineNumbers.contentY = contentY
}
}
}
}
}
I've found that you can query the line height using FontMetrics and then getting the true height by Math.ceil(fontMetrics.lineSpacing) for example:
TextEdit {
id: textArea
FontMetrics {
id: fontMetricsId
font: textArea.font
}
Component.onCompleted: {
console.log("Line spacing:" + Math.ceil(fontMetricsId.lineSpacing)
}
}

How to get Clicked or Pressed event on QML TableView header?

I I´m trying get the click or press event on QML TableView Header.
I have tried on HeaderDelegate create a MouseArea with width, height and anchors.fill from the parent, and get the onClicked or onPressed events, but don´t work.
Example:
MouseArea {
width: parent.width
height: parent.height
anchors.fill: parent
onClicked: {
console.debug("CLICKED: "+styleData.pressed)
console.debug("COLUMN: "+ styleData.column)
}
onPressed: {
console.debug("PRESSED: "+styleData.pressed)
console.debug("COLUMN: "+ styleData.column)
}
}
that doesn't log anything
I also tried use "Connections" on HeaderDelegate, with "target: styleData" and "onPressedChanged"event, and worked, but the "onPressedChanged" get 4 changes in the same time.
Example:
Connections {
target: styleData
onPressedChanged: {
console.debug("PRESSED: "+ styleData.pressed)
console.debug("COLUMN: "+ styleData.column)
}
}
Return:
qml: PRESSED: true
qml: COLUMN: 0
qml: PRESSED: true
qml: COLUMN: 0
qml: PRESSED: false
qml: COLUMN: 0
qml: PRESSED: false
qml: COLUMN: 0
The whole code from TableView:
TableView {
id: tViewEnt
width: parent.width
height: parent.height
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
TableViewColumn {
id: column0
title: "column0"
width: 30
delegate: CheckBox {
style: CheckBoxStyle {
indicator: Rectangle {
//INDICATOR PROPERTIES
}
}
}
}
TableViewColumn {
title: "column1"
role: "column1"
}
TableViewColumn {
title: "column2"
role: "column2"
}
headerDelegate: Rectangle {
height: tViewEnt.height / 15
color: styleData.column===0 ? "#4D4D4D" : "#0077B3"
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 1
anchors.topMargin: 1
width: 1
color: "#333"
}
Text {
text: styleData.value
color: "#CFF"
width: parent.width
height: parent.height
font.pointSize: 18
minimumPointSize: 3
fontSizeMode: Text.Fit
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Connections {
target: styleData
onPressedChanged: {
console.debug("PRESSED: "+ styleData.pressed)
console.debug("COLUMN: "+ styleData.column)
}
}
}
}
So, How do i get the Header Delegate click or pressed event in the right way?

Long TabBar - adding a size and position indicator to reflect the presence of off-screen tabs

I have a tab bar with a stacklayout like the following:
Rectangle {
id: rect
height: 190
anchors.right: parent.right
anchors.left: parent.left
color: "transparent"
anchors.top: uniqueHandleText.bottom
anchors.topMargin: 100
TabBar {
id: frame
anchors.right: parent.right
anchors.left: parent.left
background: Rectangle {
color: "#737373"
}
x: -hbar.position * width
Repeater {
model: wizard.categories
TabButton {
id: tabData
property bool selected: false
text: modelData.name
width: 200
font.pixelSize: 18
contentItem: Text {
text: tabData.text
font: tabData.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: "#FFFFFF"
}
background: Rectangle {
implicitWidth: frame.width
implicitHeight: 180
opacity: enabled ? 1 : 0.3
color: tabData.checked ? "#BD9CBE": "#737373"
}
}
}
}
ScrollBar {
id: hbar
hoverEnabled: true
active: hovered || pressed
orientation: Qt.Horizontal
size: rect.width / frame.width
anchors.left: parent.left
anchors.right: parent.right
anchors.top: frame.bottom
}
Text {
font.pixelSize: 18
text: "Next"
anchors.right: parent.right
visible: frame.x != frame.width ? true: false
}
StackLayout {
id: stack1
anchors.left: parent.left
anchors.right: parent.right
anchors.top: frame.bottom
currentIndex: frame.currentIndex
Repeater {
model: wizard.categories
Item {
id: homeTab
TabBar {
id: homeTabTab
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
height: 180
background: Rectangle {
color: "#958096"
}
Repeater {
model: modelData.sub_categories
TabButton {
property bool selected: false
id: currentTab
text: modelData.name
width: 200
font.pixelSize: 18
background: Rectangle {
implicitWidth: frame.width
implicitHeight: 180
opacity: enabled ? 1 : 0.3
color: currentTab.checked ? "#958096": "#8D758E"
}
contentItem: Text {
text: currentTab.text
font: currentTab.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: "#FFFFFF"
MouseArea {
anchors.fill: parent
onClicked: {
if(currentTab.checked){
currentTab.checked = false
} else {
currentTab.checked = true
}
}
onDoubleClicked: {
currentTab.selected = true
var found = false;
var someText = frame.itemAt(stack1.currentIndex).text;
print(someText)
for(var i = 0; i<wizard.selectedSkills.count; i++){
if(wizard.selectedSkills.get(i).name === someText){
wizard.selectedSkills.get(i).sub_categories.append({"name":currentTab.text});
wizard.skills.push({"name": someText})
found = true;
}
}
if(!found){
print(currentTab.text)
wizard.selectedSkills.append({"name":someText, "sub_categories":[{"name":currentTab.text}]})
}
print(window.selectedSkills)
}
}
}
}
}
}
}
}
}
}
I've tried many different things to add a scrollbar or to figure out how to use the flickable functionality that TabBar has. However, the documentation doesn't specify how it works, it just does. Therefore, they are not accessible (or even rewritteable, to use those properties). I want to add a small indicator like an arrow to specify that there is more elements for ease of navigation on desktop on top of the TabBar functionality.
It doesn't seem like the necessary properties are exposed in order to make this happen the easy way.
However, since this is QML, it means the whole object tree is gaping wide open to introspection, allowing us to establish that the item that does the flicking is the contentItem of a ListView inside the Container the ToolBar inherits. The view happens to be the second visible child, although this is technically "private implementation" that one should not rely on. So it is better to take some extra care to establish whether or not you have the correct object.
ApplicationWindow {
id: main
width: 640
height: 480
visible: true
TabBar {
id: toolbar
width: parent.width
height: 50
Repeater {
model: 10
TabButton {
text: "test " + index
width: 100
}
}
}
Rectangle {
height: 5
width: main.width * (view ? view.visibleArea.widthRatio : toolbar.width / toolbar.contentWidth)
color: "red"
anchors.top: toolbar.bottom
x: view ? (main.width - width) * (view.contentX / (view.contentWidth - view.width)) : 0
}
property ListView view: {
var l = toolbar.visibleChildren.length
while (--l) if ("cacheBuffer" in toolbar.visibleChildren[l]) return toolbar.visibleChildren[l]
return null
}
}
And there you have it. We iterate the tabview children until we find one that has a property cacheBuffer which is fairly unique to ListView, and once we have that, we can access the needed properties. As you see, for the indicator width we can do even without the list view, as the toolbar exposes a contentWidth property, but for the indicator position there is no workaround.
And it works:

How to animate a message that appears on bottom?

I'm showing a message on the bottom:
Msg.qml
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MsgForm {
id: mf
width: parent.width
y: parent.height - height - 5
}
}
MsgForm.ui.qml
import QtQuick 2.4
Item {
property alias text: msg.text
width: 200
id: message
height: msg.height+10
Rectangle {
id: rectangle
color: "#fb9191"
anchors.fill: parent
border.color: "#fd6666"
border.width: 2
Text {
id: msg
anchors.top: parent.top
anchors.topMargin: 2
textFormat: Text.PlainText
anchors.right: parent.right
anchors.rightMargin: 4
anchors.left: parent.left
anchors.leftMargin: 4
wrapMode: Text.WordWrap
clip: false
font.bold: true
font.pointSize: 12
font.family: "Tahoma"
}
}
}
How can I animate the form to appear from the bottom smoothly?
After the animation, if the window resizes, the message must stay always on the bottom.
You can play with anchors.bottomMargin property to raise the message item from the bottom.
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MsgForm {
id: mf
property bool showing: false
width: parent.width
anchors{
bottom: parent.bottom
bottomMargin: mf.showing ? 0 : -mf.height
Behavior on bottomMargin{
NumberAnimation{ }
}
}
}
}
Thanks everyone. In the end I've solved the issue by following advices received in the qtcentre forum.
The desired effect can be achieved easily by defining a local numerical property that is use to bind to either an anchors.XXXXmargin or the y property expression.
Following this approach a possible solution is the following:
MsgForm {
property bool showing: false
property int position: showing ? height : 0
width: parent.width
y: parent.height - position
Behavior on position {
NumberAnimation {duration: 500}
}
}
You can make an animation on the opacity change:
Msg.qml
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MouseArea{
anchors.fill: parent
onClicked: mf.opacity = !mf.opacity
}
MsgForm {
id: mf
//y: parent.height - height - 5
opacity:0
Behavior on opacity {
NumberAnimation{
duration:600
}
}
width: parent.width
anchors.bottom: parent.bottom
}
}
or any other NumberAnimation. I recommand you to create States, within it do some propertyChanges, and on some actions, example button clicked change states.
example in your MsgForm.ui.qml add:
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
and in the action, example:
in my mouseArea I change the state of mf
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
If you want an Animation on the y try this:
MsgForm.ui.qml
import QtQuick 2.4
Item {
id: message
property alias text: msg.text
width: parent.width
height: msg.height+10
Rectangle {
id: rectangle
color: "#fb9191"
anchors.fill: parent
border.color: "#fd6666"
border.width: 2
Text {
id: msg
anchors.top: parent.top
anchors.topMargin: 2
textFormat: Text.PlainText
anchors.right: parent.right
anchors.rightMargin: 4
anchors.left: parent.left
anchors.leftMargin: 4
wrapMode: Text.WordWrap
clip: false
font.bold: true
font.pointSize: 12
font.family: "Tahoma"
}
}
Behavior on y {
NumberAnimation{
duration:300
}
}
states: [
State {
name: "show"
PropertyChanges {
target: message
y: parent.height - height
}
},
State {
name: "hide"
PropertyChanges {
target: message
y: parent.height + height + 5
}
}
]
}
Msg.qml
import QtQuick 2.4
Rectangle {
property alias text: mf.text
width:800
height: 480
antialiasing: false
opacity: 0.9
z: 100
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
MsgForm {
id: mf
//y: parent.height - height - 5
y: parent.height +height + 5
width: parent.width
}
}

Resources