diff --git a/appveyor.yml b/appveyor.yml
index 01aeef7b810297a685c50a23504e112f3f617756..926b901b9ccb5a749fd44d5dcad2bdf4a08c090e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -14,7 +14,7 @@ skip_branch_with_pr: true
 environment:
   APPVEYOR_SAVE_CACHE_ON_ERROR: true
 
-  KF5_VERSION: 5.80
+  KF5_VERSION: 5.81
   KF5_PATCH: 0
   SNORETOAST_VERSION: 0.7.0
 
diff --git a/utils/appveyor/patches/knotifications/0001-Support-updating-Snore-notifications.patch b/utils/appveyor/patches/knotifications/0001-Support-updating-Snore-notifications.patch
index 4668850e21cc0b8e63170be5f1f443835a95c08a..832440772413ed2b3f3934bcfcaf3c706e6761d7 100644
--- a/utils/appveyor/patches/knotifications/0001-Support-updating-Snore-notifications.patch
+++ b/utils/appveyor/patches/knotifications/0001-Support-updating-Snore-notifications.patch
@@ -1,4 +1,4 @@
-From ebdd03b8052087b47587b5d8ede1c82ab1cf5648 Mon Sep 17 00:00:00 2001
+From be14d07c405b49628be6aa0eb450d896ddd3b54f Mon Sep 17 00:00:00 2001
 From: Lukas Holecek <hluk@email.cz>
 Date: Sun, 15 Nov 2020 19:06:53 +0100
 Subject: [PATCH] Support updating Snore notifications
@@ -8,24 +8,24 @@ Subject: [PATCH] Support updating Snore notifications
  1 file changed, 21 insertions(+), 8 deletions(-)
 
 diff --git a/src/notifybysnore.cpp b/src/notifybysnore.cpp
-index 2dad47a..cb32b39 100644
+index 9356bd3..b023238 100644
 --- a/src/notifybysnore.cpp
 +++ b/src/notifybysnore.cpp
-@@ -56,7 +56,7 @@ NotifyBySnore::NotifyBySnore(QObject* parent) :
+@@ -60,7 +60,7 @@ NotifyBySnore::NotifyBySnore(QObject *parent)
      m_server.listen(QString::number(qHash(qApp->applicationDirPath())));
      connect(&m_server, &QLocalServer::newConnection, this, [this]() {
-         QLocalSocket* responseSocket = m_server.nextPendingConnection();
--        connect(responseSocket, &QLocalSocket::readyRead, [this, responseSocket](){
+         QLocalSocket *responseSocket = m_server.nextPendingConnection();
+-        connect(responseSocket, &QLocalSocket::readyRead, [this, responseSocket]() {
 +        connect(responseSocket, &QLocalSocket::readyRead, this, [this, responseSocket](){
              const QByteArray rawNotificationResponse = responseSocket->readAll();
              responseSocket->deleteLater();
  
-@@ -159,9 +159,20 @@ void NotifyBySnore::notifyDeferred(KNotification* notification)
+@@ -169,9 +169,20 @@ void NotifyBySnore::notifyDeferred(KNotification *notification)
  
      // handle the icon for toast notification
      const QString iconPath = m_iconDir.path() + QLatin1Char('/') + QString::number(notification->id());
 +    const bool deleteNewIcon = !QFile::exists(iconPath);
-     const bool hasIcon = (notification->pixmap().isNull()) ? qApp->windowIcon().pixmap(1024, 1024).save(iconPath, "PNG")
+     const bool hasIcon = (notification->pixmap().isNull()) ? qApp->windowIcon().pixmap(1024, 1024).save(iconPath, "PNG") //
                                                             : notification->pixmap().save(iconPath, "PNG");
      if (hasIcon) {
 +        qCDebug(LOG_KNOTIFICATIONS) << "Created temporary icon" << iconPath;
@@ -41,21 +41,21 @@ index 2dad47a..cb32b39 100644
          snoretoastArgsList << QStringLiteral("-p") << iconPath;
      }
  
-@@ -183,19 +194,20 @@ void NotifyBySnore::notifyDeferred(KNotification* notification)
-                 qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast process stdout:"
-                     << snoretoastArgsList << data;
+@@ -189,19 +200,20 @@ void NotifyBySnore::notifyDeferred(KNotification *notification)
+         const auto data = snoretoastProcess->readAllStandardOutput();
+         qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast process stdout:" << snoretoastArgsList << data;
      });
+-    connect(snoretoastProcess, &QProcess::errorOccurred, this, [this, snoretoastProcess, snoretoastArgsList, iconPath](QProcess::ProcessError error) {
 +    QPointer<KNotification> maybeNotification = notification;
-     connect(snoretoastProcess, &QProcess::errorOccurred, this,
--            [this, snoretoastProcess, snoretoastArgsList, iconPath](QProcess::ProcessError error) {
-+            [this, snoretoastProcess, maybeNotification, snoretoastArgsList, iconPath](QProcess::ProcessError error) {
-                 qCWarning(LOG_KNOTIFICATIONS) << "SnoreToast process errored:"
-                     << snoretoastArgsList << error;
-                 snoretoastProcess->deleteLater();
--                QFile::remove(iconPath);
-+                close(maybeNotification);
++    connect(snoretoastProcess, &QProcess::errorOccurred, this, [this, snoretoastProcess, maybeNotification, snoretoastArgsList, iconPath](QProcess::ProcessError error) {
+         qCWarning(LOG_KNOTIFICATIONS) << "SnoreToast process errored:" << snoretoastArgsList << error;
+         snoretoastProcess->deleteLater();
+-        QFile::remove(iconPath);
++        close(maybeNotification);
      });
-     connect(snoretoastProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this,
+     connect(snoretoastProcess,
+             QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+             this,
 -            [this, snoretoastProcess, snoretoastArgsList, iconPath](int exitCode, QProcess::ExitStatus exitStatus) {
 +            [this, snoretoastProcess, maybeNotification, snoretoastArgsList, iconPath](int exitCode, QProcess::ExitStatus exitStatus) {
                  qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast process finished:" << snoretoastArgsList;
@@ -63,10 +63,10 @@ index 2dad47a..cb32b39 100644
                  snoretoastProcess->deleteLater();
 -                QFile::remove(iconPath);
 +                close(maybeNotification);
-     });
+             });
  
      qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast process starting:" << snoretoastArgsList;
-@@ -204,6 +216,9 @@ void NotifyBySnore::notifyDeferred(KNotification* notification)
+@@ -210,6 +222,9 @@ void NotifyBySnore::notifyDeferred(KNotification *notification)
  
  void NotifyBySnore::close(KNotification *notification)
  {
@@ -76,7 +76,7 @@ index 2dad47a..cb32b39 100644
      qCDebug(LOG_KNOTIFICATIONS) << "Requested to close notification with ID:" << notification->id();
      if (m_notifications.constFind(notification->id()) == m_notifications.constEnd()) {
          qCWarning(LOG_KNOTIFICATIONS) << "Couldn't find the notification in m_notifications. Nothing to close.";
-@@ -226,8 +241,6 @@ void NotifyBySnore::close(KNotification *notification)
+@@ -228,7 +243,5 @@ void NotifyBySnore::close(KNotification *notification)
  
  void NotifyBySnore::update(KNotification *notification, KNotifyConfig *config)
  {
@@ -85,7 +85,6 @@ index 2dad47a..cb32b39 100644
 -    qCWarning(LOG_KNOTIFICATIONS) << "updating a notification is not supported yet.";
 +    notify(notification, config);
  }
- 
 -- 
 2.30.2
 
diff --git a/utils/github/homebrew/Formula/extra-cmake-modules.rb b/utils/github/homebrew/Formula/extra-cmake-modules.rb
new file mode 100644
index 0000000000000000000000000000000000000000..57dae82eb4a90ff735ccd1e369680f0bd443a04f
--- /dev/null
+++ b/utils/github/homebrew/Formula/extra-cmake-modules.rb
@@ -0,0 +1,35 @@
+class ExtraCmakeModules < Formula
+  desc "Extra modules and scripts for CMake"
+  homepage "https://api.kde.org/frameworks/extra-cmake-modules/html/index.html"
+  url "https://download.kde.org/stable/frameworks/5.81/extra-cmake-modules-5.81.0.tar.xz"
+  sha256 "5f57e4b843069b6098d955051bb2913558d1623fead3f3b95b7017d7e1e35b83"
+  license all_of: ["BSD-2-Clause", "BSD-3-Clause", "MIT"]
+  head "https://invent.kde.org/frameworks/extra-cmake-modules.git"
+
+  depends_on "cmake" => [:build, :test]
+  depends_on "ninja" => :build
+
+  depends_on "qt@5" => :build
+
+  def install
+    args = std_cmake_args
+    args << "-DBUILD_HTML_DOCS=OFF"
+    args << "-DBUILD_MAN_DOCS=OFF"
+    args << "-DBUILD_QTHELP_DOCS=OFF"
+    args << "-DBUILD_TESTING=OFF"
+
+    mkdir "build" do
+      system "cmake", "-G", "Ninja", "..", *args
+      system "ninja"
+      system "ninja", "install"
+    end
+  end
+
+  test do
+    (testpath/"CMakeLists.txt").write("find_package(ECM REQUIRED)")
+    system "cmake", ".", "-Wno-dev"
+
+    expected="ECM_DIR:PATH=#{HOMEBREW_PREFIX}/share/ECM/cmake"
+    assert_match expected, File.read(testpath/"CMakeCache.txt")
+  end
+end
diff --git a/utils/github/homebrew/Formula/kf5-kconfig.rb b/utils/github/homebrew/Formula/kf5-kconfig.rb
index 6b38d0bb8b43a61ace726efc7eb6160f5518923e..43abc4cfb268933bce6e5d6a94805e887e1de4f1 100644
--- a/utils/github/homebrew/Formula/kf5-kconfig.rb
+++ b/utils/github/homebrew/Formula/kf5-kconfig.rb
@@ -1,14 +1,15 @@
 class Kf5Kconfig < Formula
   desc "Configuration system"
   homepage "https://www.kde.org"
-  url "https://download.kde.org/stable/frameworks/5.79/kconfig-5.79.0.tar.xz"
-  sha256 "f948718ac87f573b14bbf73e4af02d488f023cfcf011425af7cdbc0cefca510a"
+  url "https://download.kde.org/stable/frameworks/5.81/kconfig-5.81.0.tar.xz"
+  sha256 "1ddf9e384140ce72bbd555eb36a76d0db1a256391429b02b51769c08ebf0ae8f"
   head "https://invent.kde.org/frameworks/kconfig.git"
 
   depends_on "cmake" => [:build, :test]
-  depends_on "kde-extra-cmake-modules" => [:build, :test]
   depends_on "ninja" => :build
 
+  depends_on "copyq/kde/extra-cmake-modules" => [:build, :test]
+
   depends_on "qt@5"
 
   def install
diff --git a/utils/github/homebrew/Formula/kf5-kcoreaddons.rb b/utils/github/homebrew/Formula/kf5-kcoreaddons.rb
index 8d542884106d513b52674d5a6f8207e9c07dcb48..ef69d3f8f97df783a275d7d5dcb41d8d0ced2a02 100644
--- a/utils/github/homebrew/Formula/kf5-kcoreaddons.rb
+++ b/utils/github/homebrew/Formula/kf5-kcoreaddons.rb
@@ -1,14 +1,15 @@
 class Kf5Kcoreaddons < Formula
   desc "Addons to QtCore"
   homepage "https://www.kde.org"
-  url "https://download.kde.org/stable/frameworks/5.79/kcoreaddons-5.79.0.tar.xz"
-  sha256 "6f221bd93be73aeec863cd7089c69e84fef76bea83a906c6cd2c853937813659"
+  url "https://download.kde.org/stable/frameworks/5.81/kcoreaddons-5.81.0.tar.xz"
+  sha256 "ac0ccb1687dd159ad2c6926f766498a2450906266139ec924d7794839a8cfedb"
   head "https://invent.kde.org/frameworks/kcoreaddons.git"
 
   depends_on "cmake" => [:build, :test]
-  depends_on "kde-extra-cmake-modules" => [:build, :test]
   depends_on "ninja" => :build
 
+  depends_on "copyq/kde/extra-cmake-modules" => [:build, :test]
+
   depends_on "qt@5"
 
   def install
diff --git a/utils/github/homebrew/Formula/kf5-knotifications.rb b/utils/github/homebrew/Formula/kf5-knotifications.rb
index cbf23bb2acecc581e012d52470cc7e0aa8fe8485..9a9cc0dfa4f1803a9caca111c1100aaab8322b50 100644
--- a/utils/github/homebrew/Formula/kf5-knotifications.rb
+++ b/utils/github/homebrew/Formula/kf5-knotifications.rb
@@ -1,14 +1,14 @@
 class Kf5Knotifications < Formula
   desc "Abstraction for system notifications"
   homepage "https://www.kde.org"
-  url "https://download.kde.org/stable/frameworks/5.79/knotifications-5.79.0.tar.xz"
-  sha256 "129ee0ab84740d4bcd1930ddd2b6d0e692836c576175bac804c8a40f94eee485"
+  url "https://download.kde.org/stable/frameworks/5.81/knotifications-5.81.0.tar.xz"
+  sha256 "1ad7f7d0e17724085c2e55f9fda34828add9ff74966aae0bc95aa1041accce13"
   head "https://invent.kde.org/frameworks/knotifications.git"
 
   depends_on "cmake" => [:build, :test]
-  depends_on "kde-extra-cmake-modules" => [:build, :test]
   depends_on "ninja" => :build
 
+  depends_on "copyq/kde/extra-cmake-modules" => [:build, :test]
   depends_on "copyq/kde/kf5-kconfig"
   depends_on "copyq/kde/kf5-kcoreaddons"
   depends_on "copyq/kde/kf5-kwindowsystem"
diff --git a/utils/github/homebrew/Formula/kf5-kwindowsystem.rb b/utils/github/homebrew/Formula/kf5-kwindowsystem.rb
index 0ea25f6150d89d4cd21e450bf9e9f1b86f6fbddc..e581a309dadb203425ce46a75dbbbd1b51851571 100644
--- a/utils/github/homebrew/Formula/kf5-kwindowsystem.rb
+++ b/utils/github/homebrew/Formula/kf5-kwindowsystem.rb
@@ -1,14 +1,15 @@
 class Kf5Kwindowsystem < Formula
   desc "Access to the windowing system"
   homepage "https://www.kde.org"
-  url "https://download.kde.org/stable/frameworks/5.79/kwindowsystem-5.79.0.tar.xz"
-  sha256 "b8aef806276b5f12e9810473679401a6715b3b86e786eb874b12b2b6ed16f196"
+  url "https://download.kde.org/stable/frameworks/5.81/kwindowsystem-5.81.0.tar.xz"
+  sha256 "4753aaabb073b41dd8be79d454756ec616cc386f3be16f5503a77c84e12eaa86"
   head "https://invent.kde.org/frameworks/kwindowsystem.git"
 
   depends_on "cmake" => [:build, :test]
-  depends_on "kde-extra-cmake-modules" => [:build, :test]
   depends_on "ninja" => :build
 
+  depends_on "copyq/kde/extra-cmake-modules" => [:build, :test]
+
   depends_on "qt@5"
 
   def install