[libraries/ktextaddons] textautogeneratetext: Add custom openai instance (it needed by instance which use custom url

Laurent Montel <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit d30d54043735a368addbf380958fdf78f18552b5 by Laurent Montel.
Committed on 07/08/2026 at 17:59.
Pushed by mlaurent into branch 'master'.

Add custom openai instance (it needed by instance which use custom url

and support openai

M  +6    -0    textautogeneratetext/plugins/genericnetworkplugin/autotests/genericnetworkserverinfotest.cpp
M  +10   -1    textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.cpp
M  +4    -1    textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.h
M  +7    -0    textautogeneratetext/plugins/genericnetworkplugin/genericnetworknetworkpluginconfigurewidget.cpp
M  +23   -0    textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.cpp
M  +1    -0    textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.h
M  +12   -0    textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.cpp
M  +4    -0    textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.h
M  +1    -0    textautogeneratetext/plugins/plugincommon/plugincommonsettings.cpp
M  +30   -10   textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.cpp
M  +20   -0    textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.h

https://invent.kde.org/libraries/ktextaddons/-/commit/d30d54043735a368addbf380958fdf78f18552b5

diff --git a/textautogeneratetext/plugins/genericnetworkplugin/autotests/genericnetworkserverinfotest.cpp b/textautogeneratetext/plugins/genericnetworkplugin/autotests/genericnetworkserverinfotest.cpp
index 47a8bfc6d..b3b3cf40f 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/autotests/genericnetworkserverinfotest.cpp
+++ b/textautogeneratetext/plugins/genericnetworkplugin/autotests/genericnetworkserverinfotest.cpp
@@ -39,6 +39,7 @@ void GenericNetworkServerInfoTest::shouldConvertPluginNetworkTypeFromString()
     QCOMPARE(info.pluginNetworkTypeFromString(u"atlascloudai"_s), GenericNetworkManager::PluginNetworkType::AtlasCloud);
     QCOMPARE(info.pluginNetworkTypeFromString(u"gemini"_s), GenericNetworkManager::PluginNetworkType::Gemini);
     QCOMPARE(info.pluginNetworkTypeFromString(u"orcarouterai"_s), GenericNetworkManager::PluginNetworkType::OrcaRouterAI);
+    QCOMPARE(info.pluginNetworkTypeFromString(u"openaigeneric"_s), GenericNetworkManager::PluginNetworkType::OpenAIGeneric);
 }
 
 void GenericNetworkServerInfoTest::shouldCheckApiUrl()
@@ -64,6 +65,7 @@ void GenericNetworkServerInfoTest::shouldCheckApiUrl()
     QCOMPARE(info.apiUrl(GenericNetworkManager::PluginNetworkType::AtlasCloud), u"https://api.atlascloud.ai/v1/"_s);
     QCOMPARE(info.apiUrl(GenericNetworkManager::PluginNetworkType::OrcaRouterAI), u"https://api.orcarouter.ai/v1/"_s);
     QCOMPARE(info.apiUrl(GenericNetworkManager::PluginNetworkType::Gemini), u"https://generativelanguage.googleapis.com/v1beta/openai/"_s);
+    QCOMPARE(info.apiUrl(GenericNetworkManager::PluginNetworkType::OpenAIGeneric), QString());
 }
 
 void GenericNetworkServerInfoTest::shouldChatCompletionPath()
@@ -89,6 +91,7 @@ void GenericNetworkServerInfoTest::shouldChatCompletionPath()
     QCOMPARE(info.chatCompletionPath(GenericNetworkManager::PluginNetworkType::AtlasCloud), u"chat/completions"_s);
     QCOMPARE(info.chatCompletionPath(GenericNetworkManager::PluginNetworkType::Gemini), u"chat/completions"_s);
     QCOMPARE(info.chatCompletionPath(GenericNetworkManager::PluginNetworkType::OrcaRouterAI), u"chat/completions"_s);
+    QCOMPARE(info.chatCompletionPath(GenericNetworkManager::PluginNetworkType::OpenRouterAI), u"chat/completions"_s);
 }
 
 void GenericNetworkServerInfoTest::shouldResponsesPath()
@@ -114,6 +117,7 @@ void GenericNetworkServerInfoTest::shouldResponsesPath()
     QCOMPARE(info.responsesPath(GenericNetworkManager::PluginNetworkType::AtlasCloud), u"responses"_s);
     QCOMPARE(info.responsesPath(GenericNetworkManager::PluginNetworkType::Gemini), u"responses"_s);
     QCOMPARE(info.responsesPath(GenericNetworkManager::PluginNetworkType::OrcaRouterAI), u"responses"_s);
+    QCOMPARE(info.responsesPath(GenericNetworkManager::PluginNetworkType::OpenAIGeneric), u"responses"_s);
 }
 
 void GenericNetworkServerInfoTest::shouldDefinePluginName()
@@ -139,6 +143,7 @@ void GenericNetworkServerInfoTest::shouldDefinePluginName()
     QCOMPARE(info.pluginName(GenericNetworkManager::PluginNetworkType::AtlasCloud), u"atlascloudai"_s);
     QCOMPARE(info.pluginName(GenericNetworkManager::PluginNetworkType::Gemini), u"gemini"_s);
     QCOMPARE(info.pluginName(GenericNetworkManager::PluginNetworkType::OrcaRouterAI), u"orcarouterai"_s);
+    QCOMPARE(info.pluginName(GenericNetworkManager::PluginNetworkType::OpenAIGeneric), u"openaigeneric"_s);
 }
 
 void GenericNetworkServerInfoTest::shouldDefineLimitations()
@@ -164,6 +169,7 @@ void GenericNetworkServerInfoTest::shouldDefineLimitations()
     QCOMPARE(info.limitations(GenericNetworkManager::PluginNetworkType::AtlasCloud), GenericNetworkManager::Limitation::None);
     QCOMPARE(info.limitations(GenericNetworkManager::PluginNetworkType::Gemini), GenericNetworkManager::Limitation::None);
     QCOMPARE(info.limitations(GenericNetworkManager::PluginNetworkType::OrcaRouterAI), GenericNetworkManager::Limitation::None);
+    QCOMPARE(info.limitations(GenericNetworkManager::PluginNetworkType::OpenAIGeneric), GenericNetworkManager::Limitation::None);
 }
 
 #include "moc_genericnetworkserverinfotest.cpp"
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.cpp b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.cpp
index bd7911c15..d7df79250 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.cpp
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.cpp
@@ -35,6 +35,7 @@ void GenericNetworkManager::loadModels()
     if (mCheckConnect) {
         disconnect(mCheckConnect);
     }
+    qDebug() << " apiUrl() ********* " << apiUrl();
     QNetworkRequest req{QUrl::fromUserInput(apiUrl() + u"models"_s)};
     req.setHeader(QNetworkRequest::ContentTypeHeader, u"application/json"_s);
     if (mApiKey.isEmpty()) {
@@ -206,9 +207,17 @@ QString GenericNetworkManager::chatPath() const
     return mServerInfo->chatCompletionPath(mPluginNetworkType);
 }
 
+bool GenericNetworkManager::hasCustomUrl() const
+{
+    return mServerInfo->hasCustomUrl(mPluginNetworkType);
+}
+
 QString GenericNetworkManager::apiUrl() const
 {
-    return mServerInfo->apiUrl(mPluginNetworkType);
+    if (!mServerInfo->hasCustomUrl(mPluginNetworkType)) {
+        return mServerInfo->apiUrl(mPluginNetworkType);
+    }
+    return mGenericNetworkSettings->customUrl();
 }
 
 QString GenericNetworkManager::description() const
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.h b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.h
index ffeedc389..c77b8a0d5 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.h
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkmanager.h
@@ -37,7 +37,8 @@ public:
         AtlasCloud = 18,
         Gemini = 19,
         KimiAI = 20,
-        LastElement = KimiAI,
+        OpenAIGeneric = 21,
+        LastElement = OpenAIGeneric,
     };
 
     enum Limitation : uint8_t {
@@ -87,6 +88,8 @@ public:
     [[nodiscard]] bool hasSystemMessageSupport() const;
     [[nodiscard]] bool hasTextOnlySupport() const;
 
+    [[nodiscard]] bool hasCustomUrl() const;
+
 private:
     [[nodiscard]] TEXTAUTOGENERATEGENERICNETWORK_NO_EXPORT QString chatPath() const;
     [[nodiscard]] bool hasCategorySupport(const QString &currentModel, GenericNetworkModelAvailableInfo::Capability capacity) const;
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworknetworkpluginconfigurewidget.cpp b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworknetworkpluginconfigurewidget.cpp
index cbbd42b97..86edecd82 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworknetworkpluginconfigurewidget.cpp
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworknetworkpluginconfigurewidget.cpp
@@ -15,6 +15,7 @@ GenericNetworkNetworkPluginConfigureWidget::GenericNetworkNetworkPluginConfigure
     mManager->loadModels();
     setWebSiteUrl(mManager->webSite());
     setDescription(mManager->description());
+    setHasCustomUrl(mManager->hasCustomUrl());
 }
 
 GenericNetworkNetworkPluginConfigureWidget::~GenericNetworkNetworkPluginConfigureWidget() = default;
@@ -26,6 +27,9 @@ void GenericNetworkNetworkPluginConfigureWidget::loadSettings()
     setTemperature(mManager->genericNetworkSettings()->temperature());
     setSeed(mManager->genericNetworkSettings()->seed());
     setApiKey(mManager->apiKey());
+    if (mManager->hasCustomUrl()) {
+        setCustomUrl(mManager->genericNetworkSettings()->customUrl());
+    }
 }
 
 void GenericNetworkNetworkPluginConfigureWidget::saveSettings()
@@ -34,6 +38,9 @@ void GenericNetworkNetworkPluginConfigureWidget::saveSettings()
     mManager->genericNetworkSettings()->setTemperature(temperature());
     mManager->genericNetworkSettings()->setMaxTokens(maxTokens());
     mManager->genericNetworkSettings()->setSeed(seed());
+    if (mManager->hasCustomUrl()) {
+        mManager->genericNetworkSettings()->setCustomUrl(customUrl());
+    }
     mManager->setApiKey(apiKey());
 }
 
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.cpp b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.cpp
index 4637d7bb4..f8232c01b 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.cpp
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.cpp
@@ -60,6 +60,8 @@ QString GenericNetworkServerInfo::translatedName(GenericNetworkManager::PluginNe
         return i18n("AtlasCloud OpenAI-compatible API");
     case GenericNetworkManager::PluginNetworkType::Gemini:
         return i18n("Google Gemini");
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
+        return i18n("API OpenAI");
     }
     return {};
 }
@@ -90,6 +92,7 @@ QString GenericNetworkServerInfo::responsesPath(GenericNetworkManager::PluginNet
     case GenericNetworkManager::PluginNetworkType::AtlasCloud:
     case GenericNetworkManager::PluginNetworkType::Gemini:
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
         return u"responses"_s;
     }
     return {};
@@ -121,6 +124,7 @@ QString GenericNetworkServerInfo::chatCompletionPath(GenericNetworkManager::Plug
     case GenericNetworkManager::PluginNetworkType::AtlasCloud:
     case GenericNetworkManager::PluginNetworkType::Gemini:
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
         return u"chat/completions"_s;
     }
     return {};
@@ -172,6 +176,8 @@ QString GenericNetworkServerInfo::webSite(GenericNetworkManager::PluginNetworkTy
         return u"https://gemini.google.com"_s;
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
         return u"https://www.orcarouter.ai/"_s;
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
+        return {};
     }
     return {};
 }
@@ -222,6 +228,8 @@ QString GenericNetworkServerInfo::apiUrl(GenericNetworkManager::PluginNetworkTyp
         return u"https://api.orcarouter.ai/v1/"_s;
     case GenericNetworkManager::PluginNetworkType::Gemini:
         return u"https://generativelanguage.googleapis.com/v1beta/openai/"_s;
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
+        return {};
     }
     return {};
 }
@@ -267,6 +275,8 @@ QString GenericNetworkServerInfo::description(GenericNetworkManager::PluginNetwo
         return i18n("AtlasCloud OpenAI-compatible API");
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
         return i18n("Orca Router OpenAI-compatible API");
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
+        return i18n("API Open AI (custom)");
     }
     return {};
 }
@@ -317,6 +327,8 @@ QString GenericNetworkServerInfo::pluginName(GenericNetworkManager::PluginNetwor
         return u"gemini"_s;
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
         return u"orcarouterai"_s;
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
+        return u"openaigeneric"_s;
     }
     return {};
 }
@@ -363,6 +375,8 @@ GenericNetworkManager::PluginNetworkType GenericNetworkServerInfo::pluginNetwork
         return GenericNetworkManager::PluginNetworkType::Gemini;
     } else if (str == QLatin1StringView("orcarouterai")) {
         return GenericNetworkManager::PluginNetworkType::OrcaRouterAI;
+    } else if (str == QLatin1StringView("openaigeneric")) {
+        return GenericNetworkManager::PluginNetworkType::OpenAIGeneric;
     } else {
         qCWarning(AUTOGENERATETEXT_GENERICNETWORK_LOG) << "PluginNetworkType is unknown. It's a bug" << str;
         return GenericNetworkManager::PluginNetworkType::Unknown;
@@ -387,6 +401,14 @@ QList<TextAutoGenerateText::TextAutoGenerateTextClient::SupportedServer> Generic
     return listInfo;
 }
 
+bool GenericNetworkServerInfo::hasCustomUrl(GenericNetworkManager::PluginNetworkType type)
+{
+    if (type == GenericNetworkManager::PluginNetworkType::OpenAIGeneric) {
+        return true;
+    }
+    return false;
+}
+
 GenericNetworkManager::Limitations GenericNetworkServerInfo::limitations(GenericNetworkManager::PluginNetworkType type)
 {
     GenericNetworkManager::Limitations limits;
@@ -424,6 +446,7 @@ GenericNetworkManager::Limitations GenericNetworkServerInfo::limitations(Generic
     case GenericNetworkManager::PluginNetworkType::OrcaRouterAI:
     case GenericNetworkManager::PluginNetworkType::SarvamAI:
     case GenericNetworkManager::PluginNetworkType::AtlasCloud:
+    case GenericNetworkManager::PluginNetworkType::OpenAIGeneric:
         return limits;
     }
     return limits;
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.h b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.h
index 08cbb8957..a7824f412 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.h
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworkserverinfo.h
@@ -28,4 +28,5 @@ public:
     [[nodiscard]] static GenericNetworkManager::Limitations limitations(GenericNetworkManager::PluginNetworkType type);
     [[nodiscard]] static QString chatCompletionPath(GenericNetworkManager::PluginNetworkType type);
     [[nodiscard]] static QString responsesPath(GenericNetworkManager::PluginNetworkType type);
+    [[nodiscard]] static bool hasCustomUrl(GenericNetworkManager::PluginNetworkType type);
 };
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.cpp b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.cpp
index c6ea340cd..661614dee 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.cpp
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.cpp
@@ -35,6 +35,7 @@ void GenericNetworkSettings::load(const KConfigGroup &config)
     PluginCommonSettings::load(config);
     setMaxTokens(config.readEntry(u"MaxToken"_s, 2048));
     setSeed(config.readEntry(u"Seed"_s, 0));
+    setCustomUrl(config.readEntry(u"CustomUrl"_s, QString()));
 }
 
 void GenericNetworkSettings::save(KConfigGroup &config)
@@ -42,4 +43,15 @@ void GenericNetworkSettings::save(KConfigGroup &config)
     PluginCommonSettings::save(config);
     config.writeEntry(u"MaxToken"_s, maxTokens());
     config.writeEntry(u"Seed"_s, seed());
+    config.writeEntry(u"CustomUrl"_s, customUrl());
+}
+
+QString GenericNetworkSettings::customUrl() const
+{
+    return mCustomUrl;
+}
+
+void GenericNetworkSettings::setCustomUrl(const QString &newCustomUrl)
+{
+    mCustomUrl = newCustomUrl;
 }
diff --git a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.h b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.h
index 9b18f5b44..deae5d82b 100644
--- a/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.h
+++ b/textautogeneratetext/plugins/genericnetworkplugin/genericnetworksettings.h
@@ -23,7 +23,11 @@ public:
     void load(const KConfigGroup &config) override;
     void save(KConfigGroup &config) override;
 
+    [[nodiscard]] QString customUrl() const;
+    void setCustomUrl(const QString &newCustomUrl);
+
 private:
     int mMaxTokens = 2048;
     int mSeed = 0;
+    QString mCustomUrl;
 };
diff --git a/textautogeneratetext/plugins/plugincommon/plugincommonsettings.cpp b/textautogeneratetext/plugins/plugincommon/plugincommonsettings.cpp
index f1be85cce..bac4e6ca0 100644
--- a/textautogeneratetext/plugins/plugincommon/plugincommonsettings.cpp
+++ b/textautogeneratetext/plugins/plugincommon/plugincommonsettings.cpp
@@ -16,6 +16,7 @@ double PluginCommonSettings::defaultTemperature() const
 {
     return 0.8;
 }
+
 void PluginCommonSettings::load(const KConfigGroup &config)
 {
     setDisplayName(config.readEntry(u"Name"_s));
diff --git a/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.cpp b/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.cpp
index 729650941..6c73d008b 100644
--- a/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.cpp
+++ b/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.cpp
@@ -21,15 +21,16 @@ TextAutoGenerateNetworkPluginConfigureWidget::TextAutoGenerateNetworkPluginConfi
     : QWidget{parent}
     , mApiKey(new KPasswordLineEdit(this))
     , mInstanceName(new QLineEdit(this))
+    , mCustomUrl(new QLineEdit(this))
     , mMaxToken(new QSpinBox(this))
     , mTemperature(new QDoubleSpinBox(this))
     , mSeed(new QSpinBox(this))
     , mWebSite(new QLabel(this))
     , mDescription(new QLabel(this))
+    , mMainLayout(new QFormLayout(this))
 {
-    auto mainLayout = new QFormLayout(this);
-    mainLayout->setObjectName(u"mainLayout"_s);
-    mainLayout->setContentsMargins({});
+    mMainLayout->setObjectName(u"mainLayout"_s);
+    mMainLayout->setContentsMargins({});
 
     mApiKey->setObjectName(u"mApiKey"_s);
     mInstanceName->setObjectName(u"mInstanceName"_s);
@@ -41,14 +42,17 @@ TextAutoGenerateNetworkPluginConfigureWidget::TextAutoGenerateNetworkPluginConfi
     mTemperature->setSingleStep(0.1);
     mSeed->setMaximum(9999);
     mSeed->setObjectName(u"mSeed"_s);
+    mCustomUrl->setObjectName(u"mCustomUrl"_s);
 
     mApiKey->setRevealPasswordMode(KAuthorized::authorize(u"lineedit_reveal_password"_s) ? KPassword::RevealMode::OnlyNew : KPassword::RevealMode::Never);
 
-    mainLayout->addRow(i18n("Name:"), mInstanceName);
-    mainLayout->addRow(i18n("Api Key:"), mApiKey);
-    mainLayout->addRow(i18n("Max Tokens:"), mMaxToken);
-    mainLayout->addRow(i18n("Temperature:"), mTemperature);
-    mainLayout->addRow(i18n("Seed:"), mSeed);
+    mMainLayout->addRow(i18n("Name:"), mInstanceName);
+    mMainLayout->addRow(i18n("Custom URL:"), mCustomUrl);
+
+    mMainLayout->addRow(i18n("Api Key:"), mApiKey);
+    mMainLayout->addRow(i18n("Max Tokens:"), mMaxToken);
+    mMainLayout->addRow(i18n("Temperature:"), mTemperature);
+    mMainLayout->addRow(i18n("Seed:"), mSeed);
 
     KLineEditEventHandler::catchReturnKey(mApiKey->lineEdit());
     KLineEditEventHandler::catchReturnKey(mInstanceName);
@@ -56,12 +60,12 @@ TextAutoGenerateNetworkPluginConfigureWidget::TextAutoGenerateNetworkPluginConfi
     mWebSite->setTextInteractionFlags(Qt::TextBrowserInteraction);
     mWebSite->setTextFormat(Qt::RichText);
     mWebSite->setOpenExternalLinks(true);
-    mainLayout->addWidget(mWebSite);
+    mMainLayout->addWidget(mWebSite);
 
     mDescription->setObjectName(u"mDescription"_s);
     mDescription->setTextFormat(Qt::PlainText);
     mDescription->setWordWrap(true);
-    mainLayout->addWidget(mDescription);
+    mMainLayout->addWidget(mDescription);
 
     connect(mInstanceName, &QLineEdit::textChanged, this, [this](const QString &str) {
         Q_EMIT enableOkButton(!str.trimmed().isEmpty());
@@ -70,6 +74,12 @@ TextAutoGenerateNetworkPluginConfigureWidget::TextAutoGenerateNetworkPluginConfi
 
 TextAutoGenerateNetworkPluginConfigureWidget::~TextAutoGenerateNetworkPluginConfigureWidget() = default;
 
+void TextAutoGenerateNetworkPluginConfigureWidget::setHasCustomUrl(bool b)
+{
+    mMainLayout->labelForField(mCustomUrl)->setVisible(b);
+    mCustomUrl->setVisible(b);
+}
+
 void TextAutoGenerateNetworkPluginConfigureWidget::setApiKey(const QString &key)
 {
     mApiKey->setPassword(key);
@@ -138,4 +148,14 @@ void TextAutoGenerateNetworkPluginConfigureWidget::setWebSiteUrl(const QString &
     }
 }
 
+void TextAutoGenerateNetworkPluginConfigureWidget::setCustomUrl(const QString &url)
+{
+    mCustomUrl->setText(url);
+}
+
+QString TextAutoGenerateNetworkPluginConfigureWidget::customUrl() const
+{
+    return mCustomUrl->text();
+}
+
 #include "moc_textautogeneratenetworkpluginconfigurewidget.cpp"
diff --git a/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.h b/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.h
index ffb1119fa..5fe1196ca 100644
--- a/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.h
+++ b/textautogeneratetext/widgets/networkpluginconfigure/textautogeneratenetworkpluginconfigurewidget.h
@@ -13,6 +13,7 @@ class QLineEdit;
 class QSpinBox;
 class QDoubleSpinBox;
 class QLabel;
+class QFormLayout;
 namespace TextAutoGenerateText
 {
 /*!
@@ -102,6 +103,23 @@ public:
      */
     void setDescription(const QString &description);
 
+    /*!
+     * \brief setHasCustomUrl
+     * \param b
+     */
+    void setHasCustomUrl(bool b);
+
+    /*!
+     * \brief setCustomUrl
+     * \param url
+     */
+    void setCustomUrl(const QString &url);
+    /*!
+     * \brief customUrl
+     * \return
+     */
+    [[nodiscard]] QString customUrl() const;
+
 Q_SIGNALS:
     /*!
      * \brief send true if we need to update button
@@ -112,10 +130,12 @@ Q_SIGNALS:
 private:
     KPasswordLineEdit *const mApiKey;
     QLineEdit *const mInstanceName;
+    QLineEdit *const mCustomUrl;
     QSpinBox *const mMaxToken;
     QDoubleSpinBox *const mTemperature;
     QSpinBox *const mSeed;
     QLabel *const mWebSite;
     QLabel *const mDescription;
+    QFormLayout *const mMainLayout;
 };
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.