Qt: active chats control - c++

I'm trying to figure out what component that would be best to use for a active chats control.
I've attached an image with the layout that I'm aiming for.
Basically I want to add an icon to the left of each conversation, depending if the conversation is active or not. The middle column is the name of the conversation and the last column is an indicator if there are new messages for this conversation. However, if the row is selected the indicator should switch out to a close conversations button.
I've through about using:
- Listview, however this would not give me multiple columns?
- Treeview
- Tableview - this might be the best solution. However in unsure of how to add icons and buttons to different cells
Which one would be my best bet here?

I think it depends on API you want to achieve. Most importantly, who will be the close handler/listener:
You can go for a table view with three different delegates. This way the caller is responsible to set up the close event.
Or you can make it list view, which internally creates listView/GridView. This way the conversation itself would be the listener to the close event.
It's up to you to decide which of these (there may be more) is more suitable to your existing codebase

If you have a simple delegate to implement (and you work in QML), you can really use a ListView to get the job done.
Here is a self-contained prototype of your layout. Change Rectangle by Image. You see that color vary accordingly as the model give an odd or even number. You can in the same way change the Component to load, the source of an Image, whatever you can imagine.
import QtQuick 2.0
Rectangle {
width: 360
height: 200
ListView {
anchors.fill: parent
model: 3
delegate: Rectangle {
id: rect
width: parent.width
height: 60
property bool selected: false
color: selected ? "darkblue" : "transparent"
Rectangle {
id: bubbleIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
color: "lightblue"
}
Text {
id: chatName
anchors.left: bubbleIcon.right
anchors.leftMargin: 10
height: parent.height
verticalAlignment: Text.AlignVCenter
text: "chat" + modelData
}
Rectangle {
id: notificationIcon
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
//just an dummy example to show how to change representation base
//expression binding
color: (modelData % 2 === 0) ? "lightGreen" : "red"
}
MouseArea {
anchors.fill: parent
onClicked: {
selected = ! selected;
}
}
}
}
}

Related

Qt: Qt 6.1.1 Failed to create vertex shader: Error 0x80070057

Guys!
I'm a new user of qt and I faced a problem with qml. This issue has already been discussed in this article, but for python. I write in C ++/Qt 6.1.1, QtCreator 4.15.1 for open source. Help me please.
Here is the crux of the problem: qml does not work, Application output writes the following message: "Failed to create vertex shader: Error 0x80070057: ???????? ????? ???????. Failed to build graphics pipeline state ".
The Qt documentation says that this is because of "Scene Graph Adaptations". Here is the link: https://doc-snapshots.qt.io/qt6-dev/qtquick-visualcanvas-adaptations.html.
I tried to use this method from the article in main:
QQuickWindow :: setSceneGraphBackend ("QT_QUICK_BACKEND");
For it, you also need to include the library QQuickWindow.
However, Qt gives the following error: Could not create scene graph context for backend 'QT_QUICK_BACKEND' - check that plugins are installed correctly in C: /Qt/6.1.1/mingw81_64/plugins
Here I no longer understand what to do ...
I provide the code for clarity. Since in qml it is enough to create a window and include the Rectangle {} in it.
I took the code from the example (tried 3 QtQuick examples).
Here is the main function code:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
int main(int argc, char *argv[])
{
QQuickWindow::setSceneGraphBackend("QT_QUICK_BACKEND");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl("qrc:/sidepanel.qml"));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
QML code:
import QtQuick
import QtQuick.Controls
ApplicationWindow {
id: window
width: 360
height: 520
visible: true
title: qsTr("Side Panel")
//! [orientation]
readonly property bool inPortrait: window.width < window.height
//! [orientation]
ToolBar {
id: overlayHeader
z: 1
width: parent.width
parent: Overlay.overlay
Label {
id: label
anchors.centerIn: parent
text: "Qt Quick Controls"
}
}
Drawer {
id: drawer
y: overlayHeader.height
width: window.width / 2
height: window.height - overlayHeader.height
modal: inPortrait
interactive: inPortrait
position: inPortrait ? 0 : 1
visible: !inPortrait
ListView {
id: listView
anchors.fill: parent
headerPositioning: ListView.OverlayHeader
header: Pane {
id: header
z: 2
width: parent.width
contentHeight: logo.height
Image {
id: logo
width: parent.width
source: "images/qt-logo.png"
fillMode: implicitWidth > width ? Image.PreserveAspectFit : Image.Pad
}
MenuSeparator {
parent: header
width: parent.width
anchors.verticalCenter: parent.bottom
visible: !listView.atYBeginning
}
}
footer: ItemDelegate {
id: footer
text: qsTr("Footer")
width: parent.width
MenuSeparator {
parent: footer
width: parent.width
anchors.verticalCenter: parent.top
}
}
model: 10
delegate: ItemDelegate {
text: qsTr("Title %1").arg(index + 1)
width: listView.width
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
Flickable {
id: flickable
anchors.fill: parent
anchors.topMargin: overlayHeader.height
anchors.leftMargin: !inPortrait ? drawer.width : undefined
topMargin: 20
bottomMargin: 20
contentHeight: column.height
Column {
id: column
spacing: 20
anchors.margins: 20
anchors.left: parent.left
anchors.right: parent.right
Label {
font.pixelSize: 22
width: parent.width
elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter
text: qsTr("Side Panel Example")
}
Label {
width: parent.width
wrapMode: Label.WordWrap
text: qsTr("This example demonstrates how Drawer can be used as a non-closable persistent side panel.\n\n" +
"When the application is in portrait mode, the drawer is an interactive side panel that can " +
"be swiped open from the left edge. When the application is in landscape mode, the drawer " +
"and the content are laid out side by side.\n\nThe application is currently in %1 mode.").arg(inPortrait ? qsTr("portrait") : qsTr("landscape"))
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}
I have just switched from Qt 5.12 to Qt 6.1.2 and also experiencing the same problem as yours.
I'm on :
Windows x64 (with quite old CPU and so does the graphics)
Qt 6.1.2 , targeting desktop for both MSVC and MingW
In the nutshell , the working solution is to set the Qt Quick rendering to software.
But how to do it?
Nah, you just got to choose one based on your scenario:
Solution 1: Set the rendering to software permanently at OS env level
pros: you don't have to set the env value every time you create the project.
cons: this will less portable and if you move your project to another machine you might to set it again at the OS Env level.
So, this method works best for development purpose only.
How to do it?
Simply set QT_QUICK_BACKEND to software at the system env.
On Windows:
hit Win+R and type control sysdm.cpl,,3
on Environment Variables>System Variables register New... variable named QT_QUICK_BACKEND with value software
Restart Qt creator and rebuild. This should make it work without any code modification.
Solution 2: Set the QT_QUICK_BACKEND value on the fly to software
this just the same as solution 1 , but instead of writing to OS Env we just set it on the fly the flag from the code.
This method can be used either for production or development.
How to do it?
On your main.cpp simply put qputenv("QT_QUICK_BACKEND","software"); right after the main() declaration.
save and rebuild the project
Done
Solution 3: Explicitly set scene graph renderer to software
Well I see your code and that's bit miss. Instead of setting the value to QT_QUICK_BACKEND you should set to software instead.
How to do it?
on your main.cpp do importing QQuickWindow:
#include <QQuickWindow>
next, just after the main() declaration add:
QQuickWindow::setSceneGraphBackend("software");
save and rebuild project
DONE
it should works now , the window no longer show blank canvas, the QtQuick widgets are showing :
If the software renderer is not a solution, for me in the case of QtQuick3D, setting QSG_RHI_PREFER_SOFTWARE_RENDERER=1 or QT_D3D_ADAPTER_INDEX=1 as environment variables solved the issue.
See also Quick3D fails with software render backend.

QT qml TextField is not showing cursor when loaded first time

I am developing QT cross flat form application for Ubuntu and Windows. My Question is simple but as bit new to QT, i am not able to figure it out. I have bellow code in QML. I am using QT TextField in my qml. When QML is loaded for first time i want id_username TextField should show cursor by default at initial position (0) which is not happening. When i click same TextField using mouse, cursor is visible at initial position. I am doing focus: true which is not helpful. Next, i added cursorVisible: true with that cursor is visible when qml is loaded, but i am not able to type anything(Input anything) till i click on the TextField.
TextField
{
id: id_username
objectName: "id_username"
placeholderText: qsTr("username")
color: "#000000"
font.pixelSize: 20
cursorPosition: 0
selectByMouse: true
anchors.horizontalCenter: parent.horizontalCenter
focus: true
background: Rectangle
{
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: 200
border.color: id_username.focus ? "#000000": "#36404e"
border.width: id_username.focus ? 2: 1
radius: id_instruction.height / 4
}
}
Please let me know what i am doing wrong. Is there any onLoad function from where can call forceActiveFocus()
try this in TextField:
onVisibleChanged: if(visible) id_username.forceActiveFocus()
Reference link - http://www.qtcentre.org/threads/62655-How-to-gain-focus-onto-TextEdit-in-QML

Binding loop warning on Label

I am trying the similar code to the tutorial, but I get 'QML Rectangle: Binding loop detected for property "width"' on the list view delegate. This happens only on messages where words are larger than listView.width and text wrapping happens. This happens all time. How can I fix it?
delegeate: Rectangle {
id: delegateFrame
width: Math.min(messageText.implicitWidth , listView.width)
height: messageText.implicitHeight
Label {
id: messageText
anchors.fill: parent
text: model.text
wrapMode: Label.Wrap
}
}
I am using Qt 5.8.
EDIT
Changed as Felix suggested in his answer, however it only changed the "width" word in the warning to "implictWidth".
delegeate: Rectangle {
id: delegateFrame
implicitWidth: Math.min(messageText.implicitWidth , listView.width)
implicitHeight: messageText.implicitHeight
Label {
id: messageText
width: parent.width
text: model.text
wrapMode: Label.Wrap
}
}
The cause here is probably height: messageText.implicitHeight and anchors.fill: parent. Reason:
change label height --> change delegate hight --> change anchors --> change label height ...
QML detects those loops and interrupts them. In some cases, you have to live with those, because it's the only way to archive your layout.
In your case however, there might be a solution. You can try one of the following, and see if they work:
use implicitHeight and implicitWidth in the delegate. Sometimes those remove the warnings
Instead of using anchors.fill bind the width only: width: parent.width. Since you already adjust the parents height to the child, the child does not need to change it's height to the parent
Use Layouts. For example RowLayout. They provide advanced ways of placing items and use attached properties to adjust how items are displayed

Qt Creator: Button Click Signal to make a window pop- up

I’m using Qt Creator's Qt Quick and as suggested in the tutorial I made different .qml for every button.
I want when the button is clicked to make a window pop- up. What should I write after
onClicked:
in the mouseArea.
Also how to make a second window (the pop- up one), what should I add to the project so I can design it like the main one?
I read that I have to make a class that inherits with QWidget but I need a bit more information.
A short example would be great.
as suggested in the tutorial I made different .qml for every button
Surely you mean "for every button type"!?
To launch a second window:
// Main.qml
Window {
id: win
width: 640
height: 480
Button {
text: qsTr( "Open" )
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
onClicked: {
var factory = Qt.createComponent( "Popup.qml" );
factory.createObject( win );
}
}
}
// Popup.qml
Window {
height: 240
width: 320
title: qsTr( "Popup" )
visible: true
Text {
text: qsTr( "Hello" )
anchors.centerIn: parent
}
}
I read that I have to make a class that inherits with QWidget
Do not mix QML and the Qt Widgets module unless you are extending/converting a legacy system, QML has been designed to replace Qt Widgets (at some point).

QML: How can I access the id of an Item outside of repeater?

I'm new to QML and I encounter a problem when I try to access an element from inside a repeater.
I have a repeater which generates rectangles with a mouse area each. Clicking the mouse-area should change the color of the background window root defined before, but when clicked I only get: "ReferenceError: root is not defined". If I create a rectangle with mouse-area outside of the repeater then it works. So how can I access elements outside of the repeater with a mouse-area inside the repeater? Thank you for any help. I'm really stuck with this problem right now.
import QtQuick 2.0
import QtQuick.Window 2.1
Window
id: root
visible: true
width: 600; height: 600
color: "black"
{
Grid
{
columns: 3
spacing: 20
x: 20
y: 20
Repeater{
id: repeater1
model: 3
Rectangle {
color: "White"; width: 100; height: 100;
radius: 10
MouseArea
{
anchors.fill: parent
onClicked:
{
root.color="white"
}
}
}
}
}
}
I tested your code on my windows emulator, And I couldn't even run it right; it just showed me a white blank page. Maybe it's because I am not using QQuickWindow in my main.cpp.
To run it on my emulator, I changed your Window element to Rectangle and it perfectly works fine. When I click a button, the background color gets changed to white.
First import these two headers
import QtQuick 2.0
import QtQuick.Window 2.1
Second where is the curly braces {} of your window item root