[network/kio-extras/kf6] /: Import KCM from KIO

Alexander Lohnau null at kde.org
Mon Jun 5 20:36:22 BST 2023


Git commit ae7621cb724434594fee5e2098a6c1389a1364d9 by Alexander Lohnau.
Committed on 01/06/2023 at 04:32.
Pushed by ltoscano into branch 'kf6'.

Import KCM from KIO

M  +3    -1    CMakeLists.txt
M  +1    -0    doc/CMakeLists.txt
A  +6    -0    doc/kcontrol6/CMakeLists.txt
A  +2    -0    doc/kcontrol6/cookies/CMakeLists.txt
A  +208  -0    doc/kcontrol6/cookies/index.docbook
A  +2    -0    doc/kcontrol6/netpref/CMakeLists.txt
A  +109  -0    doc/kcontrol6/netpref/index.docbook
A  +2    -0    doc/kcontrol6/proxy/CMakeLists.txt
A  +174  -0    doc/kcontrol6/proxy/index.docbook
A  +2    -0    doc/kcontrol6/smb/CMakeLists.txt
A  +93   -0    doc/kcontrol6/smb/index.docbook
A  +2    -0    doc/kcontrol6/trash/CMakeLists.txt
A  +65   -0    doc/kcontrol6/trash/index.docbook
A  +2    -0    doc/kcontrol6/webshortcuts/CMakeLists.txt
A  +173  -0    doc/kcontrol6/webshortcuts/index.docbook
A  +9    -0    kcms/CMakeLists.txt
A  +32   -0    kcms/cookies/CMakeLists.txt
A  +122  -0    kcms/cookies/kcm_cookies.json
A  +81   -0    kcms/cookies/kcookiesmain.cpp  *
A  +41   -0    kcms/cookies/kcookiesmain.h  *
A  +411  -0    kcms/cookies/kcookiesmanagement.cpp     [License: GPL(v2.0+)]
A  +89   -0    kcms/cookies/kcookiesmanagement.h     [License: GPL(v2.0+)]
A  +255  -0    kcms/cookies/kcookiesmanagement.ui
A  +425  -0    kcms/cookies/kcookiespolicies.cpp     [License: GPL(v2.0+)]
A  +64   -0    kcms/cookies/kcookiespolicies.h     [License: GPL(v2.0+)]
A  +231  -0    kcms/cookies/kcookiespolicies.ui
A  +124  -0    kcms/cookies/kcookiespolicyselectiondlg.cpp     [License: GPL(v2.0+)]
A  +83   -0    kcms/cookies/kcookiespolicyselectiondlg.h     [License: GPL(v2.0+)]
A  +107  -0    kcms/cookies/kcookiespolicyselectiondlg.ui
A  +227  -0    kcms/ksaveioconfig.cpp     [License: LGPL(v2.0+)]
A  +66   -0    kcms/ksaveioconfig.h     [License: LGPL(v2.0+)]
A  +25   -0    kcms/netpref/CMakeLists.txt
A  +120  -0    kcms/netpref/kcm_netpref.json
A  +22   -0    kcms/netpref/kio_ftprc.kcfg
A  +5    -0    kcms/netpref/kio_ftprc.kcfgc
A  +51   -0    kcms/netpref/kioslave.kcfg
A  +5    -0    kcms/netpref/kioslave.kcfgc
A  +183  -0    kcms/netpref/netpref.cpp  *
A  +43   -0    kcms/netpref/netpref.h  *
A  +25   -0    kcms/proxy/CMakeLists.txt
A  +122  -0    kcms/proxy/kcm_proxy.json
A  +542  -0    kcms/proxy/kproxydlg.cpp     [License: LGPL(v2.0)]
A  +54   -0    kcms/proxy/kproxydlg.h     [License: LGPL(v2.0)]
A  +971  -0    kcms/proxy/kproxydlg.ui
A  +14   -0    kcms/smb/CMakeLists.txt
A  +121  -0    kcms/smb/kcm_smb.json
A  +119  -0    kcms/smb/smbrodlg.cpp     [License: LGPL(v2.0+)]
A  +41   -0    kcms/smb/smbrodlg.h     [License: LGPL(v2.0+)]
A  +16   -0    kcms/webshortcuts/CMakeLists.txt
A  +112  -0    kcms/webshortcuts/kcm_webshortcuts.json
A  +101  -0    kcms/webshortcuts/main.cpp     [License: GPL(v2.0+)]
A  +33   -0    kcms/webshortcuts/main.h     [License: GPL(v2.0+)]
M  +1    -1    smb/kdsoap-ws-discovery-client/CMakeLists.txt

The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


https://invent.kde.org/network/kio-extras/-/commit/ae7621cb724434594fee5e2098a6c1389a1364d9

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 661988a15..6511bd47a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,6 +58,7 @@ find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS
     Bookmarks
     GuiAddons
     SyntaxHighlighting
+    KCMUtils
 )
 
 include(KDEClangFormat)
@@ -170,7 +171,8 @@ ecm_set_disabled_deprecation_versions(
     KF 5.96
 )
 
-add_subdirectory( doc )
+add_subdirectory(doc)
+add_subdirectory(kcms)
 
 add_subdirectory( about )
 if(TARGET KF${QT_MAJOR_VERSION}::Activities AND TARGET Qt::Sql AND NOT WIN32)
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index ca45f8501..f08f721cc 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -1 +1,2 @@
 ecm_optional_add_subdirectory(kioslave)
+add_subdirectory(kcontrol6)
diff --git a/doc/kcontrol6/CMakeLists.txt b/doc/kcontrol6/CMakeLists.txt
new file mode 100644
index 000000000..6c2f21b07
--- /dev/null
+++ b/doc/kcontrol6/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_subdirectory(cookies)
+add_subdirectory(netpref)
+add_subdirectory(proxy)
+add_subdirectory(smb)
+add_subdirectory(trash)
+add_subdirectory(webshortcuts)
diff --git a/doc/kcontrol6/cookies/CMakeLists.txt b/doc/kcontrol6/cookies/CMakeLists.txt
new file mode 100644
index 000000000..dd5bb6aef
--- /dev/null
+++ b/doc/kcontrol6/cookies/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/cookies)
diff --git a/doc/kcontrol6/cookies/index.docbook b/doc/kcontrol6/cookies/index.docbook
new file mode 100644
index 000000000..66a0a23c4
--- /dev/null
+++ b/doc/kcontrol6/cookies/index.docbook
@@ -0,0 +1,208 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+<!ENTITY % addindex "IGNORE">
+<!ENTITY % English "INCLUDE" > <!-- change language only here -->
+]>
+
+<article id="cookies" lang="&language;">
+<articleinfo>
+<title>Cookies</title>
+<authorgroup>
+<author>&Krishna.Tateneni; &Krishna.Tateneni.mail;</author>
+<author>&Jost.Schenck; &Jost.Schenck.mail;</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2016-11-10</date>
+<releaseinfo>Frameworks 5.29</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>Systemsettings</keyword>
+<keyword>cookie</keyword>
+</keywordset>
+
+</articleinfo>
+
+<sect1 id="cookie">
+<title>Cookies</title>
+
+<para>Cookies are a mechanism used by web sites to store and retrieve
+information using your browser.  For example, a web site may allow you
+to customize the content and layout of the pages you see, so that your
+choices are persistent across different visits to that web site.</para>
+
+<para>The web site is able to remember your preferences by storing a
+cookie on your computer. Then, on future visits, the web site retrieves
+the information stored in the cookie to format the content of the site
+according to your previously specified preferences.</para>
+
+<para>Thus, cookies play a very useful role in web browsing.
+Unfortunately, web sites often store and retrieve information in cookies
+without your explicit knowledge or consent. Some of this information may
+be quite useful to the web site owners, for example, by allowing them to
+collect summary statistics on the number of visits different areas of
+the web sites get, or to customize banner advertising.</para>
+
+<para>The cookies page allows you to set policies
+for the use of cookies when you are browsing the web with the
+&konqueror; web browser.</para>
+
+<warning><para>Note that the policies that you set using this control
+module will <emphasis>not</emphasis> apply to other web browsers such
+as &firefox;.</para></warning>
+
+<sect2 id="cookie-policy">
+
+<title>Policy</title>
+
+<para>Using the <guilabel>Policy</guilabel> tab, you can configure the
+&kde; applications that will handle cookies. You can do this by specifying a
+general cookie policy as well as special cookie policies for certain
+domains or hosts.</para>
+
+<para>The top of the policy tab has a check box labeled <guilabel>Enable
+cookies</guilabel>. If you leave this unchecked, cookies will be
+completely disabled. However, this may make browsing rather
+inconvenient, especially as some web sites require the use of browsers
+with cookies enabled.</para>
+
+<para>You will probably want to enable cookies and then set
+specific policies on how you want them to be handled.</para>
+
+<para>The first group of options create settings that apply to all cookies.</para>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>Only accept cookies from originating server</guilabel></term>
+<listitem>
+<para>Some pages try to set cookies from servers other than the one
+you are seeing the &HTML; page from.  For example,
+they show you advertisements, and the advertisements are from another
+computer, often one that belongs to a large advertising group.  These
+advertisements may try to set a cookie which would allow them to
+track the pages you view across multiple web sites.</para>
+<para>Enabling this option will mean only cookies that come from the
+same web server as you are explicitly connecting to will be
+accepted.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guilabel>Automatically accept session cookies</guilabel></term>
+<listitem>
+
+<para>An increasingly common use for cookies is not to track your
+movements across many visits to a web site, but to just follow what you
+do during one single visit.  Session cookies are saved as long as you
+are looking at the site, and deleted when you leave it.</para>
+
+<para>Web sites can use this information for various things, most
+commonly it is a convenience so that you do not have to keep logging in
+to view pages.  For example, on a webmail site, without some kind of
+session <acronym>ID</acronym>, you would have to give your password
+again for each email you want to read.  There are other ways to
+achieve this, but cookies are simple and very common.</para>
+
+<para>Enabling this option means that session cookies are always
+accepted, even if you don't accept any other kind, and even if you
+choose to reject cookies from a particular site, session cookies from
+that site will be accepted.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+<para>The section for <guilabel>Default Policy</guilabel> sets some
+further options that are mutually exclusive — you can choose only one
+of these options as the default, but you are free to set a different
+option for any specific web server.</para>
+<note><para>Site specific policies always take precedence over the default 
+policy.</para></note>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>Accept all cookies</guilabel></term>
+<listitem>
+<para>If this option is selected, all cookies will be accepted without
+asking for confirmation.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guilabel>Accept until end of session</guilabel></term>
+<listitem>
+<para>Cookies will be accepted, but they will expire at the end
+of the session.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guilabel>Ask for confirmation</guilabel></term>
+<listitem>
+<para>If this option is selected, you will be asked for confirmation
+every time a cookie is stored or retrieved. You can selectively accept
+or reject each cookie. The confirmation dialog will also allow you to
+set a domain specific policy, if you do not want to confirm each
+cookie for that domain.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guilabel>Reject all cookies</guilabel></term>
+<listitem>
+<para>If this option is selected, all cookies will be rejected without
+asking for confirmation.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+<para>In addition to the default policy for handling of cookies, which you can
+set by selecting one of the three options described above, you can also set
+policies for specific host domains using the controls in the <guilabel>Site
+Policy</guilabel> group.</para>
+
+<para>The Ask, Accept, Accept until end of session, or Reject policy can be applied to a specific
+domain by clicking on the <guibutton>New...</guibutton> button, which
+brings up a dialog. In this dialog, you can type the name of the
+domain (with a leading dot), then select the policy you want to apply
+to this domain. Note that entries may also get added while you are
+browsing, if the default policy is to ask for confirmation, and you
+choose a general policy for a specific host (for example, by selecting
+<guilabel>Reject</guilabel> when asked to
+confirm a cookie).</para>
+
+<para>You can also select a specific host domain from the list and click the
+<guibutton>Change...</guibutton> button to choose a different policy for that
+domain than the one shown in the list.</para>
+
+<para>To delete a domain specific policy, choose a domain from the list, and
+then click the <guibutton>Delete</guibutton> button. The default policy will
+apply to domains which have been deleted from the list.</para>
+
+</sect2>
+
+<sect2 id="cookie-management">
+<title>Management</title>
+
+<para>In the <guilabel>Management</guilabel> tab you can browse and selectively
+delete cookies that have been set in the past.</para>
+
+<para>In the upper part of this dialog, you can see a list of domains displayed
+  as a tree. Click on the little <guiicon>></guiicon> next to a domain to see all
+cookies that have been set for this particular target domain. If you select one
+of these cookies, you will notice that its contents will show up in the frame
+<guilabel>Details</guilabel> below.</para>
+
+<para>By clicking the <guibutton>Delete</guibutton> button you can now delete the selected
+cookie. Click <guibutton>Delete All</guibutton> to delete all cookies stored.</para>
+
+<para>If a domain is selected, you can use <guibutton>Configure Policy...</guibutton> to set
+a site policy.</para>
+
+<para>Choose <guibutton>Reload List</guibutton> to reload the list
+from your hard disk. You might want to do this if you have had the
+module open and are testing web sites, or have made many changes in the
+module itself.</para>
+
+</sect2>
+
+</sect1>
+
+</article>
diff --git a/doc/kcontrol6/netpref/CMakeLists.txt b/doc/kcontrol6/netpref/CMakeLists.txt
new file mode 100644
index 000000000..1f7485cfe
--- /dev/null
+++ b/doc/kcontrol6/netpref/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/netpref)
diff --git a/doc/kcontrol6/netpref/index.docbook b/doc/kcontrol6/netpref/index.docbook
new file mode 100644
index 000000000..383dd8fa5
--- /dev/null
+++ b/doc/kcontrol6/netpref/index.docbook
@@ -0,0 +1,109 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+<!ENTITY % addindex "IGNORE">
+<!ENTITY % English "INCLUDE" > <!-- change language only here -->
+]>
+
+<article id="netpref" lang="&language;">
+<articleinfo>
+<title>Connection Preferences</title>
+<authorgroup>
+<author>&Lauri.Watts; &Lauri.Watts.mail;</author>
+
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2016-11-10</date>
+<releaseinfo>Frameworks 5.29</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>kdebase</keyword>
+<keyword>kcontrol</keyword>
+<keyword>network</keyword>
+<keyword>timeouts</keyword>
+</keywordset>
+
+</articleinfo>
+
+<sect1 id="timeouts">
+
+<title>Connection Preferences</title>
+
+<para>Here you can set timeout values.  You might want to tweak them
+if your connection is very slow, but the default settings are
+appropriate for most users.</para>
+
+<para>Here <guilabel>Timeout Values</guilabel> are the length of time
+an application should wait for an answer from a network operation.</para>
+
+<para>You can configure the following timeouts:</para>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>Socket read:</guilabel></term>
+<listitem>
+<para> Some applications use <firstterm>sockets</firstterm> to
+communicate.  You can think of a socket as a water tap; while it is
+open, water (or in our case, data) comes out, without any interaction.
+If something stops this flow of data, the application will wait for
+more to come.  This could be a very long time, but you can configure a
+maximum time for an application to wait with this option.</para>
+<para>This setting will only apply to &kde; applications, of course.</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Proxy connect:</guilabel></term>
+<listitem>
+<para>
+Sets how long to wait for a connection to a proxy server, if one is configured.
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Server connect:</guilabel></term>
+<listitem>
+<para>
+Sets how long to wait for a connection to a remote server.  
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Server response:</guilabel></term>
+<listitem>
+<para>
+Sets how long to wait for a reply from a remote server.
+</para>
+</listitem>
+</varlistentry>
+
+</variablelist>
+
+<para>You can configure <guilabel>FTP Options</guilabel> here.  At
+present there is just two options:</para>
+<variablelist>
+<varlistentry>
+<term><guilabel>Enable passive mode (PASV)</guilabel></term>
+<listitem><para>Passive &FTP; is often required when you are behind a firewall.
+Many firewalls only permit connections that were initiated from
+<quote>the inside</quote>.  Passive &FTP; is controlled by the client,
+which makes it usable through firewalls.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Mark partially uploaded files</guilabel></term>
+<listitem><para>When a mark is placed in this box, partially uploaded files will 
+have a <literal role="extension">.part</literal> extension added to the end 
+of the file. This extension is removed once the file download is complete.</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+
+
+</sect1>
+</article>
diff --git a/doc/kcontrol6/proxy/CMakeLists.txt b/doc/kcontrol6/proxy/CMakeLists.txt
new file mode 100644
index 000000000..5861413f7
--- /dev/null
+++ b/doc/kcontrol6/proxy/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/proxy)
diff --git a/doc/kcontrol6/proxy/index.docbook b/doc/kcontrol6/proxy/index.docbook
new file mode 100644
index 000000000..72d269fad
--- /dev/null
+++ b/doc/kcontrol6/proxy/index.docbook
@@ -0,0 +1,174 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+<!ENTITY % addindex "IGNORE">
+<!ENTITY % English "INCLUDE" > <!-- change language only here -->
+]>
+
+<article id="proxy" lang="&language;">
+<title>Proxy</title>
+<articleinfo>
+<authorgroup>
+<author>&Krishna.Tateneni; &Krishna.Tateneni.mail;</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2016-11-10</date>
+<releaseinfo>Frameworks 5.29</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>Systemsettings</keyword>
+<keyword>proxy</keyword>
+<keyword>proxies</keyword>
+</keywordset>
+
+</articleinfo>
+<sect1 id="proxies">
+<title>Proxies</title>
+
+<sect2 id="proxies-intro">
+
+<title>Introduction</title>
+
+<para>Proxies are programs running on a computer that acts a server on
+the network you are connected to (whether by modem or other
+means). These programs receive &HTTP; and &FTP; requests, retrieve the
+relevant files from the internet, and pass them on to the client
+computer that made the requests.</para>
+
+<para>When you have configured a proxy, &HTTP; and/or &FTP; requests
+are re-routed through the computer that is acting as a proxy server.
+However, you can also select specific hosts which should be contacted
+directly, rather than through the proxy server. If you are on a local
+network, for example, access to local hosts probably doesn't need to
+go through a proxy server.</para>
+
+<para>You should only need to configure a proxy server if your network
+administrator requires it (if you are a dial-up user, that would be
+your internet service provider or <acronym>ISP</acronym>). Otherwise,
+especially if you are feeling a bit confused about this proxy
+business, but everything seems to be fine with your internet
+connection, you don't need to change anything.</para>
+
+<para>Please note that using proxy servers is optional, but has the
+benefit or advantage of giving you faster access to data on the
+internet.</para>
+
+<para>If you are uncertain whether or not you need to use a proxy
+server to connect to the internet, please consult with your internet
+service provider's setup guide or your system administrator.</para>
+
+</sect2>
+
+<sect2 id="proxies-use">
+
+<title>Use</title>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>No Proxy</guilabel></term>
+<listitem>
+
+<para>Select this option if you do <emphasis>not</emphasis> want to use a proxy server
+and connect to the Internet directly.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+<para>If you have decided to use a proxy, you have several methods to
+configure the settings for it.</para>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>Detect proxy configuration automatically</guilabel></term>
+<listitem>
+
+<para>Select this option if you want the proxy setup configuration
+script file to be automatically detected and downloaded.</para>
+<para>This option only differs from the next choice in that it
+<emphasis>does not</emphasis> require you to supply the location of
+the configuration script file. Instead, it will be automatically
+downloaded using <quote>Web Proxy Auto-Discovery</quote> 
+(<acronym>WPAD</acronym>) protocol.</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Use proxy auto configuration URL:</guilabel></term>
+<listitem>
+<para>Select this option if your proxy support is provided through a
+script file located at a specific address.  You can then enter the
+address in the location text box, or use the <guiicon>folder</guiicon>
+icon to browse to it.</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Use system proxy configuration:</guilabel></term>
+<listitem>
+<para>Some systems are setup with $<envar>HTTP_PROXY</envar> to allow
+graphical as well as non-graphical applications to share the same
+proxy configuration information.</para>
+<para>If you know this applies to you, select this option and click on
+the <guibutton>Auto Detect</guibutton> button to provide the environment
+variable names used to set the address of the proxy server(s).</para>
+<!-- Exceptions fields are different for system proxy (envar) + manual proxy list of hosts/IPs? -->
+<para>In the <guilabel>Exceptions:</guilabel> field enter the environment variable,
+⪚ $<envar>NO_PROXY</envar>, used to store the 
+addresses of sites for which the proxy server should not be used.</para>
+<para>Use <guilabel>Show the value of the environment variables</guilabel> to 
+show the value of an environment variable instead of its name.
+However it is not possible to edit the values of environment variables in this module.</para>
+<!--
+How to enable Auto Detect button?
+-->
+
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guilabel>Use manually specified proxy configuration:</guilabel></term>
+<listitem>
+
+<para>The complete addressing information for the proxy includes both
+the Internet address and a port number. You should enter these into
+the relevant text boxes. Check <guilabel>Use this proxy server for all 
+protocols</guilabel> to copy the addresses and port of the &HTTP; proxy server
+into all other proxy fields, in order to help save some typing.</para>
+
+<variablelist>
+<varlistentry>
+<term><guilabel>Exceptions:</guilabel></term>
+<listitem>
+<para>Enter a comma separated list of hostnames or ip addresses that should 
+be excluded from using the above proxy settings. If you want to exclude all 
+hosts for a given domain, then simply enter the domain name preceded by a dot. 
+For example, to exclude all hostnames for kde.org, enter <userinput>.kde.org</userinput>. 
+Wildcard characters such as <userinput>*</userinput> or <userinput>?</userinput> 
+are not supported and will have no effect. 
+Additionally, you can also enter IP addresses, ⪚ 127.0.0.1 and
+IP addresses with a subnet, ⪚ 192.168.0.1/24.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+<para>You can also choose <guilabel>Use proxy settings only for addresses 
+in the Exceptions list</guilabel>.</para>
+
+<para>Check this box to reverse the use of the exception list, &ie;
+the proxy servers will only be used when the requested &URL; matches
+one of the addresses listed here.</para>
+
+<para>This feature is useful if all you need is a proxy to access a
+few specific sites, for example, an internal intranet.  If you have
+more complex requirements you might want to use a configuration
+script.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+</sect2>
+
+</sect1>
+
+</article>
diff --git a/doc/kcontrol6/smb/CMakeLists.txt b/doc/kcontrol6/smb/CMakeLists.txt
new file mode 100644
index 000000000..557477f2f
--- /dev/null
+++ b/doc/kcontrol6/smb/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/smb)
diff --git a/doc/kcontrol6/smb/index.docbook b/doc/kcontrol6/smb/index.docbook
new file mode 100644
index 000000000..d4b126b1f
--- /dev/null
+++ b/doc/kcontrol6/smb/index.docbook
@@ -0,0 +1,93 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+<!ENTITY % addindex "IGNORE">
+<!ENTITY % English "INCLUDE" > <!-- change language only here -->
+]>
+
+<article id="smb" lang="&language;">
+<articleinfo>
+<title>&Windows; Shares</title>
+<authorgroup>
+<author>&Mike.McBride; &Mike.McBride.mail;</author>
+<author>&Jost.Schenck; &Jost.Schenck.mail;</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2016-11-10</date>
+<releaseinfo>Frameworks 5.29</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>Systemsettings</keyword>
+<keyword>Windows shares</keyword>
+</keywordset>
+</articleinfo>
+<sect1 id="windows-shares">
+<title>&Windows; Shares</title>
+
+<sect2 id="windows-shares-intro">
+<title>Introduction</title>
+
+<para>In many small local area networks, the &SMB;
+protocol is used to offer network services. Names like
+<quote>&Windows; Network</quote> or <quote>&Windows; for Workgroups
+Network</quote> or <quote>LanManager</quote> are often used as
+well. Using &SMB; you can access so-called
+<quote>shares</quote> (&ie; folders made available by the server)
+as well as printers.</para>
+
+<para>&kde; comes with built-in support for the &SMB;
+protocol. As &kde; is network-transparent that means you can access
+&SMB; shares from everywhere you can access your
+local files, for example in the &konqueror; file manager and in the
+file dialog. To make use of this you should provide &kde; with some
+information on your &SMB; network. But don't worry,
+this is normally pretty simple as, for example, all the &Windows;
+clients in your network need and have the same information.</para>
+
+<!-- Don't know if the following info should go in the base
+documentation --> 
+
+<!-- this smb KIO worker doesn't support showing a list
+of hosts (like e.g. smb:/), for this you need the lan or rlan KIO worker,
+very cool thing (TM) btw. If you want to write some documentation for
+this one too, have a look at kdenetwork/lanbrowsing/lisa/README and
+contact me if you have questions. -->
+
+<note><para>For the &SMB; protocol to work, it is
+required to have &Samba; correctly installed.</para></note>
+
+<!-- TODO: link to some place which explains USING SMB, i.e. konqueror
+or file dialog manual -->
+
+</sect2>
+
+<sect2 id="windows-shares-use">
+<title>Use</title>
+
+<para>Although there are a lot of insecure &SMB;
+networks out there which allow access to anyone, in principle you have
+to authenticate yourself to access the services of an
+&SMB; server.  By default, &kde; will use the data
+entered in the <guilabel>Default user name:</guilabel> and
+<guilabel>Default password:</guilabel> fields to authenticate itself on
+&SMB; hosts. If you leave the field <guilabel>Default
+user name:</guilabel> empty, &kde; will try to access
+&SMB; hosts without a username. If you leave the
+default password empty, it will try without a password. If &kde; is
+unsuccessful accessing the host using these settings, you will be
+asked for a username and a password.</para>
+
+<important><para>While it makes things more comfortable if &kde;
+stores your &SMB; password, this may be a security
+problem. If you are using &SMB; in a security
+conscious environment, you should not store your password here but
+rather enter it anew every time you need to access an
+&SMB; host.</para></important>
+
+</sect2>
+
+</sect1>
+
+</article>
diff --git a/doc/kcontrol6/trash/CMakeLists.txt b/doc/kcontrol6/trash/CMakeLists.txt
new file mode 100644
index 000000000..1cd7a3c87
--- /dev/null
+++ b/doc/kcontrol6/trash/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/trash)
diff --git a/doc/kcontrol6/trash/index.docbook b/doc/kcontrol6/trash/index.docbook
new file mode 100644
index 000000000..ad1583734
--- /dev/null
+++ b/doc/kcontrol6/trash/index.docbook
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+  <!ENTITY % addindex "IGNORE">
+  <!ENTITY % English "INCLUDE">
+]>
+<article id="trash" lang="&language;">
+<title>Trash</title>
+<articleinfo>
+<authorgroup>
+<author>&Burkhard.Lueck;</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2018-05-31</date>
+<releaseinfo>Frameworks 5.48</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>Systemsettings</keyword>
+<keyword>trash</keyword>
+</keywordset>
+</articleinfo>
+
+<para>
+This module allows you to configure the settings for the trash.
+</para>
+
+<variablelist>
+<varlistentry><term><guilabel>Cleanup:</guilabel></term>
+<listitem><para>
+Check this box to allow automatic deletion of files that are 
+older than the value specified. Leave this disabled to <emphasis>not</emphasis> 
+automatically delete any items after a certain timespan.
+Set the number of days that files can remain in the trash. Any files 
+older than this will be automatically deleted.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term><guilabel>Size:</guilabel></term>
+<listitem><para>
+Check this box to limit the trash to the maximum amount of disk space 
+that you specify. Otherwise, it will be unlimited.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term><guilabel>Limit to</guilabel></term>
+<listitem><para>
+This is the maximum percent of disk space that will be used for the 
+trash. The calculated amount of disk space that will be allowed for 
+the trash is displayed right of the spinbox.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term><guilabel>Full trash:</guilabel></term>
+<listitem><para>
+When the size limit is reached, the selected action will be performed, 
+either the oldest or biggest files will be deleted automatically
+or you will be warned.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+</article>
diff --git a/doc/kcontrol6/webshortcuts/CMakeLists.txt b/doc/kcontrol6/webshortcuts/CMakeLists.txt
new file mode 100644
index 000000000..234007ac6
--- /dev/null
+++ b/doc/kcontrol6/webshortcuts/CMakeLists.txt
@@ -0,0 +1,2 @@
+########### install files ###############
+kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol6/webshortcuts)
diff --git a/doc/kcontrol6/webshortcuts/index.docbook b/doc/kcontrol6/webshortcuts/index.docbook
new file mode 100644
index 000000000..d41dafcd6
--- /dev/null
+++ b/doc/kcontrol6/webshortcuts/index.docbook
@@ -0,0 +1,173 @@
+<?xml version="1.0" ?>
+<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
+"dtd/kdedbx45.dtd" [
+<!ENTITY % addindex "IGNORE">
+<!ENTITY % English "INCLUDE" > <!-- change language only here -->
+]>
+
+<article id="ebrowsing" lang="&language;">
+<articleinfo>
+<title>Web Shortcuts</title>
+<authorgroup>
+<author>&Krishna.Tateneni; &Krishna.Tateneni.mail;</author>
+<author>&Yves.Arrouye; &Yves.Arrouye.mail;</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+<date>2016-11-10</date>
+<releaseinfo>Frameworks 5.29</releaseinfo>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>Systemsettings</keyword>
+<keyword>enhanced browsing</keyword>
+<keyword>web shortcuts</keyword>
+<keyword>browsing</keyword>
+</keywordset>
+
+</articleinfo>
+<sect1 id="ebrowse">
+
+<title>Web Shortcuts</title>
+
+<sect2 id="ebrowse-intro">
+
+<title>Introduction</title>
+
+<para>&konqueror; offers some features to enhance your browsing
+experience. One such feature is <emphasis>Web Shortcuts</emphasis>.</para>
+
+<para>You may already have noticed that &kde; is very Internet friendly.
+For example, you can click on the <guimenuitem>Run</guimenuitem> menu
+item or type the keyboard shortcut assigned to that command (<keycombo
+action="simul">&Alt;<keycap>F2</keycap></keycombo> or <keycombo
+action="simul">&Alt;&Space;</keycombo>,
+unless you have changed it) and type in a &URI;.
+<footnote><para>Uniform Resource Identifier. A standardized way of
+referring to a resource such as a file on your computer, a World Wide
+Web address, an email address, &etc;</para></footnote></para>
+
+<para>Web shortcuts, on the other hand, let you come up with new pseudo
+&URL; schemes, or shortcuts, that basically let you
+<emphasis>parameterize</emphasis> commonly used
+&URI;s. For example, if you like the Google search
+engine, you can configure &kde; so that a pseudo &URL;
+scheme like <emphasis>gg</emphasis> will trigger a search on
+Google. This way, typing <userinput>gg:<replaceable>my
+query</replaceable></userinput> will search for <replaceable>my
+query</replaceable> on Google.</para>
+
+<note><para>One can see why we call these pseudo &URL;
+schemes. They are used like a &URL; scheme, but the
+input is not properly &URL; encoded, so one will type
+<userinput>google:kde apps</userinput> and not
+<userinput>google:kde+apps</userinput>.</para></note>
+
+<para>You can use web
+shortcuts wherever you would normally use
+&URI;s. Shortcuts for several search engines should
+already be configured on your system, but you can add new keywords, and
+change or delete existing ones in this module.</para>
+
+</sect2>
+
+<sect2 id="ebrowse-use">
+
+<title>Web Search Keywords</title>
+
+<para>The descriptive names of defined web shortcuts are shown in a
+list box. As with other lists in &kde;, you can click on a column
+heading to toggle the sort order between ascending and
+descending, and you can resize the columns.</para>
+
+<para>At the bottom of the list the option <guilabel>Enable Web search keywords</guilabel>
+has to be checked to enable this feature. Use the buttons on the right to 
+create, modify or delete shortcuts.</para>
+
+<para>If <guilabel>Use preferred keywords only</guilabel> is checked, only
+keywords marked as preferred in the second column of the list
+are used in places where only a few select 
+shortcuts can be shown at one time.
+</para>
+ 
+<para>Below the list you find two additional options:</para>
+<variablelist>
+<varlistentry><term><guilabel>Default Web search keyword:</guilabel></term>
+<listitem>
+<para>Select the search engine to use for input boxes that provide automatic 
+lookup services when you type in normal words and phrases instead of a &URL;. 
+To disable this feature select <guilabel>None</guilabel> from the list.
+</para></listitem>
+</varlistentry>
+<varlistentry><term><guilabel>Keyword delimiter:</guilabel></term>
+<listitem>
+<para>Choose the delimiter that separates the keyword from the phrase or word to 
+be searched.</para></listitem>
+</varlistentry>
+</variablelist>
+
+<para>If you double-click on a specific entry in the list of defined
+search providers or click the <guibutton>Change...</guibutton> button,
+the details for that entry are shown in a popup
+dialog.  In addition to the descriptive name for the item, you can
+also see the &URI; which is used, as well as the
+associated shortcuts which you can type anywhere in &kde; where
+&URI;s are expected. A given search provider can have
+multiple shortcuts, each separated by a comma.</para>
+
+<para> The text boxes are used not only for displaying information
+about an item in the list of web shortcuts, but also for modifying or
+adding new items.</para>
+
+<para>You can change the contents of either the <guilabel>Shortcut 
+URL:</guilabel> or the <guilabel>Shortcuts:</guilabel> text box.
+Click <guibutton>OK</guibutton> to save your changes or
+<guibutton>Cancel</guibutton> to exit the dialog with no
+changes.</para>
+
+<para>If you examine the contents of the <guilabel>Shortcut
+URL:</guilabel> text box, you will find that most, if not all of the
+entries have a <option>\{@}</option> in them. This sequence of four
+characters acts as a parameter, which is to say that they are replaced
+by whatever you happen to type after the colon character that is
+between a shortcut and its parameter. To add this query placeholder 
+to a shortcut &URL;, click on the button at the right of the text box.
+Let's consider some examples to clarify how to use web shortcuts.</para>
+
+<para>Suppose that the &URI; is
+<userinput>https://www.google.com/search?q=\{@}</userinput>, and
+<userinput>gg</userinput> is a shortcut to this
+&URI;. Then, typing
+<userinput>gg:<replaceable>alpha</replaceable></userinput> is
+equivalent to
+<userinput>https://www.google.com/search?q=<replaceable>alpha</replaceable></userinput>.
+You could type anything after the <userinput>:</userinput> character;
+whatever you have typed simply replaces the <option>\{@}</option>
+characters, after being converted to the appropriate character set for
+the search provider and then properly
+&URL;-encoded. Only the <option>\{@}</option> part of
+the search &URI; is touched, the rest of it is
+supposed to be properly &URL;-encoded already and is
+left as is.</para>
+
+<para>You can also have shortcuts without parameters. Suppose the
+&URI; was
+<emphasis>file:/home/me/mydocs/calligra/words</emphasis> and the
+shortcut was <emphasis>mywords</emphasis>. Then, typing
+<userinput>mywords:</userinput> is the same as typing the complete
+&URI;. Note that there is nothing after the colon
+when typing the shortcut, but the colon is still required in order for
+the shortcut to be recognized as such.</para>
+
+<para>By now, you will have understood that even though these shortcuts
+are called web shortcuts, they really are shortcuts to parameterized
+&URI;s, which can point not only to web sites like
+search engines but also to anything else that can be pointed to by a
+&URI;. Web shortcuts are a very powerful feature of
+navigation in &kde;.</para>
+
+</sect2>
+
+</sect1>
+
+</article>
diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt
new file mode 100644
index 000000000..416734f3a
--- /dev/null
+++ b/kcms/CMakeLists.txt
@@ -0,0 +1,9 @@
+function(kcmutils_generate_desktop_file )
+    # TODO KF6kcmutils_generate_desktop_file is currently mocked, fix this when importing the KCMs to KIO-extras
+endfunction()
+
+add_subdirectory(webshortcuts)
+add_subdirectory(cookies)
+add_subdirectory(smb)
+add_subdirectory(proxy)
+add_subdirectory(netpref)
diff --git a/kcms/cookies/CMakeLists.txt b/kcms/cookies/CMakeLists.txt
new file mode 100644
index 000000000..f38d829cb
--- /dev/null
+++ b/kcms/cookies/CMakeLists.txt
@@ -0,0 +1,32 @@
+kcoreaddons_add_plugin(kcm_cookies INSTALL_NAMESPACE "plasma/kcms/systemsettings_qwidgets")
+
+kcmutils_generate_desktop_file(kcm_cookies)
+
+target_sources(kcm_cookies PRIVATE
+    kcookiesmain.cpp
+    kcookiespolicies.cpp
+    kcookiesmanagement.cpp
+    kcookiespolicyselectiondlg.cpp
+    ../ksaveioconfig.cpp
+)
+
+ki18n_wrap_ui(kcm_cookies
+    kcookiespolicies.ui
+    kcookiesmanagement.ui
+    kcookiespolicyselectiondlg.ui
+)
+
+target_link_libraries(kcm_cookies PRIVATE
+    Qt6::Widgets
+    Qt6::DBus
+    KF6::CoreAddons
+    KF6::ConfigCore
+    KF6::I18n
+    KF6::ItemViews
+    KF6::KCMUtils
+    KF6::KIOCore
+)
+
+if (ENABLE_PCH)
+    target_precompile_headers(kcm_cookies REUSE_FROM KIOPchCore)
+endif()
diff --git a/kcms/cookies/kcm_cookies.json b/kcms/cookies/kcm_cookies.json
new file mode 100644
index 000000000..41550e3b1
--- /dev/null
+++ b/kcms/cookies/kcm_cookies.json
@@ -0,0 +1,122 @@
+{
+    "KPlugin": {
+        "Description": "Configure the way cookies work",
+        "Description[ar]": "اضبط طريقة عمل الكعكات",
+        "Description[bg]": "Настройване на бисквитките",
+        "Description[ca at valencia]": "Configura com funcionaran les galetes",
+        "Description[ca]": "Configura com funcionaran les galetes",
+        "Description[cs]": "Nastavení chování cookies",
+        "Description[de]": "Einstellungen zu Cookies vornehmen",
+        "Description[en_GB]": "Configure the way cookies work",
+        "Description[eo]": "Agordi kiel funkcias kuketoj",
+        "Description[es]": "Configurar cómo funcionan las cookies",
+        "Description[eu]": "Konfiguratu «cookie»k lan egiteko era",
+        "Description[fi]": "Evästeiden asetukset",
+        "Description[fr]": "Configurer le mode de fonctionnement des cookies",
+        "Description[gl]": "Configurar o funcionamento dos rastros",
+        "Description[ia]": "Configura le modo de functionar del cookies",
+        "Description[is]": "Grunnstilla hvernig vefkökur virka",
+        "Description[it]": "Configura come funzionano i cookie",
+        "Description[ka]": "მოირგეთ ქუქიების მუშაობის სტილი",
+        "Description[ko]": "쿠키 작동 방법을 설정합니다",
+        "Description[nl]": "Hier kunt u het cookiesbeleid instellen",
+        "Description[nn]": "Oppsett av infokapslar",
+        "Description[pl]": "Ustawienia działania ciasteczek",
+        "Description[sl]": "Konfiguriraj način dela piškotkov",
+        "Description[tr]": "Çerezlerin nasıl çalıştığını yapılandır",
+        "Description[uk]": "Налаштування механізму кук",
+        "Description[x-test]": "xxConfigure the way cookies workxx",
+        "Description[zh_TW]": "設定 cookie 如何運作",
+        "Icon": "preferences-web-browser-cookies",
+        "Name": "Cookies",
+        "Name[ar]": "الكعك",
+        "Name[ast]": "Cookies",
+        "Name[bg]": "Бисквитки",
+        "Name[ca at valencia]": "Galetes",
+        "Name[ca]": "Galetes",
+        "Name[cs]": "Cookies",
+        "Name[de]": "Cookies",
+        "Name[en_GB]": "Cookies",
+        "Name[eo]": "Kuketoj",
+        "Name[es]": "Cookies",
+        "Name[eu]": "«Cookie»ak",
+        "Name[fi]": "Evästeet",
+        "Name[fr]": "Cookies",
+        "Name[gl]": "Rastros",
+        "Name[ia]": "Cookies",
+        "Name[is]": "Vefkökur",
+        "Name[it]": "Cookie",
+        "Name[ka]": "ქუქიები",
+        "Name[ko]": "쿠키",
+        "Name[nl]": "Cookies",
+        "Name[nn]": "Infokapslar",
+        "Name[pl]": "Ciasteczka",
+        "Name[sl]": "Piškotki",
+        "Name[tr]": "Çerezler",
+        "Name[uk]": "Куки",
+        "Name[x-test]": "xxCookiesxx",
+        "Name[zh_TW]": "Cookies"
+    },
+    "X-DocPath": "kcontrol6/cookies/index.html",
+    "X-KDE-Keywords": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains",
+    "X-KDE-Keywords[ar]": "كعكات,تصفح,انترنت,www,شبكة,سياسة,نطاقات",
+    "X-KDE-Keywords[az]": "Kukilər, Baxış, İnternet, WWW,Şəbəkə,Davranış, Xidmətlər",
+    "X-KDE-Keywords[be at latin]": "Cookie,Ahliad,Internet,WWW,Sietka,Palityka,Damieny",
+    "X-KDE-Keywords[be]": "Cookie,Агляд,Інтэрнэт,WWW,Сетка,Палітыка,Дамены",
+    "X-KDE-Keywords[bg]": "Бисквитки,Сърфиране,Интернет,WWW,Мрежа,Политика,Домейни",
+    "X-KDE-Keywords[bs]": "Kolačići,Pregledanje,Internet,WWW,Mreža,Polisa,Domeni",
+    "X-KDE-Keywords[ca at valencia]": "Galetes,Navegació,Internet,WWW,Xarxa,Polítiques,Dominis",
+    "X-KDE-Keywords[ca]": "Galetes,Navegació,Internet,WWW,Xarxa,Polítiques,Dominis",
+    "X-KDE-Keywords[cs]": "Cookies,Prohlížení,Internet,WWW,Síť,Pravidla,Domény",
+    "X-KDE-Keywords[cy]": "Cwcis,Pori,Rhyngrwyd,WWW,Rhwydwaith,Polisi,Parthau",
+    "X-KDE-Keywords[da]": "Cookies,browsing,internet,www,netværk,politik,domæner",
+    "X-KDE-Keywords[de]": "Durchsuchen,Browsen,Surfen,Netzwerk,Regelungen",
+    "X-KDE-Keywords[el]": "Cookies,Περιήγησ,Διαδίκτυο,WWW,Δίκτυο,Πολιτική,Τομείς",
+    "X-KDE-Keywords[en_GB]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains",
+    "X-KDE-Keywords[es]": "Cookies,Navegación,Internet,WWW,Red,Políticas,Dominios",
+    "X-KDE-Keywords[et]": "Küpsised,Sirvimine,Internet,WWW,Võrk,Reeglid,Domeenid",
+    "X-KDE-Keywords[eu]": "Cookie-ak,Arakatzea,Internet,WWW,Sarea,Gidalerroa,Domeinuak",
+    "X-KDE-Keywords[fi]": "Evästeet,Selaus,Selailu,Internet,WWW,Verkko,Käytäntö,Käytänne,Verkkoalueet",
+    "X-KDE-Keywords[fr]": "Cookies, navigation, Internet, WWW, réseau, politique, domaines",
+    "X-KDE-Keywords[gd]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,briosgaidean,criomagan,brabhsadh,eadar-lìon,lìonra,poileasaidh,àrainnean",
+    "X-KDE-Keywords[gl]": "cookies,navegar,Internet,www,rede,política,dominios",
+    "X-KDE-Keywords[hu]": "Sütik,Böngészés,Internet,WWW,Hálózat,Házirend,Tartományok",
+    "X-KDE-Keywords[ia]": "Cookies,Navigation,Internet,WWW,Rete,Politica,Dominios",
+    "X-KDE-Keywords[id]": "Cookies,Menelusuri,Internet,WWW,Jaringan,Kebijakan,Domain",
+    "X-KDE-Keywords[ie]": "Cookies,Navigation,Internet,WWW,Rete,Politica,Dominias",
+    "X-KDE-Keywords[is]": "Kökur,Vafra,Internet,WWW,Netkerfi,Regla,Lén",
+    "X-KDE-Keywords[it]": "Cookie,navigazione,Internet,WWW,rete,politica,domini",
+    "X-KDE-Keywords[ka]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains",
+    "X-KDE-Keywords[ko]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,쿠키,브라우징,인터넷,네트워크,정책,도메인",
+    "X-KDE-Keywords[lt]": "Slapukai,Naršymas,Narsymas,Internetas,WWW,Saitynas,Žiniatinklis,Ziniatinklis,Tinklas,Taisyklės,Taisyklės,Politika,Sritys,Domenai",
+    "X-KDE-Keywords[ml]": "കുക്കീകൾ,ബ്രൗസിംഗ്,ഇന്റർനെറ്റ്,WWW,നെറ്റ്‍വർക്ക്,പോളിസി,ഡൊമെയിനുകൾ",
+    "X-KDE-Keywords[my]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,ကွတ်ကီး",
+    "X-KDE-Keywords[nb]": "Infokapsler,Nettlesing,Internett,WWW.Nettverk,Praksis,Domener",
+    "X-KDE-Keywords[nl]": "Cookies,browsen,internet,www,netwerk,beleid,domeinen",
+    "X-KDE-Keywords[nn]": "infokapslar,informasjonskapslar,cookies,surfing,Internett,WWW,nettverk,regler,domene",
+    "X-KDE-Keywords[pa]": "ਕੂਕੀਜ਼,ਬਰਾਊਜ਼ਿੰਗ,ਇੰਟਰਨੈੱਟ,ਨੈੱਟਵਰਕ,ਪਾਲਸੀ,ਡੋਮੇਨਾਂ",
+    "X-KDE-Keywords[pl]": "Ciasteczka,Przeglądanie,Internet,WWW,Sieć,Polityka,Domeny",
+    "X-KDE-Keywords[pt]": "Cookies,Navegação,Internet,WWW,Rede,Política,Domínios",
+    "X-KDE-Keywords[pt_BR]": "Cookies,Navegação,Internet,WWW,Rede,Política,Domínios",
+    "X-KDE-Keywords[ro]": "cookie,navigare,internet,www,rețea,politică,domenii",
+    "X-KDE-Keywords[ru]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,Интернет,веб-сёрфинг,сеть,домены,политика,правило,куки",
+    "X-KDE-Keywords[sk]": "Cookies,Sufrovanie,Internet,WWW,Sieť,Politika,Domény",
+    "X-KDE-Keywords[sl]": "Piškotki,brskanje,internet,WWW,omrežje,pravilniki,domene",
+    "X-KDE-Keywords[sr at ijekavian]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,колачићи,прегледање,Интернет,веб,мрежа,смерница,домени",
+    "X-KDE-Keywords[sr at ijekavianlatin]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,kolačići,pregledanje,Internet,veb,mreža,smernica,domeni",
+    "X-KDE-Keywords[sr at latin]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,kolačići,pregledanje,Internet,veb,mreža,smernica,domeni",
+    "X-KDE-Keywords[sr]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,колачићи,прегледање,Интернет,веб,мрежа,смерница,домени",
+    "X-KDE-Keywords[sv]": "Kakor,Webbläsning,Internet,WWW,Nätverk,Princip,Domäner",
+    "X-KDE-Keywords[ta]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,நினைவிகள்,குக்கிகள்,உலாவல்,இணையம்,பிணையம்,கொள்கை,ஆள்களம்",
+    "X-KDE-Keywords[tg]": "Кукиҳо,Тамошо,Интернет,WWW,Шабака,Сиёсат,Доменҳо",
+    "X-KDE-Keywords[tok]": "suwi linluwi, alasa linluwi, linluwi, ma WWW, kulupu ilo, lawa, nimi linluwi",
+    "X-KDE-Keywords[tr]": "Çerezler,Tarama,İnternet,WWW,Ağ,Politika,Alan Adları",
+    "X-KDE-Keywords[uk]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,кука,куки,перегляд,інтернет,мережа,правило,правила,домен,домени",
+    "X-KDE-Keywords[vi]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,Bánh quy,Duyệt,Liên Mạng,WWW,Mạng,Chính sách,Miền",
+    "X-KDE-Keywords[x-test]": "xxCookiesxx,xxBrowsingxx,xxInternetxx,xxWWWxx,xxNetworkxx,xxPolicyxx,xxDomainsxx",
+    "X-KDE-Keywords[zh_CN]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains,浏览,互联网,网络,策略,域名",
+    "X-KDE-Keywords[zh_TW]": "Cookies,Browsing,Internet,WWW,Network,Policy,Domains",
+    "X-KDE-ParentApp": "kcontrol",
+    "X-KDE-System-Settings-Parent-Category": "networksettings",
+    "X-KDE-Weight": 90
+}
diff --git a/kcms/cookies/kcookiesmain.cpp b/kcms/cookies/kcookiesmain.cpp
new file mode 100644
index 000000000..dc59503d8
--- /dev/null
+++ b/kcms/cookies/kcookiesmain.cpp
@@ -0,0 +1,81 @@
+/*
+    kcookiesmain.cpp - Cookies configuration
+
+    First version of cookies configuration:
+        SPDX-FileCopyrightText: Waldo Bastian <bastian at kde.org>
+    This dialog box:
+        SPDX-FileCopyrightText: David Faure <faure at kde.org>
+*/
+
+// Own
+#include "kcookiesmain.h"
+
+// Local
+#include "kcookiesmanagement.h"
+#include "kcookiespolicies.h"
+
+// Qt
+#include <QTabWidget>
+
+// KDE
+#include <KLocalizedString>
+#include <KPluginFactory>
+
+K_PLUGIN_CLASS_WITH_JSON(KCookiesMain, "kcm_cookies.json")
+
+KCookiesMain::KCookiesMain(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+{
+    management = nullptr;
+    bool managerOK = true;
+
+    QVBoxLayout *layout = new QVBoxLayout(widget());
+    tab = new QTabWidget(widget());
+    layout->addWidget(tab);
+
+    policies = new KCookiesPolicies(widget(), data, args);
+    tab->addTab(policies->widget(), i18n("&Policy"));
+    connect(policies, &KCModule::needsSaveChanged, this, [this]() {
+        setNeedsSave(policies->needsSave());
+    });
+
+    if (managerOK) {
+        management = new KCookiesManagement(widget(), data, args);
+        tab->addTab(management->widget(), i18n("&Management"));
+        connect(management, &KCModule::needsSaveChanged, this, [this]() {
+            setNeedsSave(management->needsSave());
+        });
+    }
+}
+
+KCookiesMain::~KCookiesMain()
+{
+}
+
+void KCookiesMain::save()
+{
+    policies->save();
+    if (management) {
+        management->save();
+    }
+}
+
+void KCookiesMain::load()
+{
+    policies->load();
+    if (management) {
+        management->load();
+    }
+}
+
+void KCookiesMain::defaults()
+{
+    QWidget *current = tab->currentWidget();
+    if (current == policies->widget()) {
+        policies->defaults();
+    } else if (management && current == management->widget()) {
+        management->defaults();
+    }
+}
+
+#include "kcookiesmain.moc"
diff --git a/kcms/cookies/kcookiesmain.h b/kcms/cookies/kcookiesmain.h
new file mode 100644
index 000000000..a5a277086
--- /dev/null
+++ b/kcms/cookies/kcookiesmain.h
@@ -0,0 +1,41 @@
+/*
+    kcookiesmain.h - Cookies configuration
+
+    First version of cookies configuration:
+        SPDX-FileCopyrightText: Waldo Bastian <bastian at kde.org>
+    This dialog box:
+        SPDX-FileCopyrightText: David Faure <faure at kde.org>
+*/
+
+#ifndef __KCOOKIESMAIN_H
+#define __KCOOKIESMAIN_H
+
+#include <KCModule>
+
+class QTabWidget;
+class KCookiesPolicies;
+class KCookiesManagement;
+
+class KCookiesMain : public KCModule
+{
+    Q_OBJECT
+public:
+    KCookiesMain(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KCookiesMain() override;
+
+    KCookiesPolicies *policyDlg()
+    {
+        return policies;
+    }
+
+    void save() override;
+    void load() override;
+    void defaults() override;
+
+private:
+    QTabWidget *tab;
+    KCookiesPolicies *policies;
+    KCookiesManagement *management;
+};
+
+#endif // __KCOOKIESMAIN_H
diff --git a/kcms/cookies/kcookiesmanagement.cpp b/kcms/cookies/kcookiesmanagement.cpp
new file mode 100644
index 000000000..fa88c2219
--- /dev/null
+++ b/kcms/cookies/kcookiesmanagement.cpp
@@ -0,0 +1,411 @@
+/*
+    kcookiesmanagement.cpp - Cookies manager
+
+    SPDX-FileCopyrightText: 2000-2001 Marco Pinelli <pinmc at orion.it>
+    SPDX-FileCopyrightText: 2000-2001 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Own
+#include "kcookiesmanagement.h"
+
+// Qt
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include <QPushButton>
+
+// KDE
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <QDateTime>
+#include <QLocale>
+// Local
+#include "kcookiesmain.h"
+#include "kcookiespolicies.h"
+
+QString tolerantFromAce(const QByteArray &_domain);
+
+struct CookieProp {
+    QString host;
+    QString name;
+    QString value;
+    QString domain;
+    QString path;
+    QString expireDate;
+    QString secure;
+    bool allLoaded;
+};
+
+CookieListViewItem::CookieListViewItem(QTreeWidget *parent, const QString &dom)
+    : QTreeWidgetItem(parent)
+{
+    init(nullptr, dom);
+}
+
+CookieListViewItem::CookieListViewItem(QTreeWidgetItem *parent, CookieProp *cookie)
+    : QTreeWidgetItem(parent)
+{
+    init(cookie);
+}
+
+CookieListViewItem::~CookieListViewItem()
+{
+    delete mCookie;
+}
+
+void CookieListViewItem::init(CookieProp *cookie, const QString &domain, bool cookieLoaded)
+{
+    mCookie = cookie;
+    mDomain = domain;
+    mCookiesLoaded = cookieLoaded;
+
+    if (mCookie) {
+        if (mDomain.isEmpty()) {
+            setText(0, tolerantFromAce(mCookie->host.toLatin1()));
+        } else {
+            setText(0, tolerantFromAce(mDomain.toLatin1()));
+        }
+        setText(1, mCookie->name);
+    } else {
+        QString siteName;
+        if (mDomain.startsWith(QLatin1Char('.'))) {
+            siteName = mDomain.mid(1);
+        } else {
+            siteName = mDomain;
+        }
+        setText(0, tolerantFromAce(siteName.toLatin1()));
+    }
+}
+
+CookieProp *CookieListViewItem::leaveCookie()
+{
+    CookieProp *ret = mCookie;
+    mCookie = nullptr;
+    return ret;
+}
+
+KCookiesManagement::KCookiesManagement(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+    , mDeleteAllFlag(false)
+    , mMainWidget(widget())
+{
+    mUi.setupUi(widget());
+    mUi.searchLineEdit->setTreeWidget(mUi.cookiesTreeWidget);
+    mUi.cookiesTreeWidget->setColumnWidth(0, 150);
+
+    connect(mUi.deleteButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteCurrent);
+    connect(mUi.deleteAllButton, &QAbstractButton::clicked, this, &KCookiesManagement::deleteAll);
+    connect(mUi.reloadButton, &QAbstractButton::clicked, this, &KCookiesManagement::reload);
+    connect(mUi.cookiesTreeWidget, &QTreeWidget::itemExpanded, this, &KCookiesManagement::listCookiesForDomain);
+    connect(mUi.cookiesTreeWidget, &QTreeWidget::currentItemChanged, this, &KCookiesManagement::updateForItem);
+    connect(mUi.cookiesTreeWidget, &QTreeWidget::itemDoubleClicked, this, &KCookiesManagement::showConfigPolicyDialog);
+    connect(mUi.configPolicyButton, &QAbstractButton::clicked, this, &KCookiesManagement::showConfigPolicyDialog);
+}
+
+KCookiesManagement::~KCookiesManagement()
+{
+}
+
+void KCookiesManagement::load()
+{
+    defaults();
+}
+
+void KCookiesManagement::save()
+{
+    // If delete all cookies was requested!
+    if (mDeleteAllFlag) {
+        QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                            QStringLiteral("/modules/kcookiejar"),
+                            QStringLiteral("org.kde.KCookieServer"),
+                            QDBusConnection::sessionBus());
+        QDBusReply<void> reply = kded.call(QStringLiteral("deleteAllCookies"));
+        if (!reply.isValid()) {
+            const QString title = i18n("D-Bus Communication Error");
+            const QString message = i18n("Unable to delete all the cookies as requested.");
+            KMessageBox::error(widget(), message, title);
+            return;
+        }
+        mDeleteAllFlag = false; // deleted[Cookies|Domains] have been cleared yet
+    }
+
+    // Certain groups of cookies were deleted...
+    QMutableStringListIterator it(mDeletedDomains);
+    while (it.hasNext()) {
+        QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                            QStringLiteral("/modules/kcookiejar"),
+                            QStringLiteral("org.kde.KCookieServer"),
+                            QDBusConnection::sessionBus());
+        QDBusReply<void> reply = kded.call(QStringLiteral("deleteCookiesFromDomain"), (it.next()));
+        if (!reply.isValid()) {
+            const QString title = i18n("D-Bus Communication Error");
+            const QString message = i18n("Unable to delete cookies as requested.");
+            KMessageBox::error(widget(), message, title);
+            return;
+        }
+        it.remove();
+    }
+
+    // Individual cookies were deleted...
+    bool success = true; // Maybe we can go on...
+    QMutableHashIterator<QString, CookiePropList> cookiesDom(mDeletedCookies);
+    while (cookiesDom.hasNext()) {
+        cookiesDom.next();
+        CookiePropList list = cookiesDom.value();
+        for (auto it = list.begin(); it < list.end(); ++it) {
+            CookieProp *cookie = *it;
+            QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                                QStringLiteral("/modules/kcookiejar"),
+                                QStringLiteral("org.kde.KCookieServer"),
+                                QDBusConnection::sessionBus());
+            QDBusReply<void> reply = kded.call(QStringLiteral("deleteCookie"), cookie->domain, cookie->host, cookie->path, cookie->name);
+            if (!reply.isValid()) {
+                success = false;
+                break;
+            }
+
+            list.removeOne(cookie);
+        }
+
+        if (!success) {
+            break;
+        }
+
+        mDeletedCookies.remove(cookiesDom.key());
+    }
+
+    setNeedsSave(false);
+}
+
+void KCookiesManagement::defaults()
+{
+    reset();
+    reload();
+}
+
+void KCookiesManagement::reset(bool deleteAll)
+{
+    if (!deleteAll) {
+        mDeleteAllFlag = false;
+    }
+
+    clearCookieDetails();
+    mDeletedDomains.clear();
+    mDeletedCookies.clear();
+
+    mUi.cookiesTreeWidget->clear();
+    mUi.deleteButton->setEnabled(false);
+    mUi.deleteAllButton->setEnabled(false);
+    mUi.configPolicyButton->setEnabled(false);
+}
+
+void KCookiesManagement::clearCookieDetails()
+{
+    mUi.nameLineEdit->clear();
+    mUi.valueLineEdit->clear();
+    mUi.domainLineEdit->clear();
+    mUi.pathLineEdit->clear();
+    mUi.expiresLineEdit->clear();
+    mUi.secureLineEdit->clear();
+}
+
+void KCookiesManagement::reload()
+{
+    QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                        QStringLiteral("/modules/kcookiejar"),
+                        QStringLiteral("org.kde.KCookieServer"),
+                        QDBusConnection::sessionBus());
+    QDBusReply<QStringList> reply = kded.call(QStringLiteral("findDomains"));
+
+    if (!reply.isValid()) {
+        const QString title = i18n("Information Lookup Failure");
+        const QString message = i18n(
+            "Unable to retrieve information about the "
+            "cookies stored on your computer.");
+        KMessageBox::error(widget(), message, title);
+        return;
+    }
+
+    if (mUi.cookiesTreeWidget->topLevelItemCount() > 0) {
+        reset();
+    }
+
+    CookieListViewItem *dom;
+    const QStringList domains(reply.value());
+    for (const QString &domain : domains) {
+        const QString siteName = (domain.startsWith(QLatin1Char('.')) ? domain.mid(1) : domain);
+        if (mUi.cookiesTreeWidget->findItems(siteName, Qt::MatchFixedString).isEmpty()) {
+            dom = new CookieListViewItem(mUi.cookiesTreeWidget, domain);
+            dom->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
+        }
+    }
+
+    // are there any cookies?
+    mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0);
+    mUi.cookiesTreeWidget->sortItems(0, Qt::AscendingOrder);
+    setNeedsSave(false);
+}
+
+Q_DECLARE_METATYPE(QList<int>)
+
+void KCookiesManagement::listCookiesForDomain(QTreeWidgetItem *item)
+{
+    CookieListViewItem *cookieDom = static_cast<CookieListViewItem *>(item);
+    if (!cookieDom || cookieDom->cookiesLoaded()) {
+        return;
+    }
+
+    QStringList cookies;
+    const QList<int> fields{0, 1, 2, 3};
+    // Always check for cookies in both "foo.bar" and ".foo.bar" domains...
+    const QString domain = cookieDom->domain() + QLatin1String(" .") + cookieDom->domain();
+    QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                        QStringLiteral("/modules/kcookiejar"),
+                        QStringLiteral("org.kde.KCookieServer"),
+                        QDBusConnection::sessionBus());
+    QDBusReply<QStringList> reply = kded.call(QStringLiteral("findCookies"), QVariant::fromValue(fields), domain, QString(), QString(), QString());
+    if (reply.isValid()) {
+        cookies.append(reply.value());
+    }
+
+    QStringListIterator it(cookies);
+    while (it.hasNext()) {
+        CookieProp *details = new CookieProp;
+        details->domain = it.next();
+        details->path = it.next();
+        details->name = it.next();
+        details->host = it.next();
+        details->allLoaded = false;
+        new CookieListViewItem(item, details);
+    }
+
+    if (!cookies.isEmpty()) {
+        static_cast<CookieListViewItem *>(item)->setCookiesLoaded();
+        mUi.searchLineEdit->updateSearch();
+    }
+}
+
+bool KCookiesManagement::cookieDetails(CookieProp *cookie)
+{
+    const QList<int> fields{4, 5, 7};
+
+    QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                        QStringLiteral("/modules/kcookiejar"),
+                        QStringLiteral("org.kde.KCookieServer"),
+                        QDBusConnection::sessionBus());
+    QDBusReply<QStringList> reply =
+        kded.call(QStringLiteral("findCookies"), QVariant::fromValue(fields), cookie->domain, cookie->host, cookie->path, cookie->name);
+    if (!reply.isValid()) {
+        return false;
+    }
+
+    const QStringList fieldVal = reply.value();
+
+    auto c = fieldVal.cbegin();
+    if (c == fieldVal.cend()) { // empty list, do not crash
+        return false;
+    }
+
+    bool ok;
+    cookie->value = *c++;
+    qint64 tmp = (*c++).toLongLong(&ok);
+
+    if (!ok || tmp == 0) {
+        cookie->expireDate = i18n("End of session");
+    } else {
+        QDateTime expDate = QDateTime::fromSecsSinceEpoch(tmp);
+        cookie->expireDate = QLocale().toString((expDate), QLocale::ShortFormat);
+    }
+
+    tmp = (*c).toUInt(&ok);
+    cookie->secure = i18n((ok && tmp) ? "Yes" : "No");
+    cookie->allLoaded = true;
+    return true;
+}
+
+void KCookiesManagement::updateForItem(QTreeWidgetItem *item)
+{
+    if (item) {
+        CookieListViewItem *cookieItem = static_cast<CookieListViewItem *>(item);
+        CookieProp *cookie = cookieItem->cookie();
+
+        if (cookie) {
+            if (cookie->allLoaded || cookieDetails(cookie)) {
+                mUi.nameLineEdit->setText(cookie->name);
+                mUi.valueLineEdit->setText(cookie->value);
+                mUi.domainLineEdit->setText(cookie->domain);
+                mUi.pathLineEdit->setText(cookie->path);
+                mUi.expiresLineEdit->setText(cookie->expireDate);
+                mUi.secureLineEdit->setText(cookie->secure);
+            }
+
+            mUi.configPolicyButton->setEnabled(false);
+        } else {
+            clearCookieDetails();
+            mUi.configPolicyButton->setEnabled(true);
+        }
+    } else {
+        mUi.configPolicyButton->setEnabled(false);
+    }
+    mUi.deleteButton->setEnabled(item != nullptr);
+}
+
+void KCookiesManagement::showConfigPolicyDialog()
+{
+    // Get current item
+    CookieListViewItem *item = static_cast<CookieListViewItem *>(mUi.cookiesTreeWidget->currentItem());
+    Q_ASSERT(item); // the button is disabled otherwise
+
+    if (item) {
+        KCookiesMain *mainDlg = qobject_cast<KCookiesMain *>(mMainWidget);
+        // must be present or something is really wrong.
+        Q_ASSERT(mainDlg);
+
+        KCookiesPolicies *policyDlg = mainDlg->policyDlg();
+        // must be present unless someone rewrote the widget in which case
+        // this needs to be re-written as well.
+        Q_ASSERT(policyDlg);
+
+        policyDlg->setPolicy(item->domain());
+    }
+}
+
+void KCookiesManagement::deleteCurrent()
+{
+    QTreeWidgetItem *currentItem = mUi.cookiesTreeWidget->currentItem();
+    Q_ASSERT(currentItem); // the button is disabled otherwise
+    CookieListViewItem *item = static_cast<CookieListViewItem *>(currentItem);
+    if (item->cookie()) {
+        CookieListViewItem *parent = static_cast<CookieListViewItem *>(item->parent());
+        CookiePropList list = mDeletedCookies.value(parent->domain());
+        list.append(item->leaveCookie());
+        mDeletedCookies.insert(parent->domain(), list);
+        delete item;
+        if (parent->childCount() == 0) {
+            delete parent;
+        }
+    } else {
+        mDeletedDomains.append(item->domain());
+        delete item;
+    }
+
+    currentItem = mUi.cookiesTreeWidget->currentItem();
+    if (currentItem) {
+        mUi.cookiesTreeWidget->setCurrentItem(currentItem);
+    } else {
+        clearCookieDetails();
+    }
+
+    mUi.deleteAllButton->setEnabled(mUi.cookiesTreeWidget->topLevelItemCount() > 0);
+
+    setNeedsSave(true);
+}
+
+void KCookiesManagement::deleteAll()
+{
+    mDeleteAllFlag = true;
+    reset(true);
+    setNeedsSave(true);
+}
diff --git a/kcms/cookies/kcookiesmanagement.h b/kcms/cookies/kcookiesmanagement.h
new file mode 100644
index 000000000..f002af901
--- /dev/null
+++ b/kcms/cookies/kcookiesmanagement.h
@@ -0,0 +1,89 @@
+/*
+    kcookiesmanagement.h - Cookies manager
+
+    SPDX-FileCopyrightText: 2000-2001 Marco Pinelli <pinmc at orion.it>
+    SPDX-FileCopyrightText: 2000-2001 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef KCOOKIESMANAGEMENT_H
+#define KCOOKIESMANAGEMENT_H
+
+#include <QHash>
+#include <QList>
+#include <QStringList>
+#include <QTreeWidget>
+
+#include "ui_kcookiesmanagement.h"
+#include <KCModule>
+
+struct CookieProp;
+
+class CookieListViewItem : public QTreeWidgetItem
+{
+public:
+    CookieListViewItem(QTreeWidget *parent, const QString &dom);
+    CookieListViewItem(QTreeWidgetItem *parent, CookieProp *cookie);
+    ~CookieListViewItem() override;
+
+    QString domain() const
+    {
+        return mDomain;
+    }
+    CookieProp *cookie() const
+    {
+        return mCookie;
+    }
+    CookieProp *leaveCookie();
+    void setCookiesLoaded()
+    {
+        mCookiesLoaded = true;
+    }
+    bool cookiesLoaded() const
+    {
+        return mCookiesLoaded;
+    }
+
+private:
+    void init(CookieProp *cookie, const QString &domain = QString(), bool cookieLoaded = false);
+    CookieProp *mCookie;
+    QString mDomain;
+    bool mCookiesLoaded;
+};
+
+class KCookiesManagement : public KCModule
+{
+    Q_OBJECT
+
+public:
+    explicit KCookiesManagement(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KCookiesManagement() override;
+
+    void load() override;
+    void save() override;
+    void defaults() override;
+
+private Q_SLOTS:
+    void deleteCurrent();
+    void deleteAll();
+    void reload();
+    void listCookiesForDomain(QTreeWidgetItem *);
+    void updateForItem(QTreeWidgetItem *);
+    void showConfigPolicyDialog();
+
+private:
+    void reset(bool deleteAll = false);
+    bool cookieDetails(CookieProp *cookie);
+    void clearCookieDetails();
+
+    bool mDeleteAllFlag;
+    QWidget *mMainWidget;
+    Ui::KCookiesManagementUI mUi;
+
+    QStringList mDeletedDomains;
+    typedef QList<CookieProp *> CookiePropList;
+    QHash<QString, CookiePropList> mDeletedCookies;
+};
+
+#endif // KCOOKIESMANAGEMENT_H
diff --git a/kcms/cookies/kcookiesmanagement.ui b/kcms/cookies/kcookiesmanagement.ui
new file mode 100644
index 000000000..ec20b053d
--- /dev/null
+++ b/kcms/cookies/kcookiesmanagement.ui
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KCookiesManagementUI</class>
+ <widget class="QWidget" name="KCookiesManagementUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>526</width>
+    <height>443</height>
+   </rect>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="KTreeWidgetSearchLine" name="searchLineEdit">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>Search</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" rowspan="5">
+    <widget class="QTreeWidget" name="cookiesTreeWidget">
+     <property name="toolTip">
+      <string>Search interactively for domains and hosts</string>
+     </property>
+     <property name="sortingEnabled">
+      <bool>true</bool>
+     </property>
+     <property name="allColumnsShowFocus">
+      <bool>true</bool>
+     </property>
+     <attribute name="headerDefaultSectionSize">
+      <number>200</number>
+     </attribute>
+     <attribute name="headerMinimumSectionSize">
+      <number>100</number>
+     </attribute>
+     <column>
+      <property name="text">
+       <string>Site</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Cookie Name</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QPushButton" name="deleteButton">
+     <property name="text">
+      <string>D&elete</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QPushButton" name="deleteAllButton">
+     <property name="text">
+      <string>Delete A&ll</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QPushButton" name="configPolicyButton">
+     <property name="text">
+      <string>Configure &Policy...</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QPushButton" name="reloadButton">
+     <property name="text">
+      <string>&Reload List</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>18</width>
+       <height>114</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="6" column="0" colspan="2">
+    <widget class="QGroupBox" name="detailsGroupBox">
+     <property name="title">
+      <string>Details</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <property name="verticalSpacing">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="nameLabel">
+        <property name="text">
+         <string>Name:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>nameLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="nameLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="valueLabel">
+        <property name="text">
+         <string>Value:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>valueLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLineEdit" name="valueLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="domainLabel">
+        <property name="text">
+         <string>Domain:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>domainLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLineEdit" name="domainLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="patchLabel">
+        <property name="text">
+         <string>Path:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>pathLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QLineEdit" name="pathLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="expiresLabel">
+        <property name="text">
+         <string>Expires:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>expiresLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QLineEdit" name="expiresLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="0">
+       <widget class="QLabel" name="secureLabel">
+        <property name="text">
+         <string>Secure:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>secureLineEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QLineEdit" name="secureLineEdit">
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KTreeWidgetSearchLine</class>
+   <extends>QLineEdit</extends>
+   <header>ktreewidgetsearchline.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/kcms/cookies/kcookiespolicies.cpp b/kcms/cookies/kcookiespolicies.cpp
new file mode 100644
index 000000000..bc4a5a573
--- /dev/null
+++ b/kcms/cookies/kcookiespolicies.cpp
@@ -0,0 +1,425 @@
+/**
+    kcookiespolicies.cpp - Cookies configuration
+
+    Original Authors
+    SPDX-FileCopyrightText: Waldo Bastian <bastian at kde.org>
+    SPDX-FileCopyrightText: 1999 David Faure <faure at kde.org>
+    SPDX-FileCopyrightText: 2008 Urs Wolfer <uwolfer @ kde.org>
+
+    Re-written by:
+    SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Own
+#include "kcookiespolicies.h"
+
+// Local
+#include "../ksaveioconfig.h"
+
+// Qt
+#include <QCheckBox>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include <QPushButton>
+
+// KDE
+#include <KConfig>
+#include <KConfigGroup>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <QUrl>
+
+// QUrl::fromAce/toAce don't accept a domain that starts with a '.', like we do here.
+// So we use these wrappers.
+QString tolerantFromAce(const QByteArray &_domain)
+{
+    QByteArray domain(_domain);
+    const bool hasDot = domain.startsWith('.');
+    if (hasDot) {
+        domain.remove(0, 1);
+    }
+    QString ret = QUrl::fromAce(domain);
+    if (hasDot) {
+        ret.prepend(QLatin1Char('.'));
+    }
+    return ret;
+}
+
+static QByteArray tolerantToAce(const QString &_domain)
+{
+    QString domain(_domain);
+    const bool hasDot = domain.startsWith(QLatin1Char('.'));
+    if (hasDot) {
+        domain.remove(0, 1);
+    }
+    QByteArray ret = QUrl::toAce(domain);
+    if (hasDot) {
+        ret.prepend('.');
+    }
+    return ret;
+}
+
+KCookiesPolicies::KCookiesPolicies(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+    , mSelectedItemsCount(0)
+{
+    mUi.setupUi(widget());
+    mUi.kListViewSearchLine->setTreeWidget(mUi.policyTreeWidget);
+    QList<int> columns;
+    columns.append(0);
+    mUi.kListViewSearchLine->setSearchColumns(columns);
+
+    mUi.pbNew->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
+    mUi.pbChange->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
+    mUi.pbDelete->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
+    mUi.pbDeleteAll->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
+
+    // Connect the main switch :) Enable/disable cookie support
+    connect(mUi.cbEnableCookies, &QAbstractButton::toggled, this, &KCookiesPolicies::cookiesEnabled);
+    connect(mUi.cbEnableCookies, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+
+    // Connect the preference check boxes...
+    connect(mUi.cbRejectCrossDomainCookies, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+    connect(mUi.cbAutoAcceptSessionCookies, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+
+    connect(mUi.rbPolicyAsk, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+    connect(mUi.rbPolicyAccept, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+    connect(mUi.rbPolicyAcceptForSession, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+    connect(mUi.rbPolicyReject, &QAbstractButton::toggled, this, &KCookiesPolicies::configChanged);
+    // Connect signals from the domain specific policy listview.
+    connect(mUi.policyTreeWidget, &QTreeWidget::itemSelectionChanged, this, &KCookiesPolicies::selectionChanged);
+    connect(mUi.policyTreeWidget, &QTreeWidget::itemDoubleClicked, this, qOverload<>(&KCookiesPolicies::changePressed));
+
+    // Connect the buttons...
+    connect(mUi.pbNew, &QAbstractButton::clicked, this, qOverload<>(&KCookiesPolicies::addPressed));
+    connect(mUi.pbChange, &QAbstractButton::clicked, this, qOverload<>(&KCookiesPolicies::changePressed));
+    connect(mUi.pbDelete, &QAbstractButton::clicked, this, &KCookiesPolicies::deletePressed);
+    connect(mUi.pbDeleteAll, &QAbstractButton::clicked, this, &KCookiesPolicies::deleteAllPressed);
+}
+
+KCookiesPolicies::~KCookiesPolicies()
+{
+}
+
+void KCookiesPolicies::configChanged()
+{
+    // kDebug() << "KCookiesPolicies::configChanged...";
+    setNeedsSave(true);
+}
+
+void KCookiesPolicies::cookiesEnabled(bool enable)
+{
+    mUi.bgDefault->setEnabled(enable);
+    mUi.bgPreferences->setEnabled(enable);
+    mUi.gbDomainSpecific->setEnabled(enable);
+}
+
+void KCookiesPolicies::setPolicy(const QString &domain)
+{
+    QTreeWidgetItemIterator it(mUi.policyTreeWidget);
+    bool hasExistingPolicy = false;
+    while (*it) {
+        if ((*it)->text(0) == domain) {
+            hasExistingPolicy = true;
+            break;
+        }
+        ++it;
+    }
+
+    if (hasExistingPolicy) {
+        changePressed((*it), false);
+    } else {
+        addPressed(domain);
+    }
+}
+
+void KCookiesPolicies::changePressed()
+{
+    changePressed(mUi.policyTreeWidget->currentItem());
+}
+
+void KCookiesPolicies::addPressed()
+{
+    addPressed(QString());
+}
+
+void KCookiesPolicies::changePressed(QTreeWidgetItem *item, bool state)
+{
+    Q_ASSERT(item);
+    const QString oldDomain(item->text(0));
+
+    KCookiesPolicySelectionDlg pdlg(widget());
+    pdlg.setWindowTitle(i18nc("@title:window", "Change Cookie Policy"));
+    pdlg.setPolicy(KCookieAdvice::strToAdvice(QString::fromLatin1(mDomainPolicyMap.value(oldDomain))));
+    pdlg.setEnableHostEdit(state, oldDomain);
+
+    if (pdlg.exec() && !pdlg.domain().isEmpty()) {
+        const QString newDomain = tolerantFromAce(pdlg.domain().toLatin1());
+        int advice = pdlg.advice();
+        if (newDomain == oldDomain || !handleDuplicate(newDomain, advice)) {
+            mDomainPolicyMap[newDomain] = KCookieAdvice::adviceToStr(advice);
+            item->setText(0, newDomain);
+            item->setText(1, i18n(mDomainPolicyMap.value(newDomain)));
+            configChanged();
+        }
+    }
+}
+
+void KCookiesPolicies::addPressed(const QString &domain, bool state)
+{
+    KCookiesPolicySelectionDlg pdlg(widget());
+    pdlg.setWindowTitle(i18nc("@title:window", "New Cookie Policy"));
+    pdlg.setEnableHostEdit(state, domain);
+
+    if (mUi.rbPolicyAccept->isChecked()) {
+        pdlg.setPolicy(KCookieAdvice::Reject);
+    } else {
+        pdlg.setPolicy(KCookieAdvice::Accept);
+    }
+
+    if (pdlg.exec() && !pdlg.domain().isEmpty()) {
+        const QString domain = tolerantFromAce(pdlg.domain().toLatin1());
+        int advice = pdlg.advice();
+
+        if (!handleDuplicate(domain, advice)) {
+            const char *strAdvice = KCookieAdvice::adviceToStr(advice);
+            const QStringList items{
+                domain,
+                i18n(strAdvice),
+            };
+            QTreeWidgetItem *item = new QTreeWidgetItem(mUi.policyTreeWidget, items);
+            mDomainPolicyMap.insert(item->text(0), strAdvice);
+            configChanged();
+            updateButtons();
+        }
+    }
+}
+
+bool KCookiesPolicies::handleDuplicate(const QString &domain, int advice)
+{
+    QTreeWidgetItem *item = mUi.policyTreeWidget->topLevelItem(0);
+    while (item != nullptr) {
+        if (item->text(0) == domain) {
+            const int res = KMessageBox::warningContinueCancel(widget(),
+                                                               i18n("<qt>A policy already exists for"
+                                                                    "<center><b>%1</b></center>"
+                                                                    "Do you want to replace it?</qt>",
+                                                                    domain),
+                                                               i18nc("@title:window", "Duplicate Policy"),
+                                                               KGuiItem(i18n("Replace")));
+            if (res == KMessageBox::Continue) {
+                mDomainPolicyMap[domain] = KCookieAdvice::adviceToStr(advice);
+                item->setText(0, domain);
+                item->setText(1, i18n(mDomainPolicyMap.value(domain)));
+                configChanged();
+                return true;
+            } else {
+                return true; // User Cancelled!!
+            }
+        }
+        item = mUi.policyTreeWidget->itemBelow(item);
+    }
+    return false;
+}
+
+void KCookiesPolicies::deletePressed()
+{
+    QTreeWidgetItem *nextItem = nullptr;
+
+    const QList<QTreeWidgetItem *> selectedItems = mUi.policyTreeWidget->selectedItems();
+    for (const QTreeWidgetItem *item : selectedItems) {
+        nextItem = mUi.policyTreeWidget->itemBelow(item);
+        if (!nextItem) {
+            nextItem = mUi.policyTreeWidget->itemAbove(item);
+        }
+
+        mDomainPolicyMap.remove(item->text(0));
+        delete item;
+    }
+
+    if (nextItem) {
+        nextItem->setSelected(true);
+    }
+
+    updateButtons();
+    configChanged();
+}
+
+void KCookiesPolicies::deleteAllPressed()
+{
+    mDomainPolicyMap.clear();
+    mUi.policyTreeWidget->clear();
+    updateButtons();
+    configChanged();
+}
+
+void KCookiesPolicies::updateButtons()
+{
+    bool hasItems = mUi.policyTreeWidget->topLevelItemCount() > 0;
+
+    mUi.pbChange->setEnabled((hasItems && mSelectedItemsCount == 1));
+    mUi.pbDelete->setEnabled((hasItems && mSelectedItemsCount > 0));
+    mUi.pbDeleteAll->setEnabled(hasItems);
+}
+
+void KCookiesPolicies::updateDomainList(const QStringList &domainConfig)
+{
+    mUi.policyTreeWidget->clear();
+
+    QStringList::ConstIterator it = domainConfig.begin();
+    for (; it != domainConfig.end(); ++it) {
+        QString domain;
+        KCookieAdvice::Value advice = KCookieAdvice::Dunno;
+        splitDomainAdvice(*it, domain, advice);
+        if (!domain.isEmpty()) {
+            const QStringList items{
+                tolerantFromAce(domain.toLatin1()),
+                i18n(KCookieAdvice::adviceToStr(advice)),
+            };
+            QTreeWidgetItem *item = new QTreeWidgetItem(mUi.policyTreeWidget, items);
+            mDomainPolicyMap[item->text(0)] = KCookieAdvice::adviceToStr(advice);
+        }
+    }
+
+    mUi.policyTreeWidget->sortItems(0, Qt::AscendingOrder);
+}
+
+void KCookiesPolicies::selectionChanged()
+{
+    mSelectedItemsCount = mUi.policyTreeWidget->selectedItems().count();
+    updateButtons();
+}
+
+void KCookiesPolicies::load()
+{
+    mSelectedItemsCount = 0;
+
+    KConfig cfg(QStringLiteral("kcookiejarrc"));
+    KConfigGroup group = cfg.group("Cookie Policy");
+
+    bool enableCookies = group.readEntry("Cookies", true);
+    mUi.cbEnableCookies->setChecked(enableCookies);
+    cookiesEnabled(enableCookies);
+
+    // Warning: the default values are duplicated in kcookiejar.cpp
+    KCookieAdvice::Value advice = KCookieAdvice::strToAdvice(group.readEntry("CookieGlobalAdvice", "Accept"));
+    switch (advice) {
+    case KCookieAdvice::Accept:
+        mUi.rbPolicyAccept->setChecked(true);
+        break;
+    case KCookieAdvice::AcceptForSession:
+        mUi.rbPolicyAcceptForSession->setChecked(true);
+        break;
+    case KCookieAdvice::Reject:
+        mUi.rbPolicyReject->setChecked(true);
+        break;
+    case KCookieAdvice::Ask:
+    case KCookieAdvice::Dunno:
+    default:
+        mUi.rbPolicyAsk->setChecked(true);
+    }
+
+    bool enable = group.readEntry("RejectCrossDomainCookies", true);
+    mUi.cbRejectCrossDomainCookies->setChecked(enable);
+
+    bool sessionCookies = group.readEntry("AcceptSessionCookies", true);
+    mUi.cbAutoAcceptSessionCookies->setChecked(sessionCookies);
+    updateDomainList(group.readEntry("CookieDomainAdvice", QStringList()));
+
+    if (enableCookies) {
+        updateButtons();
+    }
+}
+
+void KCookiesPolicies::save()
+{
+    KConfig cfg(QStringLiteral("kcookiejarrc"));
+    KConfigGroup group = cfg.group("Cookie Policy");
+
+    bool state = mUi.cbEnableCookies->isChecked();
+    group.writeEntry("Cookies", state);
+    state = mUi.cbRejectCrossDomainCookies->isChecked();
+    group.writeEntry("RejectCrossDomainCookies", state);
+    state = mUi.cbAutoAcceptSessionCookies->isChecked();
+    group.writeEntry("AcceptSessionCookies", state);
+
+    QString advice;
+    if (mUi.rbPolicyAccept->isChecked()) {
+        advice = QString::fromLatin1(KCookieAdvice::adviceToStr(KCookieAdvice::Accept));
+    } else if (mUi.rbPolicyAcceptForSession->isChecked()) {
+        advice = QString::fromLatin1(KCookieAdvice::adviceToStr(KCookieAdvice::AcceptForSession));
+    } else if (mUi.rbPolicyReject->isChecked()) {
+        advice = QString::fromLatin1(KCookieAdvice::adviceToStr(KCookieAdvice::Reject));
+    } else {
+        advice = QString::fromLatin1(KCookieAdvice::adviceToStr(KCookieAdvice::Ask));
+    }
+
+    group.writeEntry("CookieGlobalAdvice", advice);
+
+    QStringList domainConfig;
+    QMapIterator<QString, const char *> it(mDomainPolicyMap);
+    while (it.hasNext()) {
+        it.next();
+        const QString policy = QLatin1String(tolerantToAce(it.key())) + QLatin1Char(':') + QLatin1String(it.value());
+        domainConfig << policy;
+    }
+
+    group.writeEntry("CookieDomainAdvice", domainConfig);
+    group.sync();
+
+    // Update the cookiejar...
+    if (!mUi.cbEnableCookies->isChecked()) {
+        QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                            QStringLiteral("/modules/kcookiejar"),
+                            QStringLiteral("org.kde.KCookieServer"),
+                            QDBusConnection::sessionBus());
+        kded.call(QStringLiteral("shutdown"));
+    } else {
+        QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"),
+                            QStringLiteral("/modules/kcookiejar"),
+                            QStringLiteral("org.kde.KCookieServer"),
+                            QDBusConnection::sessionBus());
+        QDBusReply<void> reply = kded.call(QStringLiteral("reloadPolicy"));
+        if (!reply.isValid()) {
+            KMessageBox::error(nullptr,
+                               i18n("Unable to communicate with the cookie handler service.\n"
+                                    "Any changes you made will not take effect until the service "
+                                    "is restarted."));
+        }
+    }
+
+    // Force running KIO workers to reload configurations...
+    KSaveIOConfig::updateRunningWorkers(widget());
+    setNeedsSave(false);
+}
+
+void KCookiesPolicies::defaults()
+{
+    mUi.cbEnableCookies->setChecked(true);
+    mUi.rbPolicyAsk->setChecked(true);
+    mUi.rbPolicyAccept->setChecked(false);
+    mUi.rbPolicyAcceptForSession->setChecked(false);
+    mUi.rbPolicyReject->setChecked(false);
+    mUi.cbRejectCrossDomainCookies->setChecked(true);
+    mUi.cbAutoAcceptSessionCookies->setChecked(false);
+    mUi.policyTreeWidget->clear();
+    mDomainPolicyMap.clear();
+
+    cookiesEnabled(mUi.cbEnableCookies->isChecked());
+    updateButtons();
+}
+
+void KCookiesPolicies::splitDomainAdvice(const QString &cfg, QString &domain, KCookieAdvice::Value &advice)
+{
+    int sepPos = cfg.lastIndexOf(QLatin1Char(':'));
+
+    // Ignore any policy that does not contain a domain...
+    if (sepPos <= 0) {
+        return;
+    }
+
+    domain = cfg.left(sepPos);
+    advice = KCookieAdvice::strToAdvice(cfg.mid(sepPos + 1));
+}
diff --git a/kcms/cookies/kcookiespolicies.h b/kcms/cookies/kcookiespolicies.h
new file mode 100644
index 000000000..5cf0bb39d
--- /dev/null
+++ b/kcms/cookies/kcookiespolicies.h
@@ -0,0 +1,64 @@
+/*
+    kcookiespolicies.h - Cookies configuration
+
+    Original Authors
+    SPDX-FileCopyrightText: Waldo Bastian <bastian at kde.org>
+    SPDX-FileCopyrightText: 1999 David Faure <faure at kde.org>
+
+    Re-written by:
+    SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef KCOOKIESPOLICIES_H
+#define KCOOKIESPOLICIES_H
+
+#include <KCModule>
+#include <QMap>
+
+#include "kcookiespolicyselectiondlg.h"
+#include "ui_kcookiespolicies.h"
+
+class QTreeWidgetItem;
+
+class KCookiesPolicies : public KCModule
+{
+    Q_OBJECT
+
+public:
+    explicit KCookiesPolicies(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KCookiesPolicies() override;
+
+    void load() override;
+    void save() override;
+    void defaults() override;
+
+    void setPolicy(const QString &domain);
+
+protected Q_SLOTS:
+    void cookiesEnabled(bool);
+    void configChanged();
+
+    void selectionChanged();
+    void updateButtons();
+
+    void deleteAllPressed();
+    void deletePressed();
+    void changePressed();
+    void addPressed();
+    void changePressed(QTreeWidgetItem *, bool state = true);
+    void addPressed(const QString &, bool state = true);
+
+private:
+    void updateDomainList(const QStringList &list);
+    bool handleDuplicate(const QString &domain, int);
+    void splitDomainAdvice(const QString &configStr, QString &domain, KCookieAdvice::Value &advice);
+
+private:
+    quint64 mSelectedItemsCount;
+    Ui::KCookiePoliciesUI mUi;
+    QMap<QString, const char *> mDomainPolicyMap;
+};
+
+#endif // KCOOKIESPOLICIES_H
diff --git a/kcms/cookies/kcookiespolicies.ui b/kcms/cookies/kcookiespolicies.ui
new file mode 100644
index 000000000..0f0300f3f
--- /dev/null
+++ b/kcms/cookies/kcookiespolicies.ui
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KCookiePoliciesUI</class>
+ <widget class="QWidget" name="KCookiePoliciesUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>555</width>
+    <height>317</height>
+   </rect>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <item row="0" column="0">
+    <widget class="QCheckBox" name="cbEnableCookies">
+     <property name="whatsThis">
+      <string><qt>
+<p>Enable cookie support. Normally you will want to have cookie support enabled and customize it to suit your privacy needs.</p><p>
+Please note that disabling cookie support might make many web sites unbrowsable.</p>
+</qt></string>
+     </property>
+     <property name="text">
+      <string>Enable coo&kies</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QGroupBox" name="bgPreferences">
+     <layout class="QVBoxLayout">
+      <item>
+       <widget class="QCheckBox" name="cbRejectCrossDomainCookies">
+        <property name="whatsThis">
+         <string><qt>
+Reject the so called third-party cookies. These are cookies that originate from a site other than the one you are currently browsing. For example, if you visit <b>www.foobar.com</b> while this option is on, only cookies that originate from www.foobar.com will be processed per your settings. Cookies from any other site will be rejected. This reduces the chances of site operators compiling a profile about your daily browsing habits.
+</qt></string>
+        </property>
+        <property name="text">
+         <string>Only acce&pt cookies from originating server</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="cbAutoAcceptSessionCookies">
+        <property name="whatsThis">
+         <string><p>
+Automatically accept temporary cookies meant to expire at the end of the current session. Such cookies will not be stored in your computer's hard drive or storage device. Instead, they are deleted when you close all applications (e.g. your browser) that use them.</p><p><u>NOTE</u> Checking this option overrides your default as well as site specific cookie policies for session cookies.</p></string>
+        </property>
+        <property name="text">
+         <string>Automaticall&y accept session cookies</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QGroupBox" name="bgDefault">
+     <property name="whatsThis">
+      <string><qt>
+Determines how cookies received from a remote machine will be handled: 
+<ul>
+<li><b>Ask</b> will cause KDE to ask for your confirmation whenever a server wants to set a cookie.</li>
+<li><b>Accept</b> will cause cookies to be accepted without prompting you.</li>
+<li><b>Accept until end of session</b> will cause cookies to be accepted but they will expire at the end of the session.</li>
+<li><b>Reject</b> will cause the cookiejar to refuse all cookies it receives.</li>
+</ul><p>
+<u>NOTE:</u> Domain specific policies, which can be set below, always take precedence over the default policy.</p>
+</qt></string>
+     </property>
+     <property name="title">
+      <string>Default Policy</string>
+     </property>
+     <layout class="QVBoxLayout">
+      <item>
+       <widget class="QRadioButton" name="rbPolicyAccept">
+        <property name="text">
+         <string>Accep&t all cookies</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="rbPolicyAcceptForSession">
+        <property name="text">
+         <string>Accept &until end of session</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="rbPolicyAsk">
+        <property name="text">
+         <string>Ask &for confirmation</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="rbPolicyReject">
+        <property name="text">
+         <string>Re&ject all cookies</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>40</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QGroupBox" name="gbDomainSpecific">
+     <property name="whatsThis">
+      <string><qt>
+To add a new policy, simply click on the <b>Add...</b> button and supply the necessary information. To change an existing policy, use the <b>Change...</b> button and choose the new policy from the policy dialog box. Clicking on the <b>Delete</b> button will remove the currently selected policy causing the default policy setting to be used for that domain, whereas <b>Delete All</b> will remove all the site specific policies.
+</qt></string>
+     </property>
+     <property name="title">
+      <string>Site Policy</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="KTreeWidgetSearchLine" name="kListViewSearchLine">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="toolTip">
+         <string>Search interactively for domains</string>
+        </property>
+        <property name="placeholderText">
+         <string>Search...</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" rowspan="5">
+       <widget class="QTreeWidget" name="policyTreeWidget">
+        <property name="whatsThis">
+         <string><qt>
+List of sites for which you have set a specific cookie policy. Specific policies override the default policy setting for these sites.
+</qt></string>
+        </property>
+        <property name="selectionMode">
+         <enum>QAbstractItemView::ExtendedSelection</enum>
+        </property>
+        <property name="rootIsDecorated">
+         <bool>false</bool>
+        </property>
+        <property name="sortingEnabled">
+         <bool>true</bool>
+        </property>
+        <property name="allColumnsShowFocus">
+         <bool>true</bool>
+        </property>
+        <column>
+         <property name="text">
+          <string>Domain</string>
+         </property>
+        </column>
+        <column>
+         <property name="text">
+          <string>Policy</string>
+         </property>
+        </column>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="pbNew">
+        <property name="text">
+         <string>&New...</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QPushButton" name="pbChange">
+        <property name="text">
+         <string>Chan&ge...</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QPushButton" name="pbDelete">
+        <property name="text">
+         <string>D&elete</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QPushButton" name="pbDeleteAll">
+        <property name="text">
+         <string>Delete A&ll</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <spacer>
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>81</width>
+          <height>47</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KTreeWidgetSearchLine</class>
+   <extends>QLineEdit</extends>
+   <header>ktreewidgetsearchline.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/kcms/cookies/kcookiespolicyselectiondlg.cpp b/kcms/cookies/kcookiespolicyselectiondlg.cpp
new file mode 100644
index 000000000..b07dd039a
--- /dev/null
+++ b/kcms/cookies/kcookiespolicyselectiondlg.cpp
@@ -0,0 +1,124 @@
+/*
+    SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Own
+#include "kcookiespolicyselectiondlg.h"
+
+// Qt
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QValidator>
+#include <QWhatsThis>
+
+// KDE
+#include <QLineEdit>
+#include <QVBoxLayout>
+
+class DomainNameValidator : public QValidator
+{
+    Q_OBJECT
+public:
+    DomainNameValidator(QObject *parent)
+        : QValidator(parent)
+    {
+        setObjectName(QStringLiteral("domainValidator"));
+    }
+
+    State validate(QString &input, int &) const override
+    {
+        if (input.isEmpty() || (input == QLatin1Char('.'))) {
+            return Intermediate;
+        }
+
+        const int length = input.length();
+
+        for (int i = 0; i < length; i++) {
+            if (!input[i].isLetterOrNumber() && input[i] != QLatin1Char('.') && input[i] != QLatin1Char('-')) {
+                return Invalid;
+            }
+        }
+
+        return Acceptable;
+    }
+};
+
+KCookiesPolicySelectionDlg::KCookiesPolicySelectionDlg(QWidget *parent, Qt::WindowFlags flags)
+    : QDialog(parent, flags)
+    , mOldPolicy(-1)
+    , mButtonBox(nullptr)
+{
+    QWidget *mainWidget = new QWidget(this);
+    QVBoxLayout *mainLayout = new QVBoxLayout(this);
+    mainLayout->addWidget(mainWidget);
+    mUi.setupUi(mainWidget);
+    mUi.leDomain->setValidator(new DomainNameValidator(mUi.leDomain));
+    mUi.cbPolicy->setMinimumWidth(mUi.cbPolicy->fontMetrics().maxWidth() * 15);
+
+    mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+    mainLayout->addWidget(mButtonBox);
+
+    connect(mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+    connect(mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+    mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+    connect(mUi.leDomain, &QLineEdit::textEdited, this, &KCookiesPolicySelectionDlg::slotTextChanged);
+    connect(mUi.cbPolicy, qOverload<int>(&QComboBox::currentIndexChanged), this, [this](const int index) {
+        slotPolicyChanged(mUi.cbPolicy->itemText(index));
+    });
+
+    mUi.leDomain->setFocus();
+}
+
+void KCookiesPolicySelectionDlg::setEnableHostEdit(bool state, const QString &host)
+{
+    if (!host.isEmpty()) {
+        mUi.leDomain->setText(host);
+        mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(state);
+    }
+
+    mUi.leDomain->setEnabled(state);
+}
+
+void KCookiesPolicySelectionDlg::setPolicy(int policy)
+{
+    if (policy > -1 && policy <= static_cast<int>(mUi.cbPolicy->count())) {
+        const bool blocked = mUi.cbPolicy->blockSignals(true);
+        mUi.cbPolicy->setCurrentIndex(policy - 1);
+        mUi.cbPolicy->blockSignals(blocked);
+        mOldPolicy = policy;
+    }
+
+    if (!mUi.leDomain->isEnabled()) {
+        mUi.cbPolicy->setFocus();
+    }
+}
+
+int KCookiesPolicySelectionDlg::advice() const
+{
+    return mUi.cbPolicy->currentIndex() + 1;
+}
+
+QString KCookiesPolicySelectionDlg::domain() const
+{
+    return mUi.leDomain->text();
+}
+
+void KCookiesPolicySelectionDlg::slotTextChanged(const QString &text)
+{
+    mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(text.length() > 1);
+}
+
+void KCookiesPolicySelectionDlg::slotPolicyChanged(const QString &policyText)
+{
+    const int policy = KCookieAdvice::strToAdvice(policyText);
+    if (!mUi.leDomain->isEnabled()) {
+        mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(policy != mOldPolicy);
+    } else {
+        slotTextChanged(policyText);
+    }
+}
+
+#include "kcookiespolicyselectiondlg.moc"
diff --git a/kcms/cookies/kcookiespolicyselectiondlg.h b/kcms/cookies/kcookiespolicyselectiondlg.h
new file mode 100644
index 000000000..c7a508cde
--- /dev/null
+++ b/kcms/cookies/kcookiespolicyselectiondlg.h
@@ -0,0 +1,83 @@
+/*
+    SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef KCOOKIESPOLICYSELECTIONDLG_H
+#define KCOOKIESPOLICYSELECTIONDLG_H
+
+#include "ui_kcookiespolicyselectiondlg.h"
+#include <KLazyLocalizedString>
+#include <QDialog>
+
+class QWidget;
+class QDialogButtonBox;
+
+class KCookieAdvice
+{
+public:
+    enum Value { Dunno = 0, Accept, AcceptForSession, Reject, Ask };
+
+    static const char *adviceToStr(const int &advice)
+    {
+        switch (advice) {
+        case KCookieAdvice::Accept:
+            return kli18n("Accept").untranslatedText();
+        case KCookieAdvice::AcceptForSession:
+            return kli18n("Accept For Session").untranslatedText();
+        case KCookieAdvice::Reject:
+            return kli18n("Reject").untranslatedText();
+        case KCookieAdvice::Ask:
+            return kli18n("Ask").untranslatedText();
+        default:
+            return kli18n("Do Not Know").untranslatedText();
+        }
+    }
+
+    static KCookieAdvice::Value strToAdvice(const QString &_str)
+    {
+        if (_str.isEmpty())
+            return KCookieAdvice::Dunno;
+
+        QString advice = _str.toLower().remove(QLatin1Char(' '));
+
+        if (advice == QLatin1String("accept"))
+            return KCookieAdvice::Accept;
+        else if (advice == QLatin1String("acceptforsession"))
+            return KCookieAdvice::AcceptForSession;
+        else if (advice == QLatin1String("reject"))
+            return KCookieAdvice::Reject;
+        else if (advice == QLatin1String("ask"))
+            return KCookieAdvice::Ask;
+
+        return KCookieAdvice::Dunno;
+    }
+};
+
+class KCookiesPolicySelectionDlg : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit KCookiesPolicySelectionDlg(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
+    ~KCookiesPolicySelectionDlg() override
+    {
+    }
+
+    int advice() const;
+    QString domain() const;
+
+    void setEnableHostEdit(bool, const QString &host = QString());
+    void setPolicy(int policy);
+
+protected Q_SLOTS:
+    void slotTextChanged(const QString &);
+    void slotPolicyChanged(const QString &);
+
+private:
+    int mOldPolicy;
+    Ui::KCookiesPolicySelectionDlgUI mUi;
+    QDialogButtonBox *mButtonBox;
+};
+#endif
diff --git a/kcms/cookies/kcookiespolicyselectiondlg.ui b/kcms/cookies/kcookiespolicyselectiondlg.ui
new file mode 100644
index 000000000..25f3bf24b
--- /dev/null
+++ b/kcms/cookies/kcookiespolicyselectiondlg.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KCookiesPolicySelectionDlgUI</class>
+ <widget class="QWidget" name="KCookiesPolicySelectionDlgUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>287</width>
+    <height>81</height>
+   </rect>
+  </property>
+  <layout class="QFormLayout" name="formLayout">
+   <property name="fieldGrowthPolicy">
+    <enum>QFormLayout::ExpandingFieldsGrow</enum>
+   </property>
+   <item row="0" column="0">
+    <widget class="QLabel" name="lbDomain">
+     <property name="whatsThis">
+      <string><qt>
+Enter the host or domain to which this policy applies, e.g. <b>www.kde.org</b> or <b>.kde.org</b>.
+</qt></string>
+     </property>
+     <property name="text">
+      <string>Site name:</string>
+     </property>
+     <property name="wordWrap">
+      <bool>false</bool>
+     </property>
+     <property name="buddy">
+      <cstring>leDomain</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="leDomain">
+     <property name="whatsThis">
+      <string>Enter the host or domain name, e.g. .kde.org, this policy applies to.</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="lbPolicy">
+     <property name="whatsThis">
+      <string><qt>
+Select the desired policy:
+<ul>
+<li><b>Accept</b> - Allows this site to set cookies</li>
+<li><b>Accept until end of session</b> - Allows this site to set cookies but they will expire at the end of the session.</li>
+<li><b>Reject</b> - Refuse all cookies sent from this site</li>
+<li><b>Ask</b> - Prompt when cookies are received from this site</li>
+</ul>
+</qt></string>
+     </property>
+     <property name="text">
+      <string>Policy:</string>
+     </property>
+     <property name="wordWrap">
+      <bool>false</bool>
+     </property>
+     <property name="buddy">
+      <cstring>cbPolicy</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QComboBox" name="cbPolicy">
+     <property name="whatsThis">
+      <string><qt>
+Select the desired policy:
+<ul>
+<li><b>Accept</b> - Allows this site to set cookies</li>
+<li><b>Accept until end of session</b> - Allows this site to set cookies but they will expire at the end of the session.</li>
+<li><b>Reject</b> - Refuse all cookies sent from this site</li>
+<li><b>Ask</b> - Prompt when cookies are received from this site</li>
+</ul>
+</qt></string>
+     </property>
+     <item>
+      <property name="text">
+       <string>Accept</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Accept until end of session</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Reject</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Ask</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/kcms/ksaveioconfig.cpp b/kcms/ksaveioconfig.cpp
new file mode 100644
index 000000000..666149e9a
--- /dev/null
+++ b/kcms/ksaveioconfig.cpp
@@ -0,0 +1,227 @@
+/*
+    SPDX-FileCopyrightText: 2001 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+// Own
+#include "ksaveioconfig.h"
+
+// Qt
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QDBusReply>
+
+// KDE
+#include <KConfig>
+#include <KConfigGroup>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <kio/ioworker_defaults.h>
+class KSaveIOConfigPrivate
+{
+public:
+    KSaveIOConfigPrivate();
+    ~KSaveIOConfigPrivate();
+
+    KConfig *config = nullptr;
+    KConfig *http_config = nullptr;
+};
+
+Q_GLOBAL_STATIC(KSaveIOConfigPrivate, d)
+
+KSaveIOConfigPrivate::KSaveIOConfigPrivate()
+{
+}
+
+KSaveIOConfigPrivate::~KSaveIOConfigPrivate()
+{
+    delete config;
+    delete http_config;
+}
+
+static KConfig *config()
+{
+    if (!d->config) {
+        d->config = new KConfig(QStringLiteral("kioslaverc"), KConfig::NoGlobals);
+        // KF6 TODO: rename to kioworkerrc here and elsewhere. See also T15956.
+    }
+
+    return d->config;
+}
+
+static KConfig *http_config()
+{
+    if (!d->http_config) {
+        d->http_config = new KConfig(QStringLiteral("kio_httprc"), KConfig::NoGlobals);
+    }
+
+    return d->http_config;
+}
+
+int KSaveIOConfig::proxyDisplayUrlFlags()
+{
+    KConfigGroup cfg(config(), QString());
+    return cfg.readEntry("ProxyUrlDisplayFlags", 0);
+}
+
+void KSaveIOConfig::setProxyDisplayUrlFlags(int flags)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("ProxyUrlDisplayFlags", flags);
+    cfg.sync();
+}
+
+void KSaveIOConfig::reparseConfiguration()
+{
+    delete d->config;
+    d->config = nullptr;
+    delete d->http_config;
+    d->http_config = nullptr;
+}
+
+void KSaveIOConfig::setReadTimeout(int _timeout)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("ReadTimeout", qMax(MIN_TIMEOUT_VALUE, _timeout));
+    cfg.sync();
+}
+
+void KSaveIOConfig::setConnectTimeout(int _timeout)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("ConnectTimeout", qMax(MIN_TIMEOUT_VALUE, _timeout));
+    cfg.sync();
+}
+
+void KSaveIOConfig::setProxyConnectTimeout(int _timeout)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("ProxyConnectTimeout", qMax(MIN_TIMEOUT_VALUE, _timeout));
+    cfg.sync();
+}
+
+void KSaveIOConfig::setResponseTimeout(int _timeout)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("ResponseTimeout", qMax(MIN_TIMEOUT_VALUE, _timeout));
+    cfg.sync();
+}
+
+void KSaveIOConfig::setMarkPartial(bool _mode)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("MarkPartial", _mode);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setMinimumKeepSize(int _size)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("MinimumKeepSize", _size);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setAutoResume(bool _mode)
+{
+    KConfigGroup cfg(config(), QString());
+    cfg.writeEntry("AutoResume", _mode);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setUseCache(bool _mode)
+{
+    KConfigGroup cfg(http_config(), QString());
+    cfg.writeEntry("UseCache", _mode);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setMaxCacheSize(int cache_size)
+{
+    KConfigGroup cfg(http_config(), QString());
+    cfg.writeEntry("MaxCacheSize", cache_size);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setCacheControl(KIO::CacheControl policy)
+{
+    KConfigGroup cfg(http_config(), QString());
+    QString tmp = KIO::getCacheControlString(policy);
+    cfg.writeEntry("cache", tmp);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setMaxCacheAge(int cache_age)
+{
+    KConfigGroup cfg(http_config(), QString());
+    cfg.writeEntry("MaxCacheAge", cache_age);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setUseReverseProxy(bool mode)
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    cfg.writeEntry("ReversedException", mode);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setProxyType(KProtocolManager::ProxyType type)
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    cfg.writeEntry("ProxyType", static_cast<int>(type));
+    cfg.sync();
+}
+
+QString KSaveIOConfig::noProxyFor()
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    return cfg.readEntry("NoProxyFor");
+}
+
+void KSaveIOConfig::setNoProxyFor(const QString &_noproxy)
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    cfg.writeEntry("NoProxyFor", _noproxy);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setProxyFor(const QString &protocol, const QString &_proxy)
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    cfg.writeEntry(protocol.toLower() + QLatin1String("Proxy"), _proxy);
+    cfg.sync();
+}
+
+void KSaveIOConfig::setProxyConfigScript(const QString &_url)
+{
+    KConfigGroup cfg(config(), "Proxy Settings");
+    cfg.writeEntry("Proxy Config Script", _url);
+    cfg.sync();
+}
+
+void KSaveIOConfig::updateRunningWorkers(QWidget *parent)
+{
+    // Inform all running KIO workers about the changes...
+    // if we cannot update, KIO workers inform the end user...
+    QDBusMessage message =
+        QDBusMessage::createSignal(QStringLiteral("/KIO/Scheduler"), QStringLiteral("org.kde.KIO.Scheduler"), QStringLiteral("reparseSlaveConfiguration"));
+    message << QString();
+    if (!QDBusConnection::sessionBus().send(message)) {
+        KMessageBox::information(parent,
+                                 i18n("You have to restart the running applications "
+                                      "for these changes to take effect."),
+                                 i18nc("@title:window", "Update Failed"));
+    }
+}
+
+void KSaveIOConfig::updateProxyScout(QWidget *parent)
+{
+    // Inform the proxyscout kded module about changes if we cannot update,
+    // KIO workers inform the end user...
+    QDBusInterface kded(QStringLiteral("org.kde.kcookiejar5"), QStringLiteral("/modules/proxyscout"), QStringLiteral("org.kde.KPAC.ProxyScout"));
+    QDBusReply<void> reply = kded.call(QStringLiteral("reset"));
+    if (!reply.isValid()) {
+        KMessageBox::information(parent, i18n("You have to restart KDE for these changes to take effect."), i18nc("@title:window", "Update Failed"));
+    }
+}
diff --git a/kcms/ksaveioconfig.h b/kcms/ksaveioconfig.h
new file mode 100644
index 000000000..15d34ec24
--- /dev/null
+++ b/kcms/ksaveioconfig.h
@@ -0,0 +1,66 @@
+/*
+    SPDX-FileCopyrightText: 2001 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KSAVEIO_CONFIG_H_
+#define KSAVEIO_CONFIG_H_
+
+#include <kprotocolmanager.h>
+
+class QWidget;
+
+namespace KSaveIOConfig
+{
+int proxyDisplayUrlFlags();
+void setProxyDisplayUrlFlags(int);
+
+/* Reload config file (kioslaverc) */
+void reparseConfiguration();
+
+/** Timeout Settings */
+void setReadTimeout(int);
+
+void setConnectTimeout(int);
+
+void setProxyConnectTimeout(int);
+
+void setResponseTimeout(int);
+
+/** Cache Settings */
+void setMaxCacheAge(int);
+
+void setUseCache(bool);
+
+void setMaxCacheSize(int);
+
+void setCacheControl(KIO::CacheControl);
+
+/** Proxy Settings */
+void setUseReverseProxy(bool);
+
+void setProxyType(KProtocolManager::ProxyType);
+
+void setProxyConfigScript(const QString &);
+
+void setProxyFor(const QString &, const QString &);
+
+QString noProxyFor();
+void setNoProxyFor(const QString &);
+
+/** Miscellaneous Settings */
+void setMarkPartial(bool);
+
+void setMinimumKeepSize(int);
+
+void setAutoResume(bool);
+
+/** Update all running KIO workers */
+void updateRunningWorkers(QWidget *parent = nullptr);
+
+/** Update proxy scout */
+void updateProxyScout(QWidget *parent = nullptr);
+}
+
+#endif
diff --git a/kcms/netpref/CMakeLists.txt b/kcms/netpref/CMakeLists.txt
new file mode 100644
index 000000000..a5d5253e7
--- /dev/null
+++ b/kcms/netpref/CMakeLists.txt
@@ -0,0 +1,25 @@
+find_package(KF6TextWidgets ${KF_DEP_VERSION} REQUIRED)
+
+kcoreaddons_add_plugin(kcm_netpref INSTALL_NAMESPACE "plasma/kcms/systemsettings_qwidgets")
+
+kcmutils_generate_desktop_file(kcm_netpref)
+target_sources(kcm_netpref PRIVATE
+    netpref.cpp
+    ../ksaveioconfig.cpp
+)
+
+target_link_libraries(kcm_netpref
+  PUBLIC
+    Qt6::DBus
+    KF6::ConfigCore
+    KF6::KCMUtils
+    KF6::KIOCore
+    KF6::TextWidgets # KPluralHandlingSpinBox
+  PRIVATE
+    KF6::I18n
+    KF6::CoreAddons
+)
+
+if (ENABLE_PCH)
+    target_precompile_headers(kcm_netpref REUSE_FROM KIOPchCore)
+endif()
diff --git a/kcms/netpref/kcm_netpref.json b/kcms/netpref/kcm_netpref.json
new file mode 100644
index 000000000..82226ac77
--- /dev/null
+++ b/kcms/netpref/kcm_netpref.json
@@ -0,0 +1,120 @@
+{
+    "KPlugin": {
+        "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=systemsettings&component=kcm_netpref",
+        "Description": "Configure generic network preferences, like timeout values",
+        "Description[ar]": "يضبط تفضيلات الشبكة العامة مثل قيم المهلات الإتصالات",
+        "Description[bg]": "Настройване на общите мрежови параметри",
+        "Description[ca at valencia]": "Configureu les preferències genèriques de la xarxa, com ara els valors dels temps d'espera",
+        "Description[ca]": "Configuració de les preferències genèriques de la xarxa, com ara els valors dels temps d'espera",
+        "Description[cs]": "Nastavení obecných předvoleb sítě, např. časových limitů",
+        "Description[de]": "Einfache Netzwerkeinstellungen vornehmen wie z. B. Zeitüberschreitungen",
+        "Description[en_GB]": "Configure generic network preferences, like timeout values",
+        "Description[eo]": "Agordi ĝeneralajn retprefereojn, kiel ekz. tempolimvaloroj",
+        "Description[es]": "Configurar las preferencias de red genéricas, como los valores de espera",
+        "Description[eu]": "Konfiguratu sarerako hobespen orokorrak, denbora-muga balioak, besteak beste",
+        "Description[fi]": "Yleiset verkkoasetukset",
+        "Description[fr]": "Configurer les préférences génériques du réseau, comme les valeurs des délais impartis",
+        "Description[gl]": "Configurar as preferencias xenéricas de rede, como os tempos límite",
+        "Description[ia]": "Configura le preferentia de rete generic, como valores pro expirationes de tempore",
+        "Description[is]": "Grunnstilla almennar netstillingar, eins og hámarkstíma",
+        "Description[it]": "Configura le preferenze di rete generiche, come i tempi di scadenza",
+        "Description[ka]": "ქსელის ზოგადი პარამეტრების მორგება",
+        "Description[ko]": "제한 시간 값 같이 일반 네트워크에서 기본이 되는 값 설정하기",
+        "Description[nl]": "Instellen van algemene netwerkvoorkeuren, zoals tijdslimietwaarden",
+        "Description[nn]": "Oppsett av generelle nettverksinnstillingar, som for eksempel tidsgrenser",
+        "Description[pl]": "Ustawienia niskopoziomowych ustawień sieciowych np. limitu czasu",
+        "Description[sl]": "Konfiguriraj splošne preference omrežja ko npr. časovne omejitve",
+        "Description[tr]": "Zaman aşımı değerleri gibi genel ağ tercihlerini yapılandır",
+        "Description[uk]": "Налаштування загальних параметрів мережі, зокрема значень тайм-аутів",
+        "Description[x-test]": "xxConfigure generic network preferences, like timeout valuesxx",
+        "Description[zh_TW]": "調整一般網路設定,例如逾時值",
+        "Icon": "preferences-system-network-connection",
+        "Name": "Connection Preferences",
+        "Name[ar]": "تفضيلات الاتّصال",
+        "Name[bg]": "Настройване на връзката",
+        "Name[ca at valencia]": "Preferències de connexió",
+        "Name[ca]": "Preferències de connexió",
+        "Name[cs]": "Předvolby připojení",
+        "Name[de]": "Verbindungseinstellungen",
+        "Name[en_GB]": "Connection Preferences",
+        "Name[eo]": "Preferoj pri Konektado",
+        "Name[es]": "Preferencias de la conexión",
+        "Name[eu]": "Konexio hobespenak",
+        "Name[fi]": "Yhteysasetukset",
+        "Name[fr]": "Préférences de connexion",
+        "Name[gl]": "Configuración da conexión",
+        "Name[ia]": "Preferentias de connexion",
+        "Name[is]": "Kjörstillingar tengingar",
+        "Name[it]": "Preferenze delle connessioni",
+        "Name[ka]": "კავშირის პარამეტრები",
+        "Name[ko]": "연결 설정",
+        "Name[nl]": "Verbindingsvoorkeuren",
+        "Name[nn]": "Tilkoplingsinnstillingar",
+        "Name[pl]": "Ustawienia połączeń",
+        "Name[sl]": "Preference povezave",
+        "Name[tr]": "Bağlantı Tercihleri",
+        "Name[uk]": "Параметри з'єднання",
+        "Name[x-test]": "xxConnection Preferencesxx",
+        "Name[zh_TW]": "連線設定"
+    },
+    "X-DocPath": "kcontrol6/netpref/index.html",
+    "X-KDE-Keywords": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[ar]": "وقت المهلة,iopref,netpref,تفضيلات الشبكة,ftp",
+    "X-KDE-Keywords[az]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[be at latin]": "termin čakannia,iopref,netpref,nalady sietki,ftp",
+    "X-KDE-Keywords[be]": "тэрмін чакання,iopref,netpref,налады сеткі,ftp",
+    "X-KDE-Keywords[bg]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[bs]": "tajmaut,iopref,netpref,mrežne preferencije,ftp",
+    "X-KDE-Keywords[ca at valencia]": "temps d'espera,iopref,netpref,preferències de xarxa,ftp",
+    "X-KDE-Keywords[ca]": "temps d'espera,iopref,netpref,preferències de xarxa,ftp",
+    "X-KDE-Keywords[cy]": "goramser,iopref,netpref,dewisiadau rhwydwaith, ftp",
+    "X-KDE-Keywords[da]": "tidsudløb,timeout,iopref,netpref,netværksindstillinger,ftp",
+    "X-KDE-Keywords[de]": "Zeitlimit,Zeitüberschreitung,Netzwerkeinstellungen,Ein-/Ausgabemodul-Einstellungen",
+    "X-KDE-Keywords[el]": "χρονικό όριο,iopref,netpref,προτιμήσεις δικτύου,ftp",
+    "X-KDE-Keywords[en_GB]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[es]": "tiempo de espera,iopref,netpref,preferencias de red,ftp",
+    "X-KDE-Keywords[et]": "aegumine,iopref,netpref,võrk,eelistused,ftp",
+    "X-KDE-Keywords[eu]": "denbora muga,iopref,netpref,sare hobespenak,ftp",
+    "X-KDE-Keywords[fi]": "aikakatkaisu,iopref,netpref,verkkoasetukset,ftp",
+    "X-KDE-Keywords[fr]": "délai dépassé, iopref, netpref, paramètres réseau, ftp",
+    "X-KDE-Keywords[gd]": "timeout,iopref,netpref,network preferences,ftp,ùine,falbh,falbhaidh an ùine,roghainnean an lìonraidh,lìonra",
+    "X-KDE-Keywords[gl]": "tempo límite,iopref,netpref,rede,preferencias,ftp",
+    "X-KDE-Keywords[hu]": "időtúllépés,iopref,netpref,hálózati beállítások,ftp",
+    "X-KDE-Keywords[ia]": "expiration,iopref,prefderete,rete,preferentias,ftp",
+    "X-KDE-Keywords[id]": "batas waktu,iopref,netpref,preferensi jaringan,ftp",
+    "X-KDE-Keywords[ie]": "timeout,iopref,netpref,preferenties del rete,ftp",
+    "X-KDE-Keywords[is]": "tímalokun,iopref,netpref,kjörstillingar nets,ftp",
+    "X-KDE-Keywords[it]": "scadenza,iopref,netpref,preferenze di rete,ftp",
+    "X-KDE-Keywords[ka]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[ko]": "timeout,iopref,netpref,network preferences,ftp,시간,시간 초과,네트워크 설정",
+    "X-KDE-Keywords[lt]": "skirtasis laikas,skirtas laikas,laiko limitas,laukimo laikas,tinklo nuostatos,tinklo nustatymai,tinklo parinktys,ftp",
+    "X-KDE-Keywords[my]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-Keywords[nb]": "tidsavbrudd,iopref,netpref,nettverksoppsett,ftp",
+    "X-KDE-Keywords[nl]": "timeout,iopref,netpref,netwerk voorkeuren,ftp",
+    "X-KDE-Keywords[nn]": "tidsavbrot,iopref,netpref,nettverksinnstillinger,ftp",
+    "X-KDE-Keywords[pa]": "ਟਾਈਮਆਉਟ,ਸਮਾਂ-ਸਮਾਪਤ,ਪਸੰਦ,ਤਰਜੀਹਾਂ,ਐਫਟੀਪੀ,ਨੈੱਟਵਰਕ",
+    "X-KDE-Keywords[pl]": "czas oczekiwania,iopref,netpref,ustawienia sieci,ftp",
+    "X-KDE-Keywords[pt]": "tempo-limite,iopref,netpref,preferências da rede,ftp",
+    "X-KDE-Keywords[pt_BR]": "tempo-limite,iopref,netpref,preferências de rede,ftp",
+    "X-KDE-Keywords[ro]": "expirare,iopref,netpref,preferințe rețea,ftp",
+    "X-KDE-Keywords[ru]": "timeout,iopref,netpref,network preferences,ftp,задержка,время ожидания,таймаут,параметры сети",
+    "X-KDE-Keywords[sk]": "timeout,iopref,netpref,sieťové nastavenia,ftp",
+    "X-KDE-Keywords[sl]": "časovna omejitev,iopref,netpref,možnosti omrežja,ftp",
+    "X-KDE-Keywords[sr at ijekavian]": "timeout,iopref,netpref,network preferences,ftp,прековреме,мрежне поставке,ФТП",
+    "X-KDE-Keywords[sr at ijekavianlatin]": "timeout,iopref,netpref,network preferences,ftp,prekovreme,mrežne postavke,FTP",
+    "X-KDE-Keywords[sr at latin]": "timeout,iopref,netpref,network preferences,ftp,prekovreme,mrežne postavke,FTP",
+    "X-KDE-Keywords[sr]": "timeout,iopref,netpref,network preferences,ftp,прековреме,мрежне поставке,ФТП",
+    "X-KDE-Keywords[sv]": "tidsgräns,iopref,netpref,nätverk,inställningar,ftp",
+    "X-KDE-Keywords[ta]": "timeout,iopref,netpref,network preferences,ftp,காலாவதி,பிணைய விருப்பத்தேர்வுகள்,இணைய விருப்பத்தேர்வுகள்",
+    "X-KDE-Keywords[tg]": "анҷоми вақти интизорӣ,iopref,хусусиятҳои интернет,хусусиятҳои шабака,ftp",
+    "X-KDE-Keywords[tok]": "kulupu ilo,linja,tenpo suli,ftp,linluwi",
+    "X-KDE-Keywords[tr]": "zaman aşımı,girdi çıktı tercihleri,ağ tercihleri,ağ ayarları,ftp",
+    "X-KDE-Keywords[uk]": "timeout,iopref,netpref,network preferences,ftp,очікування,тайм-аут,мережа,параметри,налаштування",
+    "X-KDE-Keywords[vi]": "timeout,iopref,netpref,network preferences,ftp,thời hạn,các thiết lập mạng",
+    "X-KDE-Keywords[x-test]": "xxtimeoutxx,xxioprefxx,xxnetprefxx,xxnetwork preferencesxx,xxftpxx",
+    "X-KDE-Keywords[zh_CN]": "timeout,iopref,netpref,network preferences,ftp,超时,网络首选项",
+    "X-KDE-Keywords[zh_TW]": "timeout,iopref,netpref,network preferences,ftp",
+    "X-KDE-ParentApp": "kcontrol",
+    "X-KDE-System-Settings-Parent-Category": "networksettings",
+    "X-KDE-Weight": 50
+}
diff --git a/kcms/netpref/kio_ftprc.kcfg b/kcms/netpref/kio_ftprc.kcfg
new file mode 100644
index 000000000..610b2e68a
--- /dev/null
+++ b/kcms/netpref/kio_ftprc.kcfg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 
+                          http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kio_ftprc" />
+ <group name="DesktopIcons" >
+ 
+   <entry name="DisablePassiveMode" type="Bool">
+     <label>Disable Passive FTP</label>
+     <whatsthis>When FTP connections are passive the client connects to the server, instead of the other way round, so firewalls do not block the connection; old FTP servers may not support Passive FTP though.</whatsthis>
+     <default>false</default>
+   </entry>
+
+   <entry name="MarkPartial" type="Bool">
+     <label>Mark partially uploaded files</label>
+     <whatsthis>While a file is being uploaded its extension is ".part". When fully uploaded it is renamed to its real name.</whatsthis>
+     <default>true</default>
+   </entry>
+
+ </group>
+</kcfg>
diff --git a/kcms/netpref/kio_ftprc.kcfgc b/kcms/netpref/kio_ftprc.kcfgc
new file mode 100644
index 000000000..7b5ca780f
--- /dev/null
+++ b/kcms/netpref/kio_ftprc.kcfgc
@@ -0,0 +1,5 @@
+File=kio_ftprc.kcfg
+ClassName=KioFtp
+Singleton=true
+Mutators=true
+
diff --git a/kcms/netpref/kioslave.kcfg b/kcms/netpref/kioslave.kcfg
new file mode 100644
index 000000000..b017d4a6d
--- /dev/null
+++ b/kcms/netpref/kioslave.kcfg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 
+                          http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kioslaverc" />
+ <group name="General">
+   <entry name="PersistentProxyConnection" type="Bool">
+     <default>false</default>
+   </entry>
+   <entry name="ProxyConnectTimeout" type="UInt" >
+     <default>10</default>
+     <min>2</min>
+     <max>3600</max>
+   </entry>
+   <entry name="ConnectTimeout" type="UInt" >
+     <default>20</default>
+     <min>2</min>
+     <max>3600</max>
+   </entry>
+   <entry name="ReadTimeout" type="UInt" >
+     <default>15</default>
+     <min>2</min>
+     <max>3600</max>
+   </entry>
+   <entry name="ResponseTimeout" type="UInt" >
+     <default>600</default>
+     <min>2</min>
+     <max>3600</max>
+   </entry>
+ </group>
+ <group name="Global Options">
+   <entry name="MarkPartial" type="Bool">
+     <label>Mark partially uploaded files</label>
+     <whatsthis>While a file is being uploaded its extension is ".part". When fully uploaded it is renamed to its real name.</whatsthis>
+     <default>true</default>
+   </entry>
+ </group>
+ <group name="Proxy Settings" >
+   <entry name="AuthMode" type="String" >
+   </entry>
+   <entry name="ReversedException" type="Bool">
+   </entry>
+   <entry name="ftpProxy" type="String">
+   </entry>
+   <entry name="httpProxy" type="String">
+   </entry>
+   <entry name="httpsProxy" type="String">
+   </entry>
+ </group>
+</kcfg>
diff --git a/kcms/netpref/kioslave.kcfgc b/kcms/netpref/kioslave.kcfgc
new file mode 100644
index 000000000..fd522c042
--- /dev/null
+++ b/kcms/netpref/kioslave.kcfgc
@@ -0,0 +1,5 @@
+File=kioslave.kcfg
+ClassName=KioSlave
+Singleton=true
+Mutators=true
+
diff --git a/kcms/netpref/netpref.cpp b/kcms/netpref/netpref.cpp
new file mode 100644
index 000000000..491a8d4b2
--- /dev/null
+++ b/kcms/netpref/netpref.cpp
@@ -0,0 +1,183 @@
+
+// Own
+#include "netpref.h"
+
+// Qt
+#include <QCheckBox>
+#include <QFormLayout>
+#include <QGroupBox>
+
+// KDE
+#include <KConfig>
+#include <KConfigGroup>
+#include <KLocalizedString>
+#include <KPluginFactory>
+#include <KPluralHandlingSpinBox>
+#include <kio/ioworker_defaults.h>
+
+// Local
+#include "../ksaveioconfig.h"
+
+static constexpr int s_maxTimeoutValue = 3600;
+
+K_PLUGIN_CLASS_WITH_JSON(KIOPreferences, "kcm_netpref.json")
+
+KIOPreferences::KIOPreferences(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+{
+    QVBoxLayout *mainLayout = new QVBoxLayout(widget());
+    mainLayout->setContentsMargins(0, 0, 0, 0);
+    gb_Timeout = new QGroupBox(i18n("Timeout Values"), widget());
+    gb_Timeout->setWhatsThis(
+        i18np("Here you can set timeout values. "
+              "You might want to tweak them if your "
+              "connection is very slow. The maximum "
+              "allowed value is 1 second.",
+              "Here you can set timeout values. "
+              "You might want to tweak them if your "
+              "connection is very slow. The maximum "
+              "allowed value is %1 seconds.",
+              s_maxTimeoutValue));
+    mainLayout->addWidget(gb_Timeout);
+
+    QFormLayout *timeoutLayout = new QFormLayout(gb_Timeout);
+    sb_socketRead = new KPluralHandlingSpinBox(widget());
+    sb_socketRead->setSuffix(ki18np(" second", " seconds"));
+    connect(sb_socketRead, qOverload<int>(&QSpinBox::valueChanged), this, &KIOPreferences::configChanged);
+    timeoutLayout->addRow(i18n("Soc&ket read:"), sb_socketRead);
+
+    sb_proxyConnect = new KPluralHandlingSpinBox(widget());
+    sb_proxyConnect->setValue(0);
+    sb_proxyConnect->setSuffix(ki18np(" second", " seconds"));
+    connect(sb_proxyConnect, qOverload<int>(&QSpinBox::valueChanged), this, &KIOPreferences::configChanged);
+    timeoutLayout->addRow(i18n("Pro&xy connect:"), sb_proxyConnect);
+
+    sb_serverConnect = new KPluralHandlingSpinBox(widget());
+    sb_serverConnect->setValue(0);
+    sb_serverConnect->setSuffix(ki18np(" second", " seconds"));
+    connect(sb_serverConnect, qOverload<int>(&QSpinBox::valueChanged), this, &KIOPreferences::configChanged);
+    timeoutLayout->addRow(i18n("Server co&nnect:"), sb_serverConnect);
+
+    sb_serverResponse = new KPluralHandlingSpinBox(widget());
+    sb_serverResponse->setValue(0);
+    sb_serverResponse->setSuffix(ki18np(" second", " seconds"));
+    connect(sb_serverResponse, qOverload<int>(&QSpinBox::valueChanged), this, &KIOPreferences::configChanged);
+    timeoutLayout->addRow(i18n("&Server response:"), sb_serverResponse);
+
+    QGroupBox *gb_Global = new QGroupBox(i18n("Global Options"), widget());
+    mainLayout->addWidget(gb_Global);
+    QVBoxLayout *globalLayout = new QVBoxLayout(gb_Global);
+
+    cb_globalMarkPartial = new QCheckBox(i18n("Mark &partially uploaded files"), widget());
+    cb_globalMarkPartial->setWhatsThis(
+        i18n("<p>Marks partially uploaded files "
+             "through SMB, SFTP and other protocols."
+             "</p><p>When this option is "
+             "enabled, partially uploaded files "
+             "will have a \".part\" extension. "
+             "This extension will be removed "
+             "once the transfer is complete.</p>"));
+    connect(cb_globalMarkPartial, &QAbstractButton::toggled, this, &KIOPreferences::configChanged);
+    globalLayout->addWidget(cb_globalMarkPartial);
+
+    auto partialWidget = new QWidget(widget());
+    connect(cb_globalMarkPartial, &QAbstractButton::toggled, partialWidget, &QWidget::setEnabled);
+    globalLayout->addWidget(partialWidget);
+    auto partialLayout = new QFormLayout(partialWidget);
+    partialLayout->setContentsMargins(20, 0, 0, 0); // indent below mark partial
+
+    sb_globalMinimumKeepSize = new KPluralHandlingSpinBox(widget());
+    sb_globalMinimumKeepSize->setSuffix(ki18np(" byte", " bytes"));
+    connect(sb_globalMinimumKeepSize, qOverload<int>(&QSpinBox::valueChanged), this, &KIOPreferences::configChanged);
+    partialLayout->addRow(i18nc("@label:spinbox", "If cancelled, automatically delete partially uploaded files smaller than:"), sb_globalMinimumKeepSize);
+
+    gb_Ftp = new QGroupBox(i18n("FTP Options"), widget());
+    mainLayout->addWidget(gb_Ftp);
+    QVBoxLayout *ftpLayout = new QVBoxLayout(gb_Ftp);
+
+    cb_ftpEnablePasv = new QCheckBox(i18n("Enable passive &mode (PASV)"), widget());
+    cb_ftpEnablePasv->setWhatsThis(
+        i18n("Enables FTP's \"passive\" mode. "
+             "This is required to allow FTP to "
+             "work from behind firewalls."));
+    connect(cb_ftpEnablePasv, &QAbstractButton::toggled, this, &KIOPreferences::configChanged);
+    ftpLayout->addWidget(cb_ftpEnablePasv);
+
+    cb_ftpMarkPartial = new QCheckBox(i18n("Mark &partially uploaded files"), widget());
+    cb_ftpMarkPartial->setWhatsThis(
+        i18n("<p>Marks partially uploaded FTP "
+             "files.</p><p>When this option is "
+             "enabled, partially uploaded files "
+             "will have a \".part\" extension. "
+             "This extension will be removed "
+             "once the transfer is complete.</p>"));
+    connect(cb_ftpMarkPartial, &QAbstractButton::toggled, this, &KIOPreferences::configChanged);
+    ftpLayout->addWidget(cb_ftpMarkPartial);
+
+    mainLayout->addStretch(1);
+}
+
+KIOPreferences::~KIOPreferences()
+{
+}
+
+void KIOPreferences::load()
+{
+    KProtocolManager proto;
+
+    sb_socketRead->setRange(MIN_TIMEOUT_VALUE, s_maxTimeoutValue);
+    sb_serverResponse->setRange(MIN_TIMEOUT_VALUE, s_maxTimeoutValue);
+    sb_serverConnect->setRange(MIN_TIMEOUT_VALUE, s_maxTimeoutValue);
+    sb_proxyConnect->setRange(MIN_TIMEOUT_VALUE, s_maxTimeoutValue);
+
+    sb_socketRead->setValue(proto.readTimeout());
+    sb_serverResponse->setValue(proto.responseTimeout());
+    sb_serverConnect->setValue(proto.connectTimeout());
+    sb_proxyConnect->setValue(proto.proxyConnectTimeout());
+
+    cb_globalMarkPartial->setChecked(proto.markPartial());
+    sb_globalMinimumKeepSize->setRange(0, 1024 * 1024 * 1024 /* 1 GiB */);
+    sb_globalMinimumKeepSize->setValue(proto.minimumKeepSize());
+
+    KConfig config(QStringLiteral("kio_ftprc"), KConfig::NoGlobals);
+    cb_ftpEnablePasv->setChecked(!config.group("").readEntry("DisablePassiveMode", false));
+    cb_ftpMarkPartial->setChecked(config.group("").readEntry("MarkPartial", true));
+    setNeedsSave(false);
+}
+
+void KIOPreferences::save()
+{
+    KSaveIOConfig::setReadTimeout(sb_socketRead->value());
+    KSaveIOConfig::setResponseTimeout(sb_serverResponse->value());
+    KSaveIOConfig::setConnectTimeout(sb_serverConnect->value());
+    KSaveIOConfig::setProxyConnectTimeout(sb_proxyConnect->value());
+
+    KSaveIOConfig::setMarkPartial(cb_globalMarkPartial->isChecked());
+    KSaveIOConfig::setMinimumKeepSize(sb_globalMinimumKeepSize->value());
+
+    KConfig config(QStringLiteral("kio_ftprc"), KConfig::NoGlobals);
+    config.group("").writeEntry("DisablePassiveMode", !cb_ftpEnablePasv->isChecked());
+    config.group("").writeEntry("MarkPartial", cb_ftpMarkPartial->isChecked());
+    config.sync();
+
+    KSaveIOConfig::updateRunningWorkers(widget());
+
+    setNeedsSave(false);
+}
+
+void KIOPreferences::defaults()
+{
+    sb_socketRead->setValue(DEFAULT_READ_TIMEOUT);
+    sb_serverResponse->setValue(DEFAULT_RESPONSE_TIMEOUT);
+    sb_serverConnect->setValue(DEFAULT_CONNECT_TIMEOUT);
+    sb_proxyConnect->setValue(DEFAULT_PROXY_CONNECT_TIMEOUT);
+
+    cb_globalMarkPartial->setChecked(true);
+
+    cb_ftpEnablePasv->setChecked(true);
+    cb_ftpMarkPartial->setChecked(true);
+
+    setNeedsSave(true);
+}
+
+#include "netpref.moc"
diff --git a/kcms/netpref/netpref.h b/kcms/netpref/netpref.h
new file mode 100644
index 000000000..fecae0fde
--- /dev/null
+++ b/kcms/netpref/netpref.h
@@ -0,0 +1,43 @@
+#ifndef NETPREF_H
+#define NETPREF_H
+
+#include <KCModule>
+
+class QGroupBox;
+class QCheckBox;
+
+class KPluralHandlingSpinBox;
+
+class KIOPreferences : public KCModule
+{
+    Q_OBJECT
+
+public:
+    KIOPreferences(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KIOPreferences() override;
+
+    void load() override;
+    void save() override;
+    void defaults() override;
+
+protected Q_SLOTS:
+    void configChanged()
+    {
+        setNeedsSave(true);
+    }
+
+private:
+    QGroupBox *gb_Ftp;
+    QGroupBox *gb_Timeout;
+    QCheckBox *cb_globalMarkPartial;
+    KPluralHandlingSpinBox *sb_globalMinimumKeepSize;
+    QCheckBox *cb_ftpEnablePasv;
+    QCheckBox *cb_ftpMarkPartial;
+
+    KPluralHandlingSpinBox *sb_socketRead;
+    KPluralHandlingSpinBox *sb_proxyConnect;
+    KPluralHandlingSpinBox *sb_serverConnect;
+    KPluralHandlingSpinBox *sb_serverResponse;
+};
+
+#endif // NETPREF_H
diff --git a/kcms/proxy/CMakeLists.txt b/kcms/proxy/CMakeLists.txt
new file mode 100644
index 000000000..5db3d2468
--- /dev/null
+++ b/kcms/proxy/CMakeLists.txt
@@ -0,0 +1,25 @@
+kcoreaddons_add_plugin(kcm_proxy INSTALL_NAMESPACE "plasma/kcms/systemsettings_qwidgets")
+
+kcmutils_generate_desktop_file(kcm_smb)
+
+target_sources(kcm_proxy PRIVATE
+    kproxydlg.cpp
+    ../ksaveioconfig.cpp
+)
+
+ki18n_wrap_ui(kcm_proxy
+    kproxydlg.ui
+)
+
+target_link_libraries(kcm_proxy PRIVATE
+    Qt6::Widgets
+    KF6::CoreAddons
+    KF6::ConfigCore
+    KF6::I18n
+    KF6::KCMUtils
+    KF6::KIOWidgets
+)
+
+if (ENABLE_PCH)
+    target_precompile_headers(kcm_proxy REUSE_FROM KIOPchWidgets)
+endif()
diff --git a/kcms/proxy/kcm_proxy.json b/kcms/proxy/kcm_proxy.json
new file mode 100644
index 000000000..06151a8e6
--- /dev/null
+++ b/kcms/proxy/kcm_proxy.json
@@ -0,0 +1,122 @@
+{
+    "KPlugin": {
+        "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=systemsettings&component=kcm_proxy",
+        "Description": "Configure the proxy servers used",
+        "Description[ar]": "اضبط خواديم الوسطاء المستخدمة",
+        "Description[bg]": "Настройване на прокси сървъра",
+        "Description[ca at valencia]": "Configura els servidors intermediaris emprats",
+        "Description[ca]": "Configura els servidors intermediaris emprats",
+        "Description[cs]": "Nastavení proxy serverů",
+        "Description[de]": "Proxy-Server einrichten",
+        "Description[en_GB]": "Configure the proxy servers used",
+        "Description[eo]": "Agordi la prokurservilojn uzatajn",
+        "Description[es]": "Configurar los servidores proxy que se usan",
+        "Description[eu]": "Konfiguratu erabilitako ordezkari zerbitzariak",
+        "Description[fi]": "Välityspalvelimien asetukset",
+        "Description[fr]": "Configurer les serveurs mandataires utilisés",
+        "Description[gl]": "Configurar os servidores proxy usados",
+        "Description[ia]": "Configura le servitores de proxy usate",
+        "Description[is]": "Grunnstilla milliþjóna sem á að nota",
+        "Description[it]": "Configura i server proxy da usare",
+        "Description[ka]": "პროქსი სერვერის მორგება",
+        "Description[ko]": "사용할 프록시 서버 설정",
+        "Description[nl]": "Hier kunt u de Proxy-servers instellen",
+        "Description[nn]": "Oppsett av mellomtenarar",
+        "Description[pl]": "Ustawienia serwerów pośredniczących",
+        "Description[sl]": "Konfiguraj uporabljene posredniške strežnike",
+        "Description[tr]": "Kullanılan vekil sunucuları yapılandır",
+        "Description[uk]": "Налаштування проксі-сервера",
+        "Description[x-test]": "xxConfigure the proxy servers usedxx",
+        "Description[zh_TW]": "設定代理伺服器如何被使用",
+        "Icon": "preferences-system-network-proxy",
+        "Name": "Proxy",
+        "Name[ar]": "الوسيط",
+        "Name[ast]": "Proxy",
+        "Name[bg]": "Прокси",
+        "Name[ca at valencia]": "Servidor intermediari",
+        "Name[ca]": "Servidor intermediari",
+        "Name[cs]": "Proxy",
+        "Name[de]": "Proxy",
+        "Name[en_GB]": "Proxy",
+        "Name[eo]": "Prokurilo",
+        "Name[es]": "Proxy",
+        "Name[eu]": "Ordezkaria",
+        "Name[fi]": "Välityspalvelin",
+        "Name[fr]": "Serveur mandataire",
+        "Name[gl]": "Proxy",
+        "Name[ia]": "Proxy",
+        "Name[is]": "Milliþjónn (proxy)",
+        "Name[it]": "Proxy",
+        "Name[ka]": "პროქსი",
+        "Name[ko]": "프록시",
+        "Name[nl]": "Proxy",
+        "Name[nn]": "Mellomtenar",
+        "Name[pl]": "Pośrednik",
+        "Name[sl]": "Posrednik",
+        "Name[tr]": "Vekil",
+        "Name[uk]": "Проксі",
+        "Name[x-test]": "xxProxyxx",
+        "Name[zh_TW]": "代理伺服器"
+    },
+    "X-DocPath": "kcontrol6/proxy/index.html",
+    "X-KDE-Keywords": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[ar]": "وسيط,خادم وسيط,جدار حماية,سكود",
+    "X-KDE-Keywords[az]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[be at latin]": "Proksi,Proksi-siervier,Fajrvol,Squid",
+    "X-KDE-Keywords[be]": "Проксі,Проксі-сервер,Файрвол,Squid",
+    "X-KDE-Keywords[bg]": "Прокси,Прокси сървър,Защитна стена,Squid",
+    "X-KDE-Keywords[bs]": "Proksi,Proksi server,Firewall,Squid",
+    "X-KDE-Keywords[ca at valencia]": "Intermediari,Servidor intermediari,Tallafoc,Squid",
+    "X-KDE-Keywords[ca]": "Intermediari,Servidor intermediari,Tallafoc,Squid",
+    "X-KDE-Keywords[cs]": "Proxy,Server Proxy,Firewall,Squid",
+    "X-KDE-Keywords[cy]": "Dirprwy,Gweinydd dirprwyol,Mur gwarchod,Squid",
+    "X-KDE-Keywords[da]": "Proxy,Proxy-server,Firewall,Squid",
+    "X-KDE-Keywords[de]": "Proxy-Server",
+    "X-KDE-Keywords[el]": "Διαμεσολαβητής,Proxy server,Τείχος προστασίας,Squid",
+    "X-KDE-Keywords[en_GB]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[es]": "Proxy,Servidor proxy,Cortafuegos,Squid",
+    "X-KDE-Keywords[et]": "Puhver,Puhverserver,Tulemüür,Squid",
+    "X-KDE-Keywords[eu]": "Proxy,Proxy zerbitzari,Suhesi,Squid",
+    "X-KDE-Keywords[fi]": "Proxy,Välitys,Välityspalvelin,Firewall,Palomuuri,Squid",
+    "X-KDE-Keywords[fr]": "Serveur mandataire, serveur (proxy), pare-feu, squid",
+    "X-KDE-Keywords[gd]": "Proxy,Proxy server,Firewall,Squid,progsaidh,frithealaiche progsaidh,cachaileith-theine",
+    "X-KDE-Keywords[gl]": "Proxy,servidor proxy,devasa,Squid",
+    "X-KDE-Keywords[hu]": "Proxy,Proxy kiszolgáló,Tűzfal,Squid",
+    "X-KDE-Keywords[ia]": "Proxy,Servitor de Proxy,Talia Foco,Squid",
+    "X-KDE-Keywords[id]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[ie]": "Proxy,Servitor proxy,Firewall,Squid",
+    "X-KDE-Keywords[is]": "Milliþjónn,Proxy,Eldveggur,Squid",
+    "X-KDE-Keywords[it]": "Proxy,Server proxy server,Firewall,Squid",
+    "X-KDE-Keywords[ka]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[ko]": "Proxy,Proxy server,Firewall,Squid,proxy,프록시,프록시 서버,방화벽",
+    "X-KDE-Keywords[lt]": "Įgaliotasis serveris,Įgaliotasis,Tarpinis,Tarpinis serveris,Užkarda,Uzkarda,Ugniasienė,Ugniasiene,Squid",
+    "X-KDE-Keywords[my]": "Proxy,Proxy server,Firewall,Squid,ကြားခံ",
+    "X-KDE-Keywords[nb]": "Mellomtjener,Brannmur,Squid",
+    "X-KDE-Keywords[nl]": "Proxy,proxy-server,firewall,squid",
+    "X-KDE-Keywords[nn]": "proxy,proxy-server,mellomtenar,brannmur,Squid",
+    "X-KDE-Keywords[pa]": "ਪ੍ਰੌਕਸੀ,ਪ੍ਰਾਕਸੀ,ਪਰਾਕਸੀ, ਪਰਾਕਸੀ ਸਰਵਰ,ਫਾਇਰਵਾਲ,ਸਕਵਿਡ",
+    "X-KDE-Keywords[pl]": "Pośrednik,Serwer pośrednika,Zapora sieciowa,Squid",
+    "X-KDE-Keywords[pt]": "Proxy,Servidor 'proxy','firewall',Squid",
+    "X-KDE-Keywords[pt_BR]": "Proxy,Servidor proxy,Firewall,Squid",
+    "X-KDE-Keywords[ro]": "Proxy,Server proxy,Firewall,Squid",
+    "X-KDE-Keywords[ru]": "Proxy,Proxy server,Firewall,Squid,прокси,прокси-сервер,брандмауэр,защитный экран",
+    "X-KDE-Keywords[sk]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-Keywords[sl]": "Proxy,Posredniški strežnik,Požarni zid,Squid",
+    "X-KDE-Keywords[sr at ijekavian]": "Proxy,Proxy server,Firewall,Squid,прокси,прокси сервер,Сквид,заштитни зид",
+    "X-KDE-Keywords[sr at ijekavianlatin]": "Proxy,Proxy server,Firewall,Squid,proksi,proksi server,Squid,zaštitni zid",
+    "X-KDE-Keywords[sr at latin]": "Proxy,Proxy server,Firewall,Squid,proksi,proksi server,Squid,zaštitni zid",
+    "X-KDE-Keywords[sr]": "Proxy,Proxy server,Firewall,Squid,прокси,прокси сервер,Сквид,заштитни зид",
+    "X-KDE-Keywords[sv]": "Proxy,Proxyserver,Brandvägg,Squid",
+    "X-KDE-Keywords[ta]": "Proxy,Proxy server,Firewall,Squid,தீயரண்,சேவையகம்,வழங்கி,பதிலி",
+    "X-KDE-Keywords[tg]": "Прокси, хизматрасони прокси, девори оташ,Squid",
+    "X-KDE-Keywords[tok]": "nasin linja,linluwi,sinpin,awen,squid",
+    "X-KDE-Keywords[tr]": "Vekil,Vekil sunucu,Güvenlik duvarı,Squid",
+    "X-KDE-Keywords[uk]": "Proxy,Proxy server,Firewall,Squid,proxy,проксі,сервер,проксі-сервер,брандмауер,файрвол",
+    "X-KDE-Keywords[vi]": "Proxy,Proxy server,Firewall,Squid,Uỷ nhiệm,Máy chủ uỷ nhiệm,Tường lửa",
+    "X-KDE-Keywords[x-test]": "xxProxyxx,xxProxy serverxx,xxFirewallxx,xxSquidxx",
+    "X-KDE-Keywords[zh_CN]": "Proxy,Proxy server,Firewall,Squid,代理,代理服务器,防火墙",
+    "X-KDE-Keywords[zh_TW]": "Proxy,Proxy server,Firewall,Squid",
+    "X-KDE-ParentApp": "kcontrol",
+    "X-KDE-System-Settings-Parent-Category": "networksettings",
+    "X-KDE-Weight": 40
+}
diff --git a/kcms/proxy/kproxydlg.cpp b/kcms/proxy/kproxydlg.cpp
new file mode 100644
index 000000000..8a4569a33
--- /dev/null
+++ b/kcms/proxy/kproxydlg.cpp
@@ -0,0 +1,542 @@
+/*
+    kproxydlg.cpp - Proxy configuration dialog
+    SPDX-FileCopyrightText: 2001, 2011 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+// Own
+#include "kproxydlg.h"
+
+// Local
+#include "../ksaveioconfig.h"
+
+// KDE
+#include <KLineEdit> // Needed for KUrlRequester::lineEdit()
+#include <KLocalizedString>
+#include <KPluginFactory>
+#include <kurifilter.h>
+
+// Qt
+#include <QSpinBox>
+#include <QUrl>
+
+K_PLUGIN_CLASS_WITH_JSON(KProxyDialog, "kcm_proxy.json")
+
+class InputValidator : public QValidator
+{
+public:
+    State validate(QString &input, int &pos) const override
+    {
+        if (input.isEmpty()) {
+            return Acceptable;
+        }
+
+        const QChar ch = input.at((pos > 0 ? pos - 1 : pos));
+        if (ch.isSpace()) {
+            return Invalid;
+        }
+
+        return Acceptable;
+    }
+};
+
+static QString manualProxyToText(const QLineEdit *edit, const QSpinBox *spinBox, const QChar &separator)
+{
+    const QString value = edit->text() + separator + QString::number(spinBox->value());
+
+    return value;
+}
+
+static void setManualProxyFromText(const QString &value, QLineEdit *edit, QSpinBox *spinBox)
+{
+    if (value.isEmpty()) {
+        return;
+    }
+
+    const QStringList values = value.split(QLatin1Char(' '));
+    edit->setText(values.at(0));
+    bool ok = false;
+    const int num = values.at(1).toInt(&ok);
+    if (ok) {
+        spinBox->setValue(num);
+    }
+}
+
+static void showSystemProxyUrl(QLineEdit *edit, QString *value)
+{
+    Q_ASSERT(edit);
+    Q_ASSERT(value);
+
+    *value = edit->text();
+    edit->setEnabled(false);
+    const QByteArray envVar(edit->text().toUtf8());
+    edit->setText(QString::fromUtf8(qgetenv(envVar.constData())));
+}
+
+static QString proxyUrlFromInput(KProxyDialog::DisplayUrlFlags *flags,
+                                 const QLineEdit *edit,
+                                 const QSpinBox *spinBox,
+                                 const QString &defaultScheme = QString(),
+                                 KProxyDialog::DisplayUrlFlag flag = KProxyDialog::HideNone)
+{
+    Q_ASSERT(edit);
+    Q_ASSERT(spinBox);
+
+    QString proxyStr;
+
+    if (edit->text().isEmpty()) {
+        return proxyStr;
+    }
+
+    if (flags && !edit->text().contains(QLatin1String("://"))) {
+        *flags |= flag;
+    }
+
+    KUriFilterData data;
+    data.setData(edit->text());
+    data.setCheckForExecutables(false);
+    if (!defaultScheme.isEmpty()) {
+        data.setDefaultUrlScheme(defaultScheme);
+    }
+
+    if (KUriFilter::self()->filterUri(data, QStringList{QStringLiteral("kshorturifilter")})) {
+        QUrl url = data.uri();
+        const int portNum = (spinBox->value() > 0 ? spinBox->value() : url.port());
+        url.setPort(-1);
+
+        proxyStr = url.url();
+        if (portNum > -1) {
+            proxyStr += QLatin1Char(' ') + QString::number(portNum);
+        }
+    } else {
+        proxyStr = edit->text();
+        if (spinBox->value() > 0) {
+            proxyStr += QLatin1Char(' ') + QString::number(spinBox->value());
+        }
+    }
+
+    return proxyStr;
+}
+
+static void setProxyInformation(const QString &value,
+                                int proxyType,
+                                QLineEdit *manEdit,
+                                QLineEdit *sysEdit,
+                                QSpinBox *spinBox,
+                                const QString &defaultScheme,
+                                KProxyDialog::DisplayUrlFlag flag)
+{
+    const bool isSysProxy =
+        !value.contains(QLatin1Char(' ')) && !value.contains(QLatin1Char('.')) && !value.contains(QLatin1Char(',')) && !value.contains(QLatin1Char(':'));
+
+    if (proxyType == KProtocolManager::EnvVarProxy || isSysProxy) {
+#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
+        sysEdit->setText(value);
+#endif
+        return;
+    }
+
+    if (spinBox) {
+        KUriFilterData data;
+        data.setData(value);
+        data.setCheckForExecutables(false);
+        if (!defaultScheme.isEmpty()) {
+            data.setDefaultUrlScheme(defaultScheme);
+        }
+
+        QUrl url;
+        if (KUriFilter::self()->filterUri(data, QStringList{QStringLiteral("kshorturifilter")})) {
+            url = QUrl(data.uri());
+            url.setUserName(QString());
+            url.setPassword(QString());
+            url.setPath(QString());
+        } else {
+            url = QUrl(value);
+        }
+
+        if (url.port() > -1) {
+            spinBox->setValue(url.port());
+        }
+        url.setPort(-1);
+        manEdit->setText((KSaveIOConfig::proxyDisplayUrlFlags() & flag) ? url.host() : url.url());
+        return;
+    }
+
+    manEdit->setText(value); // Manual proxy exception...
+}
+
+KProxyDialog::KProxyDialog(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+{
+    mUi.setupUi(widget());
+
+    connect(mUi.autoDetectButton, &QPushButton::clicked, this, &KProxyDialog::autoDetect);
+    connect(mUi.showEnvValueCheckBox, &QAbstractButton::toggled, this, &KProxyDialog::showEnvValue);
+    connect(mUi.useSameProxyCheckBox, &QPushButton::clicked, this, &KProxyDialog::setUseSameProxy);
+    connect(mUi.manualProxyHttpEdit, &QLineEdit::textChanged, this, [this](const QString &text) {
+        mUi.useSameProxyCheckBox->setEnabled(!text.isEmpty());
+    });
+    connect(mUi.manualNoProxyEdit, &QLineEdit::textChanged, this, [this](const QString &text) {
+        mUi.useReverseProxyCheckBox->setEnabled(!text.isEmpty());
+    });
+    connect(mUi.manualProxyHttpEdit, &QLineEdit::textEdited, this, &KProxyDialog::syncProxies);
+    connect(mUi.manualProxyHttpSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, &KProxyDialog::syncProxyPorts);
+
+    mUi.systemProxyGroupBox->setVisible(false);
+    mUi.manualProxyGroupBox->setVisible(false);
+    mUi.autoDetectButton->setVisible(false);
+    mUi.proxyConfigScriptGroupBox->setVisible(false);
+
+    mUi.infoMessageWidget->setIcon(QIcon::fromTheme(QStringLiteral("dialog-warning")));
+    mUi.infoMessageWidget->setText(xi18nc("@info",
+                                          "Not all applications will use this proxy setting. \
+In particular, <application>Firefox</application> and <application>Chromium</application> or \
+anything derived from them, or anything using <application>QtWebEngine</application> - which \
+includes <application>Konqueror</application> using the <application>WebEnginePart</application>, \
+<application>Akregator</application> and <application>Falkon</application> - will not use \
+these settings. Some applications may allow the proxy to be configured in their own settings."));
+
+    InputValidator *v = new InputValidator;
+    mUi.proxyScriptUrlRequester->lineEdit()->setValidator(v);
+    mUi.manualProxyHttpEdit->setValidator(v);
+    mUi.manualProxyHttpsEdit->setValidator(v);
+    mUi.manualProxyFtpEdit->setValidator(v);
+    mUi.manualProxySocksEdit->setValidator(v);
+    mUi.manualNoProxyEdit->setValidator(v);
+
+    // Signals and slots connections
+    connect(mUi.noProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.autoDiscoverProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.autoScriptProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.noProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.useReverseProxyCheckBox, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+    connect(mUi.useSameProxyCheckBox, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+
+    connect(mUi.proxyScriptUrlRequester, &KUrlRequester::textChanged, this, &KProxyDialog::slotChanged);
+
+    connect(mUi.manualProxyHttpEdit, &QLineEdit::textChanged, this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxyHttpsEdit, &QLineEdit::textChanged, this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxyFtpEdit, &QLineEdit::textChanged, this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxySocksEdit, &QLineEdit::textChanged, this, &KProxyDialog::slotChanged);
+    connect(mUi.manualNoProxyEdit, &QLineEdit::textChanged, this, &KProxyDialog::slotChanged);
+
+    connect(mUi.manualProxyHttpSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxyHttpsSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxyFtpSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, &KProxyDialog::slotChanged);
+    connect(mUi.manualProxySocksSpinBox, qOverload<int>(&QSpinBox::valueChanged), this, &KProxyDialog::slotChanged);
+
+    connect(mUi.systemProxyHttpEdit, &QLineEdit::textEdited, this, &KProxyDialog::slotChanged);
+    connect(mUi.systemProxyHttpsEdit, &QLineEdit::textEdited, this, &KProxyDialog::slotChanged);
+    connect(mUi.systemProxyFtpEdit, &QLineEdit::textEdited, this, &KProxyDialog::slotChanged);
+    connect(mUi.systemProxySocksEdit, &QLineEdit::textEdited, this, &KProxyDialog::slotChanged);
+    connect(mUi.systemNoProxyEdit, &QLineEdit::textEdited, this, &KProxyDialog::slotChanged);
+
+#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
+    connect(mUi.systemProxyRadioButton, &QAbstractButton::toggled, mUi.systemProxyGroupBox, &QWidget::setVisible);
+#else
+    mUi.autoDetectButton->setVisible(false);
+#endif
+    connect(mUi.systemProxyRadioButton, &QPushButton::clicked, this, &KProxyDialog::slotChanged);
+}
+
+KProxyDialog::~KProxyDialog()
+{
+}
+
+void KProxyDialog::load()
+{
+    mProxyMap.insert(QStringLiteral("HttpProxy"), KProtocolManager::proxyFor(QStringLiteral("http")));
+    mProxyMap.insert(QStringLiteral("HttpsProxy"), KProtocolManager::proxyFor(QStringLiteral("https")));
+    mProxyMap.insert(QStringLiteral("FtpProxy"), KProtocolManager::proxyFor(QStringLiteral("ftp")));
+    mProxyMap.insert(QStringLiteral("SocksProxy"), KProtocolManager::proxyFor(QStringLiteral("socks")));
+    mProxyMap.insert(QStringLiteral("ProxyScript"), KProtocolManager::proxyConfigScript());
+    mProxyMap.insert(QStringLiteral("NoProxy"), KSaveIOConfig::noProxyFor());
+
+    const int proxyType = KProtocolManager::proxyType();
+
+    // Make sure showEnvValueCheckBox is unchecked before setting proxy env var names
+    mUi.showEnvValueCheckBox->setChecked(false);
+
+    setProxyInformation(mProxyMap.value(QStringLiteral("HttpProxy")),
+                        proxyType,
+                        mUi.manualProxyHttpEdit,
+                        mUi.systemProxyHttpEdit,
+                        mUi.manualProxyHttpSpinBox,
+                        QStringLiteral("http"),
+                        HideHttpUrlScheme);
+    setProxyInformation(mProxyMap.value(QStringLiteral("HttpsProxy")),
+                        proxyType,
+                        mUi.manualProxyHttpsEdit,
+                        mUi.systemProxyHttpsEdit,
+                        mUi.manualProxyHttpsSpinBox,
+                        QStringLiteral("http"),
+                        HideHttpsUrlScheme);
+    setProxyInformation(mProxyMap.value(QStringLiteral("FtpProxy")),
+                        proxyType,
+                        mUi.manualProxyFtpEdit,
+                        mUi.systemProxyFtpEdit,
+                        mUi.manualProxyFtpSpinBox,
+                        QStringLiteral("ftp"),
+                        HideFtpUrlScheme);
+    setProxyInformation(mProxyMap.value(QStringLiteral("SocksProxy")),
+                        proxyType,
+                        mUi.manualProxySocksEdit,
+                        mUi.systemProxySocksEdit,
+                        mUi.manualProxySocksSpinBox,
+                        QStringLiteral("socks"),
+                        HideSocksUrlScheme);
+    setProxyInformation(mProxyMap.value(QStringLiteral("NoProxy")), proxyType, mUi.manualNoProxyEdit, mUi.systemNoProxyEdit, nullptr, QString(), HideNone);
+
+    // Check the "Use this proxy server for all protocols" if all the proxy URLs are the same...
+    const QString httpProxy(mUi.manualProxyHttpEdit->text());
+    if (!httpProxy.isEmpty()) {
+        const int httpProxyPort = mUi.manualProxyHttpSpinBox->value();
+        mUi.useSameProxyCheckBox->setChecked(httpProxy == mUi.manualProxyHttpsEdit->text() /* clang-format off */
+                                             && httpProxy == mUi.manualProxyFtpEdit->text()
+                                             && httpProxy == mUi.manualProxySocksEdit->text()
+                                             && httpProxyPort == mUi.manualProxyHttpsSpinBox->value()
+                                             && httpProxyPort == mUi.manualProxyFtpSpinBox->value()
+                                             && httpProxyPort == mUi.manualProxySocksSpinBox->value()); /* clang-format on */
+    }
+
+    // Validate and Set the automatic proxy configuration script url.
+    QUrl u(mProxyMap.value(QStringLiteral("ProxyScript")));
+    if (u.isValid() && !u.isEmpty()) {
+        u.setUserName(QString());
+        u.setPassword(QString());
+        mUi.proxyScriptUrlRequester->setUrl(u);
+    }
+
+    // Set use reverse proxy checkbox...
+    mUi.useReverseProxyCheckBox->setChecked((!mProxyMap.value(QStringLiteral("NoProxy")).isEmpty() && KProtocolManager::useReverseProxy()));
+
+    switch (proxyType) {
+    case KProtocolManager::WPADProxy:
+        mUi.autoDiscoverProxyRadioButton->setChecked(true);
+        break;
+    case KProtocolManager::PACProxy:
+        mUi.autoScriptProxyRadioButton->setChecked(true);
+        break;
+    case KProtocolManager::ManualProxy:
+        mUi.manualProxyRadioButton->setChecked(true);
+        break;
+    case KProtocolManager::EnvVarProxy:
+        mUi.systemProxyRadioButton->setChecked(true);
+        break;
+    case KProtocolManager::NoProxy:
+    default:
+        mUi.noProxyRadioButton->setChecked(true);
+        break;
+    }
+}
+
+static bool isPACProxyType(KProtocolManager::ProxyType type)
+{
+    return (type == KProtocolManager::PACProxy || type == KProtocolManager::WPADProxy);
+}
+
+void KProxyDialog::save()
+{
+    const KProtocolManager::ProxyType lastProxyType = KProtocolManager::proxyType();
+    KProtocolManager::ProxyType proxyType = KProtocolManager::NoProxy;
+    DisplayUrlFlags displayUrlFlags = static_cast<DisplayUrlFlags>(KSaveIOConfig::proxyDisplayUrlFlags());
+
+    if (mUi.manualProxyRadioButton->isChecked()) {
+        DisplayUrlFlags flags = HideNone;
+        proxyType = KProtocolManager::ManualProxy;
+        mProxyMap[QStringLiteral("HttpProxy")] =
+            proxyUrlFromInput(&flags, mUi.manualProxyHttpEdit, mUi.manualProxyHttpSpinBox, QStringLiteral("http"), HideHttpUrlScheme);
+        mProxyMap[QStringLiteral("HttpsProxy")] =
+            proxyUrlFromInput(&flags, mUi.manualProxyHttpsEdit, mUi.manualProxyHttpsSpinBox, QStringLiteral("http"), HideHttpsUrlScheme);
+        mProxyMap[QStringLiteral("FtpProxy")] =
+            proxyUrlFromInput(&flags, mUi.manualProxyFtpEdit, mUi.manualProxyFtpSpinBox, QStringLiteral("ftp"), HideFtpUrlScheme);
+        mProxyMap[QStringLiteral("SocksProxy")] =
+            proxyUrlFromInput(&flags, mUi.manualProxySocksEdit, mUi.manualProxySocksSpinBox, QStringLiteral("socks"), HideSocksUrlScheme);
+        mProxyMap[QStringLiteral("NoProxy")] = mUi.manualNoProxyEdit->text();
+        displayUrlFlags = flags;
+    } else if (mUi.systemProxyRadioButton->isChecked()) {
+        proxyType = KProtocolManager::EnvVarProxy;
+        if (!mUi.showEnvValueCheckBox->isChecked()) {
+            mProxyMap[QStringLiteral("HttpProxy")] = mUi.systemProxyHttpEdit->text();
+            mProxyMap[QStringLiteral("HttpsProxy")] = mUi.systemProxyHttpsEdit->text();
+            mProxyMap[QStringLiteral("FtpProxy")] = mUi.systemProxyFtpEdit->text();
+            mProxyMap[QStringLiteral("SocksProxy")] = mUi.systemProxySocksEdit->text();
+            mProxyMap[QStringLiteral("NoProxy")] = mUi.systemNoProxyEdit->text();
+        } else {
+            mProxyMap[QStringLiteral("HttpProxy")] = mProxyMap.take(mUi.systemProxyHttpEdit->objectName());
+            mProxyMap[QStringLiteral("HttpsProxy")] = mProxyMap.take(mUi.systemProxyHttpsEdit->objectName());
+            mProxyMap[QStringLiteral("FtpProxy")] = mProxyMap.take(mUi.systemProxyFtpEdit->objectName());
+            mProxyMap[QStringLiteral("SocksProxy")] = mProxyMap.take(mUi.systemProxySocksEdit->objectName());
+            mProxyMap[QStringLiteral("NoProxy")] = mProxyMap.take(mUi.systemNoProxyEdit->objectName());
+        }
+    } else if (mUi.autoScriptProxyRadioButton->isChecked()) {
+        proxyType = KProtocolManager::PACProxy;
+        mProxyMap[QStringLiteral("ProxyScript")] = mUi.proxyScriptUrlRequester->text();
+    } else if (mUi.autoDiscoverProxyRadioButton->isChecked()) {
+        proxyType = KProtocolManager::WPADProxy;
+    }
+
+    KSaveIOConfig::setProxyType(proxyType);
+    KSaveIOConfig::setProxyDisplayUrlFlags(displayUrlFlags);
+    KSaveIOConfig::setUseReverseProxy(mUi.useReverseProxyCheckBox->isChecked());
+
+    // Save the common proxy setting...
+    KSaveIOConfig::setProxyFor(QStringLiteral("http"), mProxyMap.value(QStringLiteral("HttpProxy")));
+    KSaveIOConfig::setProxyFor(QStringLiteral("https"), mProxyMap.value(QStringLiteral("HttpsProxy")));
+    KSaveIOConfig::setProxyFor(QStringLiteral("ftp"), mProxyMap.value(QStringLiteral("FtpProxy")));
+    KSaveIOConfig::setProxyFor(QStringLiteral("socks"), mProxyMap.value(QStringLiteral("SocksProxy")));
+
+    KSaveIOConfig::setProxyConfigScript(mProxyMap.value(QStringLiteral("ProxyScript")));
+    KSaveIOConfig::setNoProxyFor(mProxyMap.value(QStringLiteral("NoProxy")));
+
+    KSaveIOConfig::updateRunningWorkers(widget());
+    if (isPACProxyType(lastProxyType) || isPACProxyType(proxyType)) {
+        KSaveIOConfig::updateProxyScout(widget());
+    }
+
+    setNeedsSave(false);
+}
+
+void KProxyDialog::defaults()
+{
+    mUi.noProxyRadioButton->setChecked(true);
+    mUi.proxyScriptUrlRequester->clear();
+
+    mUi.manualProxyHttpEdit->clear();
+    mUi.manualProxyHttpsEdit->clear();
+    mUi.manualProxyFtpEdit->clear();
+    mUi.manualProxySocksEdit->clear();
+    mUi.manualNoProxyEdit->clear();
+
+    mUi.manualProxyHttpSpinBox->setValue(0);
+    mUi.manualProxyHttpsSpinBox->setValue(0);
+    mUi.manualProxyFtpSpinBox->setValue(0);
+    mUi.manualProxySocksSpinBox->setValue(0);
+
+    mUi.systemProxyHttpEdit->clear();
+    mUi.systemProxyHttpsEdit->clear();
+    mUi.systemProxyFtpEdit->clear();
+    mUi.systemProxySocksEdit->clear();
+
+    setNeedsSave(true);
+}
+
+bool KProxyDialog::autoDetectSystemProxy(QLineEdit *edit, const QString &envVarStr, bool showValue)
+{
+    const QStringList envVars = envVarStr.split(QLatin1Char(','), Qt::SkipEmptyParts);
+    for (const QString &envVar : envVars) {
+        const QByteArray envVarUtf8(envVar.toUtf8());
+        const QByteArray envVarValue = qgetenv(envVarUtf8.constData());
+        if (!envVarValue.isEmpty()) {
+            if (showValue) {
+                mProxyMap[edit->objectName()] = envVar;
+                edit->setText(QString::fromUtf8(envVarValue));
+            } else {
+                edit->setText(envVar);
+            }
+            edit->setEnabled(!showValue);
+            return true;
+        }
+    }
+    return false;
+}
+
+void KProxyDialog::autoDetect()
+{
+    const bool showValue = mUi.showEnvValueCheckBox->isChecked();
+    bool wasChanged = false;
+
+    wasChanged |= autoDetectSystemProxy(mUi.systemProxyHttpEdit, QStringLiteral("HTTP_PROXY,http_proxy,HTTPPROXY,httpproxy,PROXY,proxy"), showValue);
+    wasChanged |= autoDetectSystemProxy(mUi.systemProxyHttpsEdit, QStringLiteral("HTTPS_PROXY,https_proxy,HTTPSPROXY,httpsproxy,PROXY,proxy"), showValue);
+    wasChanged |= autoDetectSystemProxy(mUi.systemProxyFtpEdit, QStringLiteral("FTP_PROXY,ftp_proxy,FTPPROXY,ftpproxy,PROXY,proxy"), showValue);
+    wasChanged |= autoDetectSystemProxy(mUi.systemProxySocksEdit, QStringLiteral("SOCKS_PROXY,socks_proxy,SOCKSPROXY,socksproxy,PROXY,proxy"), showValue);
+    wasChanged |= autoDetectSystemProxy(mUi.systemNoProxyEdit, QStringLiteral("NO_PROXY,no_proxy"), showValue);
+
+    if (wasChanged) {
+        setNeedsSave(true);
+    }
+}
+
+void KProxyDialog::syncProxies(const QString &text)
+{
+    if (!mUi.useSameProxyCheckBox->isChecked()) {
+        return;
+    }
+
+    mUi.manualProxyHttpsEdit->setText(text);
+    mUi.manualProxyFtpEdit->setText(text);
+    mUi.manualProxySocksEdit->setText(text);
+}
+
+void KProxyDialog::syncProxyPorts(int value)
+{
+    if (!mUi.useSameProxyCheckBox->isChecked()) {
+        return;
+    }
+
+    mUi.manualProxyHttpsSpinBox->setValue(value);
+    mUi.manualProxyFtpSpinBox->setValue(value);
+    mUi.manualProxySocksSpinBox->setValue(value);
+}
+
+void KProxyDialog::showEnvValue(bool on)
+{
+    if (on) {
+        showSystemProxyUrl(mUi.systemProxyHttpEdit, &mProxyMap[mUi.systemProxyHttpEdit->objectName()]);
+        showSystemProxyUrl(mUi.systemProxyHttpsEdit, &mProxyMap[mUi.systemProxyHttpsEdit->objectName()]);
+        showSystemProxyUrl(mUi.systemProxyFtpEdit, &mProxyMap[mUi.systemProxyFtpEdit->objectName()]);
+        showSystemProxyUrl(mUi.systemProxySocksEdit, &mProxyMap[mUi.systemProxySocksEdit->objectName()]);
+        showSystemProxyUrl(mUi.systemNoProxyEdit, &mProxyMap[mUi.systemNoProxyEdit->objectName()]);
+        return;
+    }
+
+    mUi.systemProxyHttpEdit->setText(mProxyMap.take(mUi.systemProxyHttpEdit->objectName()));
+    mUi.systemProxyHttpEdit->setEnabled(true);
+    mUi.systemProxyHttpsEdit->setText(mProxyMap.take(mUi.systemProxyHttpsEdit->objectName()));
+    mUi.systemProxyHttpsEdit->setEnabled(true);
+    mUi.systemProxyFtpEdit->setText(mProxyMap.take(mUi.systemProxyFtpEdit->objectName()));
+    mUi.systemProxyFtpEdit->setEnabled(true);
+    mUi.systemProxySocksEdit->setText(mProxyMap.take(mUi.systemProxySocksEdit->objectName()));
+    mUi.systemProxySocksEdit->setEnabled(true);
+    mUi.systemNoProxyEdit->setText(mProxyMap.take(mUi.systemNoProxyEdit->objectName()));
+    mUi.systemNoProxyEdit->setEnabled(true);
+}
+
+void KProxyDialog::setUseSameProxy(bool on)
+{
+    if (on) {
+        mProxyMap[QStringLiteral("ManProxyHttps")] = manualProxyToText(mUi.manualProxyHttpsEdit, mUi.manualProxyHttpsSpinBox, QLatin1Char(' '));
+        mProxyMap[QStringLiteral("ManProxyFtp")] = manualProxyToText(mUi.manualProxyFtpEdit, mUi.manualProxyFtpSpinBox, QLatin1Char(' '));
+        mProxyMap[QStringLiteral("ManProxySocks")] = manualProxyToText(mUi.manualProxySocksEdit, mUi.manualProxySocksSpinBox, QLatin1Char(' '));
+
+        const QString &httpProxy = mUi.manualProxyHttpEdit->text();
+        if (!httpProxy.isEmpty()) {
+            mUi.manualProxyHttpsEdit->setText(httpProxy);
+            mUi.manualProxyFtpEdit->setText(httpProxy);
+            mUi.manualProxySocksEdit->setText(httpProxy);
+        }
+        const int httpProxyPort = mUi.manualProxyHttpSpinBox->value();
+        if (httpProxyPort > 0) {
+            mUi.manualProxyHttpsSpinBox->setValue(httpProxyPort);
+            mUi.manualProxyFtpSpinBox->setValue(httpProxyPort);
+            mUi.manualProxySocksSpinBox->setValue(httpProxyPort);
+        }
+        return;
+    }
+
+    setManualProxyFromText(mProxyMap.take(QStringLiteral("ManProxyHttps")), mUi.manualProxyHttpsEdit, mUi.manualProxyHttpsSpinBox);
+    setManualProxyFromText(mProxyMap.take(QStringLiteral("ManProxyFtp")), mUi.manualProxyFtpEdit, mUi.manualProxyFtpSpinBox);
+    setManualProxyFromText(mProxyMap.take(QStringLiteral("ManProxySocks")), mUi.manualProxySocksEdit, mUi.manualProxySocksSpinBox);
+}
+
+void KProxyDialog::slotChanged()
+{
+    const bool proxyWarning = mUi.autoScriptProxyRadioButton->isChecked() || mUi.manualProxyRadioButton->isChecked();
+    mUi.infoMessageWidget->setVisible(proxyWarning);
+
+    setNeedsSave(true);
+}
+
+#include "kproxydlg.moc"
diff --git a/kcms/proxy/kproxydlg.h b/kcms/proxy/kproxydlg.h
new file mode 100644
index 000000000..3e7453540
--- /dev/null
+++ b/kcms/proxy/kproxydlg.h
@@ -0,0 +1,54 @@
+/*
+    kproxydlg.h - Proxy configuration dialog
+    SPDX-FileCopyrightText: 2001, 2011 Dawit Alemayehu <adawit at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#ifndef KPROXYDLG_H
+#define KPROXYDLG_H
+
+#include "ui_kproxydlg.h"
+#include <KCModule>
+
+class KProxyDialog : public KCModule
+{
+    Q_OBJECT
+
+public:
+    enum DisplayUrlFlag {
+        HideNone = 0x00,
+        HideHttpUrlScheme = 0x01,
+        HideHttpsUrlScheme = 0x02,
+        HideFtpUrlScheme = 0x04,
+        HideSocksUrlScheme = 0x08,
+    };
+    Q_DECLARE_FLAGS(DisplayUrlFlags, DisplayUrlFlag)
+
+    KProxyDialog(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KProxyDialog() override;
+
+    void load() override;
+    void save() override;
+    void defaults() override;
+
+private Q_SLOTS:
+    void autoDetect();
+    void showEnvValue(bool);
+    void setUseSameProxy(bool);
+    void syncProxies(const QString &);
+    void syncProxyPorts(int);
+
+    void slotChanged();
+
+private:
+    bool autoDetectSystemProxy(QLineEdit *edit, const QString &envVarStr, bool showValue);
+
+    Ui::ProxyDialogUI mUi;
+    QStringList mNoProxyForList;
+    QMap<QString, QString> mProxyMap;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KProxyDialog::DisplayUrlFlags)
+
+#endif // KPROXYDLG_H
diff --git a/kcms/proxy/kproxydlg.ui b/kcms/proxy/kproxydlg.ui
new file mode 100644
index 000000000..16f34f00e
--- /dev/null
+++ b/kcms/proxy/kproxydlg.ui
@@ -0,0 +1,971 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProxyDialogUI</class>
+ <widget class="QWidget" name="ProxyDialogUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>513</width>
+    <height>567</height>
+   </rect>
+  </property>
+  <property name="whatsThis">
+   <string><qt>
+Setup proxy configuration.
+<p>
+A proxy server is an intermediate machine that sits between your computer and the Internet and provides services such as web page caching and filtering. Caching proxy servers give you faster access to web sites you have already visited by locally storing or caching those pages; filtering proxy servers usually provide the ability to block out requests for ads, spam, or anything else you want to block.
+<p>
+If you are uncertain whether or not you need to use a proxy server to connect to the Internet, consult your Internet service provider's setup guide or your system administrator.
+</qt></string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QRadioButton" name="noProxyRadioButton">
+     <property name="whatsThis">
+      <string>Connect to the Internet directly.</string>
+     </property>
+     <property name="text">
+      <string>No Proxy</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QRadioButton" name="autoDiscoverProxyRadioButton">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="whatsThis">
+      <string><qt>
+Automatically detect and configure the proxy settings.<p>
+Automatic detection is performed using the <b>Web Proxy Auto-Discovery Protocol (WPAD)</b>.<p>
+<b>NOTE:</b> This option might not work properly or not work at all in some UNIX/Linux distributions.
+</qt></string>
+     </property>
+     <property name="text">
+      <string>Detect proxy configuration automatically</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QRadioButton" name="autoScriptProxyRadioButton">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="whatsThis">
+      <string>Use the specified proxy script to configure the proxy settings.</string>
+     </property>
+     <property name="text">
+      <string>Use proxy auto configuration URL:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="4">
+    <widget class="QGroupBox" name="proxyConfigScriptGroupBox">
+     <property name="flat">
+      <bool>true</bool>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="leftMargin">
+       <number>20</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="KUrlRequester" name="proxyScriptUrlRequester">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string>Enter the address for the proxy configuration script.</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="4" column="0">
+    <widget class="QRadioButton" name="systemProxyRadioButton">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="whatsThis">
+      <string><qt><p>Use proxy settings defined on the system.</p>
+<p>Some platforms offer system wide proxy configuration information and selecting this option allows you to use those settings.</p>
+<p>On Mac platforms</p>
+<p>On Windows platforms</p>
+<p>On Unix and Linux platforms, such system proxy settings are usually defined through environment variables. The following environment variables are detected and used when present: <b>HTTP_PROXY</b>, <b>HTTPS_PROXY</b>, <b>FTP_PROXY</b>, <b>NO_PROXY</b>.</p>
+</qt></string>
+     </property>
+     <property name="text">
+      <string>Use system proxy configuration:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="3">
+    <widget class="QPushButton" name="autoDetectButton">
+     <property name="whatsThis">
+      <string><qt>Attempt automatic discovery of the environment variables used for setting system wide proxy information.<p> This feature works by searching for commonly used variable names such as HTTP_PROXY, FTP_PROXY and NO_PROXY.</qt></string>
+     </property>
+     <property name="text">
+      <string>Auto D&etect</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0" colspan="4">
+    <widget class="QGroupBox" name="systemProxyGroupBox">
+     <property name="flat">
+      <bool>true</bool>
+     </property>
+     <layout class="QFormLayout" name="formLayout_2">
+      <property name="leftMargin">
+       <number>20</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="systemProxyHttpLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>HTTP_PROXY</b>, used to store the address of the HTTP proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+        <property name="text">
+         <string>HTTP Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>systemProxyHttpEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="systemProxyHttpEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>HTTP_PROXY</b>, used to store the address of the HTTP proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="systemProxyHttpsLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>HTTPS_PROXY</b>, used to store the address of the HTTPS proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+        <property name="text">
+         <string>SSL Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>systemProxyHttpsEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLineEdit" name="systemProxyHttpsEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>HTTPS_PROXY</b>, used to store the address of the HTTPS proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="systemProxyFtpLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>FTP_PROXY</b>, used to store the address of the FTP proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+        <property name="text">
+         <string>FTP Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>systemProxyFtpEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLineEdit" name="systemProxyFtpEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>FTP_PROXY</b>, used to store the address of the FTP proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="systemProxySocksLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the name of the environment variable, e.g. <b>SOCKS_PROXY</b>, used to store the address of the SOCKS proxy server.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.</p>
+</qt></string>
+        </property>
+        <property name="text">
+         <string>SOCKS Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>systemProxySocksEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QLineEdit" name="systemProxySocksEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>Enter the name of the environment variable, e.g. <b>SOCKS_PROXY</b>, used to store the address of the SOCKS proxy server.<p>Alternatively, you can click on the <b>&quot;Auto Detect&quot;</b> button to attempt an automatic discovery of this variable.</p></qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="sysNoProxyLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the environment variable, e.g. <b>NO_PROXY</b>, used to store the addresses of sites for which the proxy server should not be used.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.
+</qt></string>
+        </property>
+        <property name="text">
+         <string>Exceptions:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>systemNoProxyEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QLineEdit" name="systemNoProxyEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>Enter the environment variable, e.g. <b>NO_PROXY</b>, used to store the addresses of sites for which the above proxy settings should not be used.<p>Alternatively, you can click on the <b>&quot;Auto Detect&quot;</b> button to attempt an automatic discovery of this variable.</p></qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QCheckBox" name="showEnvValueCheckBox">
+        <property name="text">
+         <string>Show the &value of the environment variables</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="6" column="0" colspan="2">
+    <widget class="QRadioButton" name="manualProxyRadioButton">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="whatsThis">
+      <string>Manually enter proxy server configuration information.</string>
+     </property>
+     <property name="text">
+      <string>Use manually specified proxy configuration:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" colspan="4">
+    <widget class="QGroupBox" name="manualProxyGroupBox">
+     <property name="title">
+      <string/>
+     </property>
+     <property name="flat">
+      <bool>true</bool>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <property name="fieldGrowthPolicy">
+       <enum>QFormLayout::ExpandingFieldsGrow</enum>
+      </property>
+      <property name="leftMargin">
+       <number>20</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="manualProxyHttpEditLabel">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>HTTP Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>manualProxyHttpEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <item>
+         <widget class="QLineEdit" name="manualProxyHttpEdit">
+          <property name="whatsThis">
+           <string>Enter the address of the HTTP proxy server.</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="manualProxyHttpSpinBoxLabel">
+          <property name="text">
+           <string>Port:</string>
+          </property>
+          <property name="buddy">
+           <cstring>manualProxyHttpSpinBox</cstring>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="manualProxyHttpSpinBox">
+          <property name="maximumSize">
+           <size>
+            <width>32767</width>
+            <height>32767</height>
+           </size>
+          </property>
+          <property name="whatsThis">
+           <string>Enter the port number of the HTTP proxy server.</string>
+          </property>
+          <property name="maximum">
+           <number>65536</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="1" column="1">
+       <widget class="QCheckBox" name="useSameProxyCheckBox">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="text">
+         <string>Use this proxy server for a&ll protocols</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="manualProxyHttpsEditLabel">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>SSL Proxy:</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>manualProxyHttpsEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
+         <widget class="QLineEdit" name="manualProxyHttpsEdit">
+          <property name="whatsThis">
+           <string>Enter the address of the HTTPS proxy server.</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="manualProxyHttpsSpinBoxLabel">
+          <property name="text">
+           <string>Port:</string>
+          </property>
+          <property name="buddy">
+           <cstring>manualProxyHttpsSpinBox</cstring>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="manualProxyHttpsSpinBox">
+          <property name="whatsThis">
+           <string>Enter the port number of the HTTPS proxy server.</string>
+          </property>
+          <property name="maximum">
+           <number>65536</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="manualProxyFtpEditLabel">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>FTP Proxy:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>manualProxyFtpEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <item>
+         <widget class="QLineEdit" name="manualProxyFtpEdit">
+          <property name="whatsThis">
+           <string>Enter the address of the FTP proxy server.</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="manualProxyFtpSpinBoxLabel">
+          <property name="text">
+           <string>Port:</string>
+          </property>
+          <property name="buddy">
+           <cstring>manualProxyFtpSpinBox</cstring>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="manualProxyFtpSpinBox">
+          <property name="whatsThis">
+           <string>Enter the port number of the FTP proxy server.</string>
+          </property>
+          <property name="maximum">
+           <number>65536</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="manualProxySocksEditLabel">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>SOCKS Proxy:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="buddy">
+         <cstring>manualProxySocksEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QLineEdit" name="manualProxySocksEdit">
+          <property name="whatsThis">
+           <string>Enter the address of the SOCKS proxy server.</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="manualProxySocksSpinBoxLabel">
+          <property name="text">
+           <string>Port:</string>
+          </property>
+          <property name="buddy">
+           <cstring>manualProxySocksSpinBox</cstring>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="manualProxySocksSpinBox">
+          <property name="whatsThis">
+           <string>Enter the port number of the SOCKS proxy server.</string>
+          </property>
+          <property name="maximum">
+           <number>65536</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="5" column="0">
+       <widget class="QLabel" name="manNoProxyLabel">
+        <property name="whatsThis">
+         <string><qt>
+Enter the environment variable, e.g. <b>NO_PROXY</b>, used to store the addresses of sites for which the proxy server should not be used.<p>
+Alternatively, you can click on the <b>"Auto Detect"</b> button to attempt an automatic discovery of this variable.
+</qt></string>
+        </property>
+        <property name="text">
+         <string>Exceptions:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+        <property name="buddy">
+         <cstring>manualNoProxyEdit</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QLineEdit" name="manualNoProxyEdit">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="whatsThis">
+         <string><qt>
+<p>Enter a comma separated list of hostnames or ip addresses that should be excluded from using the above proxy settings.</p>
+<p>If you want to exclude all hosts for a given domain, then simply enter the domain name preceded by a dot. For example, to exclude all hostnames for <i>kde.org</i>, enter <i>.kde.org</i>. Wildcard characters such as '*' or '?' are not supported and will have no effect.</p>
+<p>Additionally, you can also enter IP addresses, e.g. 127.0.0.1 and IP addresses with a subnet, e.g. 192.168.0.1/24.</p>
+</qt></string>
+        </property>
+       </widget>
+      </item>
+      <item row="6" column="1">
+       <widget class="QCheckBox" name="useReverseProxyCheckBox">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="whatsThis">
+         <string><qt>
+Check this box if you want the above proxy settings to apply only to the addresses listed in the <i>Exceptions</i> list.</qt></string>
+        </property>
+        <property name="text">
+         <string>Use proxy settings only for addresses in the Exceptions list</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="8" column="0" colspan="4">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType">
+      <enum>QSizePolicy::MinimumExpanding</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>42</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="9" column="0" colspan="4">
+     <widget class="KMessageWidget" name="infoMessageWidget">
+       <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+         </sizepolicy>
+       </property>
+       <property name="messageType">
+	 <enum>KMessageWidget::Warning</enum>
+       </property>
+       <property name="wordWrap">
+	 <bool>true</bool>
+       </property>
+       <property name="closeButtonVisible">
+	 <bool>false</bool>
+       </property>
+       <property name="visible">
+	 <bool>false</bool>
+       </property>
+     </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KUrlRequester</class>
+   <extends>QFrame</extends>
+   <header>kurlrequester.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>KMessageWidget</class>
+   <extends>QFrame</extends>
+   <header>kmessagewidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>noProxyRadioButton</tabstop>
+  <tabstop>autoDiscoverProxyRadioButton</tabstop>
+  <tabstop>autoScriptProxyRadioButton</tabstop>
+  <tabstop>proxyScriptUrlRequester</tabstop>
+  <tabstop>systemProxyRadioButton</tabstop>
+  <tabstop>autoDetectButton</tabstop>
+  <tabstop>systemProxyHttpEdit</tabstop>
+  <tabstop>systemProxyHttpsEdit</tabstop>
+  <tabstop>systemProxyFtpEdit</tabstop>
+  <tabstop>systemProxySocksEdit</tabstop>
+  <tabstop>systemNoProxyEdit</tabstop>
+  <tabstop>showEnvValueCheckBox</tabstop>
+  <tabstop>manualProxyRadioButton</tabstop>
+  <tabstop>manualProxyHttpEdit</tabstop>
+  <tabstop>manualProxyHttpSpinBox</tabstop>
+  <tabstop>useSameProxyCheckBox</tabstop>
+  <tabstop>manualProxyHttpsEdit</tabstop>
+  <tabstop>manualProxyHttpsSpinBox</tabstop>
+  <tabstop>manualProxyFtpEdit</tabstop>
+  <tabstop>manualProxyFtpSpinBox</tabstop>
+  <tabstop>manualProxySocksEdit</tabstop>
+  <tabstop>manualProxySocksSpinBox</tabstop>
+  <tabstop>manualNoProxyEdit</tabstop>
+  <tabstop>useReverseProxyCheckBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>systemProxyRadioButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemProxyGroupBox</receiver>
+   <slot>setVisible(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>97</x>
+     <y>121</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>23</x>
+     <y>150</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>manualProxyRadioButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxyGroupBox</receiver>
+   <slot>setVisible(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>76</x>
+     <y>304</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>18</x>
+     <y>333</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxyHttpsEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>249</x>
+     <y>370</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>250</x>
+     <y>384</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxyFtpEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>218</x>
+     <y>364</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>215</x>
+     <y>414</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxySocksEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>191</x>
+     <y>362</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>187</x>
+     <y>440</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>showEnvValueCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemNoProxyEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>352</x>
+     <y>282</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>353</x>
+     <y>259</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>showEnvValueCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemProxySocksEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>275</x>
+     <y>278</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>273</x>
+     <y>231</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>showEnvValueCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemProxyFtpEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>299</x>
+     <y>279</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>299</x>
+     <y>206</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>showEnvValueCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemProxyHttpsEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>349</x>
+     <y>280</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>336</x>
+     <y>185</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>showEnvValueCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>systemProxyHttpEdit</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>272</x>
+     <y>279</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>236</x>
+     <y>156</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>autoScriptProxyRadioButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>proxyConfigScriptGroupBox</receiver>
+   <slot>setVisible(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>120</x>
+     <y>63</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>120</x>
+     <y>79</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>systemProxyRadioButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>autoDetectButton</receiver>
+   <slot>setVisible(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>186</x>
+     <y>119</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>433</x>
+     <y>124</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxyHttpsSpinBox</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>155</x>
+     <y>361</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>464</x>
+     <y>385</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxyFtpSpinBox</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>139</x>
+     <y>364</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>451</x>
+     <y>421</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useSameProxyCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>manualProxySocksSpinBox</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>157</x>
+     <y>363</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>438</x>
+     <y>449</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/kcms/smb/CMakeLists.txt b/kcms/smb/CMakeLists.txt
new file mode 100644
index 000000000..b518cf8e5
--- /dev/null
+++ b/kcms/smb/CMakeLists.txt
@@ -0,0 +1,14 @@
+kcoreaddons_add_plugin(kcm_smb SOURCES smbrodlg.cpp INSTALL_NAMESPACE "plasma/kcms/systemsettings_qwidgets")
+
+kcmutils_generate_desktop_file(kcm_smb)
+target_sources(kcm_smb PRIVATE
+    smbrodlg.cpp
+)
+
+target_link_libraries(kcm_smb PRIVATE
+    Qt6::Widgets
+    KF6::CoreAddons
+    KF6::ConfigCore
+    KF6::I18n
+    KF6::KCMUtils
+)
diff --git a/kcms/smb/kcm_smb.json b/kcms/smb/kcm_smb.json
new file mode 100644
index 000000000..da24ca7a8
--- /dev/null
+++ b/kcms/smb/kcm_smb.json
@@ -0,0 +1,121 @@
+{
+    "KPlugin": {
+        "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=systemsettings&component=kcm_smb",
+        "Description": "Credentials used to access SMB shares",
+        "Description[ar]": "معلومات الصلاحيات المستخدمة للوصول إلى ملفات سامبا الشبكية",
+        "Description[bg]": "Идентификационни данни за достъп до SMB споделяния",
+        "Description[ca at valencia]": "Credencials utilitzades per a accedir a les comparticions SMB",
+        "Description[ca]": "Credencials usades per a accedir a les comparticions SMB",
+        "Description[cs]": "Přihlašovací údaje pro přístup k úložišti SMB",
+        "Description[de]": "Anmeldungsdaten für den Zugriff auf SMB-Freigaben",
+        "Description[en_GB]": "Credentials used to access SMB shares",
+        "Description[eo]": "Identigiloj uzataj por aliri SMB-komundosierujojn",
+        "Description[es]": "Credenciales que se usan para acceder a los recursos compartidos SMB",
+        "Description[eu]": "SMB partekatzeetara sartzeko egiaztagiriak",
+        "Description[fi]": "Käyttäjätiedot SMB-jakoihin pääsemiseksi",
+        "Description[fr]": "Identifiants utilisés pour accéder aux partages « SMB »",
+        "Description[gl]": "Credenciais que se usan para acceder a comparticións de SMB",
+        "Description[ia]": "Credentiales usate per acceder al partes SMB",
+        "Description[is]": "Auðkenni notuð til að opna SMB-sameignir",
+        "Description[it]": "Credenziali utilizzate per accedere alle condivisioni SMB",
+        "Description[ka]": "SMB გაზიარებულებთან წვდომის მომხმარებელი და პაროლი",
+        "Description[ko]": "SMB 공유에 접근할 때 사용할 자격 증명",
+        "Description[nl]": "Gebruikte credentials voor toegang tot SMB shares",
+        "Description[nn]": "Brukardata brukt til å få tilgang til SMB-ressursar",
+        "Description[pl]": "Dane poufne wykorzystywane do dostępu do udziałów SMB",
+        "Description[sl]": "Poverilnice uporabljene za dostop do skupnih diskov SMB",
+        "Description[tr]": "SMB paylaşımlarına erişmek için kullanılan kimlik bilgileri",
+        "Description[uk]": "Реєстраційні дані для доступу до спільних ресурсів SMB",
+        "Description[x-test]": "xxCredentials used to access SMB sharesxx",
+        "Description[zh_TW]": "用以存取 SMB 共享硬碟的認證資訊",
+        "Icon": "preferences-system-network-share-windows",
+        "Name": "Windows Shares",
+        "Name[ar]": "مشاركات وندوز",
+        "Name[ast]": "Comparticiones de Windows",
+        "Name[bg]": "Споделяне с Windows",
+        "Name[ca at valencia]": "Recursos compartits de Windows",
+        "Name[ca]": "Recursos compartits de Windows",
+        "Name[cs]": "Sdílené disky systému Microsoft Windows",
+        "Name[de]": "Windows-Freigaben",
+        "Name[en_GB]": "Windows Shares",
+        "Name[eo]": "Komunigitaj Dosierujoj de Vidozo",
+        "Name[es]": "Recursos compartidos de Windows",
+        "Name[eu]": "«Windows»ek partekatutakoak",
+        "Name[fi]": "Windows-jaot",
+        "Name[fr]": "Partage Windows",
+        "Name[gl]": "Comparticións de Windows",
+        "Name[ia]": "Areas Compartite de Windows",
+        "Name[is]": "Windows-netdrif",
+        "Name[it]": "Condivisioni Windows",
+        "Name[ka]": "Windows-ის ზიარები",
+        "Name[ko]": "Windows 공유",
+        "Name[nl]": "Windows-netwerken",
+        "Name[nn]": "Delte Windows-ressursar",
+        "Name[pl]": "Udostępniane zasoby Windows",
+        "Name[sl]": "Skupni diski Windows",
+        "Name[tr]": "Windows Paylaşımları",
+        "Name[uk]": "Спільні ресурси Windows",
+        "Name[x-test]": "xxWindows Sharesxx",
+        "Name[zh_TW]": "Windows 共享硬碟"
+    },
+    "X-DocPath": "kcontrol6/smb/index.html",
+    "X-KDE-Keywords": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[ar]": "SMB,سامبا,زبون سامبا,شبكة ويندز,شبكة محلية,شبكة,الجوار,خادم,نشر,ويندوز,مشاركة,ولوج,كلمات سر",
+    "X-KDE-Keywords[az]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords SMB, SAMBA, SMB müştəri, Windows şəbəkəsi, LAN, Şəbəkə, qonşuluq, Server,Yayım, WINS, Paylaş, Giriş, Şifrələr",
+    "X-KDE-Keywords[be at latin]": "SMB,SAMBA,Klijent SMB,Sietka Windows,LAN,Sietka,Sietkavaje asiaroddzie,Siervier,Transliacyja,WINS,Ahuĺnyja resursy,Lahin,Paroli",
+    "X-KDE-Keywords[be]": "SMB,SAMBA,Кліент SMB,Сетка Windows,LAN,Сетка,Сеткавае асяроддзе,Сервер,Трансляцыя,WINS,Агульныя рэсурсы,Лагін,Паролі",
+    "X-KDE-Keywords[bg]": "SMB,SAMBA,SMB клиент,Мрежа на Windows,LAN,Мрежа,neighborhood,Server,Broadcast,WINS,Споделяния,Влизане,Пароли",
+    "X-KDE-Keywords[bs]": "SMB,SAMBA,SMB klijent,Vindovs mreža,LAN,Mreža,komšiluk,Server,Emitovanje,WINS,Dijeljenje,Prijavljivanje,Lozinke",
+    "X-KDE-Keywords[ca at valencia]": "SMB,SAMBA,Client SMB,Xarxa Windows,LAN,Xarxa,veïnat,Servidor,Difusió,WINS,Compartició,Connexió,Contrasenyes",
+    "X-KDE-Keywords[ca]": "SMB,SAMBA,Client SMB,Xarxa Windows,LAN,Xarxa,veïnat,Servidor,Difusió,WINS,Compartició,Connexió,Contrasenyes",
+    "X-KDE-Keywords[cs]": "SMB,SAMBA,klient SMB,Síť Windows,LAN,Síť,okolí,Server,Broadcast,WINS,Úložiště,Přihlášení,Hesla",
+    "X-KDE-Keywords[cy]": "SMB,SAMBA,dibynnydd SMB,Rhwydwaith Windows,LAN,Rhwydwaith,cymdogaeth,Gweinydd,Darllediad,WINS,Rhanniad,Mewngofnodi,Cyfrineiriau",
+    "X-KDE-Keywords[da]": "SMB,SAMBA,SMB-klient,Windows netværk,LAN,netværk,nabolag,Server,Broadcast,WINS,Share,Login,adgangskoder",
+    "X-KDE-Keywords[de]": "SMB-Client,Windows-Netzwerk,Netzwerk,Netzumgebung,Netzwerkumgebung,Umgebung,Freigabe,Anmeldung,Passwörter",
+    "X-KDE-Keywords[el]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[en_GB]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[es]": "SMB,SAMBA,Cliente SMB,Red de Windows,LAN,Red,entorno de red,Servidor,Emisión,WINS,Recurso compartido,Inicio de sesión,Contraseñas",
+    "X-KDE-Keywords[et]": "SMB,SAMBA,SMB klient,Windowsi võrk,LAN,Võrk,naabrus,Server,Leviedastus,Broadcast,WINS,Jagatud ressurss,Sisselogimine,Paroolid",
+    "X-KDE-Keywords[eu]": "SMB,SAMBA,SMB bezero,Windows partekatze,LAN,Sare,auzoa,Zerbitzari,Igorpen,WINS,Partekatze,Saio,Pasahitzak",
+    "X-KDE-Keywords[fi]": "SMB,SAMBA,SMB client,SMB-asiakas,SMB-ohjelma,Windows-verkko,LAN,Verkko,ympäristö,Palvelin,Broadcast,Yleislähetys,WINS,Jako,Kirjautuminen,Salasanat",
+    "X-KDE-Keywords[fr]": "SMB, SAMBA,client SMB, réseau Windows, LAN, réseau, voisinage,Serveur, diffusion, WINS, partages, connexion, mots de passe",
+    "X-KDE-Keywords[gd]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,cliant SMB,lìonra Windows,lìonra,nàbaidheachd,nàbaidhean,frithealaiche,craoladh,co-roinneadh,clàradh a-steach,clàraich a-steach,facal-faire,faclan-faire",
+    "X-KDE-Keywords[gl]": "SMB,SAMBA,cliente SMB,rede de Windows,LAN,rede,veciñanza,servidor, retransmisión,WINS,compartición,compartir,acceso,contrasinais",
+    "X-KDE-Keywords[hu]": "SMB,SAMBA,SMB kliens,Windows hálózat,LAN,Hálózat,szomszédszág,Kiszolgáló,Üzenetszórás,WINS,Megosztás,Bejelentkezés,Jelszavak",
+    "X-KDE-Keywords[ia]": "SMB,SAMBA,Cliente SMB,rete de Windows,LAN,rete,vicinitate,Servitor,Transmission,WINS,Compartite,Authentication,Contrasignos",
+    "X-KDE-Keywords[id]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[ie]": "SMB,SAMBA,Cliente SMB,Rete de Windows,LAN,Rete,neighborhood,Servitor,Broadcast,WINS,Partite,Session,Login,Contrasignes",
+    "X-KDE-Keywords[is]": "SMB,SAMBA,SMB-biðlari,Windows-netkerfi,LAN,Netkerfi,nágrenni,miðlari, þjónn,Útvörpun,WINS,deila,Innskráning,Lykilorð",
+    "X-KDE-Keywords[it]": "SMB,SAMBA,client SMB,rete di Windows,LAN,Rete,vicinanza,Server,Broadcast,WINS,Share,Login,Password",
+    "X-KDE-Keywords[ka]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[ko]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,삼바,윈도우,윈도우 네트워크,네트워크 환경,내 네트워크 환경,로그인,공유,암호,비밀번호",
+    "X-KDE-Keywords[lt]": "SMB,SAMBA,SMB klientas,SMB kliento programa,Windows tinklas,LAN,tinklas,tinklo aplinka,kaimynystė,Serveris,Transliavimas,WINS,Bendrinti,Bendrinimas,Viešinys,Viesinys,Viešiniai,Viesiniai,Prisijungti,Prisijungimas,Slaptažodžiai,Slaptazodziai",
+    "X-KDE-Keywords[my]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-Keywords[nb]": "SMB,SAMBA,SMB-klient,Windows-nettverk,LAN,Nettverk,nabolag,Tjener,Kringkasting,WINS,Ressurs,Login,Passord",
+    "X-KDE-Keywords[nl]": "SMB,SAMBA,SMB-client,Windows-netwerk,LAN,netwerk,nabije omgeving,server,broadcast,WINS,delen,aanmelden,wachtwoorden",
+    "X-KDE-Keywords[nn]": "SMB,SAMBA,SMB-klient,Windows-nettverk,LAN,nettverk,lokalnett,tenar,server,kringkasting,WINS,ressurs,innlogging,brukarnamn,passord",
+    "X-KDE-Keywords[pa]": "ਐਸਐਮਬੀ,ਸਾਂਬਾ,ਸਾਂਬਾ ਕਲਾਈਂਟ,ਵਿੰਡੋਜ਼ ਨੈੱਟਵਰਕ,ਲਾਨ,ਨੈੱਟਵਰਕ,ਗੁਆਂਢ,ਸਰਵਰ,ਬਰਾਡਕਾਸਟ,ਵਿਨਜ਼,ਸਾਂਝ,ਸ਼ੇਅਰ,ਲਾਗਇਨ,ਪਾਸਵਰਡ",
+    "X-KDE-Keywords[pl]": "SMB,SAMBA,Klient SMB,Sieć Windows, LAN,Sieć,otoczenie,Serwer,Broadcast,WINS,Udostępnianie,Współdzielenie,Login,Hasła",
+    "X-KDE-Keywords[pt]": "SMB,SAMBA,cliente de SMB,rede Windows,LAN,Rede,vizinhança,Servidor,Difusão,WINS,Partilha,Utilizador,Senhas",
+    "X-KDE-Keywords[pt_BR]": "SMB,SAMBA,Cliente de SMB,Rede Windows,LAN,Rede,vizinhança,Servidor,Difusão,WINS,Compartilhamento,Autenticação,Senhas",
+    "X-KDE-Keywords[ro]": "SMB,SAMBA,client SMB,rețea Windows,LAN,rețea,vecinătate,informații sistem,server,difuzare,rețea locală,wins,partajare,autentificare,parole",
+    "X-KDE-Keywords[ru]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,клиент SMB,сеть Windows,сеть,соседи,широковещание,совместный доступ,логин,имя пользователя,пароль",
+    "X-KDE-Keywords[sk]": "SMB,SAMBA,SMB klient,Sieť Windows,LAN,Sieť,okolie,Server,Broadcast,WINS,Zdieľanie,Login,Heslá",
+    "X-KDE-Keywords[sl]": "SMB,SAMBA,Odjemalec SMB,omrežje Windows,LAN,Omrežje,soseska,Strežnik,Vsesmerno oddajanje,WINS,Deljenje,Souporaba,Prijava,Gesla",
+    "X-KDE-Keywords[sr at ijekavian]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,СМБ,Самба,СМБ клијент,виндоуз мрежа,ЛАН,мрежа,суседство,сервер,емитовање,ВИНС,дељење,пријава,лозинка",
+    "X-KDE-Keywords[sr at ijekavianlatin]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,SMB,Samba,SMB klijent,windows mreža,LAN,mreža,susedstvo,server,emitovanje,WINS,deljenje,prijava,lozinka",
+    "X-KDE-Keywords[sr at latin]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,SMB,Samba,SMB klijent,windows mreža,LAN,mreža,susedstvo,server,emitovanje,WINS,deljenje,prijava,lozinka",
+    "X-KDE-Keywords[sr]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,СМБ,Самба,СМБ клијент,виндоуз мрежа,ЛАН,мрежа,суседство,сервер,емитовање,ВИНС,дељење,пријава,лозинка",
+    "X-KDE-Keywords[sv]": "SMB,SAMBA,SMB klient,Windows nätverk,LAN,Nätverk,grannskap,Server,Utsändning,WINS,Dela,Inloggning,Lösenord",
+    "X-KDE-Keywords[ta]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,விண்டோஸ்,கடவுச்சொற்கள்,பிணையம்,இணைப்பு,நுழைவு,பகிர்வு",
+    "X-KDE-Keywords[tg]": "SMB,SAMBA,мизоҷи SMB,шабакаи Windows,LAN,Шабака,ҳамҳудудӣ, Хизматрасон,Пахшкунӣ,WINS,Мубодила,Воридшавӣ,Ниҳонвожаҳо",
+    "X-KDE-Keywords[tok]": "SMB,SAMBA,ilo SMB,Windows,linluwi,LAN,ilo linluwi,nimi len",
+    "X-KDE-Keywords[tr]": "SMB,SAMBA,SMB istemcisi,Windows ağı,LAN,Ağ,komşu,Sunucu,Yayın,WINS,Paylaşım,Giriş,Parolalar",
+    "X-KDE-Keywords[uk]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,клієнт,віндоус,віндовс,віндовз,оточення,локальна,сервер,трансляція,ресурс,спільний,пароль,вхід,реєстрація",
+    "X-KDE-Keywords[vi]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,trình khách SMB,mạng Windows,mạng,lân cận,Máy chủ,Quảng bá,Chia sẻ,Đăng nhập,Mật khẩu",
+    "X-KDE-Keywords[x-test]": "xxSMBxx,xxSAMBAxx,xxSMB clientxx,xxWindows networkxx,xxLANxx,xxNetworkxx,xxneighborhoodxx,xxServerxx,xxBroadcastxx,xxWINSxx,xxSharexx,xxLoginxx,xxPasswordsxx",
+    "X-KDE-Keywords[zh_CN]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords,SMB 客户端,Windows 网络,网络,网上邻居,服务器,广播,共享,登录,密码",
+    "X-KDE-Keywords[zh_TW]": "SMB,SAMBA,SMB client,Windows network,LAN,Network,neighborhood,Server,Broadcast,WINS,Share,Login,Passwords",
+    "X-KDE-ParentApp": "kcontrol",
+    "X-KDE-System-Settings-Parent-Category": "networksettings"
+}
diff --git a/kcms/smb/smbrodlg.cpp b/kcms/smb/smbrodlg.cpp
new file mode 100644
index 000000000..87235eae7
--- /dev/null
+++ b/kcms/smb/smbrodlg.cpp
@@ -0,0 +1,119 @@
+/*
+    This file is part of the KDE project
+    SPDX-FileCopyrightText: 2000 Alexander Neundorf <neundorf at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+// Own
+#include "smbrodlg.h"
+
+// Qt
+#include <QGridLayout>
+#include <QLabel>
+
+// KDE
+#include <KConfig>
+#include <KConfigGroup>
+#include <KLocalizedString>
+#include <KPluginFactory>
+
+K_PLUGIN_CLASS_WITH_JSON(SMBRoOptions, "kcm_smb.json")
+
+SMBRoOptions::SMBRoOptions(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+{
+    QGridLayout *layout = new QGridLayout(widget());
+    QLabel *label = new QLabel(i18n("These settings apply to network browsing only."), widget());
+    layout->addWidget(label, 0, 0, 1, 2);
+
+    m_userLe = new QLineEdit(widget());
+    label = new QLabel(i18n("Default user name:"), widget());
+    label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+    label->setBuddy(m_userLe);
+    layout->addWidget(label, 1, 0);
+    layout->addWidget(m_userLe, 1, 1);
+
+    m_passwordLe = new QLineEdit(widget());
+    m_passwordLe->setEchoMode(QLineEdit::Password);
+    label = new QLabel(i18n("Default password:"), widget());
+    label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+    label->setBuddy(m_passwordLe);
+    layout->addWidget(label, 2, 0);
+    layout->addWidget(m_passwordLe, 2, 1);
+
+    layout->addWidget(new QWidget(widget()), 4, 0);
+
+    connect(m_userLe, &QLineEdit::textChanged, this, &SMBRoOptions::changed);
+    connect(m_passwordLe, &QLineEdit::textChanged, this, &SMBRoOptions::changed);
+
+    layout->setRowStretch(4, 1);
+}
+
+SMBRoOptions::~SMBRoOptions() = default;
+
+void SMBRoOptions::load()
+{
+    KConfig *cfg = new KConfig(QStringLiteral("kioslaverc"));
+
+    KConfigGroup group = cfg->group("Browser Settings/SMBro");
+    m_userLe->setText(group.readEntry("User"));
+
+    // unscramble
+    QString scrambled = group.readEntry("Password");
+    QString password;
+    const int passwordLength = scrambled.length() / 3;
+    password.reserve(passwordLength);
+    for (int i = 0; i < passwordLength; ++i) {
+        QChar qc1 = scrambled[i * 3];
+        QChar qc2 = scrambled[i * 3 + 1];
+        QChar qc3 = scrambled[i * 3 + 2];
+        unsigned int a1 = qc1.toLatin1() - '0';
+        unsigned int a2 = qc2.toLatin1() - 'A';
+        unsigned int a3 = qc3.toLatin1() - '0';
+        unsigned int num = ((a1 & 0x3F) << 10) | ((a2 & 0x1F) << 5) | (a3 & 0x1F);
+        password[i] = QLatin1Char((num - 17) ^ 173); // restore
+    }
+    m_passwordLe->setText(password);
+
+    delete cfg;
+}
+
+void SMBRoOptions::save()
+{
+    KConfig *cfg = new KConfig(QStringLiteral("kioslaverc"));
+
+    KConfigGroup group = cfg->group("Browser Settings/SMBro");
+    group.writeEntry("User", m_userLe->text());
+
+    // taken from Nicola Brodu's smb ioslave
+    // it's not really secure, but at
+    // least better than storing the plain password
+    QString password(m_passwordLe->text());
+    QString scrambled;
+    for (const QChar c : std::as_const(password)) {
+        unsigned int num = (c.unicode() ^ 173) + 17;
+        unsigned int a1 = (num & 0xFC00) >> 10;
+        unsigned int a2 = (num & 0x3E0) >> 5;
+        unsigned int a3 = (num & 0x1F);
+        scrambled += QLatin1Char((char)(a1 + '0'));
+        scrambled += QLatin1Char((char)(a2 + 'A'));
+        scrambled += QLatin1Char((char)(a3 + '0'));
+    }
+    group.writeEntry("Password", scrambled);
+
+    delete cfg;
+}
+
+void SMBRoOptions::defaults()
+{
+    m_userLe->setText(QString());
+    m_passwordLe->setText(QString());
+}
+
+void SMBRoOptions::changed()
+{
+    setNeedsSave(true);
+}
+
+#include "smbrodlg.moc"
diff --git a/kcms/smb/smbrodlg.h b/kcms/smb/smbrodlg.h
new file mode 100644
index 000000000..f8556a5a5
--- /dev/null
+++ b/kcms/smb/smbrodlg.h
@@ -0,0 +1,41 @@
+/*
+    This file is part of the KDE project
+    SPDX-FileCopyrightText: 2000, 2005 Alexander Neundorf <neundorf at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef __SMBRODLG_H
+#define __SMBRODLG_H
+
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QWidget>
+
+#include <KCModule>
+
+class KComboBox;
+
+class SMBRoOptions : public KCModule
+{
+    Q_OBJECT
+public:
+    SMBRoOptions(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~SMBRoOptions() override;
+
+    void load() override;
+    void save() override;
+    void defaults() override;
+
+private Q_SLOTS:
+    void changed();
+
+private:
+    QLineEdit *m_userLe;
+    QLineEdit *m_passwordLe;
+    //      QLineEdit *m_workgroupLe; //currently unused, Alex
+    //      QCheckBox *m_showHiddenShares; //currently unused, Alex
+    //      KComboBox *m_encodingList; //currently unused
+};
+
+#endif
diff --git a/kcms/webshortcuts/CMakeLists.txt b/kcms/webshortcuts/CMakeLists.txt
new file mode 100644
index 000000000..63bc375f4
--- /dev/null
+++ b/kcms/webshortcuts/CMakeLists.txt
@@ -0,0 +1,16 @@
+kcoreaddons_add_plugin(kcm_webshortcuts SOURCES main.cpp INSTALL_NAMESPACE "plasma/kcms/systemsettings_qwidgets")
+
+kcmutils_generate_desktop_file(kcm_webshortcuts)
+
+target_link_libraries(kcm_webshortcuts
+  PUBLIC
+    KF6::KCMUtils # KCModule
+    KF6::KIOWidgets    # KUriFilter
+  PRIVATE
+    KF6::I18n
+    KF6::CoreAddons
+)
+
+if (ENABLE_PCH)
+    target_precompile_headers(kcm_webshortcuts REUSE_FROM KIOPchWidgets)
+endif()
diff --git a/kcms/webshortcuts/kcm_webshortcuts.json b/kcms/webshortcuts/kcm_webshortcuts.json
new file mode 100644
index 000000000..ba208eca1
--- /dev/null
+++ b/kcms/webshortcuts/kcm_webshortcuts.json
@@ -0,0 +1,112 @@
+{
+    "Categories": "Qt;KDE;X-KDE-settings-webbrowsing;",
+    "KPlugin": {
+        "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=systemsettings&component=kcm_webshortcuts",
+        "Description": "Configure web search keywords",
+        "Description[ar]": "اضبط بحث الوبّ",
+        "Description[bg]": "Конфигуриране на ключови думи за уеб търсене",
+        "Description[ca at valencia]": "Configura les paraules clau de busca en la web",
+        "Description[ca]": "Configura les paraules clau de cerca a la web",
+        "Description[cs]": "Nastavit klíčová slova pro hledání na webu",
+        "Description[de]": "Web-Kürzel einrichten",
+        "Description[en_GB]": "Configure web search keywords",
+        "Description[eo]": "Agordi retserĉajn ŝlosilvortojn",
+        "Description[es]": "Configurar las palabras clave de búsqueda web",
+        "Description[eu]": "Konfiguratu web bilaketarako gako-hitzak",
+        "Description[fi]": "Aseta verkkohaun hakusanat",
+        "Description[fr]": "Configurer les mots clé de recherche sur Internet",
+        "Description[gl]": "Configurar as palabras clave de busca na web",
+        "Description[ia]": "Configura  parolas clave de cerca de Web",
+        "Description[is]": "Grunnstilla stikkorð fyrir leit á vefnum",
+        "Description[it]": "Configure le parole chiave per ricerca web",
+        "Description[ka]": "ვებშ ძებნის საკვანძო სიტყვების მორგება",
+        "Description[ko]": "웹 검색 키워드 설정",
+        "Description[nl]": "Webzoektrefwoorden configureren",
+        "Description[nn]": "Set opp nøkkelord for vevsøk",
+        "Description[pl]": "Ustawienia skrótów sieciowych",
+        "Description[sl]": "Konfiguriraj ključne besede iskanja po spletu",
+        "Description[tr]": "Web araması anahtar sözcüklerini yapılandır",
+        "Description[uk]": "Налаштування ключових слів пошуку в інтернеті",
+        "Description[x-test]": "xxConfigure web search keywordsxx",
+        "Description[zh_TW]": "設定網路搜尋關鍵字",
+        "Icon": "preferences-web-browser-shortcuts",
+        "Name": "Web Search Keywords",
+        "Name[ar]": "كلمات بحث الويب",
+        "Name[bg]": "Ключови думи за уеб търсене",
+        "Name[ca at valencia]": "Paraules clau de busca en la web",
+        "Name[ca]": "Paraules clau de cerca a la web",
+        "Name[cs]": "Klíčová slova pro hledání na webu",
+        "Name[de]": "Web-Kürzel",
+        "Name[en_GB]": "Web Search Keywords",
+        "Name[eo]": "Retserĉaj Ŝlosilvortoj",
+        "Name[es]": "Palabras clave de búsqueda web",
+        "Name[eu]": "Web bilaketarako gako-hitzak",
+        "Name[fi]": "Verkkohaun hakusanat",
+        "Name[fr]": "Mots clé de recherche sur Internet",
+        "Name[gl]": "Palabras clave de busca na web",
+        "Name[ia]": "Parolas clave de cerca de web",
+        "Name[is]": "Stikkorð í vefleit",
+        "Name[it]": "Parole chiave per ricerca web",
+        "Name[ka]": "ვებში ძებნის საკვანძო სიტყვები",
+        "Name[ko]": "웹 검색 키워드",
+        "Name[nl]": "Webzoektrefwoorden",
+        "Name[nn]": "Nøkkelord for vevsøk",
+        "Name[pl]": "Słowa kluczowe do wyszukiwania w sieci",
+        "Name[sl]": "Ključne besede iskanja po spletu",
+        "Name[tr]": "Web Araması Anahtar Sözcükleri",
+        "Name[uk]": "Ключові слова пошуку в інтернеті",
+        "Name[x-test]": "xxWeb Search Keywordsxx",
+        "Name[zh_TW]": "網路搜尋關鍵字"
+    },
+    "X-DocPath": "kcontrol6/webshortcuts/index.html",
+    "X-KDE-Keywords": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[ar]": "الكلمات الأساسية لبحث الويب,بحث الويب,البحث,الكلمات الرئيسية,اختصارات الويب,التصفح,WWW ,الإنترنت,مصفيات الإنترنت,الشبكة,محركات البحث,الاختصارات",
+    "X-KDE-Keywords[az]": "Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts İnternetdə axtarış açar sözləri, Tarama, WWW, İnternet, İnternet Filtrləri, Şəbəkə, Axtarış motorları,Qısa yollar",
+    "X-KDE-Keywords[be at latin]": "Kliučavyja slovy dlia sieciŭnaha pošuku,Sieciŭny pošuk,Pošuk,Kliučavoje slova,Sieciŭnyja skaroty,Ahliad,WWW,Internet,Sieciŭnyja fiĺtry,Sietka,Sistemy pošuku,Skaroty",
+    "X-KDE-Keywords[be]": "Ключавыя словы для сеціўнага пошуку,Сеціўны пошук,Пошук,Ключавое слова,Сеціўныя скароты,Агляд,WWW,Інтэрнэт,Сеціўныя фільтры,Сетка,Сістэмы пошуку,Скароты",
+    "X-KDE-Keywords[bg]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[bs]": "Ključne riječi za veb pretraživanje,Veb Pretraživanje,Pretraga,Ključna riječ,Prečice za Veb,Pregledavanje,WWW,Internet,Internet Filteri,Mreža,Pretraživači,Prečice",
+    "X-KDE-Keywords[ca at valencia]": "Paraules clau de busca en la web,Busca en la web,Busca,Paraules clau,Dreceres web,Navegació,WWW,Internet,Filtres d'internet,Xarxa,Motors de busca,Dreceres",
+    "X-KDE-Keywords[ca]": "Paraules clau de cerca a la web,Cerca a la web,Cerca,Paraules clau,Dreceres web,Navegació,WWW,Internet,Filtres d'internet,Xarxa,Motors de cerca,Dreceres",
+    "X-KDE-Keywords[cs]": "Klíčová slova pro hledání na webu,Hledání na webu,Hledání,Klíčové slovo,Webové zkratky, Prohlížení,WWW,Internet,Internetové filtry,Síť,Vyhledávací nástroje,Zkratky",
+    "X-KDE-Keywords[cy]": "Allweddeiriau Chwilio Gwe, Chilwio Gwe, Chwilio, Allweddair, Byrlwybrau Gwe, Pori, WWW, Rhyngrwyd, Hidlau Rhyngrwyd, Rhwydwaith, Peiriannau Chwilio, Llwybrau Byr",
+    "X-KDE-Keywords[da]": "Nøgleord til web søgning,Webgenveje,browsing,www,internet,internetfiltre,netværk,søgemaskiner,genveje",
+    "X-KDE-Keywords[de]": "Web-Kürzel, Browsen,Websuche,Stichwörter,Filter,Netz,Internetfilter,Suchmaschinen,Kurzbefehle,Netzwerk",
+    "X-KDE-Keywords[el]": "Λέξεις κλειδιά αναζήτησης στον ιστό,αναζήτηση στον ιστό,αναζήτηση,συντομεύσεις ιστού, περιήγηση,WWW,Διαδίκτυο,διαδικτυακά φίλτρα,Δίκτυο,μηχανές αναζήτησης,συντομεύσεις",
+    "X-KDE-Keywords[en_GB]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[es]": "Palabras clave de búsqueda web,Búsqueda web,Buscar,Palabra clave,Accesos rápidos Web,Navegación,WWW,Internet,Filtros de Internet,Red,Motores de búsqueda,Accesos rápidos,Atajos Web,Atajos",
+    "X-KDE-Keywords[et]": "Veebiotsingu kiirkorraldused,Veebiotsing,Võtmesõna,Veebi kiirkorraldused,Sirvimine,WWW,Veeb,Internet,Internetifiltrid,Võrk,Otsing,Otsimine,Otsimootorid,Otsimismootorid,Kiirkorraldused",
+    "X-KDE-Keywords[eu]": "Web bilaketarako gako-hitzak,Web bilaketa,Bilaketa,Gako-hitza,Web lasterbideak,Arakatzea,Nabigatzea,WWW,Internet,Internet iragazkiak,Sarea,Bilatzaileak,Lasterbideak",
+    "X-KDE-Keywords[fi]": "Verkkohaun hakusanat,Verkkohaku,Haku,Hakusana,Pikavalinnat,Selaus,WWW,Internet,Internetsuodattimet,Verkko,Hakukoneet",
+    "X-KDE-Keywords[fr]": "Mots clé de recherche sur Internet, Rechercher sur Internet, Recherche, Mot clé, Raccourcis Web, Navigation, www, Internet, Filtres Internet, Réseau, Moteurs de Recherche, Raccourcis",
+    "X-KDE-Keywords[hu]": "Webes keresési kulcsszavak,Webes keresés,Keresés,KulcsszóKeresési azonosítók,Böngészés,WWW,Internet,Internetes szűrők,Hálózat,Keresőmotorok,Gyorsbillentyűk",
+    "X-KDE-Keywords[ia]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[id]": "Kata Kunci Pencarian Web,Pencarian Web,Pencarian,Kata Kunci,Pintasan Web,Menelusuri,WWW,Internet,Filter Internet,Jaringan,Mesin Pencari,Pintasan",
+    "X-KDE-Keywords[ie]": "Clav-paroles de sercha web,Sercha web,Sercha,Clav-parole,Web Shortcuts,Navigation,WWW,Internet,Filtres de Internet,Rete,Provisores de sercha,Shortcuts",
+    "X-KDE-Keywords[is]": "Stikkorð vefleitar,Vefleit,Leit,Stikkorð,Veftenglar,Flakk,WWW,Internet, Internetsíur,Netkerfi,Leitarvél,Flýtileið",
+    "X-KDE-Keywords[it]": "Parole chiave per ricerca web,Ricerca web,Ricerca,Parola chiave,Scorciatoie del Web,Navigazione,Browsing,WWW,Internet,Filtri Internet,Rete,Motori di ricerca,Scorciatoie",
+    "X-KDE-Keywords[ka]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[ko]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,웹 검색 키워드, 웹 검색,검색,찾기,키워드,검색어,웹 바로 가기,탐색,인터넷,인터넷 필터,네트워크,검색 엔진",
+    "X-KDE-Keywords[lt]": "Paieškos žiniatinklyje raktažodžiai,Paieskos ziniatinklyje raktazodziai,Paieskos saityne raktazodziai,Paieškos saityne raktažodžiai,Ieškoti,Ieskoti,Raktažodžiai,Raktazodziai,Raktažodis,Raktazodis,Žiniatinklio trumpiniai,Ziniatinklio trumpiniai,Saityno trumpiniai,Naršymas,WWW,Saitynas,Internetas,Interneto filtrai,Tinklas,Paieškos varikliai,Paieskos varikliai,Paieškos sistemos,Paieskos sistemos,Ieškyklės,Ieskykles,Trumpiniai",
+    "X-KDE-Keywords[my]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts",
+    "X-KDE-Keywords[nl]": "Web-zoeken op trefwoorden,web-zoeken,zoeken,trefwoord,web-sneltoetsen,browsing,www,internet,internet-filters,netwerk,zoekmachines,sneltoetsen",
+    "X-KDE-Keywords[nn]": "vevsnarvegar,vevsøk,nettsidesnarvegar,nettsidesøk,søk,nøkkelord,surfing,WWW,Internett,Internett-filter,nettverk,søkjemotorar,snarvegar",
+    "X-KDE-Keywords[pa]": "ਵੈੱਬ ਖੋਜ ਸ਼ਬਦ, ਵੈੱਬ ਖੋਜ,ਖੋਜ,ਸ਼ਬਦ,ਕੀਵਰਡ,ਵੈੱਬ ਸ਼ਾਰਟਕੱਟ,ਬਰਾਊਜ਼ਿੰਗ,ਬਰਾਊਜ਼,ਇੰਟਰਨੈੱਟ,ਇੰਟਰਨੈੱਟ ਫਿਲਟਰ,ਨੈੱਟਵਰਕ,ਖੋਜ ਇੰਜਣ,ਸ਼ਾਰਟਕੱਟ,ਇੰਟਰਨੈਟ",
+    "X-KDE-Keywords[pl]": "Skróty sieciowe, Przeglądanie,WWW,Internet,Filtry internetowe,Sieć,Wyszukiwarki,Silniki wyszukiwania,Skróty",
+    "X-KDE-Keywords[pt]": "Palavras-Chave de Pesquisa na Web,Pesquisa na Web,Pesquisa,Palavra-Chave,Atalhos Web,Navegação,WWW,Internet,Filtros da Internet,Rede,Motores de Busca,Atalhos",
+    "X-KDE-Keywords[pt_BR]": "Palavras-chave de pesquisa na web,Pesquisa na web,Pesquisa,Procurar,Atalhos da Web, Navegação,WWW,Internet,Filtros da Internet,Rede,Mecanismos de busca,Mecanismos de pesquisa,Atalhos",
+    "X-KDE-Keywords[ru]": "ключевые слова для веб-поиска, поиск в интернете,веб-сокращения,браузер,веб,WWW,Интернет,фильтры для Интернета,сеть,поисковые системы,поисковики,сокращения",
+    "X-KDE-Keywords[sk]": "Kľúčové slová webového vyhľadávania,Webové vyhľadávanie,Vyhľadávanie,Kľúčové slovo,Webové skratky,Surfovanie,WWW,Internet,Internetové filtre,Sieť,Vyhľadávacie nástroje,Skratky",
+    "X-KDE-Keywords[sl]": "Ključne besede iskanja po spletu,Iskanje po spletu,Iskanje,Ključna beseda,Spletne bližnjice,Brskanje,WWW,Internet,Splet,Internetni filtri,Omrežje,Iskalni pogoni,Bližnjice",
+    "X-KDE-Keywords[sv]": "Webbsökningsnyckelord,Webbsökning,Nyckelord,Webbgenvägar,Bläddring,WWW,Internet,Internetfilter,Nätverk,Söktjänster,Genvägar",
+    "X-KDE-Keywords[ta]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,இணையம்,வடிகட்டி,வழிகட்டி,பிணையம்,தேடல் சேவை,சுருக்குவழி,குறுக்குவழி,முதன்மைச்சொற்கள்,முதன்மைச்சொல்,இணையத் தேடல் முதன்மைச்சொற்கள்",
+    "X-KDE-Keywords[tg]": "Калидвожаҳои ҷустуҷӯии интернетӣ,Ҷустуҷӯи интернетӣ,Ҷустуҷӯ,Калидвожа,Миёнбурҳои интернетӣ,Тамошои интернетӣ,WWW,Интернет,полои интернетӣ,Шабака,Низомҳои ҷустуҷӯӣ,Миёнбурҳо",
+    "X-KDE-Keywords[tok]": "nimi,alasa,linluwi,www",
+    "X-KDE-Keywords[tr]": "Web Arama Kısayolları,Anahtar sözcük,Web Kısayolları,Tarama,WWW,İnternet,İnternet Süzgeçleri,Ağ,Arama Motorları,Kısayollar",
+    "X-KDE-Keywords[uk]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,ключові,слова,вебпошук,пошук,слово,додатково,додатковий,інтернет,фільтри,фільтрування,фільтр,мережа,рушій,пошук,рушії пошуку,скорочення,вебскорочення",
+    "X-KDE-Keywords[vi]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,Từ khoá tìm kiếm web,Tìm kiếm web,Tìm kiếm,Từ khoá,Lối tắt web,Duyệt,WWW,Liên Mạng,Bộ lọc Liên Mạng,Mạng,Dụng cụ tìm kiếm,Lối tắt",
+    "X-KDE-Keywords[x-test]": "xxWeb Search Keywordsxx,xxWeb Searchxx,xxSearchxx,xxKeywordxx,xxWeb Shortcutsxx,xxBrowsingxx,xxWWWxx,xxInternetxx,xxInternet Filtersxx,xxNetworkxx,xxSearch Enginesxx,xxShortcutsxx",
+    "X-KDE-Keywords[zh_CN]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,网页搜索关键字,网页搜索,搜索,关键字,网页快捷方式,浏览,万维网,互联网,互联网过滤器,网络,搜索引擎,快捷方式",
+    "X-KDE-Keywords[zh_TW]": "Web Search Keywords,Web Search,Search,Keyword,Web Shortcuts,Browsing,WWW,Internet,Internet Filters,Network,Search Engines,Shortcuts,網路搜尋關鍵字,捷徑,網路",
+    "X-KDE-ParentApp": "kcontrol"
+}
diff --git a/kcms/webshortcuts/main.cpp b/kcms/webshortcuts/main.cpp
new file mode 100644
index 000000000..d7e2878c0
--- /dev/null
+++ b/kcms/webshortcuts/main.cpp
@@ -0,0 +1,101 @@
+/*
+    SPDX-FileCopyrightText: 2000 Yves Arrouye <yves at realnames.com>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Own
+#include "main.h"
+
+// Qt
+#include <QTabWidget>
+#include <QVBoxLayout>
+
+// KDE
+#include <KAboutData>
+#include <KLocalizedString>
+#include <KPluginFactory>
+#include <KPluginMetaData>
+#include <kurifilter.h>
+
+K_PLUGIN_CLASS_WITH_JSON(KURIFilterModule, "kcm_webshortcuts.json")
+
+KURIFilterModule::KURIFilterModule(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
+    : KCModule(parent, data, args)
+    , m_widget(nullptr)
+{
+    KCModule::setButtons(KCModule::Buttons(KCModule::Default | KCModule::Apply | KCModule::Help));
+
+    filter = KUriFilter::self();
+
+    QMap<QString, KCModule *> helper;
+    // Load the plugins. This saves a public method in KUriFilter just for this.
+
+    const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/urifilters"));
+    for (const KPluginMetaData &pluginMetaData : plugins) {
+        if (auto factory = KPluginFactory::loadFactory(pluginMetaData).plugin) {
+            if (KCModule *module = factory->create<KCModule>(widget())) {
+                modules.append(module);
+                helper.insert(module->name(), module);
+                connect(module, &KCModule::needsSaveChanged, this, [module, this]() {
+                    setNeedsSave(module->needsSave());
+                });
+            }
+        }
+    }
+
+    if (modules.count() > 1) {
+        QTabWidget *tab = new QTabWidget(widget());
+
+        QMap<QString, KCModule *>::iterator it2;
+        for (it2 = helper.begin(); it2 != helper.end(); ++it2) {
+            tab->addTab(it2.value()->widget(), it2.key());
+        }
+
+        tab->setCurrentIndex(tab->indexOf(modules.first()->widget()));
+        m_widget = tab;
+    } else if (modules.count() == 1) {
+        m_widget = modules.first()->widget();
+        if (m_widget->layout()) {
+            m_widget->layout()->setContentsMargins(0, 0, 0, 0);
+        }
+    }
+
+    widget()->setMinimumWidth(700);
+}
+
+void KURIFilterModule::load()
+{
+    static bool firstLoad = true;
+
+    // Modules automatically call load() when first shown, but subsequent
+    // calls need to be propagated to make the`Reset` button work
+    if (firstLoad) {
+        firstLoad = false;
+        return;
+    }
+
+    for (KCModule *module : std::as_const(modules)) {
+        module->load();
+    }
+}
+
+void KURIFilterModule::save()
+{
+    for (KCModule *module : std::as_const(modules)) {
+        module->save();
+    }
+}
+
+void KURIFilterModule::defaults()
+{
+    for (KCModule *module : std::as_const(modules)) {
+        module->defaults();
+    }
+}
+
+KURIFilterModule::~KURIFilterModule()
+{
+}
+
+#include "main.moc"
diff --git a/kcms/webshortcuts/main.h b/kcms/webshortcuts/main.h
new file mode 100644
index 000000000..cd1021f5c
--- /dev/null
+++ b/kcms/webshortcuts/main.h
@@ -0,0 +1,33 @@
+/*
+    SPDX-FileCopyrightText: 2000 Yves Arrouye <yves at realnames.com>
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <KCModule>
+
+class KUriFilter;
+
+class KURIFilterModule : public KCModule
+{
+    Q_OBJECT
+
+public:
+    KURIFilterModule(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
+    ~KURIFilterModule() override;
+
+    void load() override; // TODO KF6: remove it, not needed
+    void save() override;
+    void defaults() override;
+
+private:
+    KUriFilter *filter;
+
+    QWidget *m_widget;
+    QList<KCModule *> modules;
+};
+
+#endif
diff --git a/smb/kdsoap-ws-discovery-client/CMakeLists.txt b/smb/kdsoap-ws-discovery-client/CMakeLists.txt
index e2f6af53b..18ae4cc49 100644
--- a/smb/kdsoap-ws-discovery-client/CMakeLists.txt
+++ b/smb/kdsoap-ws-discovery-client/CMakeLists.txt
@@ -34,7 +34,7 @@ include(GenerateExportHeader)
 set(REQUIRED_QT_VERSION 5.9.0)
 find_package(Qt${QT_MAJOR_VERSION} ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Core Network Xml)
 
-find_package(KDSoap 1.9.0 REQUIRED)
+find_package(KDSoap-qt6 1.9.0 REQUIRED)
 set_package_properties(KDSoap PROPERTIES
     DESCRIPTION "A Qt-based client-side and server-side SOAP component"
     URL "http://www.kdab.com/products/kd-soap"



More information about the kde-doc-english mailing list