refactor: UI for opening content from chat (#318)

* refactor: Changed options to opening images from chat
* refactor: Add customizable tooltip
This commit is contained in:
Petr Mironychev
2026-02-25 07:49:37 +01:00
committed by GitHub
parent 3de1619bf0
commit 2ba58a403f
5 changed files with 118 additions and 49 deletions

View File

@ -117,8 +117,10 @@ QVariant ChatModel::data(const QModelIndex &index, int role) const
QString contentFolder = QDir(dirPath).filePath(baseName + "_content"); QString contentFolder = QDir(dirPath).filePath(baseName + "_content");
QString fullPath = QDir(contentFolder).filePath(image.storedPath); QString fullPath = QDir(contentFolder).filePath(image.storedPath);
imageMap["imageUrl"] = QUrl::fromLocalFile(fullPath).toString(); imageMap["imageUrl"] = QUrl::fromLocalFile(fullPath).toString();
imageMap["filePath"] = fullPath;
} else { } else {
imageMap["imageUrl"] = QString(); imageMap["imageUrl"] = QString();
imageMap["filePath"] = QString();
} }
imagesList.append(imageMap); imagesList.append(imageMap);

View File

@ -181,9 +181,12 @@ Rectangle {
onClicked: function() { onClicked: function() {
root.resetChatToMessage(root.messageIndex) root.resetChatToMessage(root.messageIndex)
} }
ToolTip.visible: hovered
ToolTip.text: qsTr("Reset chat to this message and edit") QoAToolTip {
ToolTip.delay: 500 visible: stopButtonId.hovered
text: qsTr("Reset chat to this message and edit")
delay: 500
}
} }
component TextComponent : TextBlock { component TextComponent : TextBlock {
@ -267,33 +270,21 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => { onClicked: (mouse) => {
if (mouse.button === Qt.LeftButton) { if (mouse.modifiers & Qt.ShiftModifier) {
fileItem.openFileInExternalEditor()
} else {
fileItem.openFileInEditor() fileItem.openFileInEditor()
} else if (mouse.button === Qt.RightButton) {
attachmentContextMenu.popup()
} }
} }
ToolTip.visible: containsMouse QoAToolTip {
ToolTip.text: qsTr("Left click: Open in Qt Creator\nRight click: More options") visible: attachFileMouseArea.containsMouse
ToolTip.delay: 500 text: qsTr("Click: Open in Qt Creator\nShift+Click: Open in System Editor")
} delay: 500
Menu {
id: attachmentContextMenu
MenuItem {
text: qsTr("Open in Qt Creator")
onTriggered: fileItem.openFileInEditor()
}
MenuItem {
text: qsTr("Open in System Editor")
onTriggered: fileItem.openFileInExternalEditor()
} }
} }
} }
@ -315,7 +306,7 @@ Rectangle {
FileItem { FileItem {
id: imageFileItem id: imageFileItem
filePath: itemData.imageUrl ? itemData.imageUrl.toString().replace("file://", "") : "" filePath: itemData.filePath || ""
} }
ColumnLayout { ColumnLayout {
@ -371,33 +362,21 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => { onClicked: (mouse) => {
if (mouse.button === Qt.LeftButton) { if (mouse.modifiers & Qt.ShiftModifier) {
imageFileItem.openFileInExternalEditor()
} else {
imageFileItem.openFileInEditor() imageFileItem.openFileInEditor()
} else if (mouse.button === Qt.RightButton) {
imageContextMenu.popup()
} }
} }
ToolTip.visible: containsMouse QoAToolTip {
ToolTip.text: qsTr("Left click: Open in System\nRight click: More options") visible: imageMouseArea.containsMouse
ToolTip.delay: 500 text: qsTr("Click: Open in Qt Creator\nShift+Click: Open in System Editor")
} delay: 500
Menu {
id: imageContextMenu
MenuItem {
text: qsTr("Open in Qt Creator")
onTriggered: imageFileItem.openFileInEditor()
}
MenuItem {
text: qsTr("Open in System Viewer")
onTriggered: imageFileItem.openFileInExternalEditor()
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2024-2025 Petr Mironychev * Copyright (C) 2024-2026 Petr Mironychev
* *
* This file is part of QodeAssist. * This file is part of QodeAssist.
* *
@ -21,6 +21,7 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import ChatView import ChatView
import UIControls
Flow { Flow {
id: root id: root
@ -78,9 +79,11 @@ Flow {
} }
} }
ToolTip.visible: containsMouse QoAToolTip {
ToolTip.delay: 500 visible: mouse.containsMouse
ToolTip.text: "Click: Open in Qt Creator\nShift+Click: Open in external editor\nCtrl+Click / Middle Click: Remove" delay: 500
text: "Click: Open in Qt Creator\nShift+Click: Open in external editor\nCtrl+Click / Middle Click: Remove"
}
} }
Menu { Menu {

View File

@ -13,11 +13,12 @@ qt_add_qml_module(QodeAssistUIControls
qml/QoATextSlider.qml qml/QoATextSlider.qml
qml/QoAComboBox.qml qml/QoAComboBox.qml
qml/FadeListItemAnimation.qml qml/FadeListItemAnimation.qml
qml/QoASeparator.qml
qml/QoAToolTip.qml
RESOURCES RESOURCES
icons/dropdown-arrow-light.svg icons/dropdown-arrow-light.svg
icons/dropdown-arrow-dark.svg icons/dropdown-arrow-dark.svg
QML_FILES qml/QoASeparator.qml
) )
target_link_libraries(QodeAssistUIControls target_link_libraries(QodeAssistUIControls

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2026 Petr Mironychev
*
* This file is part of QodeAssist.
*
* QodeAssist is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QodeAssist is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
ToolTip {
id: root
padding: 8
contentItem: Text {
text: root.text
font: root.font
color: palette.toolTipText
wrapMode: Text.Wrap
}
background: Item {
implicitWidth: bg.implicitWidth
implicitHeight: bg.implicitHeight
Rectangle {
anchors.fill: bg
anchors.margins: -2
color: Qt.rgba(palette.shadow.r, palette.shadow.g, palette.shadow.b, 0.12)
radius: 8
z: -2
}
Rectangle {
anchors.fill: bg
anchors.margins: -1
color: Qt.rgba(palette.shadow.r, palette.shadow.g, palette.shadow.b, 0.08)
radius: 7
z: -1
}
Rectangle {
id: bg
anchors.fill: parent
color: palette.toolTipBase
border.color: Qt.darker(palette.toolTipBase, 1.2)
border.width: 1
radius: 6
}
}
enter: Transition {
NumberAnimation {
property: "opacity"
from: 0.0
to: 1.0
duration: 150
easing.type: Easing.OutQuad
}
}
exit: Transition {
NumberAnimation {
property: "opacity"
from: 1.0
to: 0.0
duration: 100
easing.type: Easing.InQuad
}
}
}