Loading editor/qml/AiTab.qml +109 −0 Original line number Diff line number Diff line import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Dialogs Item { id: aiTab property bool isBusy: false ListModel { id: attachedFilesModel } FileDialog { id: attachFileDialog title: qsTr("Dateien anhängen") fileMode: FileDialog.OpenFiles nameFilters: [ qsTr("Alle Dateien (*)"), qsTr("Textdateien (*.txt *.md *.csv *.json *.xml *.yaml *.yml)"), qsTr("Quellcode (*.cpp *.h *.js *.ts *.css *.html *.qml *.py)"), qsTr("Dokumente (*.txt *.md *.rst)") ] onAccepted: { for (var i = 0; i < selectedFiles.length; i++) { var filePath = selectedFiles[i].toString() if (filePath.startsWith("file://")) filePath = filePath.substring(7) // Avoid duplicates var isDuplicate = false for (var j = 0; j < attachedFilesModel.count; j++) { if (attachedFilesModel.get(j).filePath === filePath) { isDuplicate = true break } } if (!isDuplicate) { var parts = filePath.split("/") attachedFilesModel.append({ "filePath": filePath, "fileName": parts[parts.length - 1] }) } } } } ColumnLayout { anchors.fill: parent anchors.margins: 12 Loading Loading @@ -48,6 +87,67 @@ Item { checked: true } // --- Dateianhänge --- RowLayout { Layout.fillWidth: true Label { text: qsTr("Dateianhänge:") font.bold: true Layout.fillWidth: true } Button { text: qsTr("+ Dateien") onClicked: attachFileDialog.open() } Button { text: qsTr("Alle entfernen") visible: attachedFilesModel.count > 0 onClicked: attachedFilesModel.clear() } } ListView { id: attachedFilesList Layout.fillWidth: true Layout.preferredHeight: Math.min(attachedFilesModel.count * 28, 112) visible: attachedFilesModel.count > 0 model: attachedFilesModel clip: true delegate: RowLayout { width: attachedFilesList.width spacing: 4 Label { text: model.fileName elide: Text.ElideMiddle Layout.fillWidth: true color: Theme.textPrimary font.pixelSize: 12 ToolTip.text: model.filePath ToolTip.visible: fileMouseArea.containsMouse MouseArea { id: fileMouseArea anchors.fill: parent hoverEnabled: true } } Button { text: "✕" flat: true implicitWidth: 24 implicitHeight: 24 onClicked: attachedFilesModel.remove(index) } } } Label { text: qsTr("Keine Dateien angehängt") visible: attachedFilesModel.count === 0 color: Theme.textSecondary font.pixelSize: 11 } RowLayout { Layout.fillWidth: true Loading Loading @@ -121,6 +221,15 @@ Item { if(s2) req += "\nCSS (mystyle.css):\n" + s2 } // Angehängte Dateien einbinden for (var i = 0; i < attachedFilesModel.count; i++) { var entry = attachedFilesModel.get(i) var content = localApi.readTextFile(entry.filePath) if (content) { req += "\n\n=== Attached File: " + entry.fileName + " ===\n" + content } } return localApi.generateAiPrompt(req); } Loading Loading
editor/qml/AiTab.qml +109 −0 Original line number Diff line number Diff line import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Dialogs Item { id: aiTab property bool isBusy: false ListModel { id: attachedFilesModel } FileDialog { id: attachFileDialog title: qsTr("Dateien anhängen") fileMode: FileDialog.OpenFiles nameFilters: [ qsTr("Alle Dateien (*)"), qsTr("Textdateien (*.txt *.md *.csv *.json *.xml *.yaml *.yml)"), qsTr("Quellcode (*.cpp *.h *.js *.ts *.css *.html *.qml *.py)"), qsTr("Dokumente (*.txt *.md *.rst)") ] onAccepted: { for (var i = 0; i < selectedFiles.length; i++) { var filePath = selectedFiles[i].toString() if (filePath.startsWith("file://")) filePath = filePath.substring(7) // Avoid duplicates var isDuplicate = false for (var j = 0; j < attachedFilesModel.count; j++) { if (attachedFilesModel.get(j).filePath === filePath) { isDuplicate = true break } } if (!isDuplicate) { var parts = filePath.split("/") attachedFilesModel.append({ "filePath": filePath, "fileName": parts[parts.length - 1] }) } } } } ColumnLayout { anchors.fill: parent anchors.margins: 12 Loading Loading @@ -48,6 +87,67 @@ Item { checked: true } // --- Dateianhänge --- RowLayout { Layout.fillWidth: true Label { text: qsTr("Dateianhänge:") font.bold: true Layout.fillWidth: true } Button { text: qsTr("+ Dateien") onClicked: attachFileDialog.open() } Button { text: qsTr("Alle entfernen") visible: attachedFilesModel.count > 0 onClicked: attachedFilesModel.clear() } } ListView { id: attachedFilesList Layout.fillWidth: true Layout.preferredHeight: Math.min(attachedFilesModel.count * 28, 112) visible: attachedFilesModel.count > 0 model: attachedFilesModel clip: true delegate: RowLayout { width: attachedFilesList.width spacing: 4 Label { text: model.fileName elide: Text.ElideMiddle Layout.fillWidth: true color: Theme.textPrimary font.pixelSize: 12 ToolTip.text: model.filePath ToolTip.visible: fileMouseArea.containsMouse MouseArea { id: fileMouseArea anchors.fill: parent hoverEnabled: true } } Button { text: "✕" flat: true implicitWidth: 24 implicitHeight: 24 onClicked: attachedFilesModel.remove(index) } } } Label { text: qsTr("Keine Dateien angehängt") visible: attachedFilesModel.count === 0 color: Theme.textSecondary font.pixelSize: 11 } RowLayout { Layout.fillWidth: true Loading Loading @@ -121,6 +221,15 @@ Item { if(s2) req += "\nCSS (mystyle.css):\n" + s2 } // Angehängte Dateien einbinden for (var i = 0; i < attachedFilesModel.count; i++) { var entry = attachedFilesModel.get(i) var content = localApi.readTextFile(entry.filePath) if (content) { req += "\n\n=== Attached File: " + entry.fileName + " ===\n" + content } } return localApi.generateAiPrompt(req); } Loading