diff --git a/gpt4all-chat/CMakeLists.txt b/gpt4all-chat/CMakeLists.txt index 6c96330b..51b9d517 100644 --- a/gpt4all-chat/CMakeLists.txt +++ b/gpt4all-chat/CMakeLists.txt @@ -94,6 +94,7 @@ qt_add_qml_module(chat qml/Theme.qml qml/MyButton.qml qml/MyComboBox.qml + qml/MyDirectoryField.qml qml/MyTextField.qml qml/MyCheckBox.qml qml/MyBusyIndicator.qml diff --git a/gpt4all-chat/llm.cpp b/gpt4all-chat/llm.cpp index 19fc9f77..41478adc 100644 --- a/gpt4all-chat/llm.cpp +++ b/gpt4all-chat/llm.cpp @@ -63,6 +63,22 @@ bool LLM::checkForUpdates() const return QProcess::startDetached(fileName); } +bool LLM::directoryExists(const QString &path) const +{ + const QUrl url(path); + const QString localFilePath = url.isLocalFile() ? url.toLocalFile() : path; + const QFileInfo info(localFilePath); + return info.exists() && info.isDir(); +} + +bool LLM::fileExists(const QString &path) const +{ + const QUrl url(path); + const QString localFilePath = url.isLocalFile() ? url.toLocalFile() : path; + const QFileInfo info(localFilePath); + return info.exists() && info.isFile(); +} + int32_t LLM::threadCount() const { return m_threadCount; diff --git a/gpt4all-chat/llm.h b/gpt4all-chat/llm.h index 3674406b..d0e88bc9 100644 --- a/gpt4all-chat/llm.h +++ b/gpt4all-chat/llm.h @@ -25,6 +25,8 @@ public: bool compatHardware() const { return m_compatHardware; } Q_INVOKABLE bool checkForUpdates() const; + Q_INVOKABLE bool directoryExists(const QString &path) const; + Q_INVOKABLE bool fileExists(const QString &path) const; Q_SIGNALS: void chatListModelChanged(); diff --git a/gpt4all-chat/qml/LocalDocs.qml b/gpt4all-chat/qml/LocalDocs.qml index 699293f7..487601ae 100644 --- a/gpt4all-chat/qml/LocalDocs.qml +++ b/gpt4all-chat/qml/LocalDocs.qml @@ -9,8 +9,8 @@ import localdocs Item { id: root - property string collection: "" - property string folder_path: "" + property alias collection: collection.text + property alias folder_path: folderEdit.text property int defaultChunkSize: 256 property int defaultRetrievalSize: 3 @@ -60,24 +60,19 @@ Item { placeholderTextColor: theme.mutedTextColor ToolTip.text: qsTr("Name of the collection to add (Required)") ToolTip.visible: hovered - onEditingFinished: { - root.collection = text - } Accessible.role: Accessible.EditableText Accessible.name: collection.text Accessible.description: ToolTip.text } - MyTextField { - id: folderLabel + MyDirectoryField { + id: folderEdit anchors.left: collection.right anchors.leftMargin: 10 anchors.right: browseButton.left anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter text: root.folder_path - readOnly: true - color: theme.textColor placeholderText: qsTr("Folder path...") placeholderTextColor: theme.mutedTextColor ToolTip.text: qsTr("Folder path to documents (Required)") @@ -100,7 +95,7 @@ Item { text: qsTr("Add") anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - enabled: root.collection !== "" && root.folder_path != "" + enabled: root.collection !== "" && root.folder_path !== "" && folderEdit.isValid Accessible.role: Accessible.Button Accessible.name: text Accessible.description: qsTr("Add button") diff --git a/gpt4all-chat/qml/ModelDownloaderDialog.qml b/gpt4all-chat/qml/ModelDownloaderDialog.qml index e3bd048e..ebc69063 100644 --- a/gpt4all-chat/qml/ModelDownloaderDialog.qml +++ b/gpt4all-chat/qml/ModelDownloaderDialog.qml @@ -386,7 +386,8 @@ Dialog { title: "Please choose a directory" currentFolder: "file://" + Download.downloadLocalModelsPath onAccepted: { - Download.downloadLocalModelsPath = selectedFolder + modelPathDisplayField.text = selectedFolder + Download.downloadLocalModelsPath = modelPathDisplayField.text settings.modelPath = Download.downloadLocalModelsPath settings.sync() } @@ -398,20 +399,23 @@ Dialog { Layout.row: 1 Layout.column: 0 } - TextField { - id: modelPathDisplayLabel + MyDirectoryField { + id: modelPathDisplayField text: Download.downloadLocalModelsPath - readOnly: true - color: theme.textColor Layout.fillWidth: true ToolTip.text: qsTr("Path where model files will be downloaded to") ToolTip.visible: hovered Accessible.role: Accessible.ToolTip - Accessible.name: modelPathDisplayLabel.text + Accessible.name: modelPathDisplayField.text Accessible.description: ToolTip.text - background: Rectangle { - color: theme.backgroundLighter - radius: 10 + onEditingFinished: { + if (isValid) { + Download.downloadLocalModelsPath = modelPathDisplayField.text + settings.modelPath = Download.downloadLocalModelsPath + settings.sync() + } else { + text = Download.downloadLocalModelsPath + } } } MyButton { diff --git a/gpt4all-chat/qml/MyDirectoryField.qml b/gpt4all-chat/qml/MyDirectoryField.qml new file mode 100644 index 00000000..e5dbe1b0 --- /dev/null +++ b/gpt4all-chat/qml/MyDirectoryField.qml @@ -0,0 +1,17 @@ +import QtCore +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import llm + +TextField { + id: myDirectoryField + padding: 10 + property bool isValid: LLM.directoryExists(text) + color: text === "" || isValid ? theme.textColor : theme.textErrorColor + background: Rectangle { + implicitWidth: 150 + color: theme.backgroundLighter + radius: 10 + } +} diff --git a/gpt4all-chat/qml/SettingsDialog.qml b/gpt4all-chat/qml/SettingsDialog.qml index f6d9f79b..82125d8a 100644 --- a/gpt4all-chat/qml/SettingsDialog.qml +++ b/gpt4all-chat/qml/SettingsDialog.qml @@ -651,7 +651,8 @@ Dialog { title: "Please choose a directory" currentFolder: "file://" + Download.downloadLocalModelsPath onAccepted: { - Download.downloadLocalModelsPath = selectedFolder + modelPathDisplayField.text = selectedFolder + Download.downloadLocalModelsPath = modelPathDisplayField.text settings.modelPath = Download.downloadLocalModelsPath settings.sync() } @@ -663,24 +664,26 @@ Dialog { Layout.row: 2 Layout.column: 0 } - TextField { - id: modelPathDisplayLabel + MyDirectoryField { + id: modelPathDisplayField text: Download.downloadLocalModelsPath - readOnly: true - color: theme.textColor implicitWidth: 300 - padding: 10 Layout.row: 2 Layout.column: 1 Layout.fillWidth: true ToolTip.text: qsTr("Path where model files will be downloaded to") ToolTip.visible: hovered Accessible.role: Accessible.ToolTip - Accessible.name: modelPathDisplayLabel.text + Accessible.name: modelPathDisplayField.text Accessible.description: ToolTip.text - background: Rectangle { - color: theme.backgroundLighter - radius: 10 + onEditingFinished: { + if (isValid) { + Download.downloadLocalModelsPath = modelPathDisplayField.text + settings.modelPath = Download.downloadLocalModelsPath + settings.sync() + } else { + text = Download.downloadLocalModelsPath + } } } MyButton {