[libraries/ktextaddons] textautogeneratetext: Prepare to implement textautogeneratetextpromptmodel
Laurent Montel <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 65b7a3e2ff6ab637688ebbe3c8c569d0d86d1481 by Laurent Montel.
Committed on 27/07/2026 at 20:21.
Pushed by mlaurent into branch 'master'.
Prepare to implement textautogeneratetextpromptmodel
M +3 -0 textautogeneratetext/CMakeLists.txt
A +237 -0 textautogeneratetext/core/models/textautogeneratetextpromptmodel.cpp [License: GPL(v2.0+)]
A +135 -0 textautogeneratetext/core/models/textautogeneratetextpromptmodel.h [License: GPL(v2.0+)]
https://invent.kde.org/libraries/ktextaddons/-/commit/65b7a3e2ff6ab637688ebbe3c8c569d0d86d1481
diff --git a/textautogeneratetext/CMakeLists.txt b/textautogeneratetext/CMakeLists.txt
index 1fbc4ab8d..a2b31d90b 100644
--- a/textautogeneratetext/CMakeLists.txt
+++ b/textautogeneratetext/CMakeLists.txt
@@ -180,6 +180,8 @@ target_sources(
core/models/textautogeneratetextinstancemodel.cpp
core/models/textautogeneratetextinstancesortfilterproxymodel.h
core/models/textautogeneratetextinstancesortfilterproxymodel.cpp
+ core/models/textautogeneratetextpromptmodel.cpp
+ core/models/textautogeneratetextpromptmodel.h
core/localdatabase/textautogeneratelocaldatabaseutils.h
core/localdatabase/textautogeneratelocaldatabaseutils.cpp
core/localdatabase/textautogeneratelocaldatabaseabstract.h
@@ -557,6 +559,7 @@ ecm_generate_headers(TextAutoGenerateText_Camelcasestextautogeneratetextcoremode
TextAutoGenerateMessagesModel
TextAutoGenerateSearchMessagesModel
TextAutoGenerateChatsModel
+ TextAutoGenerateTextPromptModel
REQUIRED_HEADERS TextAutoGenerateText_textautogeneratetextcoremodels_HEADERS
PREFIX TextAutoGenerateText
RELATIVE core/models
diff --git a/textautogeneratetext/core/models/textautogeneratetextpromptmodel.cpp b/textautogeneratetext/core/models/textautogeneratetextpromptmodel.cpp
new file mode 100644
index 000000000..439802910
--- /dev/null
+++ b/textautogeneratetext/core/models/textautogeneratetextpromptmodel.cpp
@@ -0,0 +1,237 @@
+/*
+ SPDX-FileCopyrightText: 2026 Laurent Montel <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#include "textautogeneratetextpromptmodel.h"
+#include "core/textautogeneratetextplugin.h"
+#include "textautogeneratetextcore_debug.h"
+
+using namespace TextAutoGenerateText;
+TextAutoGenerateTextPromptModel::TextAutoGenerateTextPromptModel(QObject *parent)
+ : QAbstractListModel{parent}
+{
+}
+
+TextAutoGenerateTextPromptModel::~TextAutoGenerateTextPromptModel()
+{
+ qDeleteAll(mTextInstances);
+}
+
+int TextAutoGenerateTextPromptModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) {
+ return 0; // flat model
+ }
+ return mTextInstances.count();
+}
+
+bool TextAutoGenerateTextPromptModel::setData(const QModelIndex &idx, const QVariant &value, int role)
+{
+ if (!idx.isValid() || idx.row() < 0 || idx.row() >= mTextInstances.count()) {
+ qCWarning(TEXTAUTOGENERATETEXT_CORE_LOG) << "ERROR: invalid index";
+ return false;
+ }
+ const int id = idx.row();
+ const auto &instance = mTextInstances[id];
+ switch (role) {
+ case Qt::CheckStateRole:
+ case InstanceRoles::Enabled:
+ instance->setEnabled(value.toBool());
+ Q_EMIT dataChanged(idx, idx, {InstanceRoles::Enabled});
+ return true;
+ default:
+ break;
+ }
+ return QAbstractListModel::setData(idx, value, role);
+}
+
+QVariant TextAutoGenerateTextPromptModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= mTextInstances.count()) {
+ return {};
+ }
+ const auto &instance = mTextInstances[index.row()];
+ switch (role) {
+ case Qt::DisplayRole:
+ case InstanceRoles::Name:
+ return instance->displayName();
+ case InstanceRoles::PluginName:
+ return instance->pluginName();
+ case InstanceRoles::Uuid:
+ return instance->instanceUuid();
+ case InstanceRoles::PluginIdentifier:
+ return instance->pluginIdentifier();
+ case InstanceRoles::Plugin:
+ return QVariant::fromValue(instance->plugin());
+ case Qt::CheckStateRole:
+ return instance->enabled() ? Qt::Checked : Qt::Unchecked;
+ case InstanceRoles::Enabled:
+ return instance->enabled();
+ case InstanceRoles::IsDefault:
+ return !instance->instanceUuid().isEmpty() && !mCurrentinstance.isEmpty() && (instance->instanceUuid() == mCurrentinstance) && instance->enabled();
+ case InstanceRoles::TranslatedPluginName:
+ return instance->plugin()->translatedPluginName();
+ default:
+ break;
+ }
+ return {};
+}
+
+QStringList TextAutoGenerateTextPromptModel::instanceDisplayNames() const
+{
+ QStringList lstDisplayNames;
+ lstDisplayNames.reserve(mTextInstances.size());
+ for (const auto &inst : mTextInstances) {
+ lstDisplayNames.append(inst->displayName());
+ }
+ return lstDisplayNames;
+}
+
+QList<TextAutoGenerateTextInstance *> TextAutoGenerateTextPromptModel::textInstances() const
+{
+ return mTextInstances;
+}
+
+void TextAutoGenerateTextPromptModel::setTextInstances(const QList<TextAutoGenerateTextInstance *> &newTextInstances)
+{
+ beginResetModel();
+ qDeleteAll(mTextInstances);
+ mTextInstances.clear();
+ mTextInstances = newTextInstances;
+ endResetModel();
+}
+
+bool TextAutoGenerateTextPromptModel::isEmpty() const
+{
+ if (mTextInstances.isEmpty()) {
+ return true;
+ }
+ for (const auto &inst : mTextInstances) {
+ if (inst->enabled()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+QByteArray TextAutoGenerateTextPromptModel::currentInstance() const
+{
+ return mCurrentinstance;
+}
+
+void TextAutoGenerateTextPromptModel::setCurrentInstance(const QByteArray &newCurrentinstance)
+{
+ if (mCurrentinstance != newCurrentinstance) {
+ auto matchesUuid = [&](TextAutoGenerateTextInstance *instance) {
+ return instance->instanceUuid() == newCurrentinstance;
+ };
+ const auto answerIt = std::find_if(mTextInstances.constBegin(), mTextInstances.constEnd(), matchesUuid);
+
+ // Notify for old current instance row before changing state
+ auto notifyRow = [&](const QByteArray &uuid) {
+ auto it = std::find_if(mTextInstances.constBegin(), mTextInstances.constEnd(), [&](TextAutoGenerateTextInstance *instance) {
+ return instance->instanceUuid() == uuid;
+ });
+ if (it != mTextInstances.constEnd()) {
+ const int row = std::distance(mTextInstances.constBegin(), it);
+ const auto idx = index(row, 0);
+ Q_EMIT dataChanged(idx, idx, {InstanceRoles::IsDefault});
+ }
+ };
+
+ if (answerIt == mTextInstances.constEnd()) {
+ // If we don't find it. => clear it.
+ const QByteArray oldInstance = mCurrentinstance;
+ mCurrentinstance.clear();
+ notifyRow(oldInstance);
+ return;
+ }
+ notifyRow(mCurrentinstance);
+ mCurrentinstance = newCurrentinstance;
+ const int newRow = std::distance(mTextInstances.constBegin(), answerIt);
+ const auto newIdx = index(newRow, 0);
+ Q_EMIT dataChanged(newIdx, newIdx, {InstanceRoles::IsDefault});
+ }
+}
+
+TextAutoGenerateTextPlugin *TextAutoGenerateTextPromptModel::currentPlugin() const
+{
+ if (isEmpty()) {
+ return nullptr;
+ }
+ if (mCurrentinstance.isEmpty()) {
+ // Fall back to first enable instance
+ for (const auto &inst : mTextInstances) {
+ if (inst->enabled()) {
+ return inst->plugin();
+ }
+ }
+ return nullptr;
+ }
+ auto matchesUuid = [&](TextAutoGenerateTextInstance *instance) {
+ return (instance->instanceUuid() == mCurrentinstance) && instance->enabled();
+ };
+ const auto answerIt = std::find_if(mTextInstances.constBegin(), mTextInstances.constEnd(), matchesUuid);
+ if (answerIt != mTextInstances.constEnd()) {
+ return (*answerIt)->plugin();
+ }
+ // Fall back to first enable instance
+ for (const auto &inst : mTextInstances) {
+ if (inst->enabled()) {
+ return inst->plugin();
+ }
+ }
+ return nullptr;
+}
+
+void TextAutoGenerateTextPromptModel::addInstance(TextAutoGenerateTextInstance *instance)
+{
+ beginInsertRows(QModelIndex(), mTextInstances.count(), mTextInstances.count());
+ mTextInstances.append(instance);
+ endInsertRows();
+}
+
+void TextAutoGenerateTextPromptModel::removeInstance(const QByteArray &uuid)
+{
+ auto matchesUuid = [&](TextAutoGenerateTextInstance *instance) {
+ return instance->instanceUuid() == uuid;
+ };
+ const auto answerIt = std::find_if(mTextInstances.constBegin(), mTextInstances.constEnd(), matchesUuid);
+ if (answerIt != mTextInstances.constEnd()) {
+ const int i = std::distance(mTextInstances.constBegin(), answerIt);
+ beginRemoveRows(QModelIndex(), i, i);
+ auto instance = mTextInstances.at(i);
+ mTextInstances.removeAt(i);
+ endRemoveRows();
+ if (auto plugin = instance->plugin()) {
+ plugin->remove();
+ }
+ delete instance;
+ }
+}
+
+TextAutoGenerateTextPlugin *TextAutoGenerateTextPromptModel::editInstance(const QByteArray &uuid)
+{
+ auto matchesUuid = [&](TextAutoGenerateTextInstance *instance) {
+ return instance->instanceUuid() == uuid;
+ };
+ const auto answerIt = std::find_if(mTextInstances.constBegin(), mTextInstances.constEnd(), matchesUuid);
+ if (answerIt != mTextInstances.constEnd()) {
+ const int i = std::distance(mTextInstances.constBegin(), answerIt);
+ return mTextInstances.at(i)->plugin();
+ }
+ qCWarning(TEXTAUTOGENERATETEXT_CORE_LOG) << "Instance not found for uuid:" << uuid;
+ return nullptr;
+}
+
+Qt::ItemFlags TextAutoGenerateTextPromptModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid()) {
+ return Qt::NoItemFlags;
+ }
+
+ return Qt::ItemIsUserCheckable | QAbstractListModel::flags(index);
+}
+
+#include "moc_textautogeneratetextpromptmodel.cpp"
diff --git a/textautogeneratetext/core/models/textautogeneratetextpromptmodel.h b/textautogeneratetext/core/models/textautogeneratetextpromptmodel.h
new file mode 100644
index 000000000..0db0ab382
--- /dev/null
+++ b/textautogeneratetext/core/models/textautogeneratetextpromptmodel.h
@@ -0,0 +1,135 @@
+/*
+ SPDX-FileCopyrightText: 2026 Laurent Montel <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#pragma once
+
+#include "textautogeneratetext_export.h"
+#include <QAbstractListModel>
+#include <TextAutoGenerateText/TextAutoGenerateTextInstance>
+namespace TextAutoGenerateText
+{
+/*!
+ * \class TextAutoGenerateText::TextAutoGenerateTextPromptModel
+ * \brief The TextAutoGenerateTextPromptModel class
+ * \author Laurent Montel <[email protected]>
+ * \inmodule TextAutoGenerateText
+ * \inheaderfile TextAutoGenerateText/TextAutoGenerateTextPromptModel
+ */
+class TEXTAUTOGENERATETEXT_EXPORT TextAutoGenerateTextPromptModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum InstanceRoles : uint16_t {
+ Name = Qt::UserRole + 1,
+ PluginName,
+ PluginIdentifier,
+ Uuid,
+ Plugin,
+ Enabled,
+ IsDefault,
+ TranslatedPluginName,
+ };
+ /*!
+ * Constructs a new TextAutoGenerateTextPromptModel object.
+ * \param parent The parent QObject
+ */
+ explicit TextAutoGenerateTextPromptModel(QObject *parent = nullptr);
+ /*!
+ * Destroys the TextAutoGenerateTextPromptModel object.
+ */
+ ~TextAutoGenerateTextPromptModel() override;
+
+ /*!
+ * Returns the number of rows in the model.
+ * \return The row count
+ */
+ [[nodiscard]] int rowCount(const QModelIndex & = {}) const override;
+ /*!
+ * Returns the data at the given index for the specified role.
+ * \param index The model index
+ * \param role The data role
+ * \return The data value
+ */
+ [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
+ /*!
+ * Sets the data at the given index for the specified role.
+ * \param index The model index
+ * \param value The value to set
+ * \param role The data role
+ * \return true if successful, false otherwise
+ */
+ [[nodiscard]] bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ /*!
+ * Returns the flags for the given index.
+ * \param index The model index
+ * \return The item flags
+ */
+ [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;
+
+ /*!
+ * Returns the list of text instances in the model.
+ * \return The list of TextAutoGenerateTextInstance pointers
+ */
+ [[nodiscard]] QList<TextAutoGenerateTextInstance *> textInstances() const;
+ /*!
+ * Sets the list of text instances in the model.
+ * \param newTextInstances The instances to set
+ */
+ void setTextInstances(const QList<TextAutoGenerateTextInstance *> &newTextInstances);
+
+ /*!
+ * Adds an instance to the model.
+ * \param instance The instance to add
+ */
+ void addInstance(TextAutoGenerateTextInstance *instance);
+
+ /*!
+ * Removes an instance from the model by UUID.
+ * Calls plugin->remove() and deletes the instance.
+ * \param uuid The UUID of the instance to remove
+ */
+ void removeInstance(const QByteArray &uuid);
+
+ /*!
+ * Gets the plugin for editing an instance by UUID.
+ * \param uuid The UUID of the instance to edit
+ * \return The plugin from the instance
+ */
+ [[nodiscard]] TextAutoGenerateTextPlugin *editInstance(const QByteArray &uuid);
+
+ /*!
+ * Returns whether the model is empty.
+ * \return true if empty, false otherwise
+ */
+ [[nodiscard]] bool isEmpty() const;
+
+ /*!
+ * Returns the UUID of the current instance.
+ * \return The current instance UUID
+ */
+ [[nodiscard]] QByteArray currentInstance() const;
+ /*!
+ * Sets the current instance by UUID.
+ * \param newCurrentinstance The UUID to set as current
+ */
+ void setCurrentInstance(const QByteArray &newCurrentinstance);
+
+ /*!
+ * Returns the plugin of the current instance.
+ * \return The plugin pointer or nullptr
+ */
+ [[nodiscard]] TextAutoGenerateTextPlugin *currentPlugin() const;
+
+ /*!
+ * Returns a list of display names for all instances.
+ * \return List of instance display names
+ */
+ [[nodiscard]] QStringList instanceDisplayNames() const;
+
+private:
+ QList<TextAutoGenerateTextInstance *> mTextInstances;
+ QByteArray mCurrentinstance;
+};
+}