about summary refs log tree commit diff
path: root/nixpkgs/pkgs/desktops
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-05-12 14:45:39 +0000
committerAlyssa Ross <hi@alyssa.is>2020-05-12 14:56:01 +0000
commiteb7dadee9c0f903f1152f8dd4165453bfa48ccf4 (patch)
treea6bd66dcbec895aae167465672af08a1ca70f089 /nixpkgs/pkgs/desktops
parent3879b925f5dae3a0eb5c98b10c1ac5a0e4d729a3 (diff)
parent683c68232e91f76386db979c461d8fbe2a018782 (diff)
downloadnixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar.gz
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar.bz2
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar.lz
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar.xz
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.tar.zst
nixlib-eb7dadee9c0f903f1152f8dd4165453bfa48ccf4.zip
Merge commit '683c68232e91f76386db979c461d8fbe2a018782'
Diffstat (limited to 'nixpkgs/pkgs/desktops')
-rw-r--r--nixpkgs/pkgs/desktops/cinnamon/cinnamon-session/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/cinnamon/mint-y-icons/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dbus-factory/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-api/default.nix53
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-calendar/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-control-center/default.nix45
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-daemon/default.nix46
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-dock/default.nix178
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-dock/wrapper.nix6
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-file-manager/default.nix61
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-kwin/default.nix6
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-launcher/default.nix27
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-network-utils/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-polkit-agent/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-qt-dbus-factory/default.nix9
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dde-session-ui/default.nix38
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-anything/default.nix25
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-calculator/default.nix15
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-desktop-base/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-desktop-schemas/default.nix19
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-editor/default.nix18
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-gettext-tools/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-gtk-theme/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-icon-theme/default.nix19
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-image-viewer/default.nix20
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-menu/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-movie-reborn/default.nix25
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-screenshot/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-shortcut-viewer/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-sound-theme/default.nix11
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-terminal/default.nix45
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-turbo/default.nix11
-rw-r--r--nixpkgs/pkgs/desktops/deepin/deepin-wallpapers/default.nix13
-rw-r--r--nixpkgs/pkgs/desktops/deepin/default.nix12
-rw-r--r--nixpkgs/pkgs/desktops/deepin/disomaster/default.nix12
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dpa-ext-gnomekeyring/default.nix13
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dtkcore/default.nix12
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dtkwidget/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/deepin/dtkwm/default.nix13
-rw-r--r--nixpkgs/pkgs/desktops/deepin/go-dbus-factory/default.nix11
-rw-r--r--nixpkgs/pkgs/desktops/deepin/go-dbus-generator/default.nix9
-rw-r--r--nixpkgs/pkgs/desktops/deepin/go-gir-generator/default.nix13
-rw-r--r--nixpkgs/pkgs/desktops/deepin/go-lib/default.nix13
-rw-r--r--nixpkgs/pkgs/desktops/deepin/qcef/default.nix42
-rw-r--r--nixpkgs/pkgs/desktops/deepin/qt5dxcb-plugin/default.nix16
-rw-r--r--nixpkgs/pkgs/desktops/deepin/qt5integration/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/deepin/startdde/default.nix51
-rw-r--r--nixpkgs/pkgs/desktops/deepin/udisks2-qt5/default.nix10
-rw-r--r--nixpkgs/pkgs/desktops/deepin/update.nix38
-rw-r--r--nixpkgs/pkgs/desktops/enlightenment/econnman.nix8
-rw-r--r--nixpkgs/pkgs/desktops/enlightenment/efl.nix71
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/accerciser/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/evolution/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/file-roller/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gedit/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-boxes/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-calendar/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-getting-started-docs/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-maps/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-music/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/gnome-weather/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/apps/polari/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/adwaita-icon-theme/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/dconf-editor/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/eog/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/epiphany/default.nix1
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/evolution-data-server/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-contacts/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-control-center/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-desktop/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-initial-setup/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-settings-daemon/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell-extensions/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/default.nix9
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/fix-bash-completion.patch10
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-terminal/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gnome-themes-extra/default.nix9
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/gucharmap/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/mutter/3.34/default.nix11
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/mutter/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/nautilus/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/core/simple-scan/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/devtools/devhelp/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/arc-menu/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/clipboard-indicator/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-dock/default.nix25
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-panel/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/gsconnect/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/no-title-bar/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/pidgin-im-integration/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/topicons-plus/default.nix2
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/extensions/window-is-ready-remover/default.nix26
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/find-latest-version.py50
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/four-in-a-row/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/gnome-klotski/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/gnome-mahjongg/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/gnome-taquin/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/gnome-tetravex/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/iagno/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/games/quadrapassel/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/misc/geary/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/misc/gnome-flashback/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/misc/pomodoro/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/gnome-3/update.nix16
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/compton-conf/default.nix20
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/default.nix73
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/libfm-qt/default.nix28
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/liblxqt/default.nix22
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/libqtxdg/default.nix28
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/libsysstat/default.nix24
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lximage-qt/default.nix23
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-about/default.nix20
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-admin/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-archiver/default.nix27
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-build-tools/default.nix29
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-config/default.nix26
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-globalkeys/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-notificationd/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-openssh-askpass/default.nix21
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-panel/default.nix41
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-policykit/default.nix26
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-powermanagement/default.nix23
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-qtplugin/default.nix23
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-runner/default.nix27
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-session/default.nix24
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-sudo/default.nix22
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/lxqt-themes/default.nix14
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/obconf-qt/default.nix22
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/pavucontrol-qt/default.nix20
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/pcmanfm-qt/default.nix22
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/qlipper/default.nix24
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/qps/default.nix37
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/qterminal/default.nix19
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/qtermwidget/default.nix26
-rw-r--r--nixpkgs/pkgs/desktops/lxqt/screengrab/default.nix22
-rwxr-xr-xnixpkgs/pkgs/desktops/lxqt/update.sh39
-rw-r--r--nixpkgs/pkgs/desktops/mate/mate-icon-theme-faenza/default.nix6
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/apps/switchboard-plugs/pantheon-shell/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix3
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/desktop/gala/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch4726
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix11
-rw-r--r--nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel/default.nix7
-rw-r--r--nixpkgs/pkgs/desktops/xfce/applications/xfce4-notifyd/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/xfce/art/xfce4-icon-theme.nix11
-rw-r--r--nixpkgs/pkgs/desktops/xfce/core/xfce4-panel/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/xfce/core/xfconf/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/xfce/core/xfwm4/default.nix4
-rw-r--r--nixpkgs/pkgs/desktops/xfce/panel-plugins/xfce4-whiskermenu-plugin/default.nix13
149 files changed, 6509 insertions, 697 deletions
diff --git a/nixpkgs/pkgs/desktops/cinnamon/cinnamon-session/default.nix b/nixpkgs/pkgs/desktops/cinnamon/cinnamon-session/default.nix
index 56ff4b106e33..96910052ac9f 100644
--- a/nixpkgs/pkgs/desktops/cinnamon/cinnamon-session/default.nix
+++ b/nixpkgs/pkgs/desktops/cinnamon/cinnamon-session/default.nix
@@ -27,13 +27,13 @@
 
 stdenv.mkDerivation rec {
   pname = "cinnamon-session";
-  version = "4.4.0";
+  version = "4.4.1";
 
   src = fetchFromGitHub {
     owner = "linuxmint";
     repo = pname;
     rev = version;
-    sha256 = "0hplck17rksfgqm2z58ajvz4p2m4zg6ksdpbc27ki20iv4fv620s";
+    sha256 = "1bkhzgdinsk4ahp1b4jf50phxwv2da23rh35cmg9fbm5c88701ga";
   };
 
   patches = [
diff --git a/nixpkgs/pkgs/desktops/cinnamon/mint-y-icons/default.nix b/nixpkgs/pkgs/desktops/cinnamon/mint-y-icons/default.nix
index d4415c4bf040..a7e22dc3d033 100644
--- a/nixpkgs/pkgs/desktops/cinnamon/mint-y-icons/default.nix
+++ b/nixpkgs/pkgs/desktops/cinnamon/mint-y-icons/default.nix
@@ -1,6 +1,7 @@
 { fetchFromGitHub
 , stdenv
 , gnome3
+, gnome-icon-theme
 , hicolor-icon-theme
 , gtk3
 }:
@@ -16,8 +17,9 @@ stdenv.mkDerivation rec {
     sha256 = "1c2a79ylk363i982czwwqcwc7cw6dyzlqphcypqm6nll7xlafq8s";
   };
 
-  propagatedUserEnvPkgs = [
+  propagatedBuildInputs = [
     gnome3.adwaita-icon-theme
+    gnome-icon-theme
     hicolor-icon-theme
   ];
 
@@ -25,15 +27,19 @@ stdenv.mkDerivation rec {
     gtk3
   ];
 
-  postFixup =  ''
-    gtk-update-icon-cache $out/share/icons/*
-  '';
-
   dontDropIconThemeCache = true;
 
   installPhase = ''
+    runHook preInstall
+
     mkdir -p $out
     mv usr/share $out
+
+    for theme in $out/share/icons/*; do
+      gtk-update-icon-cache $theme
+    done
+
+    runHook postInstall
   '';
 
   meta = with stdenv.lib; {
diff --git a/nixpkgs/pkgs/desktops/deepin/dbus-factory/default.nix b/nixpkgs/pkgs/desktops/deepin/dbus-factory/default.nix
index df7800091528..06d921cce6d8 100644
--- a/nixpkgs/pkgs/desktops/deepin/dbus-factory/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dbus-factory/default.nix
@@ -1,4 +1,10 @@
-{ stdenv, fetchFromGitHub, jq, libxml2, go-dbus-generator, deepin }:
+{ stdenv
+, fetchFromGitHub
+, jq
+, libxml2
+, go-dbus-generator
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "dbus-factory";
@@ -17,13 +23,15 @@ stdenv.mkDerivation rec {
     go-dbus-generator
   ];
 
-  makeFlags = [ "GOPATH=${placeholder "out"}/share/go" ];
+  makeFlags = [
+    "GOPATH=${placeholder "out"}/share/go"
+  ];
 
   postPatch = ''
     sed -i -e 's:/share/gocode:/share/go:' Makefile
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Generates static DBus bindings for Golang and QML at build-time";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-api/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-api/default.nix
index 9fb18d04df82..325f62f37818 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-api/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-api/default.nix
@@ -1,25 +1,28 @@
-{ stdenv, buildGoPackage, fetchFromGitHub, pkgconfig,
-  alsaLib,
-  bc,
-  blur-effect,
-  coreutils,
-  dbus-factory,
-  deepin,
-  deepin-gettext-tools,
-  fontconfig,
-  go,
-  go-dbus-factory,
-  go-gir-generator,
-  go-lib,
-  grub2,
-  gtk3,
-  libcanberra,
-  libgudev,
-  librsvg,
-  poppler,
-  pulseaudio,
-  rfkill,
-  xcur2png
+{ stdenv
+, buildGoPackage
+, fetchFromGitHub
+, pkgconfig
+, alsaLib
+, bc
+, blur-effect
+, coreutils
+, dbus-factory
+, deepin
+, deepin-gettext-tools
+, fontconfig
+, go
+, go-dbus-factory
+, go-gir-generator
+, go-lib
+, grub2
+, gtk3
+, libcanberra
+, libgudev
+, librsvg
+, poppler
+, pulseaudio
+, rfkill
+, xcur2png
 }:
 
 buildGoPackage rec {
@@ -37,8 +40,6 @@ buildGoPackage rec {
 
   goDeps = ./deps.nix;
 
-  outputs = [ "out" ];
-
   nativeBuildInputs = [
     pkgconfig
     deepin-gettext-tools # build
@@ -109,14 +110,14 @@ buildGoPackage rec {
   installPhase = ''
     make install PREFIX="$out" SYSTEMD_LIB_DIR="$out/lib" -C go/src/${goPackagePath}
     mv $out/share/gocode $out/share/go
-    remove-references-to -t ${go} $out/bin/* $out/lib/deepin-api/*
+    remove-references-to -t ${go} $out/lib/deepin-api/*
   '';
 
   postFixup = ''
     searchHardCodedPaths $out  # debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Go-lang bindings for dde-daemon";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-calendar/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-calendar/default.nix
index e148df51a875..094f3447c6b7 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-calendar/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-calendar/default.nix
@@ -1,5 +1,13 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, cmake, qttools,
-  deepin-gettext-tools, dtkcore, dtkwidget, deepin
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, qttools
+, deepin-gettext-tools
+, dtkcore
+, dtkwidget
+, deepin
 }:
 
 mkDerivation rec {
@@ -37,7 +45,7 @@ mkDerivation rec {
       -e "s,/usr/bin/deepin-desktop-ts-convert,deepin-desktop-ts-convert,"
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Calendar for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-control-center/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-control-center/default.nix
index adc05e1ea7e1..be2846fc87e9 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-control-center/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-control-center/default.nix
@@ -1,9 +1,40 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, cmake, deepin, qttools, qtdeclarative,
- networkmanager, qtsvg, qtx11extras,  dtkcore, dtkwidget, geoip, gsettings-qt,
- dde-network-utils, networkmanager-qt, xorg, mtdev, fontconfig, freetype, dde-api,
- dde-daemon, qt5integration, deepin-desktop-base, deepin-desktop-schemas, dbus,
- systemd, dde-qt-dbus-factory, qtmultimedia, qtbase, glib, gnome3, which,
- substituteAll, tzdata, wrapGAppsHook
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, deepin
+, qttools
+, qtdeclarative
+, networkmanager
+, qtsvg
+, qtx11extras
+, dtkcore
+, dtkwidget
+, geoip
+, gsettings-qt
+, dde-network-utils
+, networkmanager-qt
+, xorg
+, mtdev
+, fontconfig
+, freetype
+, dde-api
+, dde-daemon
+, qt5integration
+, deepin-desktop-base
+, deepin-desktop-schemas
+, dbus
+, systemd
+, dde-qt-dbus-factory
+, qtmultimedia
+, qtbase
+, glib
+, gnome3
+, which
+, substituteAll
+, tzdata
+, wrapGAppsHook
 }:
 
 mkDerivation rec {
@@ -107,7 +138,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Control panel of Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-daemon/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-daemon/default.nix
index fdbb7856b063..b89b2c254464 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-daemon/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-daemon/default.nix
@@ -1,10 +1,38 @@
-{ stdenv, buildGoPackage, fetchFromGitHub, fetchpatch, pkgconfig,
-  dbus-factory, go-dbus-factory, go-gir-generator, go-lib,
-  deepin-gettext-tools, gettext, dde-api, deepin-desktop-schemas,
-  deepin-wallpapers, deepin-desktop-base, alsaLib, glib, gtk3,
-  libgudev, libinput, libnl, librsvg, linux-pam, networkmanager,
-  pulseaudio, python3, hicolor-icon-theme, glibc, tzdata, go,
-  deepin, makeWrapper, xkeyboard_config, wrapGAppsHook }:
+{ stdenv
+, buildGoPackage
+, fetchFromGitHub
+, fetchpatch
+, pkgconfig
+, dbus-factory
+, go-dbus-factory
+, go-gir-generator
+, go-lib
+, deepin-gettext-tools
+, gettext
+, dde-api
+, deepin-desktop-schemas
+, deepin-wallpapers
+, deepin-desktop-base
+, alsaLib
+, glib
+, gtk3
+, libgudev
+, libinput
+, libnl
+, librsvg
+, linux-pam
+, networkmanager
+, pulseaudio
+, python3
+, hicolor-icon-theme
+, glibc
+, tzdata
+, go
+, deepin
+, makeWrapper
+, xkeyboard_config
+, wrapGAppsHook
+}:
 
 buildGoPackage rec {
   pname = "dde-daemon";
@@ -29,8 +57,6 @@ buildGoPackage rec {
 
   goDeps = ./deps.nix;
 
-  outputs = [ "out" ];
-
   nativeBuildInputs = [
     pkgconfig
     dbus-factory
@@ -123,7 +149,7 @@ buildGoPackage rec {
     searchHardCodedPaths $out  # debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Daemon for handling Deepin Desktop Environment session settings";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-dock/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-dock/default.nix
index f2edb83537d7..68f2caa63191 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-dock/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-dock/default.nix
@@ -1,94 +1,116 @@
-{ stdenv, mkDerivation, fetchFromGitHub, cmake, pkgconfig, qttools, qtx11extras,
-  qtsvg, polkit, gsettings-qt, dtkcore, dtkwidget,
-  dde-qt-dbus-factory, dde-network-utils, dde-daemon,
-  deepin-desktop-schemas, xorg, glib, wrapGAppsHook, deepin,
-  plugins ? [], symlinkJoin, makeWrapper, libdbusmenu }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, qttools
+, qtx11extras
+, qtsvg
+, polkit
+, gsettings-qt
+, dtkcore
+, dtkwidget
+, dde-qt-dbus-factory
+, dde-network-utils
+, dde-daemon
+, deepin-desktop-schemas
+, xorg
+, glib
+, wrapGAppsHook
+, deepin
+, plugins ? [ ]
+, symlinkJoin
+, makeWrapper
+, libdbusmenu
+}:
 
 let
-unwrapped = mkDerivation rec {
-  pname = "dde-dock";
-  version = "5.0.0";
+  unwrapped = mkDerivation rec {
+    pname = "dde-dock";
+    version = "5.0.0";
 
-  src = fetchFromGitHub {
-    owner = "linuxdeepin";
-    repo = pname;
-    rev = version;
-    sha256 = "12dshsqhzajnxm7r53qg0c84b6xlj313qnssnx2m25z4jdp5i7pr";
-  };
+    src = fetchFromGitHub {
+      owner = "linuxdeepin";
+      repo = pname;
+      rev = version;
+      sha256 = "12dshsqhzajnxm7r53qg0c84b6xlj313qnssnx2m25z4jdp5i7pr";
+    };
 
-  nativeBuildInputs = [
-    cmake
-    pkgconfig
-    qttools
-    wrapGAppsHook
-    deepin.setupHook
-  ];
+    nativeBuildInputs = [
+      cmake
+      pkgconfig
+      qttools
+      wrapGAppsHook
+      deepin.setupHook
+    ];
 
-  buildInputs = [
-    dde-daemon
-    dde-network-utils
-    dde-qt-dbus-factory
-    deepin-desktop-schemas
-    dtkcore
-    dtkwidget
-    glib
-    gsettings-qt
-    libdbusmenu
-    polkit
-    qtsvg
-    qtx11extras
-    xorg.libXdmcp
-    xorg.libXtst
-    xorg.libpthreadstubs
-  ];
+    buildInputs = [
+      dde-daemon
+      dde-network-utils
+      dde-qt-dbus-factory
+      deepin-desktop-schemas
+      dtkcore
+      dtkwidget
+      glib
+      gsettings-qt
+      libdbusmenu
+      polkit
+      qtsvg
+      qtx11extras
+      xorg.libXdmcp
+      xorg.libXtst
+      xorg.libpthreadstubs
+    ];
 
-  patches = [
-    ./dde-dock.plugins-dir.patch
-  ];
+    patches = [
+      ./dde-dock.plugins-dir.patch
+    ];
 
-  postPatch = ''
-    searchHardCodedPaths
-    patchShebangs translate_generation.sh
-    fixPath $out                 /etc/dde-dock                plugins/keyboard-layout/CMakeLists.txt
-    fixPath $out                 /usr                         cmake/DdeDock/DdeDockConfig.cmake
-    fixPath $out                 /usr                         dde-dock.pc
-    fixPath $out                 /usr/bin/dde-dock            frame/com.deepin.dde.Dock.service
-    fixPath $out                 /usr/share/dbus-1            CMakeLists.txt
-    fixPath ${dde-daemon}        /usr/lib/deepin-daemon       frame/item/showdesktopitem.cpp
-    fixPath ${dde-network-utils} /usr/share/dde-network-utils frame/main.cpp
-    fixPath ${polkit}            /usr/bin/pkexec              plugins/overlay-warning/overlay-warning-plugin.cpp
+    postPatch = ''
+      searchHardCodedPaths
+      patchShebangs translate_generation.sh
+      fixPath $out                 /etc/dde-dock                plugins/keyboard-layout/CMakeLists.txt
+      fixPath $out                 /usr                         cmake/DdeDock/DdeDockConfig.cmake
+      fixPath $out                 /usr                         dde-dock.pc
+      fixPath $out                 /usr/bin/dde-dock            frame/com.deepin.dde.Dock.service
+      fixPath $out                 /usr/share/dbus-1            CMakeLists.txt
+      fixPath ${dde-daemon}        /usr/lib/deepin-daemon       frame/item/showdesktopitem.cpp
+      fixPath ${dde-network-utils} /usr/share/dde-network-utils frame/main.cpp
+      fixPath ${polkit}            /usr/bin/pkexec              plugins/overlay-warning/overlay-warning-plugin.cpp
 
-    substituteInPlace frame/controller/dockpluginscontroller.cpp --subst-var-by out $out
-    substituteInPlace plugins/tray/system-trays/systemtrayscontroller.cpp --subst-var-by out $out
-  '';
+      substituteInPlace frame/controller/dockpluginscontroller.cpp --subst-var-by out $out
+      substituteInPlace plugins/tray/system-trays/systemtrayscontroller.cpp --subst-var-by out $out
+    '';
 
-  cmakeFlags = [ "-DDOCK_TRAY_USE_NATIVE_POPUP=YES" ];
+    cmakeFlags = [ "-DDOCK_TRAY_USE_NATIVE_POPUP=YES" ];
 
-  dontWrapQtApps = true;
+    dontWrapQtApps = true;
 
-  preFixup = ''
-    gappsWrapperArgs+=(
-      "''${qtWrapperArgs[@]}"
-    )
-  '';
+    preFixup = ''
+      gappsWrapperArgs+=(
+        "''${qtWrapperArgs[@]}"
+      )
+    '';
 
-  postFixup = ''
-    searchHardCodedPaths $out
-  '';
+    postFixup = ''
+      searchHardCodedPaths $out
+    '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+    passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
-  meta = with stdenv.lib; {
-    description = "Dock for Deepin Desktop Environment";
-    homepage = "https://github.com/linuxdeepin/dde-dock";
-    license = licenses.gpl3;
-    platforms = platforms.linux;
-    maintainers = with maintainers; [ romildo ];
+    meta = with stdenv.lib; {
+      description = "Dock for Deepin Desktop Environment";
+      homepage = "https://github.com/linuxdeepin/dde-dock";
+      license = licenses.gpl3;
+      platforms = platforms.linux;
+      maintainers = with maintainers; [ romildo ];
+    };
   };
-};
 
-in if plugins == [] then unwrapped
-    else import ./wrapper.nix {
-      inherit makeWrapper symlinkJoin plugins;
-      dde-dock = unwrapped;
-    }
+in
+if plugins == [ ]
+then unwrapped
+else import ./wrapper.nix {
+  inherit makeWrapper symlinkJoin plugins;
+  dde-dock = unwrapped;
+}
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-dock/wrapper.nix b/nixpkgs/pkgs/desktops/deepin/dde-dock/wrapper.nix
index 8f6d8a67b1a9..1690230a99e5 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-dock/wrapper.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-dock/wrapper.nix
@@ -1,4 +1,8 @@
-{ makeWrapper, symlinkJoin, dde-dock, plugins }:
+{ makeWrapper
+, symlinkJoin
+, dde-dock
+, plugins
+}:
 
 symlinkJoin {
   name = "dde-dock-with-plugins-${dde-dock.version}";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-file-manager/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-file-manager/default.nix
index a952a82dfca0..4258e2aa859e 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-file-manager/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-file-manager/default.nix
@@ -1,13 +1,52 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, avfs, dde-daemon,
-  dde-dock, dde-polkit-agent, dde-qt-dbus-factory, deepin,
-  deepin-anything, deepin-desktop-schemas, deepin-gettext-tools,
-  deepin-movie-reborn, deepin-shortcut-viewer, deepin-terminal,
-  disomaster, dtkcore, dtkwidget, ffmpegthumbnailer, file, glib,
-  gnugrep, gsettings-qt, gvfs, jemalloc, kcodecs, libX11, libsecret,
-  polkit, polkit-qt, poppler, procps, qmake, qt5integration,
-  qtmultimedia, qtsvg, qttools, qtx11extras, runtimeShell, samba,
-  shadow, taglib, udisks2-qt5, xdg-user-dirs, xorg, zlib,
-  wrapGAppsHook }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, avfs
+, dde-daemon
+, dde-dock
+, dde-polkit-agent
+, dde-qt-dbus-factory
+, deepin
+, deepin-anything
+, deepin-desktop-schemas
+, deepin-gettext-tools
+, deepin-movie-reborn
+, deepin-shortcut-viewer
+, deepin-terminal
+, disomaster
+, dtkcore
+, dtkwidget
+, ffmpegthumbnailer
+, file
+, glib
+, gnugrep
+, gsettings-qt
+, gvfs
+, jemalloc
+, kcodecs
+, libX11
+, libsecret
+, polkit
+, polkit-qt
+, poppler
+, procps
+, qmake
+, qt5integration
+, qtmultimedia
+, qtsvg
+, qttools
+, qtx11extras
+, runtimeShell
+, samba
+, shadow
+, taglib
+, udisks2-qt5
+, xdg-user-dirs
+, xorg
+, zlib
+, wrapGAppsHook
+}:
 
 mkDerivation rec {
   pname = "dde-file-manager";
@@ -247,7 +286,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "File manager and desktop module for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-kwin/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-kwin/default.nix
index 850186953f63..ce1a1a8dda03 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-kwin/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-kwin/default.nix
@@ -74,7 +74,9 @@ mkDerivation rec {
 
   # Need to add kwayland around:
   # * https://github.com/linuxdeepin/dde-kwin/blob/5226bb984c844129f9fa589da56e77decb7b39a1/plugins/kwineffects/blur/CMakeLists.txt#L14
-  NIX_CFLAGS_COMPILE = "-I${kwayland.dev}/include/KF5";
+  NIX_CFLAGS_COMPILE = [
+    "-I${kwayland.dev}/include/KF5"
+  ];
 
   cmakeFlags = [
     "-DKWIN_VERSION=${(builtins.parseDrvName kwin.name).version}"
@@ -128,7 +130,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "KWin configuration for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-launcher/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-launcher/default.nix
index a1561f5c0922..0a50f7177bae 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-launcher/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-launcher/default.nix
@@ -1,7 +1,24 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, cmake, dde-qt-dbus-factory,
-  dde-session-ui, deepin, deepin-desktop-schemas, deepin-wallpapers,
-  dtkcore, dtkwidget, gsettings-qt, qtsvg, qttools, qtx11extras,
-  which, xdg_utils, wrapGAppsHook, glib }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, dde-qt-dbus-factory
+, dde-session-ui
+, deepin
+, deepin-desktop-schemas
+, deepin-wallpapers
+, dtkcore
+, dtkwidget
+, gsettings-qt
+, qtsvg
+, qttools
+, qtx11extras
+, which
+, xdg_utils
+, wrapGAppsHook
+, glib
+}:
 
 mkDerivation rec {
   pname = "dde-launcher";
@@ -72,7 +89,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin Desktop Environment launcher module";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-network-utils/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-network-utils/default.nix
index 1550987cc739..d54558acf080 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-network-utils/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-network-utils/default.nix
@@ -1,5 +1,15 @@
-{ stdenv, mkDerivation, fetchFromGitHub, substituteAll, qmake, pkgconfig, qttools,
-  dde-qt-dbus-factory, proxychains, which, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, substituteAll
+, qmake
+, pkgconfig
+, qttools
+, dde-qt-dbus-factory
+, proxychains
+, which
+, deepin
+}:
 
 mkDerivation rec {
   pname = "dde-network-utils";
@@ -41,7 +51,7 @@ mkDerivation rec {
     searchHardCodedPaths $out  # for debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin network utils";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-polkit-agent/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-polkit-agent/default.nix
index e00ee30ca927..1ca9a80abaf1 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-polkit-agent/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-polkit-agent/default.nix
@@ -1,5 +1,15 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qttools, polkit-qt,
-  dtkcore, dtkwidget, dde-qt-dbus-factory, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qttools
+, polkit-qt
+, dtkcore
+, dtkwidget
+, dde-qt-dbus-factory
+, deepin
+}:
 
 mkDerivation rec {
   pname = "dde-polkit-agent";
@@ -38,7 +48,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "PolicyKit agent for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-qt-dbus-factory/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-qt-dbus-factory/default.nix
index 7e645473f027..c7efb0f4b044 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-qt-dbus-factory/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-qt-dbus-factory/default.nix
@@ -1,4 +1,9 @@
-{ stdenv, fetchFromGitHub, qmake, python3, deepin }:
+{ stdenv
+, fetchFromGitHub
+, qmake
+, python3
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "dde-qt-dbus-factory";
@@ -26,7 +31,7 @@ stdenv.mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Qt DBus interface library for Deepin software";
diff --git a/nixpkgs/pkgs/desktops/deepin/dde-session-ui/default.nix b/nixpkgs/pkgs/desktops/deepin/dde-session-ui/default.nix
index ddb12511c275..ff785f16c81d 100644
--- a/nixpkgs/pkgs/desktops/deepin/dde-session-ui/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dde-session-ui/default.nix
@@ -1,9 +1,33 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, dbus, dde-daemon,
-  dde-qt-dbus-factory, deepin, deepin-desktop-schemas,
-  deepin-gettext-tools, deepin-icon-theme, deepin-wallpapers, dtkcore,
-  dtkwidget, gnugrep, gsettings-qt, lightdm_qt,
-  onboard, qtsvg, qttools, qtx11extras, setxkbmap, utillinux, which,
-  xkeyboard_config, xorg, xrandr, wrapGAppsHook }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, dbus
+, dde-daemon
+, dde-qt-dbus-factory
+, deepin
+, deepin-desktop-schemas
+, deepin-gettext-tools
+, deepin-icon-theme
+, deepin-wallpapers
+, dtkcore
+, dtkwidget
+, gnugrep
+, gsettings-qt
+, lightdm_qt
+, onboard
+, qtsvg
+, qttools
+, qtx11extras
+, setxkbmap
+, utillinux
+, which
+, xkeyboard_config
+, xorg
+, xrandr
+, wrapGAppsHook
+}:
 
 mkDerivation rec {
   pname = "dde-session-ui";
@@ -121,7 +145,7 @@ mkDerivation rec {
     searchHardCodedPaths $out  # debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin desktop-environment - Session UI module";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-anything/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-anything/default.nix
index 7697c23ae141..5fa6c93951d0 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-anything/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-anything/default.nix
@@ -1,5 +1,14 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qtbase, udisks2-qt5, utillinux,
-  dtkcore, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, fetchpatch
+, pkgconfig
+, qtbase
+, udisks2-qt5
+, utillinux
+, dtkcore
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-anything";
@@ -12,6 +21,16 @@ mkDerivation rec {
     sha256 = "1kvyffrii4b012f6ld1ih14qrn7gg5cxbdpbkac0wxb22hnz0azm";
   };
 
+  patches = [
+    # fix compilation error and add support to kernel 5.6
+    # https://github.com/linuxdeepin/deepin-anything/pull/27
+    (fetchpatch {
+      name = "linux-5.6.patch";
+      url = "https://github.com/linuxdeepin/deepin-anything/commit/764b820c2bcd7248993349b32f91043fc58ee958.patch";
+      sha256 = "1ww4xllxc2s04px6fy8wp5cyw54xaz155ry30sqz21vl8awfr36h";
+    })
+  ];
+
   outputs = [ "out" "modsrc" ];
 
   nativeBuildInputs = [
@@ -51,7 +70,7 @@ mkDerivation rec {
     searchHardCodedPaths $modsrc  # for debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin file search tool";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-calculator/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-calculator/default.nix
index 38aed9cbe635..67ead7d314aa 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-calculator/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-calculator/default.nix
@@ -1,5 +1,14 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qttools, qtsvg, dtkcore,
-  dtkwidget, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qttools
+, qtsvg
+, dtkcore
+, dtkwidget
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-calculator";
@@ -36,7 +45,7 @@ mkDerivation rec {
     searchHardCodedPaths $out  # debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Easy to use calculator for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-desktop-base/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-desktop-base/default.nix
index 335c5727e919..74fa53b715d0 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-desktop-base/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-desktop-base/default.nix
@@ -1,4 +1,8 @@
-{ stdenv, fetchFromGitHub, deepin-wallpapers, deepin }:
+{ stdenv
+, fetchFromGitHub
+, deepin-wallpapers
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-desktop-base";
@@ -11,9 +15,13 @@ stdenv.mkDerivation rec {
     sha256 = "0rs7bjy35k5gc5nbba1cijhdz16zny30lgmcf2ckx1pkdszk2vra";
   };
 
-  nativeBuildInputs = [ deepin.setupHook ];
+  nativeBuildInputs = [
+    deepin.setupHook
+  ];
 
-  buildInputs = [ deepin-wallpapers ];
+  buildInputs = [
+    deepin-wallpapers
+  ];
 
   # TODO: Fedora recommended dependencies:
   #   deepin-wallpapers
@@ -40,7 +48,7 @@ stdenv.mkDerivation rec {
     ln -s ../lib/deepin/desktop-version $out/etc/deepin-version
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Base assets and definitions for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-desktop-schemas/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-desktop-schemas/default.nix
index 2105926f6828..15f9498cf0db 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-desktop-schemas/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-desktop-schemas/default.nix
@@ -1,5 +1,14 @@
-{ stdenv, fetchFromGitHub, python3, dconf, glib, deepin-gtk-theme,
-  deepin-icon-theme, deepin-sound-theme, deepin-wallpapers, deepin }:
+{ stdenv
+, fetchFromGitHub
+, python3
+, dconf
+, glib
+, deepin-gtk-theme
+, deepin-icon-theme
+, deepin-sound-theme
+, deepin-wallpapers
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-desktop-schemas";
@@ -46,7 +55,9 @@ stdenv.mkDerivation rec {
     #   /usr/share/desktop-directories
   '';
 
-  makeFlags = [ "PREFIX=${placeholder "out"}" ];
+  makeFlags = [
+    "PREFIX=${placeholder "out"}"
+  ];
 
   doCheck = true;
   checkTarget = "test";
@@ -56,7 +67,7 @@ stdenv.mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "GSettings deepin desktop-wide schemas";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-editor/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-editor/default.nix
index 9bff5b88268e..0124ca8cc9e2 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-editor/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-editor/default.nix
@@ -1,10 +1,18 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, cmake, deepin,
-  dtkcore, dtkwidget, kcodecs, qttools, syntax-highlighting,
-  wrapQtAppsHook
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, deepin
+, dtkcore
+, dtkwidget
+, kcodecs
+, qttools
+, syntax-highlighting
+, wrapQtAppsHook
 }:
 
 stdenv.mkDerivation rec {
-  name = "${pname}-${version}";
   pname = "deepin-editor";
   version = "1.2.9.1";
 
@@ -52,7 +60,7 @@ stdenv.mkDerivation rec {
     searchHardCodedPaths $out  # debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { inherit name; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Simple editor for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-gettext-tools/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-gettext-tools/default.nix
index c1aff5ed4dca..432add458deb 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-gettext-tools/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-gettext-tools/default.nix
@@ -1,4 +1,10 @@
-{ stdenv, fetchFromGitHub, gettext, python3Packages, perlPackages, deepin }:
+{ stdenv
+, fetchFromGitHub
+, gettext
+, python3Packages
+, perlPackages
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-gettext-tools";
@@ -23,7 +29,9 @@ stdenv.mkDerivation rec {
     python3Packages.python
   ];
 
-  makeFlags = [ "PREFIX=${placeholder "out"}" ];
+  makeFlags = [
+    "PREFIX=${placeholder "out"}"
+  ];
 
   postPatch = ''
     sed -e 's/sudo cp/cp/' -i src/generate_mo.py
@@ -35,7 +43,7 @@ stdenv.mkDerivation rec {
     wrapProgram $out/bin/deepin-desktop-ts-convert --set PERL5LIB $PERL5LIB
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin Internationalization utilities";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-gtk-theme/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-gtk-theme/default.nix
index 537357918468..eee074705852 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-gtk-theme/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-gtk-theme/default.nix
@@ -1,4 +1,8 @@
-{ stdenv, fetchFromGitHub, gtk-engine-murrine, deepin }:
+{ stdenv
+, fetchFromGitHub
+, gtk-engine-murrine
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-gtk-theme";
@@ -11,11 +15,15 @@ stdenv.mkDerivation rec {
     sha256 = "0zs6mq70yd1k3d9zm3q6zxnw1md56r4imad5imdxwx58yxdx47fw";
   };
 
-  propagatedUserEnvPkgs = [ gtk-engine-murrine ];
+  propagatedUserEnvPkgs = [
+    gtk-engine-murrine
+  ];
 
-  makeFlags = [ "PREFIX=${placeholder "out"}" ];
+  makeFlags = [
+    "PREFIX=${placeholder "out"}"
+  ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin GTK Theme";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-icon-theme/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-icon-theme/default.nix
index 5845e77f57c7..464d6f19ceda 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-icon-theme/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-icon-theme/default.nix
@@ -1,4 +1,11 @@
-{ stdenv, fetchFromGitHub, gtk3, xcursorgen, papirus-icon-theme, deepin, hicolor-icon-theme }:
+{ stdenv
+, fetchFromGitHub
+, gtk3
+, xcursorgen
+, papirus-icon-theme
+, deepin
+, hicolor-icon-theme
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-icon-theme";
@@ -11,11 +18,13 @@ stdenv.mkDerivation rec {
     sha256 = "12rzzjp906np95ckbxrd4mb345lm198wz69kxy48f8q1zg78q8iw";
   };
 
-  nativeBuildInputs = [ gtk3 xcursorgen ];
-
-  buildInputs = [ papirus-icon-theme ];
+  nativeBuildInputs = [
+    gtk3
+    xcursorgen
+  ];
 
   propagatedBuildInputs = [
+    papirus-icon-theme
     hicolor-icon-theme
   ];
 
@@ -39,7 +48,7 @@ stdenv.mkDerivation rec {
     cp -a ./Sea ./usr/share/icons/hicolor "$out"/share/icons/
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Icons for the Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-image-viewer/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-image-viewer/default.nix
index bedc809b2f5a..43c18c85abcb 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-image-viewer/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-image-viewer/default.nix
@@ -1,6 +1,18 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qttools, qtsvg,
-  qtx11extras, dtkcore, dtkwidget, qt5integration, freeimage, libraw,
-  libexif, deepin
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qttools
+, qtsvg
+, qtx11extras
+, dtkcore
+, dtkwidget
+, qt5integration
+, freeimage
+, libraw
+, libexif
+, deepin
 }:
 
 mkDerivation rec {
@@ -41,7 +53,7 @@ mkDerivation rec {
       -e "s,\$\$\[QT_INSTALL_PLUGINS\],$out/$qtPluginPrefix,"
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Image Viewer for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-menu/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-menu/default.nix
index 92153b84d514..983fe4e1c4d5 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-menu/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-menu/default.nix
@@ -1,5 +1,13 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, dtkcore, dtkwidget,
-  qt5integration, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, dtkcore
+, dtkwidget
+, qt5integration
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-menu";
@@ -34,7 +42,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin menu service";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-movie-reborn/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-movie-reborn/default.nix
index b95a76a39727..6763292b626c 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-movie-reborn/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-movie-reborn/default.nix
@@ -1,6 +1,22 @@
-{ stdenv, mkDerivation, fetchFromGitHub, fetchpatch, cmake, pkgconfig, qttools, qtx11extras,
-  dtkcore, dtkwidget, ffmpeg, ffmpegthumbnailer, mpv, pulseaudio,
-  libdvdnav, libdvdread, xorg, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, fetchpatch
+, cmake
+, pkgconfig
+, qttools
+, qtx11extras
+, dtkcore
+, dtkwidget
+, ffmpeg
+, ffmpegthumbnailer
+, mpv
+, pulseaudio
+, libdvdnav
+, libdvdread
+, xorg
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-movie-reborn";
@@ -48,7 +64,6 @@ mkDerivation rec {
 
   NIX_LDFLAGS = "-ldvdnav";
 
-
   postPatch = ''
     searchHardCodedPaths  # debugging
 
@@ -58,7 +73,7 @@ mkDerivation rec {
       --replace "Exec=deepin-movie" "Exec=$out/bin/deepin-movie"
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin movie player";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-screenshot/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-screenshot/default.nix
index 9b5d47d8542a..0ccc350962a0 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-screenshot/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-screenshot/default.nix
@@ -1,6 +1,19 @@
-{ stdenv, mkDerivation, fetchFromGitHub, fetchpatch, cmake, pkgconfig, xdg_utils, qttools, qtx11extras,
-  dtkcore, dtkwidget, dtkwm, deepin-turbo, deepin-shortcut-viewer,
-  deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, fetchpatch
+, cmake
+, pkgconfig
+, xdg_utils
+, qttools
+, qtx11extras
+, dtkcore
+, dtkwidget
+, dtkwm
+, deepin-turbo
+, deepin-shortcut-viewer
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-screenshot";
@@ -48,7 +61,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Easy-to-use screenshot tool for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-shortcut-viewer/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-shortcut-viewer/default.nix
index 479f2c86d30f..76d8847b73fc 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-shortcut-viewer/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-shortcut-viewer/default.nix
@@ -1,5 +1,13 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, dtkcore, dtkwidget,
-  qt5integration, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, dtkcore
+, dtkwidget
+, qt5integration
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-shortcut-viewer";
@@ -25,7 +33,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Pop-up shortcut viewer for Deepin applications";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-sound-theme/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-sound-theme/default.nix
index a868b072506b..e71c0cb77c5b 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-sound-theme/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-sound-theme/default.nix
@@ -1,4 +1,7 @@
-{ stdenv, fetchFromGitHub, deepin }:
+{ stdenv
+, fetchFromGitHub
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-sound-theme";
@@ -11,9 +14,11 @@ stdenv.mkDerivation rec {
     sha256 = "1sw4nrn7q7wk1hpicm05apyc0mihaw42iqm52wb8ib8gm1qiylr9";
   };
 
-  makeFlags = [ "PREFIX=${placeholder "out"}" ];
+  makeFlags = [
+    "PREFIX=${placeholder "out"}"
+  ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin sound theme";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-terminal/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-terminal/default.nix
index e51927142eb2..ae3121379427 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-terminal/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-terminal/default.nix
@@ -1,8 +1,39 @@
-{ stdenv, fetchFromGitHub, pkgconfig, cmake, ninja, vala_0_40, fetchpatch,
-  gettext, at-spi2-core, dbus, epoxy, expect, gtk3, json-glib,
-  libXdmcp, libgee, libpthreadstubs, librsvg, libsecret, libtasn1,
-  libxcb, libxkbcommon, p11-kit, pcre, vte, wnck, libselinux, gnutls, pcre2,
-  libsepol, utillinux, deepin-menu, deepin-shortcut-viewer, deepin, wrapGAppsHook }:
+{ stdenv
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, ninja
+, vala_0_40
+, fetchpatch
+, gettext
+, at-spi2-core
+, dbus
+, epoxy
+, expect
+, gtk3
+, json-glib
+, libXdmcp
+, libgee
+, libpthreadstubs
+, librsvg
+, libsecret
+, libtasn1
+, libxcb
+, libxkbcommon
+, p11-kit
+, pcre
+, vte
+, wnck
+, libselinux
+, gnutls
+, pcre2
+, libsepol
+, utillinux
+, deepin-menu
+, deepin-shortcut-viewer
+, deepin
+, wrapGAppsHook
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-terminal";
@@ -69,7 +100,7 @@ stdenv.mkDerivation rec {
     "-DVERSION=${version}"
   ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Default terminal emulator for Deepin";
@@ -77,7 +108,7 @@ stdenv.mkDerivation rec {
       Deepin terminal, it sharpens your focus in the world of command line!
       It is an advanced terminal emulator with workspace, multiple
       windows, remote management, quake mode and other features.
-     '';
+    '';
     homepage = "https://github.com/linuxdeepin/deepin-terminal";
     license = licenses.gpl3;
     platforms = platforms.linux;
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-turbo/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-turbo/default.nix
index f34997f51791..6bba51ac674b 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-turbo/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-turbo/default.nix
@@ -1,4 +1,11 @@
-{ stdenv, mkDerivation, fetchFromGitHub, cmake, pkgconfig, qtbase, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, qtbase
+, deepin
+}:
 
 mkDerivation rec {
   pname = "deepin-turbo";
@@ -31,7 +38,7 @@ mkDerivation rec {
     searchHardCodedPaths $out  # for debugging
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "A daemon that helps to launch applications faster";
diff --git a/nixpkgs/pkgs/desktops/deepin/deepin-wallpapers/default.nix b/nixpkgs/pkgs/desktops/deepin/deepin-wallpapers/default.nix
index 82f7214471fb..4fa3d6043d5c 100644
--- a/nixpkgs/pkgs/desktops/deepin/deepin-wallpapers/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/deepin-wallpapers/default.nix
@@ -1,4 +1,8 @@
-{ stdenv, fetchFromGitHub, dde-api, deepin }:
+{ stdenv
+, fetchFromGitHub
+, dde-api
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "deepin-wallpapers";
@@ -11,7 +15,10 @@ stdenv.mkDerivation rec {
     sha256 = "09cfnxbpms98ibqbi4xd51181q3az5n8rmndcdr9w12kyzniz7xv";
   };
 
-  nativeBuildInputs = [ dde-api deepin.setupHook ];
+  nativeBuildInputs = [
+    dde-api
+    deepin.setupHook
+  ];
 
   postPatch = ''
     searchHardCodedPaths # debugging
@@ -33,7 +40,7 @@ stdenv.mkDerivation rec {
       $out/var/cache/image-blur/$(echo -n $out/share/backgrounds/deepin/desktop.jpg | md5sum | cut -d " " -f 1).jpg
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Wallpapers for Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/default.nix b/nixpkgs/pkgs/desktops/deepin/default.nix
index 64dbdbfd104c..8d33ac154afa 100644
--- a/nixpkgs/pkgs/desktops/deepin/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/default.nix
@@ -1,10 +1,16 @@
 { pkgs, makeScope, libsForQt5 }:
-
 let
   packages = self: with self; {
     setupHook = ./setup-hook.sh;
 
-    updateScript = callPackage ./update.nix { };
+    # Update script tailored to deepin packages from git repository
+    updateScript = { pname, version, src }:
+      pkgs.genericUpdater {
+        inherit pname version;
+        attrPath = "deepin.${pname}";
+        versionLister = "${pkgs.common-updater-scripts}/bin/list-git-tags ${src.meta.homepage}";
+        ignoredVersions = "^2014(\\.|rc)|^v[0-9]+";
+      };
 
     dbus-factory = callPackage ./dbus-factory { };
     dde-api = callPackage ./dde-api { };
@@ -56,4 +62,4 @@ let
   };
 
 in
-  makeScope libsForQt5.newScope packages
+makeScope libsForQt5.newScope packages
diff --git a/nixpkgs/pkgs/desktops/deepin/disomaster/default.nix b/nixpkgs/pkgs/desktops/deepin/disomaster/default.nix
index a1db0673a46e..758c8ff76c3e 100644
--- a/nixpkgs/pkgs/desktops/deepin/disomaster/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/disomaster/default.nix
@@ -1,4 +1,12 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qtbase, libisoburn, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qtbase
+, libisoburn
+, deepin
+}:
 
 mkDerivation rec {
   pname = "disomaster";
@@ -29,7 +37,7 @@ mkDerivation rec {
        libdisomaster/libdisomaster.pro
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "A libisoburn wrapper for Qt";
diff --git a/nixpkgs/pkgs/desktops/deepin/dpa-ext-gnomekeyring/default.nix b/nixpkgs/pkgs/desktops/deepin/dpa-ext-gnomekeyring/default.nix
index 970e48941d40..2caef7ce9166 100644
--- a/nixpkgs/pkgs/desktops/deepin/dpa-ext-gnomekeyring/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dpa-ext-gnomekeyring/default.nix
@@ -1,5 +1,12 @@
-{ stdenv, fetchFromGitHub, pkgconfig, qmake, qttools, gnome3,
-  dde-polkit-agent, deepin }:
+{ stdenv
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qttools
+, gnome3
+, dde-polkit-agent
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "dpa-ext-gnomekeyring";
@@ -30,7 +37,7 @@ stdenv.mkDerivation rec {
     fixPath $out /usr dpa-ext-gnomekeyring.pro gnomekeyringextention.cpp
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "GNOME keyring extension for dde-polkit-agent";
diff --git a/nixpkgs/pkgs/desktops/deepin/dtkcore/default.nix b/nixpkgs/pkgs/desktops/deepin/dtkcore/default.nix
index 90b02a6d9301..570b0cc2c11e 100644
--- a/nixpkgs/pkgs/desktops/deepin/dtkcore/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dtkcore/default.nix
@@ -1,4 +1,12 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, gsettings-qt, pythonPackages, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, gsettings-qt
+, pythonPackages
+, deepin
+}:
 
 mkDerivation rec {
   pname = "dtkcore";
@@ -43,7 +51,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin tool kit core library";
diff --git a/nixpkgs/pkgs/desktops/deepin/dtkwidget/default.nix b/nixpkgs/pkgs/desktops/deepin/dtkwidget/default.nix
index 5a3869a2db93..9be222830db4 100644
--- a/nixpkgs/pkgs/desktops/deepin/dtkwidget/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dtkwidget/default.nix
@@ -1,6 +1,19 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qttools, qtmultimedia,
-  qtsvg, qtx11extras, librsvg, libstartup_notification, gsettings-qt,
-  dde-qt-dbus-factory, dtkcore, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qttools
+, qtmultimedia
+, qtsvg
+, qtx11extras
+, librsvg
+, libstartup_notification
+, gsettings-qt
+, dde-qt-dbus-factory
+, dtkcore
+, deepin
+}:
 
 mkDerivation rec {
   pname = "dtkwidget";
@@ -40,7 +53,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin graphical user interface library";
diff --git a/nixpkgs/pkgs/desktops/deepin/dtkwm/default.nix b/nixpkgs/pkgs/desktops/deepin/dtkwm/default.nix
index ecc11feb7496..56031f11492a 100644
--- a/nixpkgs/pkgs/desktops/deepin/dtkwm/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/dtkwm/default.nix
@@ -1,4 +1,13 @@
-{ stdenv, mkDerivation, fetchFromGitHub, fetchpatch, pkgconfig, qmake, qtx11extras, dtkcore, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, fetchpatch
+, pkgconfig
+, qmake
+, qtx11extras
+, dtkcore
+, deepin
+}:
 
 mkDerivation rec {
   pname = "dtkwm";
@@ -37,7 +46,7 @@ mkDerivation rec {
     "LIB_INSTALL_DIR=${outRef}/lib"
   ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Deepin graphical user interface library";
diff --git a/nixpkgs/pkgs/desktops/deepin/go-dbus-factory/default.nix b/nixpkgs/pkgs/desktops/deepin/go-dbus-factory/default.nix
index 52bf8e62f1d0..1c1afd9d099c 100644
--- a/nixpkgs/pkgs/desktops/deepin/go-dbus-factory/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/go-dbus-factory/default.nix
@@ -1,4 +1,7 @@
-{ stdenv, fetchFromGitHub, deepin }:
+{ stdenv
+, fetchFromGitHub
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "go-dbus-factory";
@@ -11,13 +14,15 @@ stdenv.mkDerivation rec {
     sha256 = "06fqyad9f50gcjsjkh7929yyaprahdjhnd0dr4gl2797a7wysl3f";
   };
 
-  makeFlags = [ "PREFIX=${placeholder "out"}" ];
+  makeFlags = [
+    "PREFIX=${placeholder "out"}"
+  ];
 
   postPatch = ''
     sed -i -e 's:/share/gocode:/share/go:' Makefile
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "GoLang DBus factory for the Deepin Desktop Environment";
diff --git a/nixpkgs/pkgs/desktops/deepin/go-dbus-generator/default.nix b/nixpkgs/pkgs/desktops/deepin/go-dbus-generator/default.nix
index 481f7eb2bc2d..d0b2d8c07e67 100644
--- a/nixpkgs/pkgs/desktops/deepin/go-dbus-generator/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/go-dbus-generator/default.nix
@@ -1,4 +1,9 @@
-{ stdenv, fetchFromGitHub, go, go-lib, deepin }:
+{ stdenv
+, fetchFromGitHub
+, go
+, go-lib
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "go-dbus-generator";
@@ -21,7 +26,7 @@ stdenv.mkDerivation rec {
     "GOCACHE=$(TMPDIR)/go-cache"
   ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Convert dbus interfaces to go-lang or qml wrapper code";
diff --git a/nixpkgs/pkgs/desktops/deepin/go-gir-generator/default.nix b/nixpkgs/pkgs/desktops/deepin/go-gir-generator/default.nix
index f57bae89711f..0c282aaa2276 100644
--- a/nixpkgs/pkgs/desktops/deepin/go-gir-generator/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/go-gir-generator/default.nix
@@ -1,5 +1,12 @@
-{ stdenv, fetchpatch, fetchFromGitHub, pkgconfig, go, gobject-introspection,
-  libgudev, deepin }:
+{ stdenv
+, fetchpatch
+, fetchFromGitHub
+, pkgconfig
+, go
+, gobject-introspection
+, libgudev
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "go-gir-generator";
@@ -40,7 +47,7 @@ stdenv.mkDerivation rec {
     "GOCACHE=$(TMPDIR)/go-cache"
   ];
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Generate static golang bindings for GObject";
diff --git a/nixpkgs/pkgs/desktops/deepin/go-lib/default.nix b/nixpkgs/pkgs/desktops/deepin/go-lib/default.nix
index 43fddf78f11a..d45351fd6dcb 100644
--- a/nixpkgs/pkgs/desktops/deepin/go-lib/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/go-lib/default.nix
@@ -1,5 +1,12 @@
-{ stdenv, fetchFromGitHub, glib, xorg, gdk-pixbuf, pulseaudio,
-  mobile-broadband-provider-info, deepin }:
+{ stdenv
+, fetchFromGitHub
+, glib
+, xorg
+, gdk-pixbuf
+, pulseaudio
+, mobile-broadband-provider-info
+, deepin
+}:
 
 stdenv.mkDerivation rec {
   pname = "go-lib";
@@ -27,7 +34,7 @@ stdenv.mkDerivation rec {
     rm -r $out/share/go/src/pkg.deepin.io/lib/debian
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Go bindings for Deepin Desktop Environment development";
diff --git a/nixpkgs/pkgs/desktops/deepin/qcef/default.nix b/nixpkgs/pkgs/desktops/deepin/qcef/default.nix
index 3b7207379c70..fb6bb89d9393 100644
--- a/nixpkgs/pkgs/desktops/deepin/qcef/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/qcef/default.nix
@@ -1,12 +1,35 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, cmake, qtbase, qttools,
-  qtwebchannel, qtx11extras,
-  gnome2, nss, nspr, alsaLib, atk, cairo, cups, dbus,
-  expat, fontconfig, gdk-pixbuf, glib, gtk2,
-  libxcb, pango, pulseaudio, xorg, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, cmake
+, qtbase
+, qttools
+, qtwebchannel
+, qtx11extras
+, gnome2
+, nss
+, nspr
+, alsaLib
+, atk
+, cairo
+, cups
+, dbus
+, expat
+, fontconfig
+, gdk-pixbuf
+, glib
+, gtk2
+, libxcb
+, pango
+, pulseaudio
+, xorg
+, deepin
+}:
 
 let
   rpahtLibraries = [
-    stdenv.cc.cc.lib  # libstdc++.so.6
+    stdenv.cc.cc.lib # libstdc++.so.6
     alsaLib
     atk
     cairo
@@ -35,9 +58,10 @@ let
     xorg.libXrender
     xorg.libXtst
   ];
+
   libPath = stdenv.lib.makeLibraryPath rpahtLibraries;
-in
 
+in
 mkDerivation rec {
   pname = "qcef";
   version = "1.1.7";
@@ -90,14 +114,14 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version; src = (builtins.head srcs); };
 
   meta = with stdenv.lib; {
     description = "Qt5 binding of Chromium Embedded Framework";
     homepage = "https://github.com/linuxdeepin/qcef";
     license = licenses.lgpl3;
     platforms = platforms.linux;
-    badPlatforms = [ "aarch64-linux" ];  # the cef-binary is not available
+    badPlatforms = [ "aarch64-linux" ]; # the cef-binary is not available
     maintainers = with maintainers; [ romildo ];
   };
 }
diff --git a/nixpkgs/pkgs/desktops/deepin/qt5dxcb-plugin/default.nix b/nixpkgs/pkgs/desktops/deepin/qt5dxcb-plugin/default.nix
index 1bf069821f58..4aa10fb1a93b 100644
--- a/nixpkgs/pkgs/desktops/deepin/qt5dxcb-plugin/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/qt5dxcb-plugin/default.nix
@@ -1,5 +1,15 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, qtx11extras, libSM,
-  mtdev, cairo, deepin, qtbase }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, qtx11extras
+, libSM
+, mtdev
+, cairo
+, deepin
+, qtbase
+}:
 
 mkDerivation rec {
   pname = "qt5dxcb-plugin";
@@ -43,7 +53,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version; src = (builtins.head srcs); };
 
   meta = with stdenv.lib; {
     description = "Qt platform theme integration plugin for DDE";
diff --git a/nixpkgs/pkgs/desktops/deepin/qt5integration/default.nix b/nixpkgs/pkgs/desktops/deepin/qt5integration/default.nix
index ad89957ef1b9..cc427611c34a 100644
--- a/nixpkgs/pkgs/desktops/deepin/qt5integration/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/qt5integration/default.nix
@@ -1,6 +1,19 @@
-{ stdenv, mkDerivation, fetchFromGitHub, pkgconfig, qmake, mtdev,
-  lxqt, qtx11extras, qtmultimedia, qtsvg,
-  qt5dxcb-plugin, qtstyleplugins, dtkcore, dtkwidget, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, pkgconfig
+, qmake
+, mtdev
+, lxqt
+, qtx11extras
+, qtmultimedia
+, qtsvg
+, qt5dxcb-plugin
+, qtstyleplugins
+, dtkcore
+, dtkwidget
+, deepin
+}:
 
 mkDerivation rec {
   pname = "qt5integration";
@@ -40,7 +53,7 @@ mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "Qt platform theme integration plugins for DDE";
diff --git a/nixpkgs/pkgs/desktops/deepin/startdde/default.nix b/nixpkgs/pkgs/desktops/deepin/startdde/default.nix
index 3050e7b9e13c..7d03b00928e3 100644
--- a/nixpkgs/pkgs/desktops/deepin/startdde/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/startdde/default.nix
@@ -1,13 +1,42 @@
-{ stdenv, buildGoPackage, fetchFromGitHub, pkgconfig, alsaLib,
-  coreutils, dbus-factory, dde-api, dde-daemon, dde-dock,
-  dde-file-manager, dde-polkit-agent, dde-session-ui, deepin,
-  deepin-desktop-base, deepin-desktop-schemas, deepin-turbo,
-  dde-kwin, glib, gnome3, go, go-dbus-factory, go-gir-generator,
-  go-lib, gtk3, jq, kmod, libX11, libXi, libcgroup, pciutils, psmisc,
-  pulseaudio, systemd, xorg, wrapGAppsHook }:
+{ stdenv
+, buildGoPackage
+, fetchFromGitHub
+, pkgconfig
+, alsaLib
+, coreutils
+, dbus-factory
+, dde-api
+, dde-daemon
+, dde-dock
+, dde-file-manager
+, dde-polkit-agent
+, dde-session-ui
+, deepin
+, deepin-desktop-base
+, deepin-desktop-schemas
+, deepin-turbo
+, dde-kwin
+, glib
+, gnome3
+, go
+, go-dbus-factory
+, go-gir-generator
+, go-lib
+, gtk3
+, jq
+, kmod
+, libX11
+, libXi
+, libcgroup
+, pciutils
+, psmisc
+, pulseaudio
+, systemd
+, xorg
+, wrapGAppsHook
+}:
 
 buildGoPackage rec {
-  name = "${pname}-${version}";
   pname = "startdde";
   version = "5.0.1";
 
@@ -22,8 +51,6 @@ buildGoPackage rec {
 
   goDeps = ./deps.nix;
 
-  outputs = [ "out" ];
-
   nativeBuildInputs = [
     pkgconfig
     dbus-factory
@@ -114,7 +141,7 @@ buildGoPackage rec {
   installPhase = ''
     make install PREFIX="$out" -C go/src/${goPackagePath}
     rm -rf $out/share/lightdm  # this is uselesss for NixOS
-    remove-references-to -t ${go} $out/bin/* $out/sbin/*
+    remove-references-to -t ${go} $out/sbin/*
   '';
 
   postFixup = ''
@@ -122,7 +149,7 @@ buildGoPackage rec {
   '';
 
   passthru = {
-    updateScript = deepin.updateScript { inherit name; };
+    updateScript = deepin.updateScript { inherit pname version src; };
     providedSessions = [ "deepin" ];
   };
 
diff --git a/nixpkgs/pkgs/desktops/deepin/udisks2-qt5/default.nix b/nixpkgs/pkgs/desktops/deepin/udisks2-qt5/default.nix
index d13460a4bd5d..385fedfc4780 100644
--- a/nixpkgs/pkgs/desktops/deepin/udisks2-qt5/default.nix
+++ b/nixpkgs/pkgs/desktops/deepin/udisks2-qt5/default.nix
@@ -1,4 +1,10 @@
-{ stdenv, mkDerivation, fetchFromGitHub, qmake, qtbase, deepin }:
+{ stdenv
+, mkDerivation
+, fetchFromGitHub
+, qmake
+, qtbase
+, deepin
+}:
 
 mkDerivation rec {
   pname = "udisks2-qt5";
@@ -28,7 +34,7 @@ mkDerivation rec {
     searchHardCodedPaths $out
   '';
 
-  passthru.updateScript = deepin.updateScript { name = "${pname}-${version}"; };
+  passthru.updateScript = deepin.updateScript { inherit pname version src; };
 
   meta = with stdenv.lib; {
     description = "UDisks2 D-Bus interfaces binding for Qt5";
diff --git a/nixpkgs/pkgs/desktops/deepin/update.nix b/nixpkgs/pkgs/desktops/deepin/update.nix
deleted file mode 100644
index 089d9289827e..000000000000
--- a/nixpkgs/pkgs/desktops/deepin/update.nix
+++ /dev/null
@@ -1,38 +0,0 @@
-{ stdenv, lib, writeScript, coreutils, curl, gnugrep, gnused, jq, common-updater-scripts, nix }:
-{ name, ignored-versions ? "^2014(\\.|rc)|^v[0-9]+" }:
-
-let
-  nameAndVersion = builtins.parseDrvName name;
-  packageVersion = nameAndVersion.version;
-  packageName = nameAndVersion.name;
-  attrPath = "deepin.${packageName}";
-in
-
-writeScript "update-${packageName}" ''
-  #!${stdenv.shell}
-  set -o errexit
-  set -x
-
-  # search for the latest version of the package on github
-  PATH=${lib.makeBinPath [ common-updater-scripts coreutils curl gnugrep gnused jq ]}
-  tags=$(curl -s https://api.github.com/repos/linuxdeepin/${packageName}/tags)
-  tags=$(echo "$tags" | jq -r '.[] | .name')
-  echo "# ${name}" >> git-commits.txt
-  echo "#   available tags:" >> git-commits.txt
-  echo "$tags" | ${gnused}/bin/sed -e 's/^/#      /' >> git-commits.txt
-  if [ -n "${ignored-versions}" ]; then
-    tags=$(echo "$tags" | grep -vE "${ignored-versions}")
-  fi
-  latest_tag=$(echo "$tags" | sort --version-sort | tail -1)
-
-  # generate commands to commit the changes
-  if [ "${packageVersion}" != "$latest_tag" ]; then
-    pfile=$(EDITOR=echo ${nix}/bin/nix edit -f. ${attrPath})
-    echo "   git add $pfile " >> git-commits.txt
-    echo "   git commit -m \"${attrPath}: ${packageVersion} -> $latest_tag\"" >> git-commits.txt
-  fi
-
-  # update the nix expression
-  update-source-version "${attrPath}" "$latest_tag"
-  echo "" >> git-commits.txt
-''
diff --git a/nixpkgs/pkgs/desktops/enlightenment/econnman.nix b/nixpkgs/pkgs/desktops/enlightenment/econnman.nix
index dfe294ef5c6a..1979b4518a70 100644
--- a/nixpkgs/pkgs/desktops/enlightenment/econnman.nix
+++ b/nixpkgs/pkgs/desktops/enlightenment/econnman.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, pkgconfig, efl, python2Packages, dbus, makeWrapper }:
+{ stdenv, fetchurl, pkgconfig, efl, python3Packages, dbus, makeWrapper }:
 
 stdenv.mkDerivation rec {
   pname = "econnman";
@@ -9,11 +9,11 @@ stdenv.mkDerivation rec {
     sha256 = "057pwwavlvrrq26bncqnfrf449zzaim0zq717xv86av4n940gwv0";
   };
 
-  nativeBuildInputs = [ makeWrapper pkgconfig python2Packages.wrapPython ];
+  nativeBuildInputs = [ makeWrapper pkgconfig python3Packages.wrapPython ];
 
-  buildInputs = [ efl python2Packages.python dbus ];
+  buildInputs = [ efl python3Packages.python dbus ];
 
-  pythonPath = [ python2Packages.pythonefl python2Packages.dbus-python ];
+  pythonPath = [ python3Packages.pythonefl python3Packages.dbus-python ];
 
   postInstall = ''
     wrapPythonPrograms
diff --git a/nixpkgs/pkgs/desktops/enlightenment/efl.nix b/nixpkgs/pkgs/desktops/enlightenment/efl.nix
index 7bf280cb99b5..bd6c0529925a 100644
--- a/nixpkgs/pkgs/desktops/enlightenment/efl.nix
+++ b/nixpkgs/pkgs/desktops/enlightenment/efl.nix
@@ -1,20 +1,65 @@
-{ stdenv, fetchurl, meson, ninja, pkgconfig, SDL, SDL2, alsaLib,
-  avahi, bullet, check, curl, dbus, doxygen, expat, fontconfig,
-  freetype, fribidi, ghostscript, giflib, glib, gst_all_1, gtk3,
-  harfbuzz, ibus, jbig2dec, libGL, libdrm, libinput, libjpeg, libpng,
-  libpulseaudio, libraw, librsvg, libsndfile, libspectre, libtiff,
-  libwebp, libxkbcommon, luajit, lz4, mesa, openjpeg, openssl,
-  poppler, python27Packages, systemd, udev, utillinux, writeText,
-  xorg, zlib
+{ stdenv
+, fetchurl
+, meson
+, ninja
+, pkgconfig
+, SDL
+, SDL2
+, alsaLib
+, avahi
+, bullet
+, check
+, curl
+, dbus
+, doxygen
+, expat
+, fontconfig
+, freetype
+, fribidi
+, ghostscript
+, giflib
+, glib
+, gst_all_1
+, gtk3
+, harfbuzz
+, hicolor-icon-theme
+, ibus
+, jbig2dec
+, libGL
+, libdrm
+, libinput
+, libjpeg
+, libpng
+, libpulseaudio
+, libraw
+, librsvg
+, libsndfile
+, libspectre
+, libtiff
+, libwebp
+, libxkbcommon
+, luajit
+, lz4
+, mesa
+, openjpeg
+, openssl
+, poppler
+, python3Packages
+, systemd
+, udev
+, utillinux
+, writeText
+, xorg
+, zlib
 }:
 
 stdenv.mkDerivation rec {
   pname = "efl";
-  version = "1.23.3";
+  version = "1.24.0";
 
   src = fetchurl {
     url = "http://download.enlightenment.org/rel/libs/${pname}/${pname}-${version}.tar.xz";
-    sha256 = "00b9lp3h65254kdb1ys15fv7p3ln7qsvf15jkw4kli5ymagadkjk";
+    sha256 = "1yhck2g4rwlzgnzqa4wjxw3lf6k6rd730hz4bwzajdjy7i26xfdk";
   };
 
   nativeBuildInputs = [
@@ -51,6 +96,7 @@ stdenv.mkDerivation rec {
     xorg.libXcursor
     xorg.xorgproto
     zlib
+    # still missing parent icon themes: Mint-X, RAVE-X, Faenza
   ];
 
   propagatedBuildInputs = [
@@ -77,7 +123,7 @@ stdenv.mkDerivation rec {
     luajit
     openjpeg
     poppler
-    python27Packages.dbus-python
+    python3Packages.dbus-python
     utillinux
     xorg.libXScrnSaver
     xorg.libXcomposite
@@ -95,11 +141,14 @@ stdenv.mkDerivation rec {
     xorg.xcbutilkeysyms
   ];
 
+  dontDropIconThemeCache = true;
+
   mesonFlags = [
     "--buildtype=release"
     "-D build-tests=false" # disable build tests, which are not working
     "-D drm=true"
     "-D embedded-lz4=false"
+    "-D ecore-imf-loaders-disabler=ibus,scim" # ibus is disalbed by default, scim is not availabe in nixpkgs
     "-D evas-loaders-disabler=json"
     "-D fb=true"
     "-D opengl=full"
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/accerciser/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/accerciser/default.nix
index f068d1994ec4..192c179a93f3 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/accerciser/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/accerciser/default.nix
@@ -17,13 +17,13 @@
 
  python3.pkgs.buildPythonApplication rec {
   name = "accerciser-${version}";
-  version = "3.36.0";
+  version = "3.36.1";
 
   format = "other";
 
   src = fetchurl {
     url = "mirror://gnome/sources/accerciser/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "1iwi7mnayw1f90s439flh0zkgmj4qx10dzgj38nd5f3wvqmhabk3";
+    sha256 = "1ig9zcg8z7yv2c28q0a4q57ckkpmzjsbnancx01rjihrrjbg9ib2";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/evolution/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/evolution/default.nix
index c1901110b585..467971b2dba4 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/evolution/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/evolution/default.nix
@@ -43,11 +43,11 @@
 
 stdenv.mkDerivation rec {
   pname = "evolution";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/evolution/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1f3cwc05gw75yqficcxns95r96lv7an4aih6d7hng3n3pqfwyfl7";
+    sha256 = "12ii8crp4v4bpdxrc2rkxwdxqz3qjizyfgfrmir9pcyxlg0lh2f5";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/file-roller/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/file-roller/default.nix
index 1243d5fa5cb6..a735d9f446d2 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/file-roller/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/file-roller/default.nix
@@ -3,11 +3,11 @@
 
 stdenv.mkDerivation rec {
   pname = "file-roller";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/file-roller/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0p22jxcagamvp08xfglz4cz1sp8w4p101npw0ggrkhh7vm8yb9bh";
+    sha256 = "1lkb0m8ys13sy3b6c1kj3cqrqf5d1dqvhbp8spz8v9yjv3d7z3r6";
   };
 
   LANG = "en_US.UTF-8"; # postinstall.py
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gedit/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gedit/default.nix
index c6b28e86ab83..ea33bc29324f 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gedit/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gedit/default.nix
@@ -7,11 +7,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gedit";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gedit/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "11z3lhc5i3z0gqw0qmprsm4rmvhbbm4gz6wy0f73c73x4bd8xhvd";
+    sha256 = "15s1almlhjlgl3m8lxg6jpzln8jhgdxxjr635a3b7cf58d35b1v8";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-boxes/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-boxes/default.nix
index 3d6832316cdc..e2ac4cb4b89d 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-boxes/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-boxes/default.nix
@@ -51,11 +51,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-boxes";
-  version = "3.36.2";
+  version = "3.36.3";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-boxes/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "01hjlz9hljk2skrwfqxpy3934wjs6figs71sw8bm8g2vnyaqwq7a";
+    sha256 = "18imxv1859gr53z4yay02611p5f1rd2pwnbaq093gmn77l0j9292";
   };
 
   doCheck = true;
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-calendar/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-calendar/default.nix
index 213b4f616721..88284c540e3b 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-calendar/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-calendar/default.nix
@@ -4,13 +4,13 @@
 
 let
   pname = "gnome-calendar";
-  version = "3.36.0";
+  version = "3.36.1";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "1cxy4qf83s8w1ys94rcc4ksf7ywi0hkkpfs0szkkip2v8g3j6kq2";
+    sha256 = "0ql3f509bj17riqs0jfpp434s97dzjgkjcd978i4m4y80nq2131v";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-getting-started-docs/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-getting-started-docs/default.nix
index 5d31a42301e4..bd02a5f0cc60 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-getting-started-docs/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-getting-started-docs/default.nix
@@ -2,11 +2,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-getting-started-docs";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-getting-started-docs/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "09bf9r6brmll14z87ljgivw0nr0nggcgjpbx6lg2835zq36vfmi9";
+    sha256 = "1ihxa9g687rbb4s2gxd2pf726adx98ahq4kfad868swl7a8vi504";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-maps/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-maps/default.nix
index b00c6f5dd4eb..a722ab9616ed 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-maps/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-maps/default.nix
@@ -5,13 +5,13 @@
 
 let
   pname = "gnome-maps";
-  version = "3.36.1";
+  version = "3.36.2";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "1yajq2pxd4fbzngwhn92h55rn02psxih8bbdcdxgg66qdbcyychs";
+    sha256 = "114pia3nd8k7j6ll7za7qzv0ggcdvcw6b3w4lppqqrwqvswik8jv";
   };
 
   doCheck = true;
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-music/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-music/default.nix
index 9de452404ce0..26cebe076ea4 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-music/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-music/default.nix
@@ -30,13 +30,13 @@
 
 python3.pkgs.buildPythonApplication rec {
   pname = "gnome-music";
-  version = "3.36.1";
+  version = "3.36.2";
 
   format = "other";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0cn33r9v2raizq1b8s7s0kb506y91iarc0knm0sljcsqs4qgd03v";
+    sha256 = "19c2x7h9gq4kh4995y1qcn5pyry4x04lh5n7md0q33zsxcx43bdb";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-weather/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-weather/default.nix
index 407f25165327..84be3f527434 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-weather/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/gnome-weather/default.nix
@@ -3,11 +3,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-weather";
-  version = "3.36.0";
+  version = "3.36.1";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-weather/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "15ahfgqj0rz16y2bdxb7sa4b3b3larg8hn3b41pc5ddnwf9x63zi";
+    sha256 = "11z75ky6xp9hx7lm24xng7ydr20bzh4d6p9sbi9c8ccz2m3fdrk8";
   };
 
   nativeBuildInputs = [ pkgconfig meson ninja wrapGAppsHook python3 ];
diff --git a/nixpkgs/pkgs/desktops/gnome-3/apps/polari/default.nix b/nixpkgs/pkgs/desktops/gnome-3/apps/polari/default.nix
index 394ee86d15a7..363d3c49af85 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/apps/polari/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/apps/polari/default.nix
@@ -5,13 +5,13 @@
 
 let
   pname = "polari";
-  version = "3.36.1";
+  version = "3.36.2";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "1rmmq74g22qrmsg0mjvpzk5403kkpfw0iznvnwxfqbi0dfkamhn4";
+    sha256 = "12i0gp2kwp0b7af135q32qygkhh2025f74dqbaylfbmzacbdpz5c";
   };
 
   patches = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/adwaita-icon-theme/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/adwaita-icon-theme/default.nix
index 6eafa874b836..827fd1cd96a7 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/adwaita-icon-theme/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/adwaita-icon-theme/default.nix
@@ -17,6 +17,8 @@ stdenv.mkDerivation rec {
 
   nativeBuildInputs = [ pkgconfig intltool iconnamingutils gtk3 ];
 
+  dontDropIconThemeCache = true;
+
   # remove a tree of dirs with no files within
   postInstall = '' rm -rf "$out/locale" '';
 
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/dconf-editor/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/dconf-editor/default.nix
index ba8a85352fd0..860b7b957b97 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/dconf-editor/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/dconf-editor/default.nix
@@ -3,13 +3,13 @@
 
 let
   pname = "dconf-editor";
-  version = "3.36.0";
+  version = "3.36.2";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "14q678bwgmhzmi7565xhhw51y8b0pv3cqh0f411qwzwif1bd1vkj";
+    sha256 = "1iz1ngb26llhqnm2s4p55ysvnav41iv0fx0pbw98k181gy3cikpd";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/eog/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/eog/default.nix
index d7a4b32f785c..db15cf2555c8 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/eog/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/eog/default.nix
@@ -4,13 +4,13 @@
 
 let
   pname = "eog";
-  version = "3.36.1";
+  version = "3.36.2";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "15cwghcbx9x1xmv1dwmwcdxplnhf25w6f4dhx8hk6fjymaks2m74";
+    sha256 = "135pw7ifr585grz1rbmynyyrmhd8w880pilg7c4nvq58jl16n1aw";
   };
 
   nativeBuildInputs = [ meson ninja pkgconfig gettext itstool wrapGAppsHook libxml2 gobject-introspection python3 ];
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/epiphany/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/epiphany/default.nix
index 5ede0184d219..c41f5d79eb71 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/epiphany/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/epiphany/default.nix
@@ -58,6 +58,7 @@ stdenv.mkDerivation rec {
     python3
     wrapGAppsHook
     buildPackages.glib
+    buildPackages.gtk3
   ];
 
   buildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/evolution-data-server/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/evolution-data-server/default.nix
index f5d60ee917ce..0d3c786690d1 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/evolution-data-server/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/evolution-data-server/default.nix
@@ -6,13 +6,13 @@
 
 stdenv.mkDerivation rec {
   pname = "evolution-data-server";
-  version = "3.36.1";
+  version = "3.36.2";
 
   outputs = [ "out" "dev" ];
 
   src = fetchurl {
     url = "mirror://gnome/sources/evolution-data-server/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "15k7k225jfv5a45hmjk94xq90np2r9f5v8yj0xi3166vvlp2n4hk";
+    sha256 = "0yz9fsnbnnlj2iidd81i9w7d0dhidrzqkixrnfjfdkhnxk7p9qlq";
   };
 
   patches = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-contacts/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-contacts/default.nix
index 97abd746e1b9..6e933e7b9af0 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-contacts/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-contacts/default.nix
@@ -8,11 +8,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-contacts";
-  version = "3.36";
+  version = "3.36.1";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-contacts/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0yvgsfmqm8dxbhay12m20xp6qi9v31wwyv1gz4fx7j4kklhd5jzf";
+    sha256 = "0qb2kgyk6f6wr129a0gzhvpy5wdjpwjbksxyfs6zxv183jl9s73z";
   };
 
   propagatedUserEnvPkgs = [ evolution-data-server ];
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-control-center/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-control-center/default.nix
index e4efcae889a4..79d28ae8ced8 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-control-center/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-control-center/default.nix
@@ -68,11 +68,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-control-center";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1466swjyw5vjym001qda94x6sisd4xhpyb6vq91grhkyzwf2vqzk";
+    sha256 = "05vqhj5z4w4vaphp541zxxkx6x781m371l2gqnq2vhnnqvqfz9g0";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-desktop/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-desktop/default.nix
index 3f84d0ccd559..94de64c9ea98 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-desktop/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-desktop/default.nix
@@ -4,13 +4,13 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-desktop";
-  version = "3.36.1";
+  version = "3.36.2";
 
   outputs = [ "out" "dev" "devdoc" ];
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-desktop/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1058h1ndl6pmlh8rmbqq5lw15glws3anin88cm7lw4vzasgfavwc";
+    sha256 = "12f724inw3sv289xqprvwh8r3qw89z67m74j3hyhkbp1n7f99y9q";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-initial-setup/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-initial-setup/default.nix
index e5277b07ad5c..fb801ca19a61 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-initial-setup/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-initial-setup/default.nix
@@ -36,11 +36,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-initial-setup";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1sfn6bdz8snc2qmi3nzb07vlkdhy9s1ipwxxj0v2i36a7n0gv6ci";
+    sha256 = "0mjp2j4smikmr4fa0y8wrw2srlfjahiixzphz3dmc30hx8df92sg";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-settings-daemon/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-settings-daemon/default.nix
index 6ff33660dc2b..2ee07fb09aa8 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-settings-daemon/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-settings-daemon/default.nix
@@ -40,11 +40,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-settings-daemon";
-  version = "3.36.0";
+  version = "3.36.1";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-settings-daemon/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0jddz8f2j4ps7csgq9b694h9hjxsyhlimik6rb2f8nbcxhrg0bzs";
+    sha256 = "0jzf2nznpcrjqq7fjwk66kw8a6x87kgbdjidc2msaqmm379xncry";
   };
 
   patches = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell-extensions/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell-extensions/default.nix
index c298d8b337fb..a501f9122774 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell-extensions/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell-extensions/default.nix
@@ -3,11 +3,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-shell-extensions";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-shell-extensions/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0fah7cc22g55w6w7ia3kr2wpdrc45h83xw4pimi54mhggmx9466y";
+    sha256 = "0gq0z0k02b5cfaqrikk2hzbqzjkb6qwcanaqi2jh7nswa7g050lp";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/default.nix
index 864dd45aad20..d3fb419aabcc 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/default.nix
@@ -17,11 +17,11 @@ let
 
 in stdenv.mkDerivation rec {
   pname = "gnome-shell";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-shell/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0696qw6bmbga30qlvh1k6bkiajl7877j8yis4bwmi1wxkcmkh854";
+    sha256 = "0lqpxhvn073bshnzarnisym3da3k3awsi3h906hm85hz3wm9n4iv";
   };
 
   LANG = "en_US.UTF-8";
@@ -65,7 +65,10 @@ in stdenv.mkDerivation rec {
 
     # Install bash-completions to correct prefix.
     # https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1194
-    ./fix-bash-completion.patch
+    (fetchpatch {
+      url = "https://gitlab.gnome.org/GNOME/gnome-shell/commit/9f1ad5d86ddbabaa840eb2860279d53f4e635453.patch";
+      sha256 = "f8MDFbfg9D7ORF84Ld9GIvf0xRCYuSszo3QLMji2VaE=";
+    })
 
     # Use absolute path for libshew installation to make our patched gobject-introspection
     # aware of the location to hardcode in the generated GIR file.
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/fix-bash-completion.patch b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/fix-bash-completion.patch
deleted file mode 100644
index 08f674c23773..000000000000
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-shell/fix-bash-completion.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/subprojects/extensions-tool/meson.build
-+++ a/subprojects/extensions-tool/meson.build
-@@ -39,6 +39,6 @@ subdir('src')
- 
- if bash_completion.found()
-   install_data('completion/bash/gnome-extensions',
--    install_dir: bash_completion.get_pkgconfig_variable('completionsdir')
-+    install_dir: bash_completion.get_pkgconfig_variable('completionsdir', define_variable: ['prefix', prefix])
-   )
- endif
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-terminal/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-terminal/default.nix
index 6a90bb7657ac..821d5707c7c9 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-terminal/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-terminal/default.nix
@@ -4,11 +4,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-terminal";
-  version = "3.36.1.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-terminal/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0xm3g3kanfhs1q3xh3x58r55v8906806wvqjbg4c2xvdwyhhimzk";
+    sha256 = "0inzmkmxv8xw4px2zjfw7236d08yjcv7znxcjki6dh4pvjivdla1";
   };
 
   buildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-themes-extra/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-themes-extra/default.nix
index 9cbac8c74277..fa2f4921fd91 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gnome-themes-extra/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gnome-themes-extra/default.nix
@@ -1,5 +1,5 @@
 { stdenv, fetchurl, intltool, gtk3, gnome3, librsvg, pkgconfig, pango, atk, gtk2
-, gdk-pixbuf }:
+, gdk-pixbuf, hicolor-icon-theme }:
 
 let
   pname = "gnome-themes-extra";
@@ -19,9 +19,12 @@ in stdenv.mkDerivation rec {
   };
 
   nativeBuildInputs = [ pkgconfig intltool ];
-  buildInputs = [ gtk3 librsvg pango atk gtk2 gdk-pixbuf gnome3.adwaita-icon-theme ];
+  buildInputs = [ gtk3 librsvg pango atk gtk2 gdk-pixbuf ];
+  propagatedBuildInputs = [ gnome3.adwaita-icon-theme hicolor-icon-theme ];
 
-  postFixup = ''
+  dontDropIconThemeCache = true;
+
+  postInstall = ''
     gtk-update-icon-cache "$out"/share/icons/HighContrast
   '';
 
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/gucharmap/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/gucharmap/default.nix
index 927d70345e77..fe24ac8708a0 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/gucharmap/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/gucharmap/default.nix
@@ -44,7 +44,7 @@ let
   };
 in stdenv.mkDerivation rec {
   pname = "gucharmap";
-  version = "13.0.0";
+  version = "13.0.2";
 
   outputs = [ "out" "lib" "dev" "devdoc" ];
 
@@ -53,7 +53,7 @@ in stdenv.mkDerivation rec {
     owner = "GNOME";
     repo = pname;
     rev = version;
-    sha256 = "17arjigs1lw1h428s9g171n0idrpf9ks23sndldsik1zvvwzlldh";
+    sha256 = "099za9mc6qdq9pwcbjp3d7hxjbaa43vk2w9qw4yiyswl1xq3jw62";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/mutter/3.34/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/mutter/3.34/default.nix
index 51d3c4115d9c..876969878506 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/mutter/3.34/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/mutter/3.34/default.nix
@@ -43,13 +43,13 @@
 
 stdenv.mkDerivation rec {
   pname = "mutter";
-  version = "3.34.4";
+  version = "3.34.5";
 
   outputs = [ "out" "dev" "man" ];
 
   src = fetchurl {
     url = "mirror://gnome/sources/mutter/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "18hbw98p4h3d4qz57415smwmfg72s9a0nk8mb04ds1gn2lsm2d01";
+    sha256 = "1i3r51ghfld1rf1rczzi3jhybz3mhywqcj2jyiqhfcyp1svlklfi";
   };
 
   mesonFlags = [
@@ -111,6 +111,13 @@ stdenv.mkDerivation rec {
       sha256 = "0imy2j8af9477jliwdq4jc40yw1cifsjjf196gnmwxr9rkj0hbrd";
     })
 
+    # gnome-3-34 2020-04-24
+    # also fixes https://mail.gnome.org/archives/distributor-list/2020-April/msg00001.html
+    (fetchpatch {
+      url = "https://github.com/GNOME/mutter/compare/3.34.5..3bafd234248fdcd84bc62fef5e31c29fbb613909.patch";
+      sha256 = "1a7krbdfmvx204p6av44rbp4ckp6ddg1mms8wkixxh2p871zq1pi";
+    })
+
     # Drop inheritable cap_sys_nice, to prevent the ambient set from leaking
     # from mutter/gnome-shell, see https://github.com/NixOS/nixpkgs/issues/71381
     ./drop-inheritable.patch
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/mutter/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/mutter/default.nix
index 9edb36156d19..3274044bde9b 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/mutter/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/mutter/default.nix
@@ -44,13 +44,13 @@
 
 stdenv.mkDerivation rec {
   pname = "mutter";
-  version = "3.36.1";
+  version = "3.36.2";
 
   outputs = [ "out" "dev" "man" ];
 
   src = fetchurl {
     url = "mirror://gnome/sources/mutter/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "09fqs9805d07c60a2ibskqffsb5wn72l8grwzb9fic5sl574b0im";
+    sha256 = "1x6svmd1k6w6a2m6ssq4hi997nxyq6z64fjjaid97z2rn177dcvm";
   };
 
   mesonFlags = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/nautilus/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/nautilus/default.nix
index 9914489ad257..b926f9b627f1 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/nautilus/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/nautilus/default.nix
@@ -32,11 +32,11 @@
 
 stdenv.mkDerivation rec {
   pname = "nautilus";
-  version = "3.36.1.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1pkvxyfm2fl06fpyq2jr147hhpc91y4rgdlxlilg7n8ih982y9gr";
+    sha256 = "1yknaz8n0l949sr8j3b7kdm0cm5mx2dp4n4k577m492hk6akqrr6";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/core/simple-scan/default.nix b/nixpkgs/pkgs/desktops/gnome-3/core/simple-scan/default.nix
index 99e5975eb5de..d38339425ce7 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/core/simple-scan/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/core/simple-scan/default.nix
@@ -4,11 +4,11 @@
 
 stdenv.mkDerivation rec {
   pname = "simple-scan";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/simple-scan/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0bprm9gfnlrs0k8jvy9pqm1rjq47z5pgahqjjj1i7q2k4a8g09vl";
+    sha256 = "1ya4k63q75w8xwv3vrk1gvbvbpxq876dvnkn3ym1wxzfd29pznxf";
   };
 
   buildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/devtools/devhelp/default.nix b/nixpkgs/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
index fa53b05c44b6..11bad7b89d1d 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
@@ -20,11 +20,11 @@
 
 stdenv.mkDerivation rec {
   pname = "devhelp";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/devhelp/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0gcakbq2fci6cf5z8lakydqnynasp74djfy53bh7jjmw0a9yry2c";
+    sha256 = "0phcjdxnwgg0a0z9kyidp977jy365pny6bh2qhdyzcpvkqqq8nlb";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/arc-menu/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/arc-menu/default.nix
index db1741e72bb5..7bd31f587f67 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/arc-menu/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/arc-menu/default.nix
@@ -24,6 +24,8 @@ stdenv.mkDerivation rec {
 
   makeFlags = [ "INSTALLBASE=${placeholder "out"}/share/gnome-shell/extensions" ];
 
+  uuid = "arc-menu@linxgem33.com";
+
   meta = with stdenv.lib; {
     description = "Gnome shell extension designed to replace the standard menu found in Gnome 3";
     license = licenses.gpl2Plus;
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/clipboard-indicator/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/clipboard-indicator/default.nix
index 1cc06be6ec99..640903bfe4ed 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/clipboard-indicator/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/clipboard-indicator/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-shell-extension-clipboard-indicator";
-  version = "30";
+  version = "34";
 
   src = fetchFromGitHub {
     owner = "Tudmotu";
     repo = "gnome-shell-extension-clipboard-indicator";
     rev = "v${version}";
-    sha256 = "1fmgmxv2y678bj0kmymkgnnglcpqk8ww053izlq46xg7s27jjdf6";
+    sha256 = "0i00psc1ky70zljd14jzr627y7nd8xwnwrh4xpajl1f6djabh12s";
   };
 
   uuid = "clipboard-indicator@tudmotu.com";
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-dock/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-dock/default.nix
index d508222188b8..5a546bd15794 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-dock/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-dock/default.nix
@@ -1,27 +1,36 @@
-{ stdenv, fetchFromGitHub, glib, gettext }:
+{ stdenv
+, fetchFromGitHub
+, glib
+, gettext
+}:
 
 stdenv.mkDerivation rec {
   pname = "gnome-shell-dash-to-dock-unstable";
-  version = "2020-03-19";
+  version = "2020-04-20";
 
   src = fetchFromGitHub {
     owner = "micheleg";
     repo = "dash-to-dock";
     # rev = "extensions.gnome.org-v" + version;
-    rev = "8c94a8d6db47ebc1273e690f4e0ba5e592f7f268";
-    sha256 = "7nNfxAINqOIJCgYXYaPck2EJ1IOmzt6AkfDFknZ8GaI=";
+    rev = "1788f31b049b622f78d0e65c56bef76169022ca9";
+    sha256 = "M3tlRbQ1PjKvNrKNtg0+CBEtzLSFQYauXJXQojdkHuk=";
   };
 
   nativeBuildInputs = [
-    glib gettext
+    glib
+    gettext
   ];
 
-  makeFlags = [ "INSTALLBASE=$(out)/share/gnome-shell/extensions" ];
+  makeFlags = [
+    "INSTALLBASE=${placeholder "out"}/share/gnome-shell/extensions"
+  ];
+
+  uuid = "dash-to-dock@micxgx.gmail.com";
 
   meta = with stdenv.lib; {
     description = "A dock for the Gnome Shell";
-    license = licenses.gpl2;
-    maintainers = with maintainers; [ eperuffo ];
     homepage = "https://micheleg.github.io/dash-to-dock/";
+    license = licenses.gpl2;
+    maintainers = with maintainers; [ eperuffo jtojnar ];
   };
 }
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-panel/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-panel/default.nix
index 84662505a374..e97b34460d07 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-panel/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/dash-to-panel/default.nix
@@ -17,6 +17,8 @@ stdenv.mkDerivation rec {
 
   makeFlags = [ "INSTALLBASE=$(out)/share/gnome-shell/extensions" ];
 
+  uuid = "dash-to-panel@jderose9.github.com";
+
   meta = with stdenv.lib; {
     description = "An icon taskbar for Gnome Shell";
     license = licenses.gpl2;
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/gsconnect/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/gsconnect/default.nix
index baaca39a4c4f..db113924ae60 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/gsconnect/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/gsconnect/default.nix
@@ -73,6 +73,8 @@ stdenv.mkDerivation rec {
     done
   '';
 
+  uuid = "gsconnect@andyholmes.github.io";
+
   meta = with stdenv.lib; {
     description = "KDE Connect implementation for Gnome Shell";
     homepage = "https://github.com/andyholmes/gnome-shell-extension-gsconnect/wiki";
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/no-title-bar/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/no-title-bar/default.nix
index c876b22c12c1..25ef7ddf8279 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/no-title-bar/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/no-title-bar/default.nix
@@ -25,6 +25,8 @@ stdenv.mkDerivation rec {
 
   makeFlags = [ "INSTALLBASE=$(out)/share/gnome-shell/extensions" ];
 
+  uuid = "no-title-bar@franglais125.gmail.com";
+
   meta = with stdenv.lib; {
     description = "Integrates maximized windows with the top panel";
     homepage = "https://github.com/franglais125/no-title-bar";
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/pidgin-im-integration/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/pidgin-im-integration/default.nix
index dbc65044c1bc..e13941ee0455 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/pidgin-im-integration/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/pidgin-im-integration/default.nix
@@ -21,6 +21,8 @@ stdenv.mkDerivation rec {
     mv *.js metadata.json dbus.xml schemas locale "$extensions_dir"
   '';
 
+  uuid = "pidgin@muffinmad";
+
   meta = with stdenv.lib; {
     homepage = "https://github.com/muffinmad/pidgin-im-gnome-shell-extension";
     description = "Make Pidgin IM conversations appear in the Gnome Shell message tray";
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/topicons-plus/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/topicons-plus/default.nix
index 6a1c87abf93d..860a77d2856b 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/extensions/topicons-plus/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/topicons-plus/default.nix
@@ -17,6 +17,8 @@ stdenv.mkDerivation rec {
 
   makeFlags = [ "INSTALL_PATH=$(out)/share/gnome-shell/extensions" ];
 
+  uuid = "TopIcons@phocean.net";
+
   meta = with stdenv.lib; {
     description = "Brings all icons back to the top panel, so that it's easier to keep track of apps running in the backround";
     license = licenses.gpl2;
diff --git a/nixpkgs/pkgs/desktops/gnome-3/extensions/window-is-ready-remover/default.nix b/nixpkgs/pkgs/desktops/gnome-3/extensions/window-is-ready-remover/default.nix
new file mode 100644
index 000000000000..15871e661c12
--- /dev/null
+++ b/nixpkgs/pkgs/desktops/gnome-3/extensions/window-is-ready-remover/default.nix
@@ -0,0 +1,26 @@
+{ stdenv, fetchFromGitHub }:
+
+stdenv.mkDerivation rec {
+  pname = "gnome-shell-extension-window-is-ready-remover";
+  version = "1.02";
+
+  src = fetchFromGitHub {
+    owner = "nunofarruca";
+    repo = "WindowIsReady_Remover";
+    rev = "v${version}";
+    sha256 = "1xaf95gn0if44avvkjxyf8fl29y28idn9shnrks0m9k67jcwv8ns";
+  };
+
+  uuid = "windowIsReady_Remover@nunofarruca@gmail.com";
+
+  installPhase = ''
+    mkdir -p $out/share/gnome-shell/extensions/
+    cp -r ${uuid} $out/share/gnome-shell/extensions/${uuid}
+  '';
+
+  meta = with stdenv.lib; {
+    description = "GNOME Shell extension removing window is ready notification";
+    homepage = "https://github.com/nunofarruca/WindowIsReady_Remover";
+    license = licenses.asl20;
+  };
+}
diff --git a/nixpkgs/pkgs/desktops/gnome-3/find-latest-version.py b/nixpkgs/pkgs/desktops/gnome-3/find-latest-version.py
index b0359f799699..ad80af24bcb8 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/find-latest-version.py
+++ b/nixpkgs/pkgs/desktops/gnome-3/find-latest-version.py
@@ -1,10 +1,13 @@
 import argparse
+import math
 import json
 import requests
 import sys
 
+
 def version_to_list(version):
-    return list(map(int, version.split('.')))
+    return list(map(int, version.split(".")))
+
 
 def odd_unstable(version_str, selected):
     version = version_to_list(version_str)
@@ -14,47 +17,58 @@ def odd_unstable(version_str, selected):
     even = version[1] % 2 == 0
     prerelease = (version[1] >= 90 and version[1] < 100) or (version[1] >= 900 and version[1] < 1000)
     stable = even and not prerelease
-    if selected == 'stable':
+    if selected == "stable":
         return stable
     else:
         return True
 
+
 def no_policy(version, selected):
     return True
 
+
 version_policies = {
-    'odd-unstable': odd_unstable,
-    'none': no_policy,
+    "odd-unstable": odd_unstable,
+    "none": no_policy,
 }
 
-def make_version_policy(version_predicate, selected):
-    return lambda version: version_predicate(version, selected)
 
-parser = argparse.ArgumentParser(description='Find latest version for a GNOME package by crawling their release server.')
-parser.add_argument('package-name', help='Name of the directory in https://ftp.gnome.org/pub/GNOME/sources/ containing the package.')
-parser.add_argument('version-policy', help='Policy determining which versions are considered stable. For most GNOME packages, odd minor versions are unstable but there are exceptions.', choices=version_policies.keys(), nargs='?', default='odd-unstable')
-parser.add_argument('requested-release', help='Most of the time, we will want to update to stable version but sometimes it is useful to test.', choices=['stable', 'unstable'], nargs='?', default='stable')
+def make_version_policy(version_predicate, selected, upper_bound):
+    if not upper_bound:
+        upper_bound = [math.inf, math.inf]
+    else:
+        upper_bound = version_to_list(upper_bound)
+
+    return lambda version: version_predicate(version, selected) and version_to_list(version) < upper_bound
+
+
+parser = argparse.ArgumentParser(description="Find latest version for a GNOME package by crawling their release server.")
+parser.add_argument("package-name", help="Name of the directory in https://ftp.gnome.org/pub/GNOME/sources/ containing the package.")
+parser.add_argument("version-policy", help="Policy determining which versions are considered stable. For most GNOME packages, odd minor versions are unstable but there are exceptions.", choices=version_policies.keys(), nargs="?", default="odd-unstable")
+parser.add_argument("requested-release", help="Most of the time, we will want to update to stable version but sometimes it is useful to test.", choices=["stable", "unstable"], nargs="?", default="stable")
+parser.add_argument("--upper-bound", dest="upper-bound", help="Only look for versions older than this one (useful for pinning dependencies).")
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     args = parser.parse_args()
 
-    package_name = getattr(args, 'package-name')
-    requested_release = getattr(args, 'requested-release')
-    version_predicate = version_policies[getattr(args, 'version-policy')]
-    version_policy = make_version_policy(version_predicate, requested_release)
+    package_name = getattr(args, "package-name")
+    requested_release = getattr(args, "requested-release")
+    upper_bound = getattr(args, "upper-bound")
+    version_predicate = version_policies[getattr(args, "version-policy")]
+    version_policy = make_version_policy(version_predicate, requested_release, upper_bound)
 
     # The structure of cache.json: https://gitlab.gnome.org/Infrastructure/sysadmin-bin/blob/master/ftpadmin#L762
-    cache = json.loads(requests.get('https://ftp.gnome.org/pub/GNOME/sources/{}/cache.json'.format(package_name)).text)
+    cache = json.loads(requests.get(f"https://ftp.gnome.org/pub/GNOME/sources/{package_name}/cache.json").text)
     if type(cache) != list or cache[0] != 4:
-        print('Unknown format of cache.json file.', file=sys.stderr)
+        print("Unknown format of cache.json file.", file=sys.stderr)
         sys.exit(1)
 
     versions = cache[2][package_name]
     versions = sorted(filter(version_policy, versions), key=version_to_list)
 
     if len(versions) == 0:
-        print('No versions matched.', file=sys.stderr)
+        print("No versions matched.", file=sys.stderr)
         sys.exit(1)
 
     print(versions[-1])
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/four-in-a-row/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/four-in-a-row/default.nix
index 0d73e3b3744b..1523da990e37 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/four-in-a-row/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/four-in-a-row/default.nix
@@ -4,11 +4,11 @@
 
 stdenv.mkDerivation rec {
   pname = "four-in-a-row";
-  version = "3.36.0";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/four-in-a-row/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1bl63npcbr5ymka2y06wps612qynxa4hsqlzn7bvwpz2v53pai1z";
+    sha256 = "1pjwaly0f36gn8ashf19b6w1yldmqpa8grdxcyb6h7b0k3bd54z6";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-klotski/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-klotski/default.nix
index 372c12022deb..ac15ebadce92 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-klotski/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-klotski/default.nix
@@ -5,13 +5,13 @@
 
 let
   pname = "gnome-klotski";
-  version = "3.36.0";
+  version = "3.36.2";
 in stdenv.mkDerivation rec {
   name = "${pname}-${version}";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-    sha256 = "06gsg3s8hyhhsk11f1ld2anzv1czg1429483gbv9lr2p7fnq7pyy";
+    sha256 = "1w7fp79hc2v98r7ffg57d6na3wwr355gg9jrdd7w2ad362dfg1kw";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-mahjongg/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-mahjongg/default.nix
index 701008f0c36d..fc706b89f1dc 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-mahjongg/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-mahjongg/default.nix
@@ -5,11 +5,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-mahjongg";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-mahjongg/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1a5h55amr0pab36y2iqm6ynv6mmb8al1b92rfk18wzfcfz7mhxzd";
+    sha256 = "15xfp2acqdnn0pcwg5d77dpv758jjyclwb042wm12gg07rbg3s6j";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-taquin/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-taquin/default.nix
index f50969eb52e4..ad549a7c6829 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-taquin/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-taquin/default.nix
@@ -5,11 +5,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-taquin";
-  version = "3.36.0";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-taquin/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "16ss2d8s6glb3k0wnb5ihmbqvk9i1yi18wv9hzgxfyhs1rvk496f";
+    sha256 = "0pi8kxici7p3jys8673ib0kigpif4mfkq0zlq48rsibhdqfhrlij";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-tetravex/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-tetravex/default.nix
index 4fe68a4f8a74..7061610ced1e 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/gnome-tetravex/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/gnome-tetravex/default.nix
@@ -5,11 +5,11 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-tetravex";
-  version = "3.36.0";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/gnome-tetravex/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1xbd0flh77v3x0dh4dsfspykwb6rwvga7kqwn1fq7gk421mq6n52";
+    sha256 = "0qf6s3gl5qrs5rwsgx0191b0xyknhz2n9whx5i6ma5yw5ikslmq4";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/iagno/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/iagno/default.nix
index 5db02c8dfa41..c3df9bd1099d 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/iagno/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/iagno/default.nix
@@ -5,11 +5,11 @@
 
 stdenv.mkDerivation rec {
   pname = "iagno";
-  version = "3.36.0";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/iagno/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "0ysb021mf5sy1ywicys35rn5c9v355rffjrlhxmr3z6yplrljm5b";
+    sha256 = "0hgn2iqvnfiiwm57bir28dz61b1kkp1zh6av8f342q153rxx10g6";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/games/quadrapassel/default.nix b/nixpkgs/pkgs/desktops/gnome-3/games/quadrapassel/default.nix
index 474ee5823a7f..a4c139f0671c 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/games/quadrapassel/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/games/quadrapassel/default.nix
@@ -6,11 +6,11 @@
 
 stdenv.mkDerivation rec {
   pname = "quadrapassel";
-  version = "3.36.00";
+  version = "3.36.02";
 
   src = fetchurl {
     url = "mirror://gnome/sources/quadrapassel/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "1xk9x1pp71armj47vxja7fsj6gs116kcjkd8xgwf8wi4zr4kgx7g";
+    sha256 = "0c80pzipxricyh4wydffsc94wj6ymnanqr9bg6wdx51hz1mmmilb";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/misc/geary/default.nix b/nixpkgs/pkgs/desktops/gnome-3/misc/geary/default.nix
index bbde1fa36793..0326e38aba76 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/misc/geary/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/misc/geary/default.nix
@@ -7,11 +7,11 @@
 
 stdenv.mkDerivation rec {
   pname = "geary";
-  version = "3.36.1";
+  version = "3.36.2";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "07rhmzznfa4asx5gbmvnfpybd5czy7xmzk75xrk4r1qcnr24ml03";
+    sha256 = "09l2lbcn3ar3scw6iylmdqi1lhpb408iqs6056d0wzx2l9nkmqis";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/misc/gnome-flashback/default.nix b/nixpkgs/pkgs/desktops/gnome-3/misc/gnome-flashback/default.nix
index 1fea28d24de0..cde21551a8a3 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/misc/gnome-flashback/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/misc/gnome-flashback/default.nix
@@ -30,7 +30,7 @@
 
 let
   pname = "gnome-flashback";
-  version = "3.36.1";
+  version = "3.36.3";
 
   # From data/sessions/Makefile.am
   requiredComponentsCommon = [
@@ -61,7 +61,7 @@ let
 
     src = fetchurl {
       url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
-      sha256 = "16gknn5mj29i8svlncarj92qi0swdlziggxpg9rryqslsy896a2x";
+      sha256 = "19y1a4kq6db6a19basss76l4rypiz0lwr32ajli1ra1d1yj9xfid";
     };
 
     # make .desktop Execs absolute
diff --git a/nixpkgs/pkgs/desktops/gnome-3/misc/pomodoro/default.nix b/nixpkgs/pkgs/desktops/gnome-3/misc/pomodoro/default.nix
index fce6b71c4c8e..b9489526dd71 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/misc/pomodoro/default.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/misc/pomodoro/default.nix
@@ -23,13 +23,13 @@
 
 stdenv.mkDerivation rec {
   pname = "gnome-shell-pomodoro";
-  version = "0.16.0";
+  version = "0.17.0";
 
   src = fetchFromGitHub {
     owner = "codito";
     repo = "gnome-pomodoro";
     rev = version;
-    sha256 = "1bjsjkbms9irn7nkzi0hmgr5vwcgh9xzr5vw4sk2n711wj5d96bi";
+    sha256 = "0s9wzx7wbynpqgj7nlgs5wwx4w2akz7nli89sy7pxcn4xpnahqgn";
   };
 
   nativeBuildInputs = [
diff --git a/nixpkgs/pkgs/desktops/gnome-3/update.nix b/nixpkgs/pkgs/desktops/gnome-3/update.nix
index f42b67239505..1bceddf77eb5 100644
--- a/nixpkgs/pkgs/desktops/gnome-3/update.nix
+++ b/nixpkgs/pkgs/desktops/gnome-3/update.nix
@@ -1,8 +1,18 @@
-{ stdenv, lib, writeScript, python3, common-updater-scripts }:
-{ packageName, attrPath ? packageName, versionPolicy ? "odd-unstable" }:
+{ stdenv, pkgs, lib, writeScript, python3, common-updater-scripts }:
+{ packageName, attrPath ? packageName, versionPolicy ? "odd-unstable", freeze ? false }:
 
 let
   python = python3.withPackages (p: [ p.requests ]);
+  upperBoundFlag =
+    let
+      package = lib.attrByPath (lib.splitString "." attrPath) (throw "Cannot find attribute ‘${attrPath}’.") pkgs;
+      packageVersion = lib.getVersion package;
+      versionComponents = lib.versions.splitVersion packageVersion;
+      minorVersion = lib.versions.minor packageVersion;
+      minorAvailable = builtins.length versionComponents > 1 && builtins.match "[0-9]+" minorVersion != null;
+      nextMinor = builtins.fromJSON minorVersion + 1;
+      upperBound = "${lib.versions.major packageVersion}.${builtins.toString nextMinor}";
+    in lib.optionalString (freeze && minorAvailable) ''--upper-bound="${upperBound}"'';
   updateScript = writeScript "gnome-update-script" ''
     #!${stdenv.shell}
     set -o errexit
@@ -10,7 +20,7 @@ let
     attr_path="$2"
     version_policy="$3"
     PATH=${lib.makeBinPath [ common-updater-scripts python ]}
-    latest_tag=$(python "${./find-latest-version.py}" "$package_name" "$version_policy" "stable")
+    latest_tag=$(python "${./find-latest-version.py}" "$package_name" "$version_policy" "stable" ${upperBoundFlag})
     update-source-version "$attr_path" "$latest_tag"
   '';
 in [ updateScript packageName attrPath versionPolicy ]
diff --git a/nixpkgs/pkgs/desktops/lxqt/compton-conf/default.nix b/nixpkgs/pkgs/desktops/lxqt/compton-conf/default.nix
index fe44b707f76e..b41d766c1adf 100644
--- a/nixpkgs/pkgs/desktops/lxqt/compton-conf/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/compton-conf/default.nix
@@ -1,15 +1,23 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, qtbase, qttools, lxqt,
-  libconfig }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, qtbase
+, qttools
+, lxqt
+, libconfig
+}:
 
 mkDerivation rec {
   pname = "compton-conf";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0bx21r83ahmsqf7bm1h17pi4y9js1iqsv7nwnlq58rc0ddkkhcdb";
+    sha256 = "1wqnajarkrpmc60jr1zw5w39lvlf9ii4ri9wgyn55hh1rkbzi7py";
   };
 
   nativeBuildInputs = [
@@ -27,7 +35,9 @@ mkDerivation rec {
   preConfigure = ''
     substituteInPlace autostart/CMakeLists.txt \
       --replace "DESTINATION \"\''${LXQT_ETC_XDG_DIR}" "DESTINATION \"etc/xdg" \
-    '';
+  '';
+
+  passthru.updateScript = lxqt.lxqtUpdateScript { inherit pname version src; };
 
   meta = with lib; {
     description = "GUI configuration tool for compton X composite manager";
diff --git a/nixpkgs/pkgs/desktops/lxqt/default.nix b/nixpkgs/pkgs/desktops/lxqt/default.nix
index 6b03c2a6c9e8..45714260381b 100644
--- a/nixpkgs/pkgs/desktops/lxqt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/default.nix
@@ -1,48 +1,55 @@
 { pkgs, makeScope, libsForQt5 }:
-
 let
   packages = self: with self; {
 
+    # Update script tailored to LXQt packages from git repository
+    lxqtUpdateScript = { pname, version, src }:
+      pkgs.genericUpdater {
+        inherit pname version;
+        attrPath = "lxqt.${pname}";
+        versionLister = "${pkgs.common-updater-scripts}/bin/list-git-tags ${src.meta.homepage}";
+      };
+
     # For compiling information, see:
     # - https://github.com/lxqt/lxqt/wiki/Building-from-source
 
     ### BASE
-    libqtxdg = callPackage ./libqtxdg { };
-    lxqt-build-tools = callPackage ./lxqt-build-tools { };
-    libsysstat = callPackage ./libsysstat { };
-    liblxqt = callPackage ./liblxqt { };
+    libqtxdg = callPackage ./libqtxdg {};
+    lxqt-build-tools = callPackage ./lxqt-build-tools {};
+    libsysstat = callPackage ./libsysstat {};
+    liblxqt = callPackage ./liblxqt {};
 
     ### CORE 1
-    libfm-qt = callPackage ./libfm-qt { };
-    lxqt-about = callPackage ./lxqt-about { };
-    lxqt-admin = callPackage ./lxqt-admin { };
-    lxqt-config = callPackage ./lxqt-config { };
-    lxqt-globalkeys = callPackage ./lxqt-globalkeys { };
-    lxqt-notificationd = callPackage ./lxqt-notificationd { };
-    lxqt-openssh-askpass = callPackage ./lxqt-openssh-askpass { };
-    lxqt-policykit = callPackage ./lxqt-policykit { };
-    lxqt-powermanagement = callPackage ./lxqt-powermanagement { };
-    lxqt-qtplugin = callPackage ./lxqt-qtplugin { };
-    lxqt-session = callPackage ./lxqt-session { };
-    lxqt-sudo = callPackage ./lxqt-sudo { };
-    lxqt-themes = callPackage ./lxqt-themes { };
-    pavucontrol-qt = libsForQt5.callPackage ./pavucontrol-qt { };
-    qtermwidget = callPackage ./qtermwidget { };
+    libfm-qt = callPackage ./libfm-qt {};
+    lxqt-about = callPackage ./lxqt-about {};
+    lxqt-admin = callPackage ./lxqt-admin {};
+    lxqt-config = callPackage ./lxqt-config {};
+    lxqt-globalkeys = callPackage ./lxqt-globalkeys {};
+    lxqt-notificationd = callPackage ./lxqt-notificationd {};
+    lxqt-openssh-askpass = callPackage ./lxqt-openssh-askpass {};
+    lxqt-policykit = callPackage ./lxqt-policykit {};
+    lxqt-powermanagement = callPackage ./lxqt-powermanagement {};
+    lxqt-qtplugin = callPackage ./lxqt-qtplugin {};
+    lxqt-session = callPackage ./lxqt-session {};
+    lxqt-sudo = callPackage ./lxqt-sudo {};
+    lxqt-themes = callPackage ./lxqt-themes {};
+    pavucontrol-qt = libsForQt5.callPackage ./pavucontrol-qt {};
+    qtermwidget = callPackage ./qtermwidget {};
 
     ### CORE 2
-    lxqt-panel = callPackage ./lxqt-panel { };
-    lxqt-runner = callPackage ./lxqt-runner { };
-    pcmanfm-qt = callPackage ./pcmanfm-qt { };
+    lxqt-panel = callPackage ./lxqt-panel {};
+    lxqt-runner = callPackage ./lxqt-runner {};
+    pcmanfm-qt = callPackage ./pcmanfm-qt {};
 
     ### OPTIONAL
-    qterminal = callPackage ./qterminal { };
-    compton-conf = pkgs.qt5.callPackage ./compton-conf { };
-    obconf-qt = callPackage ./obconf-qt { };
-    lximage-qt = callPackage ./lximage-qt { };
-    qps = callPackage ./qps { };
-    screengrab = callPackage ./screengrab { };
-    qlipper = callPackage ./qlipper { };
-    lxqt-archiver = callPackage ./lxqt-archiver { };
+    qterminal = callPackage ./qterminal {};
+    compton-conf = pkgs.qt5.callPackage ./compton-conf {};
+    obconf-qt = callPackage ./obconf-qt {};
+    lximage-qt = callPackage ./lximage-qt {};
+    qps = callPackage ./qps {};
+    screengrab = callPackage ./screengrab {};
+    qlipper = callPackage ./qlipper {};
+    lxqt-archiver = callPackage ./lxqt-archiver {};
 
     preRequisitePackages = [
       pkgs.gvfs # virtual file systems support for PCManFM-QT
@@ -107,5 +114,5 @@ let
     ];
 
   };
-
-in makeScope libsForQt5.newScope packages
+in
+makeScope libsForQt5.newScope packages
diff --git a/nixpkgs/pkgs/desktops/lxqt/libfm-qt/default.nix b/nixpkgs/pkgs/desktops/lxqt/libfm-qt/default.nix
index d383b46a9aed..ba83f0e3167a 100644
--- a/nixpkgs/pkgs/desktops/lxqt/libfm-qt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/libfm-qt/default.nix
@@ -1,18 +1,28 @@
-{
-  lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools,
-  pcre, libexif, xorg, libfm, menu-cache,
-  qtx11extras, qttools
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, pcre
+, libexif
+, xorg
+, libfm
+, menu-cache
+, qtx11extras
+, qttools
+, lxqtUpdateScript
 }:
 
 mkDerivation rec {
-  pname = "libfm-qt-unstable";
-  version = "2019-09-22";
+  pname = "libfm-qt";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = "libfm-qt";
-    rev = "7c94e9efb996df0602f1f2b34b0216ba9b6df498";
-    sha256 = "1fnli2kh7n4hxmqwcb1n06lyk67d9a2fx6z70gas5jzym7r2h5vw";
+    rev = version;
+    sha256 = "0isshh627zr69kdmjxsy75i1nh95ky2wfhgy90g8j4zijpkdrd3l";
   };
 
   nativeBuildInputs = [
@@ -33,6 +43,8 @@ mkDerivation rec {
     menu-cache
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Core library of PCManFM-Qt (Qt binding for libfm)";
     homepage = "https://github.com/lxqt/libfm-qt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/liblxqt/default.nix b/nixpkgs/pkgs/desktops/lxqt/liblxqt/default.nix
index ec7fe0a76652..e72593548cc0 100644
--- a/nixpkgs/pkgs/desktops/lxqt/liblxqt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/liblxqt/default.nix
@@ -1,15 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtx11extras,
-  qttools, qtsvg, libqtxdg, polkit-qt, kwindowsystem, xorg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtx11extras
+, qttools
+, qtsvg
+, libqtxdg
+, polkit-qt
+, kwindowsystem
+, xorg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "liblxqt";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0g2502lcws5j74p82qhfryz9n51cvi85hb50r5s227xhkv91q65k";
+    sha256 = "1dqxsz8fy6xyzbkxhsymmr71yw4d5dwjgqd4rdjn0r9gk8ajrfzp";
   };
 
   nativeBuildInputs = [
@@ -31,6 +43,8 @@ mkDerivation rec {
     sed -i "s|\''${POLKITQT-1_POLICY_FILES_INSTALL_DIR}|''${out}/share/polkit-1/actions|" CMakeLists.txt
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Core utility library for all LXQt components";
     homepage = "https://github.com/lxqt/liblxqt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/libqtxdg/default.nix b/nixpkgs/pkgs/desktops/lxqt/libqtxdg/default.nix
index 14bb21e14695..f5da7a4b2356 100644
--- a/nixpkgs/pkgs/desktops/lxqt/libqtxdg/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/libqtxdg/default.nix
@@ -1,28 +1,44 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, qtbase, qtsvg, lxqt-build-tools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, qtbase
+, qtsvg
+, lxqt-build-tools
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "libqtxdg";
-  version = "3.4.0";
+  version = "3.5.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "16jqnpc740a6phq7vcgy85hl7253yzyw4m5h71r0vijk79ir73b5";
+    sha256 = "00dzs6zc8prc0mxmvq0pmpy1qi8rysg97as7jfd0ndk5jii0nd85";
   };
 
-  nativeBuildInputs = [ cmake lxqt-build-tools ];
+  nativeBuildInputs = [
+    cmake
+    lxqt-build-tools
+  ];
 
-  buildInputs = [ qtbase qtsvg ];
+  buildInputs = [
+    qtbase
+    qtsvg
+  ];
 
   preConfigure = ''
     cmakeFlagsArray+=(
-      "-DQTXDGX_ICONENGINEPLUGIN_INSTALL_PATH=$out/$qtPluginPrefix"
+      "-DQTXDGX_ICONENGINEPLUGIN_INSTALL_PATH=$out/$qtPluginPrefix/iconengines"
       "-DCMAKE_INSTALL_INCLUDEDIR=include"
       "-DCMAKE_INSTALL_LIBDIR=lib"
     )
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Qt implementation of freedesktop.org xdg specs";
     homepage = "https://github.com/lxqt/libqtxdg";
diff --git a/nixpkgs/pkgs/desktops/lxqt/libsysstat/default.nix b/nixpkgs/pkgs/desktops/lxqt/libsysstat/default.nix
index 0e63d32c746e..642b57fe0d75 100644
--- a/nixpkgs/pkgs/desktops/lxqt/libsysstat/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/libsysstat/default.nix
@@ -1,19 +1,33 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, qtbase, lxqt-build-tools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, qtbase
+, lxqt-build-tools
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "libsysstat";
-  version = "0.4.2";
+  version = "0.4.3";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "10h9n7km7yx8bnmzxi4nn1yqq03hizjkrx4745j0mczy7niiffsz";
+    sha256 = "1dlshyv7pd7gwl55rd3msppjdpz2pwp5f4da9a9wapg7kiskqahf";
   };
 
-  nativeBuildInputs = [ cmake lxqt-build-tools ];
+  nativeBuildInputs = [
+    cmake
+    lxqt-build-tools
+  ];
 
-  buildInputs = [ qtbase ];
+  buildInputs = [
+    qtbase
+  ];
+
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
 
   meta = with lib; {
     description = "Library used to query system info and statistics";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lximage-qt/default.nix b/nixpkgs/pkgs/desktops/lxqt/lximage-qt/default.nix
index e47a9ec1b48a..22ce26526acb 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lximage-qt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lximage-qt/default.nix
@@ -1,15 +1,28 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, qtbase, qttools,
-  qtx11extras, qtsvg, xorg, lxqt-build-tools, libfm-qt, libexif }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, xorg
+, lxqt-build-tools
+, libfm-qt
+, libexif
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lximage-qt";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "175l2w5w6iag01v05jq90pxx0al24wpw3mgsbcgqhl4z6h860r32";
+    sha256 = "1pz0ird5vyrz1xycfn2vqh628f2mzwrx0psnp4hqdmj1xk9bjkbp";
   };
 
   nativeBuildInputs = [
@@ -29,6 +42,8 @@ mkDerivation rec {
     libexif
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "The image viewer and screenshot tool for lxqt";
     homepage = "https://github.com/lxqt/lximage-qt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-about/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-about/default.nix
index 19a06925b3ed..01365129467d 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-about/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-about/default.nix
@@ -1,14 +1,26 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtx11extras, qttools, qtsvg, kwindowsystem, liblxqt, libqtxdg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtx11extras
+, qttools
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-about";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0dj2rhbhnkzmv1iqqyq0bcp03imwnvxdr7rnpqnrs9kkjacm8zvr";
+    sha256 = "0bgwh9jbvpnsdcij0bfkgzg0pb0ljjalv65q4q0hlha430pmpv3x";
   };
 
   nativeBuildInputs = [
@@ -25,6 +37,8 @@ mkDerivation rec {
     libqtxdg
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Dialogue window providing information about LXQt and the system it's running on";
     homepage = "https://github.com/lxqt/lxqt-about";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-admin/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-admin/default.nix
index 0a9ef8cfb840..21a637bc6693 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-admin/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-admin/default.nix
@@ -1,14 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtx11extras, qttools, qtsvg, kwindowsystem, liblxqt, libqtxdg, polkit-qt }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtx11extras
+, qttools
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, polkit-qt
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-admin";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "121qj46app2bqdr24g5sz2mdjfd9w86wpgkwap46s0zgxm4li44i";
+    sha256 = "16fbnlvla8lq6rkv5gpmkw2jj9h1wzd3jcf8sjrbns6ygyfdxx3a";
   };
 
   nativeBuildInputs = [
@@ -31,6 +44,8 @@ mkDerivation rec {
       -i lxqt-admin-user/CMakeLists.txt
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "LXQt system administration tool";
     homepage = "https://github.com/lxqt/lxqt-admin";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-archiver/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-archiver/default.nix
index 2c4d040a432b..ae772272c4b2 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-archiver/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-archiver/default.nix
@@ -1,15 +1,26 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools, json-glib, libfm-qt, qtbase, qttools, qtx11extras }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, json-glib
+, libfm-qt
+, qtbase
+, qttools
+, qtx11extras
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
-  # pname = "lxqt-archiver";
-  pname = "lxqt-archiver-unstable";
-  version = "2019-09-25";
+  pname = "lxqt-archiver";
+  version = "0.1.1";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = "lxqt-archiver";
-    rev = "62501255434b2ba6a8fd043a5af13dc0df038a5b";
-    sha256 = "1af58k68karmnay7xgngzlmcgkmvx6hay5m1xbl5id9hh16n20in";
+    rev = version;
+    sha256 = "0c0y8sy12laqyanvy6mmnpjvy1yb8k3241pbxhc3nyl5zrq3hzdh";
   };
 
   nativeBuildInputs = [
@@ -26,10 +37,10 @@ mkDerivation rec {
     qtx11extras
   ];
 
-  cmakeFlags = [ "-DPULL_TRANSLATIONS=NO" ];
-
   hardeningDisable = [ "format" ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Archive tool for the LXQt desktop environment";
     homepage = "https://github.com/lxqt/lxqt-archiver/";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-build-tools/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-build-tools/default.nix
index d06cb7be9286..92ce3c2fe508 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-build-tools/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-build-tools/default.nix
@@ -1,19 +1,36 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, pcre, qtbase, glib }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, pcre
+, qtbase
+, glib
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-build-tools";
-  version = "0.6.0";
+  version = "0.7.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0i7m9s4g5rsw28vclc9nh0zcapx85cqfwxkx7rrw7wa12svy7pm2";
+    sha256 = "18l1w9lyf3nyj05wjhaj4lclak6qydlhw9bqi6kxgr1bv8k709lf";
   };
 
-  nativeBuildInputs = [ cmake pkgconfig setupHook ];
+  nativeBuildInputs = [
+    cmake
+    pkgconfig
+    setupHook
+  ];
 
-  buildInputs = [ qtbase glib pcre ];
+  buildInputs = [
+    qtbase
+    glib
+    pcre
+  ];
 
   setupHook = ./setup-hook.sh;
 
@@ -24,6 +41,8 @@ mkDerivation rec {
     cp ${./LXQtConfigVars.cmake} $out/share/cmake/lxqt-build-tools/modules/LXQtConfigVars.cmake
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Various packaging tools and scripts for LXQt applications";
     homepage = "https://github.com/lxqt/lxqt-build-tools";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-config/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-config/default.nix
index 41fe965161db..677b90b25c53 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-config/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-config/default.nix
@@ -1,16 +1,30 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools, qtbase,
-  qtx11extras, qttools, qtsvg, kwindowsystem, libkscreen, liblxqt,
-  libqtxdg, xorg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, qtbase
+, qtx11extras
+, qttools
+, qtsvg
+, kwindowsystem
+, libkscreen
+, liblxqt
+, libqtxdg
+, xorg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-config";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0x1k08587i2pakxlrj2n0l82r179sfywnzn2cphxiy89r5zpn7vi";
+    sha256 = "1nqkc716rl4c0rad4vqlqadm6lljrhwpdflaa5k9lrdiingr0s7s";
   };
 
   nativeBuildInputs = [
@@ -41,6 +55,8 @@ mkDerivation rec {
     sed -i "/\''${XORG_LIBINPUT_INCLUDE_DIRS}/a ${xorg.xf86inputlibinput.dev}/include/xorg" lxqt-config-input/CMakeLists.txt
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Tools to configure LXQt and the underlying operating system";
     homepage = "https://github.com/lxqt/lxqt-config";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-globalkeys/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-globalkeys/default.nix
index ca760d2a090c..59e2096dea43 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-globalkeys/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-globalkeys/default.nix
@@ -1,14 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtbase, qttools, qtx11extras, qtsvg, kwindowsystem, liblxqt, libqtxdg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-globalkeys";
-  version = "0.14.3";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1ij9abjnqbnkcb7qqk3x7y4amr6l7kkmwhdpc0x2qk4yikn5ijdg";
+    sha256 = "09vib713zbmnwicijycl3n9q35l45lrcw129lf9z95s3ch81x1hm";
   };
 
   nativeBuildInputs = [
@@ -26,6 +39,8 @@ mkDerivation rec {
     libqtxdg
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "LXQt service for global keyboard shortcuts registration";
     homepage = "https://github.com/lxqt/lxqt-globalkeys";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-notificationd/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-notificationd/default.nix
index 5790be3c77f5..43f9bf319324 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-notificationd/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-notificationd/default.nix
@@ -1,14 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtbase, qttools, qtsvg, kwindowsystem, liblxqt, libqtxdg, qtx11extras }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, qtx11extras
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-notificationd";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1ihaf2i361j2snyy6kg8ccpfnc8hppvacmxjqzb1lpyaf1ajd139";
+    sha256 = "0vqk1rc4fn2s0ls6sl03vzsb16xczrxab4rzjim3azm4pwsxjd1k";
   };
 
   nativeBuildInputs = [
@@ -26,6 +39,8 @@ mkDerivation rec {
     qtx11extras
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "The LXQt notification daemon";
     homepage = "https://github.com/lxqt/lxqt-notificationd";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-openssh-askpass/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-openssh-askpass/default.nix
index 26730f57b43e..a164571800ac 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-openssh-askpass/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-openssh-askpass/default.nix
@@ -1,14 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtbase, qttools, qtsvg, qtx11extras, kwindowsystem, liblxqt, libqtxdg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtsvg
+, qtx11extras
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-openssh-askpass";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "04jmvhhlhhspwzj4hfq7fnaa3h7h02z3rlq8p55hzlzkvshqqh1q";
+    sha256 = "056bj3ssp4vqapzqg3da3m95vi92043j7mv70lmpznxdwyjwgxc3";
   };
 
   nativeBuildInputs = [
@@ -26,6 +39,8 @@ mkDerivation rec {
     libqtxdg
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "GUI to query passwords on behalf of SSH agents";
     homepage = "https://github.com/lxqt/lxqt-openssh-askpass";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-panel/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-panel/default.nix
index 57938a5f521f..705d6aec7930 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-panel/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-panel/default.nix
@@ -1,21 +1,42 @@
-{
-  lib, mkDerivation, fetchFromGitHub,
-  cmake, pkgconfig, lxqt-build-tools,
-  qtbase, qttools, qtx11extras, qtsvg, libdbusmenu, kwindowsystem, solid,
-  kguiaddons, liblxqt, libqtxdg, lxqt-globalkeys, libsysstat,
-  xorg, libstatgrab, lm_sensors, libpulseaudio, alsaLib, menu-cache,
-  lxmenu-data, pcre, libXdamage
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, libdbusmenu
+, kwindowsystem
+, solid
+, kguiaddons
+, liblxqt
+, libqtxdg
+, lxqt-globalkeys
+, libsysstat
+, xorg
+, libstatgrab
+, lm_sensors
+, libpulseaudio
+, alsaLib
+, menu-cache
+, lxmenu-data
+, pcre
+, libXdamage
+, lxqtUpdateScript
 }:
 
 mkDerivation rec {
   pname = "lxqt-panel";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1py3i7qgm6h2iwjwqfjml1rp06s7ls1d7z5i9iizsmfshdzkaq86";
+    sha256 = "0k2gqf9f4g8fpny8p5m1anzk7mdxm9dgh6xlngz25nj4mshnq3xs";
   };
 
   nativeBuildInputs = [
@@ -49,6 +70,8 @@ mkDerivation rec {
     libXdamage
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "The LXQt desktop panel";
     homepage = "https://github.com/lxqt/lxqt-panel";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-policykit/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-policykit/default.nix
index 33a2d517fa41..7575c805a31c 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-policykit/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-policykit/default.nix
@@ -1,18 +1,30 @@
-{
-  lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools,
-  qtbase, qttools, qtx11extras, qtsvg, polkit-qt, kwindowsystem, liblxqt,
-  libqtxdg, pcre
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, polkit-qt
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, pcre
+, lxqtUpdateScript
 }:
 
 mkDerivation rec {
   pname = "lxqt-policykit";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0mh9jw09r0mk8xmgvmzk3yyfix0pzqya28rcx71fqjpbdv1sc44l";
+    sha256 = "001zgjxgvzp7clfqr46sx8m3a7v38xxgxjqrpz01lxx18zik3d9h";
   };
 
   nativeBuildInputs = [
@@ -33,6 +45,8 @@ mkDerivation rec {
     pcre
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "The LXQt PolicyKit agent";
     homepage = "https://github.com/lxqt/lxqt-policykit";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-powermanagement/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-powermanagement/default.nix
index 997a9cda3d97..2b48a2a04b5a 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-powermanagement/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-powermanagement/default.nix
@@ -1,14 +1,29 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtbase, qttools, qtx11extras, qtsvg, kwindowsystem, solid, kidletime, liblxqt, libqtxdg }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, kwindowsystem
+, solid
+, kidletime
+, liblxqt
+, libqtxdg
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-powermanagement";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1nhp4a28bpczhwz8b8da355zsxr1qwmkrm3bwllwp39liw947clx";
+    sha256 = "0gqxy4d05gibsvq27qdfwp5v19310l0ln4bvwaan6ailbyyya90f";
   };
 
   nativeBuildInputs = [
@@ -28,6 +43,8 @@ mkDerivation rec {
     libqtxdg
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Power management module for LXQt";
     homepage = "https://github.com/lxqt/lxqt-powermanagement";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-qtplugin/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-qtplugin/default.nix
index abb09aae838f..02a43b4a8c17 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-qtplugin/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-qtplugin/default.nix
@@ -1,18 +1,27 @@
-{
-  lib, mkDerivation, fetchFromGitHub,
-  cmake, lxqt-build-tools,
-  qtbase, qtx11extras, qttools, qtsvg, libdbusmenu, libqtxdg, libfm-qt
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qtx11extras
+, qttools
+, qtsvg
+, libdbusmenu
+, libqtxdg
+, libfm-qt
+, lxqtUpdateScript
 }:
 
 mkDerivation rec {
   pname = "lxqt-qtplugin";
-  version = "0.14.0";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "16n50lxnya03zcviw65sy5dyg9dsrn64k91mrqfvraf6d90md4al";
+    sha256 = "17x5jr78rbsf4pbvc4y3wwkpvsmynzkxy2ifvwhqyc2gmjspp8il";
   };
 
   nativeBuildInputs = [
@@ -35,6 +44,8 @@ mkDerivation rec {
       --replace "DESTINATION \"\''${QT_PLUGINS_DIR}" "DESTINATION \"$qtPluginPrefix"
   '';
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "LXQt Qt platform integration plugin";
     homepage = "https://github.com/lxqt/lxqt-qtplugin";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-runner/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-runner/default.nix
index e4f39184ffdf..8a27ef41610e 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-runner/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-runner/default.nix
@@ -1,15 +1,32 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools, qtbase, qttools, qtsvg, kwindowsystem, liblxqt, libqtxdg, lxqt-globalkeys, qtx11extras,
-menu-cache, muparser, pcre }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, lxqt-globalkeys
+, qtx11extras
+, menu-cache
+, muparser
+, pcre
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-runner";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "01a8ycpkzcbh85y4025pd3nbpnzxh98ll1xwz4ykz13yvm0l2n1w";
+    sha256 = "1x6s4k27cvj2k51hwpcp3l686c2am504ckry4fm76h0mlnkffjm5";
   };
 
   nativeBuildInputs = [
@@ -32,6 +49,8 @@ mkDerivation rec {
     pcre
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Tool used to launch programs quickly by typing their names";
     homepage = "https://github.com/lxqt/lxqt-runner";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-session/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-session/default.nix
index 0493dd9fbb13..2e513b23988f 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-session/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-session/default.nix
@@ -1,14 +1,30 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt-build-tools, qtbase, qttools, qtsvg, qtx11extras, kwindowsystem, liblxqt, libqtxdg, xorg, xdg-user-dirs }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtsvg
+, qtx11extras
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, xorg
+, xdg-user-dirs
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-session";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0s6b0lblb795zz1p7sy677c1iznhmdzc4vw3jkc2agmsrhm7if7s";
+    sha256 = "0kbk13dpmr75yd905n30k51cl7srrxz31ma4kacx450qgr5rwawn";
   };
 
   nativeBuildInputs = [
@@ -30,6 +46,8 @@ mkDerivation rec {
     xdg-user-dirs
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "An alternative session manager ported from the original razor-session";
     homepage = "https://github.com/lxqt/lxqt-session";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-sudo/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-sudo/default.nix
index 9c76f0383b57..5f8fbcd2a6a6 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-sudo/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-sudo/default.nix
@@ -1,14 +1,28 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtbase, qttools, qtx11extras, qtsvg, kwindowsystem, liblxqt, libqtxdg, sudo }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, sudo
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-sudo";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1my0wpic20493rdlabp9ghag1g3nhwafk2yklkgczlajmarakgpc";
+    sha256 = "1j8pxqxb2c10hrfq34nfx75pc0cz6044j4w458nnxbgvl5b8cdcb";
   };
 
   nativeBuildInputs = [
@@ -27,6 +41,8 @@ mkDerivation rec {
     sudo
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "GUI frontend for sudo/su";
     homepage = "https://github.com/lxqt/lxqt-sudo";
diff --git a/nixpkgs/pkgs/desktops/lxqt/lxqt-themes/default.nix b/nixpkgs/pkgs/desktops/lxqt/lxqt-themes/default.nix
index 1cc56d62a06e..4613017b8a96 100644
--- a/nixpkgs/pkgs/desktops/lxqt/lxqt-themes/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/lxqt-themes/default.nix
@@ -1,14 +1,20 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "lxqt-themes";
-  version = "0.14.0";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "09dkcgnf3lmfly8v90p6wjlj5rin83pbailvvpx2jr8a48a8zb9f";
+    sha256 = "1magzckhgrac2b5jm83hj3s8x4hyfnbh2v86lfa4c36whnfvsz29";
   };
 
   nativeBuildInputs = [
@@ -16,6 +22,8 @@ mkDerivation rec {
     lxqt-build-tools
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Themes, graphics and icons for LXQt";
     homepage = "https://github.com/lxqt/lxqt-themes";
diff --git a/nixpkgs/pkgs/desktops/lxqt/obconf-qt/default.nix b/nixpkgs/pkgs/desktops/lxqt/obconf-qt/default.nix
index 1b1e2e92b0fb..91baba60d8a6 100644
--- a/nixpkgs/pkgs/desktops/lxqt/obconf-qt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/obconf-qt/default.nix
@@ -1,15 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, pcre, qtbase, qttools,
-  qtx11extras, xorg, lxqt-build-tools, openbox }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, pcre
+, qtbase
+, qttools
+, qtx11extras
+, xorg
+, lxqt-build-tools
+, openbox
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "obconf-qt";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "15dizs072ylmld1lxwgqkvybqy8ms8zki5586xm305jnlmrkb4lq";
+    sha256 = "13bah70k78kscrr01z7dwdzwhay8mz0f7gfsg2a6w113mgqkn7ib";
   };
 
   nativeBuildInputs = [
@@ -29,6 +41,8 @@ mkDerivation rec {
     openbox
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "The Qt port of obconf, the Openbox configuration tool";
     homepage = "https://github.com/lxqt/obconf-qt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/pavucontrol-qt/default.nix b/nixpkgs/pkgs/desktops/lxqt/pavucontrol-qt/default.nix
index 308077bc0992..24343d423744 100644
--- a/nixpkgs/pkgs/desktops/lxqt/pavucontrol-qt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/pavucontrol-qt/default.nix
@@ -1,15 +1,25 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt, libpulseaudio,
-  pcre, qtbase, qttools, qtx11extras }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt
+, libpulseaudio
+, pcre
+, qtbase
+, qttools
+, qtx11extras
+}:
 
 mkDerivation rec {
   pname = "pavucontrol-qt";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "124dk41v8l5pv7afi1h7fgbhm8zj605yfd8b769sn7id2bqj7bis";
+    sha256 = "0ppm79c6pkz2hvs1rri55d3s46j6r0vhiv634wzap9qshjb1j367";
   };
 
   nativeBuildInputs = [
@@ -26,6 +36,8 @@ mkDerivation rec {
     pcre
   ];
 
+  passthru.updateScript = lxqt.lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "A Pulseaudio mixer in Qt (port of pavucontrol)";
     homepage = "https://github.com/lxqt/pavucontrol-qt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/pcmanfm-qt/default.nix b/nixpkgs/pkgs/desktops/lxqt/pcmanfm-qt/default.nix
index b294cdf52ab0..f5a5b18cfc05 100644
--- a/nixpkgs/pkgs/desktops/lxqt/pcmanfm-qt/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/pcmanfm-qt/default.nix
@@ -1,15 +1,27 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, lxqt, qtbase, qttools,
-  qtx11extras, libfm-qt, menu-cache, lxmenu-data }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, lxqt
+, qtbase
+, qttools
+, qtx11extras
+, libfm-qt
+, menu-cache
+, lxmenu-data
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "pcmanfm-qt";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1zchxlbyiifing94mqwh45pp7z3ihldknqiaz0kanq1cnma1jj6k";
+    sha256 = "16zwd2jfrmsnzfpywirkrpyilq1jj99liwvg77l20b1dbql9dc0q";
   };
 
   nativeBuildInputs = [
@@ -28,6 +40,8 @@ mkDerivation rec {
     lxmenu-data
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "File manager and desktop icon manager (Qt port of PCManFM and libfm)";
     homepage = "https://github.com/lxqt/pcmanfm-qt";
diff --git a/nixpkgs/pkgs/desktops/lxqt/qlipper/default.nix b/nixpkgs/pkgs/desktops/lxqt/qlipper/default.nix
index d5da4737f8f2..fca585c45931 100644
--- a/nixpkgs/pkgs/desktops/lxqt/qlipper/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/qlipper/default.nix
@@ -1,19 +1,33 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, qtbase, qttools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, qtbase
+, qttools
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "qlipper";
-  version = "5.1.1";
+  version = "5.1.2";
 
   src = fetchFromGitHub {
     owner = "pvanek";
     repo = pname;
     rev = version;
-    sha256 = "0vlm4ab9isi7i2bimnyrk6083j2dfdrs14qj59vjcjri7mcwmf76";
+    sha256 = "0zpkcqfylcfwvadp1bidcrr64d8ls5c7bdnkfqwjjd32sd35ly60";
   };
 
-  nativeBuildInputs = [ cmake ];
+  nativeBuildInputs = [
+    cmake
+  ];
 
-  buildInputs = [ qtbase qttools ];
+  buildInputs = [
+    qtbase
+    qttools
+  ];
+
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
 
   meta = with lib; {
     description = "Cross-platform clipboard history applet";
diff --git a/nixpkgs/pkgs/desktops/lxqt/qps/default.nix b/nixpkgs/pkgs/desktops/lxqt/qps/default.nix
index cba01522de01..7ef9db40f7c1 100644
--- a/nixpkgs/pkgs/desktops/lxqt/qps/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/qps/default.nix
@@ -1,26 +1,49 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, qtbase, qtx11extras, qttools,
-  lxqt-build-tools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, kwindowsystem
+, liblxqt
+, libqtxdg
+, lxqt-build-tools
+, lxqtUpdateScript
+, qtbase
+, qttools
+, qtx11extras
+}:
 
 mkDerivation rec {
   pname = "qps";
-  version = "2.0.0";
+  version = "2.1.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "03rl59yk3b24j0y0k8dpdpb3yi4f1l642zn5pp5br3s2vwx1vzkg";
+    sha256 = "0jg7sfhdm5xsahzcw8hc2vpp5p3sqzdqwp4my65nj85i7wzgxmva";
   };
 
-  nativeBuildInputs = [ cmake lxqt-build-tools ];
+  nativeBuildInputs = [
+    cmake
+    lxqt-build-tools
+  ];
 
-  buildInputs = [ qtbase qtx11extras qttools ];
+  buildInputs = [
+    kwindowsystem
+    liblxqt
+    libqtxdg
+    qtbase
+    qttools
+    qtx11extras
+  ];
+
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
 
   meta = with lib; {
     description = "Qt based process manager";
     homepage = "https://github.com/lxqt/qps";
     license = licenses.gpl2;
-    platforms = with platforms; linux;  # does not build on darwin
+    platforms = with platforms; linux; # does not build on darwin
     maintainers = with maintainers; [ romildo ];
   };
 }
diff --git a/nixpkgs/pkgs/desktops/lxqt/qterminal/default.nix b/nixpkgs/pkgs/desktops/lxqt/qterminal/default.nix
index 2b4844654b01..c7bcf6dad3bc 100644
--- a/nixpkgs/pkgs/desktops/lxqt/qterminal/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/qterminal/default.nix
@@ -1,15 +1,24 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, lxqt-build-tools, qtermwidget,
-  qtbase, qttools, qtx11extras }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, lxqt-build-tools
+, qtermwidget
+, qtbase
+, qttools
+, qtx11extras
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "qterminal";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "0bq6lvns56caijdmjm05nsj9vg69v9x5vid24bfxasck6q8nw24w";
+    sha256 = "1vna0fvdasrdx7l5zxaaxi1v9fy34g2qblgkdhpczxivnmmxm5a3";
   };
 
   nativeBuildInputs = [
@@ -24,6 +33,8 @@ mkDerivation rec {
     qtermwidget
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "A lightweight Qt-based terminal emulator";
     homepage = "https://github.com/lxqt/qterminal";
diff --git a/nixpkgs/pkgs/desktops/lxqt/qtermwidget/default.nix b/nixpkgs/pkgs/desktops/lxqt/qtermwidget/default.nix
index d20d4445c252..fc3fb4a5db0e 100644
--- a/nixpkgs/pkgs/desktops/lxqt/qtermwidget/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/qtermwidget/default.nix
@@ -1,19 +1,35 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, qtbase, qttools, lxqt-build-tools }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, qtbase
+, qttools
+, lxqt-build-tools
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "qtermwidget";
-  version = "0.14.1";
+  version = "0.15.0";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1pz8dwb86jpga4vfyn5v9n2s6dx3zh74yfp1kjsmsmhf878zs6lv";
+    sha256 = "07wvcc650998yav9hr4hpm842j0iqdvls3mn9n2n4v8xvm7cii2m";
   };
 
-  nativeBuildInputs = [ cmake lxqt-build-tools ];
+  nativeBuildInputs = [
+    cmake
+    lxqt-build-tools
+  ];
 
-  buildInputs = [ qtbase qttools ];
+  buildInputs = [
+    qtbase
+    qttools
+  ];
+
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
 
   meta = with lib; {
     description = "A terminal emulator widget for Qt 5";
diff --git a/nixpkgs/pkgs/desktops/lxqt/screengrab/default.nix b/nixpkgs/pkgs/desktops/lxqt/screengrab/default.nix
index 7eff539091fc..6a2e14fa50d8 100644
--- a/nixpkgs/pkgs/desktops/lxqt/screengrab/default.nix
+++ b/nixpkgs/pkgs/desktops/lxqt/screengrab/default.nix
@@ -1,14 +1,28 @@
-{ lib, mkDerivation, fetchFromGitHub, cmake, pkgconfig, qtbase, qttools, qtx11extras, qtsvg, kwindowsystem, libqtxdg, xorg, autoPatchelfHook }:
+{ lib
+, mkDerivation
+, fetchFromGitHub
+, cmake
+, pkgconfig
+, qtbase
+, qttools
+, qtx11extras
+, qtsvg
+, kwindowsystem
+, libqtxdg
+, xorg
+, autoPatchelfHook
+, lxqtUpdateScript
+}:
 
 mkDerivation rec {
   pname = "screengrab";
-  version = "2.0.0";
+  version = "2.0.1";
 
   src = fetchFromGitHub {
     owner = "lxqt";
     repo = pname;
     rev = version;
-    sha256 = "1syvdqq45dr8hwigl9ax1wxr33m8z23nh6xzzlqbflyyd93xzjmn";
+    sha256 = "07wm9q0nkrvmyb12kvh0709qrwizlxgy6i5j2czhb4giljrpr4x6";
   };
 
   nativeBuildInputs = [
@@ -28,6 +42,8 @@ mkDerivation rec {
     xorg.libXdmcp
   ];
 
+  passthru.updateScript = lxqtUpdateScript { inherit pname version src; };
+
   meta = with lib; {
     description = "Crossplatform tool for fast making screenshots";
     homepage = "https://github.com/lxqt/screengrab";
diff --git a/nixpkgs/pkgs/desktops/lxqt/update.sh b/nixpkgs/pkgs/desktops/lxqt/update.sh
deleted file mode 100755
index 47d3dfb3d5fe..000000000000
--- a/nixpkgs/pkgs/desktops/lxqt/update.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env nix-shell
-#!nix-shell -i bash -p libarchive curl common-updater-scripts
-
-set -eu -o pipefail
-
-cd "$(dirname "${BASH_SOURCE[0]}")"
-root=../../..
-export NIXPKGS_ALLOW_UNFREE=1
-
-lxqt_version=0.14.1
-lxqtrepo=https://downloads.lxqt.org/${lxqt_version}.html
-
-version() {
-    (cd "$root" && nix-instantiate --eval --strict -A "$1.version" 2>/dev/null | tr -d '"')
-}
-
-update_lxqt() {
-    local pname
-    local pversion
-    curl -sS ${lxqtrepo} | sed -rne 's|.*<a href=.*>(.+) (.+)</a><br>|\1 \2|p' |
-        while read pname pversion; do
-            local pversionold=$(version lxqt.$pname)
-            if [[ "$pversion" = "$pversionold" ]]; then
-                echo "nothing to do, $pname $pversion is current"
-            else
-                echo "$pname: $pversionold -> $pversion"
-                (cd "$root"
-                 local pfile=$(EDITOR=echo nix edit -f. lxqt.$pname 2>/dev/null)
-                 update-source-version lxqt.$pname "$pversion"
-                 git add $pfile
-                 git commit -m "lxqt.$pname: $pversionold -> $pversion"
-                )
-            fi
-            echo
-        done
-    echo DONE
-}
-
-update_lxqt
diff --git a/nixpkgs/pkgs/desktops/mate/mate-icon-theme-faenza/default.nix b/nixpkgs/pkgs/desktops/mate/mate-icon-theme-faenza/default.nix
index 26d8f86985b9..a429e1e66e3d 100644
--- a/nixpkgs/pkgs/desktops/mate/mate-icon-theme-faenza/default.nix
+++ b/nixpkgs/pkgs/desktops/mate/mate-icon-theme-faenza/default.nix
@@ -11,11 +11,7 @@ stdenv.mkDerivation rec {
 
   nativeBuildInputs = [ autoreconfHook gtk3 ];
 
-  buildInputs = [ mate.mate-icon-theme ];
-
-  propagatedBuildInputs = [
-    hicolor-icon-theme
-  ];
+  propagatedBuildInputs = [ mate.mate-icon-theme hicolor-icon-theme ];
 
   dontDropIconThemeCache = true;
 
diff --git a/nixpkgs/pkgs/desktops/pantheon/apps/switchboard-plugs/pantheon-shell/default.nix b/nixpkgs/pkgs/desktops/pantheon/apps/switchboard-plugs/pantheon-shell/default.nix
index c44875259541..a70fee63094f 100644
--- a/nixpkgs/pkgs/desktops/pantheon/apps/switchboard-plugs/pantheon-shell/default.nix
+++ b/nixpkgs/pkgs/desktops/pantheon/apps/switchboard-plugs/pantheon-shell/default.nix
@@ -4,13 +4,13 @@
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-pantheon-shell";
-  version = "2.8.3";
+  version = "2.8.4";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "0ypyppxx51l3r3fgxrvjdwnz33lpbfh1bf27fww9fx9520wixnx8";
+    sha256 = "1nnsv745inbdqk3xnbcaqmj87vr3kzh5hazbh8v3ib33cpi7wy88";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix b/nixpkgs/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
index 432f7c3ac5f1..64c4509280a0 100644
--- a/nixpkgs/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
+++ b/nixpkgs/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
@@ -103,6 +103,9 @@ stdenv.mkDerivation rec {
 
       # for the compositor
       --prefix PATH : "$out/bin"
+
+      # the theme is hardcoded
+      --prefix XDG_DATA_DIRS : "${elementary-gtk-theme}/share"
     )
   '';
 
diff --git a/nixpkgs/pkgs/desktops/pantheon/desktop/gala/default.nix b/nixpkgs/pkgs/desktops/pantheon/desktop/gala/default.nix
index 9db8baa4e94d..9b370847fc84 100644
--- a/nixpkgs/pkgs/desktops/pantheon/desktop/gala/default.nix
+++ b/nixpkgs/pkgs/desktops/pantheon/desktop/gala/default.nix
@@ -26,13 +26,13 @@
 
 stdenv.mkDerivation rec {
   pname = "gala";
-  version = "3.3.0";
+  version = "3.3.1";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "02g6x190lylng8d07pwx2bqcc71rq48f0dxh30mgndfii6k21qgs";
+    sha256 = "03cq9ihgjasnv1n4v3dn1m3ypzj26k2ybd5b1a7yrbprb35zbrs4";
   };
 
   passthru = {
diff --git a/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch
new file mode 100644
index 000000000000..c4d6d8574a53
--- /dev/null
+++ b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch
@@ -0,0 +1,4726 @@
+From 20228e34bf97f67b1dd542a22e92cd90f0db5c72 Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Thu, 9 Apr 2020 16:30:16 +0300
+Subject: [PATCH 1/8] added a single namespace
+
+---
+ meson.build                                   |  14 +-
+ src/DateIterator.vala                         |  82 -----
+ src/DateRange.vala                            |  66 ----
+ src/Indicator.vala                            | 341 +++++++++---------
+ .../calendar => Models}/CalendarModel.vala    |   4 +-
+ src/Services/TimeManager.vala                 | 230 ++++++------
+ src/Util/DateIterator.vala                    |  84 +++++
+ src/Util/DateRange.vala                       |  68 ++++
+ src/{Widgets/calendar => Util}/Util.vala      |   8 +-
+ src/Widgets/CalendarView.vala                 | 185 ++++++++++
+ src/Widgets/EventRow.vala                     | 184 +++++-----
+ src/Widgets/{calendar => }/Grid.vala          |  12 +-
+ src/Widgets/GridDay.vala                      | 180 +++++++++
+ src/Widgets/PanelLabel.vala                   |  80 ++--
+ src/Widgets/calendar/CalendarView.vala        | 183 ----------
+ src/Widgets/calendar/GridDay.vala             | 178 ---------
+ 16 files changed, 957 insertions(+), 942 deletions(-)
+ delete mode 100644 src/DateIterator.vala
+ delete mode 100644 src/DateRange.vala
+ rename src/{Widgets/calendar => Models}/CalendarModel.vala (99%)
+ create mode 100644 src/Util/DateIterator.vala
+ create mode 100644 src/Util/DateRange.vala
+ rename src/{Widgets/calendar => Util}/Util.vala (96%)
+ create mode 100644 src/Widgets/CalendarView.vala
+ rename src/Widgets/{calendar => }/Grid.vala (95%)
+ create mode 100644 src/Widgets/GridDay.vala
+ delete mode 100644 src/Widgets/calendar/CalendarView.vala
+ delete mode 100644 src/Widgets/calendar/GridDay.vala
+
+diff --git a/meson.build b/meson.build
+index 2555723..b44c5bd 100644
+--- a/meson.build
++++ b/meson.build
+@@ -39,16 +39,16 @@ endif
+ shared_module(
+     meson.project_name(),
+     gresource,
+-    'src/DateIterator.vala',
+-    'src/DateRange.vala',
+     'src/Indicator.vala',
++    'src/Util/DateIterator.vala',
++    'src/Util/DateRange.vala',
++    'src/Util/Util.vala',
++    'src/Models/CalendarModel.vala',
++    'src/Widgets/CalendarView.vala',
+     'src/Widgets/EventRow.vala',
++    'src/Widgets/Grid.vala',
++    'src/Widgets/GridDay.vala',
+     'src/Widgets/PanelLabel.vala',
+-    'src/Widgets/calendar/CalendarModel.vala',
+-    'src/Widgets/calendar/CalendarView.vala',
+-    'src/Widgets/calendar/Grid.vala',
+-    'src/Widgets/calendar/GridDay.vala',
+-    'src/Widgets/calendar/Util.vala',
+     'src/Services/TimeManager.vala',
+     dependencies: [
+         dependency('glib-2.0'),
+diff --git a/src/DateIterator.vala b/src/DateIterator.vala
+deleted file mode 100644
+index 961895b..0000000
+--- a/src/DateIterator.vala
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/*
+- * Copyright 2011-2018 elementary, Inc. (https://elementary.io)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public
+- * License along with this program; if not, write to the
+- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301 USA.
+- *
+- * Authored by: Corentin Noël <corentin@elementaryos.org>
+- */
+-
+-public class Util.DateIterator : Object, Gee.Traversable<GLib.DateTime>, Gee.Iterator<GLib.DateTime> {
+-    public GLib.DateTime current { get; construct set; }
+-    public Util.DateRange range { get; construct; }
+-
+-    // Required by Gee.Iterator
+-    public bool valid {
+-        get {
+-            return true;
+-        }
+-    }
+-
+-    // Required by Gee.Iterator
+-    public bool read_only {
+-        get {
+-            return false;
+-        }
+-    }
+-
+-    public DateIterator (Util.DateRange range) {
+-        Object (
+-            range: range,
+-            current: range.first_dt.add_days (-1)
+-        );
+-    }
+-
+-    public bool @foreach (Gee.ForallFunc<GLib.DateTime> f) {
+-        var element = range.first_dt;
+-
+-        while (element.compare (range.last_dt) < 0) {
+-            if (f (element) == false) {
+-                return false;
+-            }
+-
+-            element = element.add_days (1);
+-        }
+-
+-        return true;
+-    }
+-
+-    public bool next () {
+-        if (!has_next ()) {
+-            return false;
+-        }
+-
+-        current = this.current.add_days (1);
+-
+-        return true;
+-    }
+-
+-    public bool has_next () {
+-        return current.compare (range.last_dt) < 0;
+-    }
+-
+-    public new GLib.DateTime get () {
+-        return current;
+-    }
+-
+-    public void remove () {
+-        assert_not_reached ();
+-    }
+-}
+diff --git a/src/DateRange.vala b/src/DateRange.vala
+deleted file mode 100644
+index 08e4c00..0000000
+--- a/src/DateRange.vala
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/*
+- * Copyright 2011-2019 elementary, Inc. (https://elementary.io)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public
+- * License along with this program; if not, write to the
+- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301 USA.
+- *
+- * Authored by: Corentin Noël <corentin@elementaryos.org>
+- */
+-
+-/* Represents date range from 'first' to 'last' inclusive */
+-public class Util.DateRange : Object, Gee.Traversable<GLib.DateTime>, Gee.Iterable<GLib.DateTime> {
+-    public GLib.DateTime first_dt { get; construct; }
+-    public GLib.DateTime last_dt { get; construct; }
+-
+-    public bool @foreach (Gee.ForallFunc<GLib.DateTime> f) {
+-        foreach (var date in this) {
+-            if (f (date) == false) {
+-                return false;
+-            }
+-        }
+-
+-        return true;
+-    }
+-
+-    public DateRange (GLib.DateTime first, GLib.DateTime last) {
+-        Object (
+-            first_dt: first,
+-            last_dt: last
+-        );
+-    }
+-
+-    public bool equals (DateRange other) {
+-        return (first_dt == other.first_dt && last_dt == other.last_dt);
+-    }
+-
+-    public Gee.Iterator<GLib.DateTime> iterator () {
+-        return new DateIterator (this);
+-    }
+-
+-    public Gee.List<GLib.DateTime> to_list () {
+-        var list = new Gee.ArrayList<GLib.DateTime> ((Gee.EqualDataFunc<GLib.DateTime>? )datetime_equal_func);
+-
+-        foreach (var date in this) {
+-            list.add (date);
+-        }
+-
+-        return list;
+-    }
+-
+-    /* Returns true if 'a' and 'b' are the same GLib.DateTime */
+-    private bool datetime_equal_func (GLib.DateTime a, GLib.DateTime b) {
+-        return a.equal (b);
+-    }
+-}
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index 77aa35c..b712c12 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -17,218 +17,219 @@
+  * Boston, MA 02110-1301 USA.
+  */
+ 
+-public class DateTime.Indicator : Wingpanel.Indicator {
+-    public static GLib.Settings settings;
+-
+-    private Widgets.PanelLabel panel_label;
+-    private Gtk.Grid main_grid;
+-    private Widgets.CalendarView calendar;
+-    private Gtk.ListBox event_listbox;
+-    private uint update_events_idle_source = 0;
+-
+-    public Indicator () {
+-        Object (
+-            code_name: Wingpanel.Indicator.DATETIME,
+-            display_name: _("Date & Time"),
+-            description: _("The date and time indicator")
+-        );
+-    }
+-
+-    static construct {
+-        settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
+-    }
++namespace DateTimeIndicator {
++    public class Indicator : Wingpanel.Indicator {
++        public static GLib.Settings settings;
++
++        private Widgets.PanelLabel panel_label;
++        private Gtk.Grid main_grid;
++        private Widgets.CalendarView calendar;
++        private Gtk.ListBox event_listbox;
++        private uint update_events_idle_source = 0;
++
++        public Indicator () {
++            Object (
++                code_name: Wingpanel.Indicator.DATETIME,
++                display_name: _("Date & Time"),
++                description: _("The date and time indicator")
++            );
++        }
+ 
+-    construct {
+-        visible = true;
+-    }
++        static construct {
++            settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
++        }
+ 
+-    public override Gtk.Widget get_display_widget () {
+-        if (panel_label == null) {
+-            panel_label = new Widgets.PanelLabel ();
++        construct {
++            visible = true;
+         }
+ 
+-        return panel_label;
+-    }
++        public override Gtk.Widget get_display_widget () {
++            if (panel_label == null) {
++                panel_label = new Widgets.PanelLabel ();
++            }
+ 
+-    public override Gtk.Widget? get_widget () {
+-        if (main_grid == null) {
+-            calendar = new Widgets.CalendarView ();
+-            calendar.margin_bottom = 6;
+-
+-            var placeholder_label = new Gtk.Label (_("No Events on This Day"));
+-            placeholder_label.wrap = true;
+-            placeholder_label.wrap_mode = Pango.WrapMode.WORD;
+-            placeholder_label.margin_start = 12;
+-            placeholder_label.margin_end = 12;
+-            placeholder_label.max_width_chars = 20;
+-            placeholder_label.justify = Gtk.Justification.CENTER;
+-            placeholder_label.show_all ();
+-
+-            var placeholder_style_context = placeholder_label.get_style_context ();
+-            placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+-            placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL);
+-
+-            event_listbox = new Gtk.ListBox ();
+-            event_listbox.selection_mode = Gtk.SelectionMode.NONE;
+-            event_listbox.set_header_func (header_update_func);
+-            event_listbox.set_placeholder (placeholder_label);
+-            event_listbox.set_sort_func (sort_function);
+-
+-            var scrolled_window = new Gtk.ScrolledWindow (null, null);
+-            scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
+-            scrolled_window.add (event_listbox);
+-
+-            var settings_button = new Gtk.ModelButton ();
+-            settings_button.text = _("Date & Time Settings…");
+-
+-            main_grid = new Gtk.Grid ();
+-            main_grid.margin_top = 12;
+-            main_grid.attach (calendar, 0, 0);
+-            main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0);
+-            main_grid.attach (scrolled_window, 2, 0);
+-            main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3);
+-            main_grid.attach (settings_button, 0, 3, 3);
+-
+-            var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
+-            size_group.add_widget (calendar);
+-            size_group.add_widget (event_listbox);
+-
+-            calendar.day_double_click.connect (() => {
+-                close ();
+-            });
++            return panel_label;
++        }
+ 
+-            calendar.selection_changed.connect ((date) => {
+-                idle_update_events ();
+-            });
++        public override Gtk.Widget? get_widget () {
++            if (main_grid == null) {
++                calendar = new Widgets.CalendarView ();
++                calendar.margin_bottom = 6;
++
++                var placeholder_label = new Gtk.Label (_("No Events on This Day"));
++                placeholder_label.wrap = true;
++                placeholder_label.wrap_mode = Pango.WrapMode.WORD;
++                placeholder_label.margin_start = 12;
++                placeholder_label.margin_end = 12;
++                placeholder_label.max_width_chars = 20;
++                placeholder_label.justify = Gtk.Justification.CENTER;
++                placeholder_label.show_all ();
++
++                var placeholder_style_context = placeholder_label.get_style_context ();
++                placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL);
++                placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL);
++
++                event_listbox = new Gtk.ListBox ();
++                event_listbox.selection_mode = Gtk.SelectionMode.NONE;
++                event_listbox.set_header_func (header_update_func);
++                event_listbox.set_placeholder (placeholder_label);
++                event_listbox.set_sort_func (sort_function);
++
++                var scrolled_window = new Gtk.ScrolledWindow (null, null);
++                scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
++                scrolled_window.add (event_listbox);
++
++                var settings_button = new Gtk.ModelButton ();
++                settings_button.text = _("Date & Time Settings…");
++
++                main_grid = new Gtk.Grid ();
++                main_grid.margin_top = 12;
++                main_grid.attach (calendar, 0, 0);
++                main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0);
++                main_grid.attach (scrolled_window, 2, 0);
++                main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3);
++                main_grid.attach (settings_button, 0, 3, 3);
++
++                var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
++                size_group.add_widget (calendar);
++                size_group.add_widget (event_listbox);
++
++                calendar.day_double_click.connect (() => {
++                    close ();
++                });
++
++                calendar.selection_changed.connect ((date) => {
++                    idle_update_events ();
++                });
++
++                event_listbox.row_activated.connect ((row) => {
++                    calendar.show_date_in_maya (((EventRow) row).date);
++                    close ();
++                });
++
++                settings_button.clicked.connect (() => {
++                    try {
++                        AppInfo.launch_default_for_uri ("settings://time", null);
++                    } catch (Error e) {
++                        warning ("Failed to open time and date settings: %s", e.message);
++                    }
++                });
++            }
+ 
+-            event_listbox.row_activated.connect ((row) => {
+-                calendar.show_date_in_maya (((DateTime.EventRow) row).date);
+-                close ();
+-            });
++            return main_grid;
++        }
+ 
+-            settings_button.clicked.connect (() => {
+-                try {
+-                    AppInfo.launch_default_for_uri ("settings://time", null);
+-                } catch (Error e) {
+-                    warning ("Failed to open time and date settings: %s", e.message);
++        private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) {
++            var row = (EventRow) lbrow;
++            if (lbbefore != null) {
++                var before = (EventRow) lbbefore;
++                if (row.is_allday == before.is_allday) {
++                    row.set_header (null);
++                    return;
+                 }
+-            });
+-        }
+ 
+-        return main_grid;
+-    }
++                if (row.is_allday != before.is_allday) {
++                    var header_label = new Granite.HeaderLabel (_("During the Day"));
++                    header_label.margin_start = header_label.margin_end = 6;
+ 
+-    private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) {
+-        var row = (DateTime.EventRow) lbrow;
+-        if (lbbefore != null) {
+-            var before = (DateTime.EventRow) lbbefore;
+-            if (row.is_allday == before.is_allday) {
+-                row.set_header (null);
++                    row.set_header (header_label);
++                    return;
++                }
++            } else {
++                if (row.is_allday) {
++                    var allday_header = new Granite.HeaderLabel (_("All Day"));
++                    allday_header.margin_start = allday_header.margin_end = 6;
++
++                    row.set_header (allday_header);
++                }
+                 return;
+             }
++        }
+ 
+-            if (row.is_allday != before.is_allday) {
+-                var header_label = new Granite.HeaderLabel (_("During the Day"));
+-                header_label.margin_start = header_label.margin_end = 6;
++        [CCode (instance_pos = -1)]
++        private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) {
++            var e1 = (EventRow) child1;
++            var e2 = (EventRow) child2;
+ 
+-                row.set_header (header_label);
+-                return;
++            if (e1.start_time.compare (e2.start_time) != 0) {
++                return e1.start_time.compare (e2.start_time);
+             }
+-        } else {
+-            if (row.is_allday) {
+-                var allday_header = new Granite.HeaderLabel (_("All Day"));
+-                allday_header.margin_start = allday_header.margin_end = 6;
+ 
+-                row.set_header (allday_header);
++            // If they have the same date, sort them wholeday first
++            if (e1.is_allday) {
++                return -1;
++            } else if (e2.is_allday) {
++                return 1;
+             }
+-            return;
+-        }
+-    }
+-
+-    [CCode (instance_pos = -1)]
+-    private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) {
+-        var e1 = (EventRow) child1;
+-        var e2 = (EventRow) child2;
+ 
+-        if (e1.start_time.compare (e2.start_time) != 0) {
+-            return e1.start_time.compare (e2.start_time);
++            return 0;
+         }
+ 
+-        // If they have the same date, sort them wholeday first
+-        if (e1.is_allday) {
+-            return -1;
+-        } else if (e2.is_allday) {
+-            return 1;
++        private void update_events_model (E.Source source, Gee.Collection<ECal.Component> events) {
++            idle_update_events ();
+         }
+ 
+-        return 0;
+-    }
+-
+-    private void update_events_model (E.Source source, Gee.Collection<ECal.Component> events) {
+-        idle_update_events ();
+-    }
++        private void idle_update_events () {
++            if (update_events_idle_source > 0) {
++                GLib.Source.remove (update_events_idle_source);
++            }
+ 
+-    private void idle_update_events () {
+-        if (update_events_idle_source > 0) {
+-            GLib.Source.remove (update_events_idle_source);
++            update_events_idle_source = GLib.Idle.add (update_events);
+         }
+ 
+-        update_events_idle_source = GLib.Idle.add (update_events);
+-    }
+-
+-    private bool update_events () {
+-        foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) {
+-            widget.destroy ();
+-        }
++        private bool update_events () {
++            foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) {
++                widget.destroy ();
++            }
+ 
+-        if (calendar.selected_date == null) {
+-            update_events_idle_source = 0;
+-            return GLib.Source.REMOVE;
+-        }
++            if (calendar.selected_date == null) {
++                update_events_idle_source = 0;
++                return GLib.Source.REMOVE;
++            }
+ 
+-        var date = calendar.selected_date;
++            var date = calendar.selected_date;
+ 
+-        var model = Widgets.CalendarModel.get_default ();
++            var model = Models.CalendarModel.get_default ();
+ 
+-        var events_on_day = new Gee.TreeMap<string, DateTime.EventRow> ();
++            var events_on_day = new Gee.TreeMap<string, EventRow> ();
+ 
+-        model.source_events.@foreach ((source, component_map) => {
+-            foreach (var comp in component_map.get_values ()) {
+-                if (Util.calcomp_is_on_day (comp, date)) {
+-                    unowned ICal.Component ical = comp.get_icalcomponent ();
+-                    var event_uid = ical.get_uid ();
+-                    if (!events_on_day.has_key (event_uid)) {
+-                        events_on_day[event_uid] = new DateTime.EventRow (date, ical, source);
++            model.source_events.@foreach ((source, component_map) => {
++                foreach (var comp in component_map.get_values ()) {
++                    if (Util.calcomp_is_on_day (comp, date)) {
++                        unowned ICal.Component ical = comp.get_icalcomponent ();
++                        var event_uid = ical.get_uid ();
++                        if (!events_on_day.has_key (event_uid)) {
++                            events_on_day[event_uid] = new EventRow (date, ical, source);
+ 
+-                        event_listbox.add (events_on_day[event_uid]);
++                            event_listbox.add (events_on_day[event_uid]);
++                        }
+                     }
+                 }
+-            }
+-        });
++            });
+ 
+-        event_listbox.show_all ();
+-        update_events_idle_source = 0;
+-        return GLib.Source.REMOVE;
+-    }
++            event_listbox.show_all ();
++            update_events_idle_source = 0;
++            return GLib.Source.REMOVE;
++        }
+ 
+-    public override void opened () {
+-        calendar.show_today ();
++        public override void opened () {
++            calendar.show_today ();
+ 
+-        Widgets.CalendarModel.get_default ().events_added.connect (update_events_model);
+-        Widgets.CalendarModel.get_default ().events_updated.connect (update_events_model);
+-        Widgets.CalendarModel.get_default ().events_removed.connect (update_events_model);
+-    }
++            Models.CalendarModel.get_default ().events_added.connect (update_events_model);
++            Models.CalendarModel.get_default ().events_updated.connect (update_events_model);
++            Models.CalendarModel.get_default ().events_removed.connect (update_events_model);
++        }
+ 
+-    public override void closed () {
+-        Widgets.CalendarModel.get_default ().events_added.disconnect (update_events_model);
+-        Widgets.CalendarModel.get_default ().events_updated.disconnect (update_events_model);
+-        Widgets.CalendarModel.get_default ().events_removed.disconnect (update_events_model);
++        public override void closed () {
++            Models.CalendarModel.get_default ().events_added.disconnect (update_events_model);
++            Models.CalendarModel.get_default ().events_updated.disconnect (update_events_model);
++            Models.CalendarModel.get_default ().events_removed.disconnect (update_events_model);
++        }
+     }
+ }
+-
+ public Wingpanel.Indicator get_indicator (Module module) {
+     debug ("Activating DateTime Indicator");
+-    var indicator = new DateTime.Indicator ();
++    var indicator = new DateTimeIndicator.Indicator ();
+ 
+     return indicator;
+ }
+diff --git a/src/Widgets/calendar/CalendarModel.vala b/src/Models/CalendarModel.vala
+similarity index 99%
+rename from src/Widgets/calendar/CalendarModel.vala
+rename to src/Models/CalendarModel.vala
+index 7602303..965b93e 100644
+--- a/src/Widgets/calendar/CalendarModel.vala
++++ b/src/Models/CalendarModel.vala
+@@ -15,8 +15,8 @@
+  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
+-namespace DateTime.Widgets {
+-    public class CalendarModel : Object {
++namespace DateTimeIndicator {
++    public class Models.CalendarModel : Object {
+         /* The data_range is the range of dates for which this model is storing
+          * data.
+          *
+diff --git a/src/Services/TimeManager.vala b/src/Services/TimeManager.vala
+index b68f158..5baa136 100644
+--- a/src/Services/TimeManager.vala
++++ b/src/Services/TimeManager.vala
+@@ -32,153 +32,155 @@ interface FDO.Accounts : Object {
+     public abstract string find_user_by_name (string username) throws GLib.Error;
+ }
+ 
+-public class DateTime.Services.TimeManager : Gtk.Calendar {
+-    private static TimeManager? instance = null;
++namespace DateTimeIndicator {
++    public class Services.TimeManager : Gtk.Calendar {
++        private static TimeManager? instance = null;
+ 
+-    public signal void minute_changed ();
++        public signal void minute_changed ();
+ 
+-    private GLib.DateTime? current_time = null;
+-    private uint timeout_id = 0;
+-    private Manager? manager = null;
++        private GLib.DateTime? current_time = null;
++        private uint timeout_id = 0;
++        private Manager? manager = null;
+ 
+-    public bool clock_show_seconds { get; set; }
+-    public bool is_12h { get; set; }
++        public bool clock_show_seconds { get; set; }
++        public bool is_12h { get; set; }
+ 
+-    public TimeManager () {
+-        update_current_time ();
+-
+-        if (current_time == null) {
+-            return;
+-        }
++        public TimeManager () {
++            update_current_time ();
+ 
+-        add_timeout ();
+-        try {
+-            var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
+-            clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT);
++            if (current_time == null) {
++                return;
++            }
+ 
+-            notify["clock-show-seconds"].connect (() => {
+-                add_timeout ();
+-            });
++            add_timeout ();
++            try {
++                var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
++                clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT);
+ 
+-            // Listen for the D-BUS server that controls time settings
+-            Bus.watch_name (BusType.SYSTEM, "org.freedesktop.timedate1", BusNameWatcherFlags.NONE, on_watch, on_unwatch);
+-            // Listen for the signal that is fired when waking up from sleep, then update time
+-            manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1");
+-            manager.prepare_for_sleep.connect ((sleeping) => {
+-                if (!sleeping) {
+-                    update_current_time ();
+-                    minute_changed ();
++                notify["clock-show-seconds"].connect (() => {
+                     add_timeout ();
+-                }
+-            });
+-        } catch (Error e) {
+-            warning (e.message);
++                });
++
++                // Listen for the D-BUS server that controls time settings
++                Bus.watch_name (BusType.SYSTEM, "org.freedesktop.timedate1", BusNameWatcherFlags.NONE, on_watch, on_unwatch);
++                // Listen for the signal that is fired when waking up from sleep, then update time
++                manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1");
++                manager.prepare_for_sleep.connect ((sleeping) => {
++                    if (!sleeping) {
++                        update_current_time ();
++                        minute_changed ();
++                        add_timeout ();
++                    }
++                });
++            } catch (Error e) {
++                warning (e.message);
++            }
+         }
+-    }
+-
+-    construct {
+-        setup_time_format.begin ();
+-    }
+ 
+-    private async void setup_time_format () {
+-        try {
+-            var accounts_service = yield GLib.Bus.get_proxy<FDO.Accounts> (GLib.BusType.SYSTEM,
+-                                                                           "org.freedesktop.Accounts",
+-                                                                           "/org/freedesktop/Accounts");
+-            var user_path = accounts_service.find_user_by_name (GLib.Environment.get_user_name ());
+-
+-            var greeter_act = yield GLib.Bus.get_proxy<Pantheon.AccountsService> (GLib.BusType.SYSTEM,
+-                                                    "org.freedesktop.Accounts",
+-                                                    user_path,
+-                                                    GLib.DBusProxyFlags.GET_INVALIDATED_PROPERTIES);
+-            is_12h = ("12h" in greeter_act.time_format);
+-            ((GLib.DBusProxy) greeter_act).g_properties_changed.connect ((changed_properties, invalidated_properties) => {
+-                if (changed_properties.lookup_value ("TimeFormat", GLib.VariantType.STRING) != null) {
+-                    is_12h = ("12h" in greeter_act.time_format);
+-                }
+-            });
+-        } catch (Error e) {
+-            critical (e.message);
+-            // Connect to the GSettings instead
+-            var clock_settings = new GLib.Settings ("org.gnome.desktop.interface");
+-            clock_settings.changed["clock-format"].connect (() => {
+-                is_12h = ("12h" in clock_settings.get_string ("clock-format"));
+-            });
+-
+-            is_12h = ("12h" in clock_settings.get_string ("clock-format"));
++        construct {
++            setup_time_format.begin ();
+         }
+-    }
+ 
+-    private void on_watch (DBusConnection conn) {
+-        // Start updating the time display quicker because someone is changing settings
+-        add_timeout (true);
+-    }
++        private async void setup_time_format () {
++            try {
++                var accounts_service = yield GLib.Bus.get_proxy<FDO.Accounts> (GLib.BusType.SYSTEM,
++                                                                               "org.freedesktop.Accounts",
++                                                                               "/org/freedesktop/Accounts");
++                var user_path = accounts_service.find_user_by_name (GLib.Environment.get_user_name ());
++
++                var greeter_act = yield GLib.Bus.get_proxy<Pantheon.AccountsService> (GLib.BusType.SYSTEM,
++                                                        "org.freedesktop.Accounts",
++                                                        user_path,
++                                                        GLib.DBusProxyFlags.GET_INVALIDATED_PROPERTIES);
++                is_12h = ("12h" in greeter_act.time_format);
++                ((GLib.DBusProxy) greeter_act).g_properties_changed.connect ((changed_properties, invalidated_properties) => {
++                    if (changed_properties.lookup_value ("TimeFormat", GLib.VariantType.STRING) != null) {
++                        is_12h = ("12h" in greeter_act.time_format);
++                    }
++                });
++            } catch (Error e) {
++                critical (e.message);
++                // Connect to the GSettings instead
++                var clock_settings = new GLib.Settings ("org.gnome.desktop.interface");
++                clock_settings.changed["clock-format"].connect (() => {
++                    is_12h = ("12h" in clock_settings.get_string ("clock-format"));
++                });
+ 
+-    private void on_unwatch (DBusConnection conn) {
+-        // Stop updating the time display quicker
+-        add_timeout (false);
+-    }
++                is_12h = ("12h" in clock_settings.get_string ("clock-format"));
++            }
++        }
+ 
+-    private void add_timeout (bool update_fast = false) {
+-        uint interval;
+-        if (update_fast || clock_show_seconds) {
+-            interval = 500;
+-        } else {
+-            interval = calculate_time_until_next_minute ();
++        private void on_watch (DBusConnection conn) {
++            // Start updating the time display quicker because someone is changing settings
++            add_timeout (true);
+         }
+ 
+-        if (timeout_id > 0) {
+-            Source.remove (timeout_id);
++        private void on_unwatch (DBusConnection conn) {
++            // Stop updating the time display quicker
++            add_timeout (false);
+         }
+ 
+-        timeout_id = Timeout.add (interval, () => {
+-            update_current_time ();
+-            minute_changed ();
+-            add_timeout (update_fast);
++        private void add_timeout (bool update_fast = false) {
++            uint interval;
++            if (update_fast || clock_show_seconds) {
++                interval = 500;
++            } else {
++                interval = calculate_time_until_next_minute ();
++            }
+ 
+-            return false;
+-        });
+-    }
++            if (timeout_id > 0) {
++                Source.remove (timeout_id);
++            }
+ 
+-    public string format (string format) {
+-        if (current_time == null) {
+-            return "undef";
++            timeout_id = Timeout.add (interval, () => {
++                update_current_time ();
++                minute_changed ();
++                add_timeout (update_fast);
++
++                return false;
++            });
+         }
+ 
+-        return current_time.format (format);
+-    }
++        public string format (string format) {
++            if (current_time == null) {
++                return "undef";
++            }
+ 
+-    public GLib.DateTime get_current_time () {
+-        return current_time;
+-    }
++            return current_time.format (format);
++        }
+ 
+-    private void update_current_time () {
+-        var local_time = new GLib.DateTime.now_local ();
++        public GLib.DateTime get_current_time () {
++            return current_time;
++        }
+ 
+-        if (local_time == null) {
+-            critical ("Can't get the local time.");
++        private void update_current_time () {
++            var local_time = new GLib.DateTime.now_local ();
+ 
+-            return;
+-        }
++            if (local_time == null) {
++                critical ("Can't get the local time.");
+ 
+-        current_time = local_time;
+-    }
++                return;
++            }
+ 
+-    private uint calculate_time_until_next_minute () {
+-        if (current_time == null) {
+-            return 60 * 1000;
++            current_time = local_time;
+         }
+ 
+-        var seconds_until_next_minute = 60 - (current_time.to_unix () % 60);
++        private uint calculate_time_until_next_minute () {
++            if (current_time == null) {
++                return 60 * 1000;
++            }
+ 
+-        return (uint)seconds_until_next_minute * 1000;
+-    }
++            var seconds_until_next_minute = 60 - (current_time.to_unix () % 60);
+ 
+-    public static TimeManager get_default () {
+-        if (instance == null) {
+-            instance = new TimeManager ();
++            return (uint)seconds_until_next_minute * 1000;
+         }
+ 
+-        return instance;
++        public static TimeManager get_default () {
++            if (instance == null) {
++                instance = new TimeManager ();
++            }
++
++            return instance;
++        }
+     }
+ }
+diff --git a/src/Util/DateIterator.vala b/src/Util/DateIterator.vala
+new file mode 100644
+index 0000000..c2c771e
+--- /dev/null
++++ b/src/Util/DateIterator.vala
+@@ -0,0 +1,84 @@
++/*
++ * Copyright 2011-2018 elementary, Inc. (https://elementary.io)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public
++ * License along with this program; if not, write to the
++ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301 USA.
++ *
++ * Authored by: Corentin Noël <corentin@elementaryos.org>
++ */
++
++namespace DateTimeIndicator {
++    public class Util.DateIterator : Object, Gee.Traversable<GLib.DateTime>, Gee.Iterator<GLib.DateTime> {
++        public GLib.DateTime current { get; construct set; }
++        public Util.DateRange range { get; construct; }
++
++        // Required by Gee.Iterator
++        public bool valid {
++            get {
++                return true;
++            }
++        }
++
++        // Required by Gee.Iterator
++        public bool read_only {
++            get {
++                return false;
++            }
++        }
++
++        public DateIterator (Util.DateRange range) {
++            Object (
++                range: range,
++                current: range.first_dt.add_days (-1)
++            );
++        }
++
++        public bool @foreach (Gee.ForallFunc<GLib.DateTime> f) {
++            var element = range.first_dt;
++
++            while (element.compare (range.last_dt) < 0) {
++                if (f (element) == false) {
++                    return false;
++                }
++
++                element = element.add_days (1);
++            }
++
++            return true;
++        }
++
++        public bool next () {
++            if (!has_next ()) {
++                return false;
++            }
++
++            current = this.current.add_days (1);
++
++            return true;
++        }
++
++        public bool has_next () {
++            return current.compare (range.last_dt) < 0;
++        }
++
++        public new GLib.DateTime get () {
++            return current;
++        }
++
++        public void remove () {
++            assert_not_reached ();
++        }
++    }
++}
+diff --git a/src/Util/DateRange.vala b/src/Util/DateRange.vala
+new file mode 100644
+index 0000000..82da7c8
+--- /dev/null
++++ b/src/Util/DateRange.vala
+@@ -0,0 +1,68 @@
++/*
++ * Copyright 2011-2019 elementary, Inc. (https://elementary.io)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public
++ * License along with this program; if not, write to the
++ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301 USA.
++ *
++ * Authored by: Corentin Noël <corentin@elementaryos.org>
++ */
++
++namespace DateTimeIndicator {
++/* Represents date range from 'first' to 'last' inclusive */
++    public class Util.DateRange : Object, Gee.Traversable<GLib.DateTime>, Gee.Iterable<GLib.DateTime> {
++        public GLib.DateTime first_dt { get; construct; }
++        public GLib.DateTime last_dt { get; construct; }
++
++        public bool @foreach (Gee.ForallFunc<GLib.DateTime> f) {
++            foreach (var date in this) {
++                if (f (date) == false) {
++                    return false;
++                }
++            }
++
++            return true;
++        }
++
++        public DateRange (GLib.DateTime first, GLib.DateTime last) {
++            Object (
++                first_dt: first,
++                last_dt: last
++            );
++        }
++
++        public bool equals (DateRange other) {
++            return (first_dt == other.first_dt && last_dt == other.last_dt);
++        }
++
++        public Gee.Iterator<GLib.DateTime> iterator () {
++            return new DateIterator (this);
++        }
++
++        public Gee.List<GLib.DateTime> to_list () {
++            var list = new Gee.ArrayList<GLib.DateTime> ((Gee.EqualDataFunc<GLib.DateTime>? )datetime_equal_func);
++
++            foreach (var date in this) {
++                list.add (date);
++            }
++
++            return list;
++        }
++
++        /* Returns true if 'a' and 'b' are the same GLib.DateTime */
++        private bool datetime_equal_func (GLib.DateTime a, GLib.DateTime b) {
++            return a.equal (b);
++        }
++    }
++}
+diff --git a/src/Widgets/calendar/Util.vala b/src/Util/Util.vala
+similarity index 96%
+rename from src/Widgets/calendar/Util.vala
+rename to src/Util/Util.vala
+index e51f784..c261f4b 100644
+--- a/src/Widgets/calendar/Util.vala
++++ b/src/Util/Util.vala
+@@ -19,7 +19,7 @@
+  * Authored by: Corentin Noël <corentin@elementaryos.org>
+  */
+ 
+-namespace Util {
++namespace DateTimeIndicator.Util {
+     static bool has_scrolled = false;
+ 
+     public bool on_scroll_event (Gdk.EventScroll event) {
+@@ -35,7 +35,7 @@ namespace Util {
+ 
+         /* It's mouse scroll ! */
+         if (choice == 1 || choice == -1) {
+-            DateTime.Widgets.CalendarModel.get_default ().change_month ((int)choice);
++            Models.CalendarModel.get_default ().change_month ((int)choice);
+ 
+             return true;
+         }
+@@ -46,14 +46,14 @@ namespace Util {
+ 
+         if (choice > 0.3) {
+             reset_timer.begin ();
+-            DateTime.Widgets.CalendarModel.get_default ().change_month (1);
++            Models.CalendarModel.get_default ().change_month (1);
+ 
+             return true;
+         }
+ 
+         if (choice < -0.3) {
+             reset_timer.begin ();
+-            DateTime.Widgets.CalendarModel.get_default ().change_month (-1);
++            Models.CalendarModel.get_default ().change_month (-1);
+ 
+             return true;
+         }
+diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala
+new file mode 100644
+index 0000000..65cee28
+--- /dev/null
++++ b/src/Widgets/CalendarView.vala
+@@ -0,0 +1,185 @@
++/*-
++ * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io)
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ *
++ * Authored by: Maxwell Barvian
++ *              Corentin Noël <corentin@elementaryos.org>
++ */
++
++namespace DateTimeIndicator {
++    public class Widgets.CalendarView : Gtk.Grid {
++        public signal void day_double_click ();
++        public signal void event_updates ();
++        public signal void selection_changed (GLib.DateTime? new_date);
++
++        public GLib.DateTime? selected_date { get; private set; }
++
++        private Widgets.Grid grid;
++        private Gtk.Stack stack;
++        private Gtk.Grid big_grid;
++
++        construct {
++            var label = new Gtk.Label (new GLib.DateTime.now_local ().format (_("%OB, %Y")));
++            label.hexpand = true;
++            label.margin_start = 6;
++            label.xalign = 0;
++            label.width_chars = 13;
++
++            var provider = new Gtk.CssProvider ();
++            provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/ControlHeader.css");
++
++            var label_style_context = label.get_style_context ();
++            label_style_context.add_class ("header-label");
++            label_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++            var left_button = new Gtk.Button.from_icon_name ("pan-start-symbolic");
++            var center_button = new Gtk.Button.from_icon_name ("office-calendar-symbolic");
++            center_button.tooltip_text = _("Go to today's date");
++            var right_button = new Gtk.Button.from_icon_name ("pan-end-symbolic");
++
++            var box_buttons = new Gtk.Grid ();
++            box_buttons.margin_end = 6;
++            box_buttons.valign = Gtk.Align.CENTER;
++            box_buttons.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED);
++            box_buttons.add (left_button);
++            box_buttons.add (center_button);
++            box_buttons.add (right_button);
++
++            big_grid = create_big_grid ();
++
++            stack = new Gtk.Stack ();
++            stack.add (big_grid);
++            stack.show_all ();
++            stack.expand = true;
++
++            stack.notify["transition-running"].connect (() => {
++                if (stack.transition_running == false) {
++                    stack.get_children ().foreach ((child) => {
++                        if (child != stack.visible_child) {
++                            child.destroy ();
++                        }
++                    });
++                }
++            });
++
++            column_spacing = 6;
++            row_spacing = 6;
++            margin_start = margin_end = 10;
++            attach (label, 0, 0);
++            attach (box_buttons, 1, 0);
++            attach (stack, 0, 1, 2);
++
++            var model = Models.CalendarModel.get_default ();
++            model.notify["data-range"].connect (() => {
++                label.label = model.month_start.format (_("%OB, %Y"));
++
++                sync_with_model ();
++
++                selected_date = null;
++                selection_changed (selected_date);
++            });
++
++            left_button.clicked.connect (() => {
++                model.change_month (-1);
++            });
++
++            right_button.clicked.connect (() => {
++                model.change_month (1);
++            });
++
++            center_button.clicked.connect (() => {
++                show_today ();
++            });
++        }
++
++        private Gtk.Grid create_big_grid () {
++            grid = new Widgets.Grid ();
++            grid.show_all ();
++
++            grid.on_event_add.connect ((date) => {
++                show_date_in_maya (date);
++                day_double_click ();
++            });
++
++            grid.selection_changed.connect ((date) => {
++                selected_date = date;
++                selection_changed (date);
++            });
++
++            return grid;
++        }
++
++        public void show_today () {
++            var calmodel = Models.CalendarModel.get_default ();
++            var today = Util.strip_time (new GLib.DateTime.now_local ());
++            var start = Util.get_start_of_month (today);
++            selected_date = today;
++            if (!start.equal (calmodel.month_start)) {
++                calmodel.month_start = start;
++            }
++            sync_with_model ();
++
++            grid.set_focus_to_today ();
++        }
++
++        // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app.
++        public void show_date_in_maya (GLib.DateTime date) {
++            var command = "io.elementary.calendar --show-day %s".printf (date.format ("%F"));
++
++            try {
++                var appinfo = AppInfo.create_from_commandline (command, null, AppInfoCreateFlags.NONE);
++                appinfo.launch_uris (null, null);
++            } catch (GLib.Error e) {
++                var dialog = new Granite.MessageDialog.with_image_from_icon_name (
++                    _("Unable To Launch Calendar"),
++                    _("The program \"io.elementary.calendar\" may not be installed"),
++                    "dialog-error"
++                );
++                dialog.show_error_details (e.message);
++                dialog.run ();
++                dialog.destroy ();
++            }
++        }
++
++        /* Sets the calendar widgets to the date range of the model */
++        private void sync_with_model () {
++            var model = Models.CalendarModel.get_default ();
++            if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
++                grid.update_today ();
++                return; // nothing else to do
++            }
++
++            GLib.DateTime previous_first = null;
++            if (grid.grid_range != null)
++                previous_first = grid.grid_range.first_dt;
++
++            big_grid = create_big_grid ();
++            stack.add (big_grid);
++
++            grid.set_range (model.data_range, model.month_start);
++            grid.update_weeks (model.data_range.first_dt, model.num_weeks);
++
++            if (previous_first != null) {
++                if (previous_first.compare (grid.grid_range.first_dt) == -1) {
++                    stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT;
++                } else {
++                    stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT;
++                }
++            }
++
++            stack.set_visible_child (big_grid);
++        }
++    }
++}
+diff --git a/src/Widgets/EventRow.vala b/src/Widgets/EventRow.vala
+index 8e0513e..1268311 100644
+--- a/src/Widgets/EventRow.vala
++++ b/src/Widgets/EventRow.vala
+@@ -17,104 +17,106 @@
+  * Boston, MA 02110-1301 USA.
+  */
+ 
+-public class DateTime.EventRow : Gtk.ListBoxRow {
+-    public GLib.DateTime date { get; construct; }
+-    public unowned ICal.Component component { get; construct; }
+-    public unowned E.SourceCalendar cal { get; construct; }
+-
+-    public GLib.DateTime start_time { get; private set; }
+-    public GLib.DateTime? end_time { get; private set; }
+-    public bool is_allday { get; private set; default = false; }
+-
+-    private static Services.TimeManager time_manager;
+-    private static Gtk.CssProvider css_provider;
+-
+-    private Gtk.Grid grid;
+-    private Gtk.Image event_image;
+-    private Gtk.Label time_label;
+-
+-    public EventRow (GLib.DateTime date, ICal.Component component, E.Source source) {
+-        Object (
+-            component: component,
+-            date: date,
+-            cal: (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR)
+-        );
+-    }
+-
+-    static construct {
+-        css_provider = new Gtk.CssProvider ();
+-        css_provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/EventRow.css");
+-
+-        time_manager = Services.TimeManager.get_default ();
+-    }
++namespace DateTimeIndicator {
++    public class EventRow : Gtk.ListBoxRow {
++        public GLib.DateTime date { get; construct; }
++        public unowned ICal.Component component { get; construct; }
++        public unowned E.SourceCalendar cal { get; construct; }
++
++        public GLib.DateTime start_time { get; private set; }
++        public GLib.DateTime? end_time { get; private set; }
++        public bool is_allday { get; private set; default = false; }
++
++        private static Services.TimeManager time_manager;
++        private static Gtk.CssProvider css_provider;
++
++        private Gtk.Grid grid;
++        private Gtk.Image event_image;
++        private Gtk.Label time_label;
++
++        public EventRow (GLib.DateTime date, ICal.Component component, E.Source source) {
++            Object (
++                component: component,
++                date: date,
++                cal: (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR)
++            );
++        }
+ 
+-    construct {
+-        start_time = Util.ical_to_date_time (component.get_dtstart ());
+-        end_time = Util.ical_to_date_time (component.get_dtend ());
++        static construct {
++            css_provider = new Gtk.CssProvider ();
++            css_provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/EventRow.css");
+ 
+-        if (end_time != null && Util.is_the_all_day (start_time, end_time)) {
+-            is_allday = true;
++            time_manager = Services.TimeManager.get_default ();
+         }
+ 
+-        unowned string icon_name = "office-calendar-symbolic";
+-        if (end_time == null) {
+-            icon_name = "alarm-symbolic";
++        construct {
++            start_time = Util.ical_to_date_time (component.get_dtstart ());
++            end_time = Util.ical_to_date_time (component.get_dtend ());
++
++            if (end_time != null && Util.is_the_all_day (start_time, end_time)) {
++                is_allday = true;
++            }
++
++            unowned string icon_name = "office-calendar-symbolic";
++            if (end_time == null) {
++                icon_name = "alarm-symbolic";
++            }
++
++            event_image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.MENU);
++            event_image.valign = Gtk.Align.START;
++
++            unowned Gtk.StyleContext event_image_context = event_image.get_style_context ();
++            event_image_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++            var name_label = new Gtk.Label (component.get_summary ());
++            name_label.hexpand = true;
++            name_label.ellipsize = Pango.EllipsizeMode.END;
++            name_label.lines = 3;
++            name_label.max_width_chars = 30;
++            name_label.wrap = true;
++            name_label.wrap_mode = Pango.WrapMode.WORD_CHAR;
++            name_label.xalign = 0;
++
++            unowned Gtk.StyleContext name_label_context = name_label.get_style_context ();
++            name_label_context.add_class ("title");
++            name_label_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++            time_label = new Gtk.Label (null);
++            time_label.use_markup = true;
++            time_label.xalign = 0;
++            time_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
++
++            grid = new Gtk.Grid ();
++            grid.column_spacing = 6;
++            grid.margin = 3;
++            grid.margin_start = grid.margin_end = 6;
++            grid.attach (event_image, 0, 0);
++            grid.attach (name_label, 1, 0);
++            if (!is_allday) {
++                grid.attach (time_label, 1, 1);
++            }
++
++            unowned Gtk.StyleContext grid_context = grid.get_style_context ();
++            grid_context.add_class ("event");
++            grid_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++            add (grid);
++
++            set_color ();
++            cal.notify["color"].connect (set_color);
++
++            update_timelabel ();
++            time_manager.notify["is-12h"].connect (update_timelabel);
+         }
+ 
+-        event_image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.MENU);
+-        event_image.valign = Gtk.Align.START;
+-
+-        unowned Gtk.StyleContext event_image_context = event_image.get_style_context ();
+-        event_image_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-
+-        var name_label = new Gtk.Label (component.get_summary ());
+-        name_label.hexpand = true;
+-        name_label.ellipsize = Pango.EllipsizeMode.END;
+-        name_label.lines = 3;
+-        name_label.max_width_chars = 30;
+-        name_label.wrap = true;
+-        name_label.wrap_mode = Pango.WrapMode.WORD_CHAR;
+-        name_label.xalign = 0;
+-
+-        unowned Gtk.StyleContext name_label_context = name_label.get_style_context ();
+-        name_label_context.add_class ("title");
+-        name_label_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-
+-        time_label = new Gtk.Label (null);
+-        time_label.use_markup = true;
+-        time_label.xalign = 0;
+-        time_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+-
+-        grid = new Gtk.Grid ();
+-        grid.column_spacing = 6;
+-        grid.margin = 3;
+-        grid.margin_start = grid.margin_end = 6;
+-        grid.attach (event_image, 0, 0);
+-        grid.attach (name_label, 1, 0);
+-        if (!is_allday) {
+-            grid.attach (time_label, 1, 1);
++        private void update_timelabel () {
++            var time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h);
++            time_label.label = "<small>%s – %s</small>".printf (start_time.format (time_format), end_time.format (time_format));
+         }
+ 
+-        unowned Gtk.StyleContext grid_context = grid.get_style_context ();
+-        grid_context.add_class ("event");
+-        grid_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-
+-        add (grid);
+-
+-        set_color ();
+-        cal.notify["color"].connect (set_color);
+-
+-        update_timelabel ();
+-        time_manager.notify["is-12h"].connect (update_timelabel);
+-    }
+-
+-    private void update_timelabel () {
+-        var time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h);
+-        time_label.label = "<small>%s – %s</small>".printf (start_time.format (time_format), end_time.format (time_format));
+-    }
+-
+-    private void set_color () {
+-        Util.set_event_calendar_color (cal, grid);
+-        Util.set_event_calendar_color (cal, event_image);
++        private void set_color () {
++            Util.set_event_calendar_color (cal, grid);
++            Util.set_event_calendar_color (cal, event_image);
++        }
+     }
+ }
+diff --git a/src/Widgets/calendar/Grid.vala b/src/Widgets/Grid.vala
+similarity index 95%
+rename from src/Widgets/calendar/Grid.vala
+rename to src/Widgets/Grid.vala
+index 2b48636..165d11d 100644
+--- a/src/Widgets/calendar/Grid.vala
++++ b/src/Widgets/Grid.vala
+@@ -20,11 +20,11 @@
+  *              Corentin Noël <corentin@elementaryos.org>
+  */
+ 
+-namespace DateTime.Widgets {
++namespace DateTimeIndicator {
+ /**
+  * Represents the entire date grid as a table.
+  */
+-    public class Grid : Gtk.Grid {
++    public class Widgets.Grid : Gtk.Grid {
+         public Util.DateRange grid_range { get; private set; }
+ 
+         /*
+@@ -59,7 +59,7 @@ namespace DateTime.Widgets {
+             hexpand = true;
+             attach (week_sep_revealer, 1, 1, 1, 6);
+ 
+-            DateTime.Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT);
++            Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT);
+ 
+             data = new Gee.HashMap<uint, GridDay> ();
+             events |= Gdk.EventMask.SCROLL_MASK;
+@@ -77,7 +77,7 @@ namespace DateTime.Widgets {
+             day.set_selected (true);
+             day.set_state_flags (Gtk.StateFlags.FOCUSED, false);
+             selection_changed (selected_date);
+-            var calmodel = CalendarModel.get_default ();
++            var calmodel = Models.CalendarModel.get_default ();
+             var date_month = selected_date.get_month () - calmodel.month_start.get_month ();
+             var date_year = selected_date.get_year () - calmodel.month_start.get_year ();
+ 
+@@ -127,7 +127,7 @@ namespace DateTime.Widgets {
+             /* Create new widgets for the new range */
+ 
+             var date = Util.strip_time (today);
+-            date = date.add_days (CalendarModel.get_default ().week_starts_on - date.get_day_of_week ());
++            date = date.add_days (Models.CalendarModel.get_default ().week_starts_on - date.get_day_of_week ());
+             foreach (var label in header_labels) {
+                 label.label = date.format ("%a");
+                 date = date.add_days (1);
+@@ -221,7 +221,7 @@ namespace DateTime.Widgets {
+                 week_labels[c].add (week_label);
+                 week_labels[c].show_all ();
+ 
+-                DateTime.Indicator.settings.bind ("show-weeks", week_labels[c], "reveal-child", GLib.SettingsBindFlags.DEFAULT);
++                Indicator.settings.bind ("show-weeks", week_labels[c], "reveal-child", GLib.SettingsBindFlags.DEFAULT);
+ 
+                 attach (week_labels[c], 0, c + 1);
+ 
+diff --git a/src/Widgets/GridDay.vala b/src/Widgets/GridDay.vala
+new file mode 100644
+index 0000000..8c44443
+--- /dev/null
++++ b/src/Widgets/GridDay.vala
+@@ -0,0 +1,180 @@
++// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
++/*-
++ * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io)
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ *
++ * Authored by: Maxwell Barvian
++ *              Corentin Noël <corentin@elementaryos.org>
++ */
++
++namespace DateTimeIndicator {
++/**
++ * Represents a single day on the grid.
++ */
++    public class Widgets.GridDay : Gtk.EventBox {
++        /*
++         * Event emitted when the day is double clicked or the ENTER key is pressed.
++         */
++        public signal void on_event_add (GLib.DateTime date);
++
++        public GLib.DateTime date { get; construct set; }
++
++        private static Gtk.CssProvider provider;
++        private static Models.CalendarModel model;
++
++        private Gee.HashMap<string, Gtk.Widget> event_dots;
++        private Gtk.Grid event_grid;
++        private Gtk.Label label;
++        private bool valid_grab = false;
++
++        public GridDay (GLib.DateTime date) {
++            Object (date: date);
++        }
++
++        static construct {
++            model = Models.CalendarModel.get_default ();
++
++            provider = new Gtk.CssProvider ();
++            provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/GridDay.css");
++        }
++
++        construct {
++            unowned Gtk.StyleContext style_context = get_style_context ();
++            style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++            style_context.add_class ("circular");
++
++            label = new Gtk.Label (null);
++
++            event_grid = new Gtk.Grid ();
++            event_grid.halign = Gtk.Align.CENTER;
++            event_grid.height_request = 6;
++
++            var grid = new Gtk.Grid ();
++            grid.halign = grid.valign = Gtk.Align.CENTER;
++            grid.attach (label, 0, 0);
++            grid.attach (event_grid, 0, 1);
++
++            can_focus = true;
++            events |= Gdk.EventMask.BUTTON_PRESS_MASK;
++            events |= Gdk.EventMask.KEY_PRESS_MASK;
++            events |= Gdk.EventMask.SMOOTH_SCROLL_MASK;
++            set_size_request (35, 35);
++            halign = Gtk.Align.CENTER;
++            hexpand = true;
++            add (grid);
++            show_all ();
++
++            // Signals and handlers
++            button_press_event.connect (on_button_press);
++            key_press_event.connect (on_key_press);
++            scroll_event.connect ((event) => {return Util.on_scroll_event (event);});
++
++            notify["date"].connect (() => {
++                label.label = date.get_day_of_month ().to_string ();
++            });
++
++            event_dots = new Gee.HashMap<string, Gtk.Widget> ();
++
++            model.events_added.connect (add_event_dots);
++            model.events_removed.connect (remove_event_dots);
++        }
++
++        private void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            foreach (var component in events) {
++                if (event_dots.size >= 3) {
++                    return;
++                }
++
++                if (Util.calcomp_is_on_day (component, date)) {
++                    unowned ICal.Component ical = component.get_icalcomponent ();
++
++                    var event_uid = ical.get_uid ();
++                    if (!event_dots.has_key (event_uid)) {
++                        var event_dot = new Gtk.Image ();
++                        event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
++                        event_dot.pixel_size = 6;
++
++                        unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
++                        style_context.add_class (Granite.STYLE_CLASS_ACCENT);
++                        style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++                        var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++                        Util.set_event_calendar_color (source_calendar, event_dot);
++
++                        event_dots[event_uid] = event_dot;
++
++                        event_grid.add (event_dot);
++                    }
++                }
++            }
++
++            event_grid.show_all ();
++        }
++
++        private void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            foreach (var component in events) {
++                unowned ICal.Component ical = component.get_icalcomponent ();
++                var event_uid = ical.get_uid ();
++                var dot = event_dots[event_uid];
++                if (dot != null) {
++                    dot.destroy ();
++                    event_dots.remove (event_uid);
++                }
++            }
++        }
++
++        public void set_selected (bool selected) {
++            if (selected) {
++                set_state_flags (Gtk.StateFlags.SELECTED, true);
++            } else {
++                set_state_flags (Gtk.StateFlags.NORMAL, true);
++            }
++        }
++
++        public void grab_focus_force () {
++            valid_grab = true;
++            grab_focus ();
++        }
++
++        public override void grab_focus () {
++            if (valid_grab) {
++                base.grab_focus ();
++                valid_grab = false;
++            }
++        }
++
++        public void sensitive_container (bool sens) {
++            label.sensitive = sens;
++            event_grid.sensitive = sens;
++        }
++
++        private bool on_button_press (Gdk.EventButton event) {
++            if (event.type == Gdk.EventType.2BUTTON_PRESS && event.button == Gdk.BUTTON_PRIMARY)
++                on_event_add (date);
++            valid_grab = true;
++            grab_focus ();
++            return false;
++        }
++
++        private bool on_key_press (Gdk.EventKey event) {
++            if (event.keyval == Gdk.keyval_from_name ("Return") ) {
++                on_event_add (date);
++                return true;
++            }
++
++            return false;
++        }
++    }
++}
+diff --git a/src/Widgets/PanelLabel.vala b/src/Widgets/PanelLabel.vala
+index f253f9b..dff9a21 100644
+--- a/src/Widgets/PanelLabel.vala
++++ b/src/Widgets/PanelLabel.vala
+@@ -17,55 +17,57 @@
+  * Boston, MA 02110-1301 USA.
+  */
+ 
+-public class DateTime.Widgets.PanelLabel : Gtk.Grid {
+-    private Gtk.Label date_label;
+-    private Gtk.Label time_label;
+-    private Services.TimeManager time_manager;
++namespace DateTimeIndicator {
++    public class Widgets.PanelLabel : Gtk.Grid {
++        private Gtk.Label date_label;
++        private Gtk.Label time_label;
++        private Services.TimeManager time_manager;
+ 
+-    public string clock_format { get; set; }
+-    public bool clock_show_seconds { get; set; }
+-    public bool clock_show_weekday { get; set; }
++        public string clock_format { get; set; }
++        public bool clock_show_seconds { get; set; }
++        public bool clock_show_weekday { get; set; }
+ 
+-    construct {
+-        date_label = new Gtk.Label (null);
+-        date_label.margin_end = 12;
++        construct {
++            date_label = new Gtk.Label (null);
++            date_label.margin_end = 12;
+ 
+-        var date_revealer = new Gtk.Revealer ();
+-        date_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT;
+-        date_revealer.add (date_label);
++            var date_revealer = new Gtk.Revealer ();
++            date_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT;
++            date_revealer.add (date_label);
+ 
+-        time_label = new Gtk.Label (null);
++            time_label = new Gtk.Label (null);
+ 
+-        valign = Gtk.Align.CENTER;
+-        add (date_revealer);
+-        add (time_label);
++            valign = Gtk.Align.CENTER;
++            add (date_revealer);
++            add (time_label);
+ 
+-        var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
+-        clock_settings.bind ("clock-format", this, "clock-format", SettingsBindFlags.DEFAULT);
+-        clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT);
+-        clock_settings.bind ("clock-show-date", date_revealer, "reveal_child", SettingsBindFlags.DEFAULT);
+-        clock_settings.bind ("clock-show-weekday", this, "clock-show-weekday", SettingsBindFlags.DEFAULT);
++            var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime");
++            clock_settings.bind ("clock-format", this, "clock-format", SettingsBindFlags.DEFAULT);
++            clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT);
++            clock_settings.bind ("clock-show-date", date_revealer, "reveal_child", SettingsBindFlags.DEFAULT);
++            clock_settings.bind ("clock-show-weekday", this, "clock-show-weekday", SettingsBindFlags.DEFAULT);
+ 
+-        notify.connect (() => {
+-            update_labels ();
+-        });
++            notify.connect (() => {
++                update_labels ();
++            });
+ 
+-        time_manager = Services.TimeManager.get_default ();
+-        time_manager.minute_changed.connect (update_labels);
+-        time_manager.notify["is-12h"].connect (update_labels);
+-    }
+-
+-    private void update_labels () {
+-        string date_format;
+-        if (clock_format == "ISO8601") {
+-            date_format = "%F";
+-        } else {
+-            date_format = Granite.DateTime.get_default_date_format (clock_show_weekday, true, false);
++            time_manager = Services.TimeManager.get_default ();
++            time_manager.minute_changed.connect (update_labels);
++            time_manager.notify["is-12h"].connect (update_labels);
+         }
+ 
+-        date_label.label = time_manager.format (date_format);
++        private void update_labels () {
++            string date_format;
++            if (clock_format == "ISO8601") {
++                date_format = "%F";
++            } else {
++                date_format = Granite.DateTime.get_default_date_format (clock_show_weekday, true, false);
++            }
+ 
+-        string time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h, clock_show_seconds);
+-        time_label.label = time_manager.format (time_format);
++            date_label.label = time_manager.format (date_format);
++
++            string time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h, clock_show_seconds);
++            time_label.label = time_manager.format (time_format);
++        }
+     }
+ }
+diff --git a/src/Widgets/calendar/CalendarView.vala b/src/Widgets/calendar/CalendarView.vala
+deleted file mode 100644
+index ef3f8f9..0000000
+--- a/src/Widgets/calendar/CalendarView.vala
++++ /dev/null
+@@ -1,183 +0,0 @@
+-/*-
+- * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io)
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation, either version 3 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+- *
+- * Authored by: Maxwell Barvian
+- *              Corentin Noël <corentin@elementaryos.org>
+- */
+-
+-public class DateTime.Widgets.CalendarView : Gtk.Grid {
+-    public signal void day_double_click ();
+-    public signal void event_updates ();
+-    public signal void selection_changed (GLib.DateTime? new_date);
+-
+-    public GLib.DateTime? selected_date { get; private set; }
+-
+-    private Grid grid;
+-    private Gtk.Stack stack;
+-    private Gtk.Grid big_grid;
+-
+-    construct {
+-        var label = new Gtk.Label (new GLib.DateTime.now_local ().format (_("%OB, %Y")));
+-        label.hexpand = true;
+-        label.margin_start = 6;
+-        label.xalign = 0;
+-        label.width_chars = 13;
+-
+-        var provider = new Gtk.CssProvider ();
+-        provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/ControlHeader.css");
+-
+-        var label_style_context = label.get_style_context ();
+-        label_style_context.add_class ("header-label");
+-        label_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-
+-        var left_button = new Gtk.Button.from_icon_name ("pan-start-symbolic");
+-        var center_button = new Gtk.Button.from_icon_name ("office-calendar-symbolic");
+-        center_button.tooltip_text = _("Go to today's date");
+-        var right_button = new Gtk.Button.from_icon_name ("pan-end-symbolic");
+-
+-        var box_buttons = new Gtk.Grid ();
+-        box_buttons.margin_end = 6;
+-        box_buttons.valign = Gtk.Align.CENTER;
+-        box_buttons.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED);
+-        box_buttons.add (left_button);
+-        box_buttons.add (center_button);
+-        box_buttons.add (right_button);
+-
+-        big_grid = create_big_grid ();
+-
+-        stack = new Gtk.Stack ();
+-        stack.add (big_grid);
+-        stack.show_all ();
+-        stack.expand = true;
+-
+-        stack.notify["transition-running"].connect (() => {
+-            if (stack.transition_running == false) {
+-                stack.get_children ().foreach ((child) => {
+-                    if (child != stack.visible_child) {
+-                        child.destroy ();
+-                    }
+-                });
+-            }
+-        });
+-
+-        column_spacing = 6;
+-        row_spacing = 6;
+-        margin_start = margin_end = 10;
+-        attach (label, 0, 0);
+-        attach (box_buttons, 1, 0);
+-        attach (stack, 0, 1, 2);
+-
+-        var model = CalendarModel.get_default ();
+-        model.notify["data-range"].connect (() => {
+-            label.label = model.month_start.format (_("%OB, %Y"));
+-
+-            sync_with_model ();
+-
+-            selected_date = null;
+-            selection_changed (selected_date);
+-        });
+-
+-        left_button.clicked.connect (() => {
+-            model.change_month (-1);
+-        });
+-
+-        right_button.clicked.connect (() => {
+-            model.change_month (1);
+-        });
+-
+-        center_button.clicked.connect (() => {
+-            show_today ();
+-        });
+-    }
+-
+-    private Gtk.Grid create_big_grid () {
+-        grid = new DateTime.Widgets.Grid ();
+-        grid.show_all ();
+-
+-        grid.on_event_add.connect ((date) => {
+-            show_date_in_maya (date);
+-            day_double_click ();
+-        });
+-
+-        grid.selection_changed.connect ((date) => {
+-            selected_date = date;
+-            selection_changed (date);
+-        });
+-
+-        return grid;
+-    }
+-
+-    public void show_today () {
+-        var calmodel = CalendarModel.get_default ();
+-        var today = Util.strip_time (new GLib.DateTime.now_local ());
+-        var start = Util.get_start_of_month (today);
+-        selected_date = today;
+-        if (!start.equal (calmodel.month_start)) {
+-            calmodel.month_start = start;
+-        }
+-        sync_with_model ();
+-
+-        grid.set_focus_to_today ();
+-    }
+-
+-    // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app.
+-    public void show_date_in_maya (GLib.DateTime date) {
+-        var command = "io.elementary.calendar --show-day %s".printf (date.format ("%F"));
+-
+-        try {
+-            var appinfo = AppInfo.create_from_commandline (command, null, AppInfoCreateFlags.NONE);
+-            appinfo.launch_uris (null, null);
+-        } catch (GLib.Error e) {
+-            var dialog = new Granite.MessageDialog.with_image_from_icon_name (
+-                _("Unable To Launch Calendar"),
+-                _("The program \"io.elementary.calendar\" may not be installed"),
+-                "dialog-error"
+-            );
+-            dialog.show_error_details (e.message);
+-            dialog.run ();
+-            dialog.destroy ();
+-        }
+-    }
+-
+-    /* Sets the calendar widgets to the date range of the model */
+-    private void sync_with_model () {
+-        var model = CalendarModel.get_default ();
+-        if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
+-            grid.update_today ();
+-            return; // nothing else to do
+-        }
+-
+-        GLib.DateTime previous_first = null;
+-        if (grid.grid_range != null)
+-            previous_first = grid.grid_range.first_dt;
+-
+-        big_grid = create_big_grid ();
+-        stack.add (big_grid);
+-
+-        grid.set_range (model.data_range, model.month_start);
+-        grid.update_weeks (model.data_range.first_dt, model.num_weeks);
+-
+-        if (previous_first != null) {
+-            if (previous_first.compare (grid.grid_range.first_dt) == -1) {
+-                stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT;
+-            } else {
+-                stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT;
+-            }
+-        }
+-
+-        stack.set_visible_child (big_grid);
+-    }
+-}
+diff --git a/src/Widgets/calendar/GridDay.vala b/src/Widgets/calendar/GridDay.vala
+deleted file mode 100644
+index a9b5a28..0000000
+--- a/src/Widgets/calendar/GridDay.vala
++++ /dev/null
+@@ -1,178 +0,0 @@
+-// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
+-/*-
+- * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io)
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation, either version 3 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+- *
+- * Authored by: Maxwell Barvian
+- *              Corentin Noël <corentin@elementaryos.org>
+- */
+-
+-/**
+- * Represents a single day on the grid.
+- */
+-public class DateTime.Widgets.GridDay : Gtk.EventBox {
+-    /*
+-     * Event emitted when the day is double clicked or the ENTER key is pressed.
+-     */
+-    public signal void on_event_add (GLib.DateTime date);
+-
+-    public GLib.DateTime date { get; construct set; }
+-
+-    private static Gtk.CssProvider provider;
+-    private static Widgets.CalendarModel model;
+-
+-    private Gee.HashMap<string, Gtk.Widget> event_dots;
+-    private Gtk.Grid event_grid;
+-    private Gtk.Label label;
+-    private bool valid_grab = false;
+-
+-    public GridDay (GLib.DateTime date) {
+-        Object (date: date);
+-    }
+-
+-    static construct {
+-        model = Widgets.CalendarModel.get_default ();
+-
+-        provider = new Gtk.CssProvider ();
+-        provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/GridDay.css");
+-    }
+-
+-    construct {
+-        unowned Gtk.StyleContext style_context = get_style_context ();
+-        style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-        style_context.add_class ("circular");
+-
+-        label = new Gtk.Label (null);
+-
+-        event_grid = new Gtk.Grid ();
+-        event_grid.halign = Gtk.Align.CENTER;
+-        event_grid.height_request = 6;
+-
+-        var grid = new Gtk.Grid ();
+-        grid.halign = grid.valign = Gtk.Align.CENTER;
+-        grid.attach (label, 0, 0);
+-        grid.attach (event_grid, 0, 1);
+-
+-        can_focus = true;
+-        events |= Gdk.EventMask.BUTTON_PRESS_MASK;
+-        events |= Gdk.EventMask.KEY_PRESS_MASK;
+-        events |= Gdk.EventMask.SMOOTH_SCROLL_MASK;
+-        set_size_request (35, 35);
+-        halign = Gtk.Align.CENTER;
+-        hexpand = true;
+-        add (grid);
+-        show_all ();
+-
+-        // Signals and handlers
+-        button_press_event.connect (on_button_press);
+-        key_press_event.connect (on_key_press);
+-        scroll_event.connect ((event) => {return Util.on_scroll_event (event);});
+-
+-        notify["date"].connect (() => {
+-            label.label = date.get_day_of_month ().to_string ();
+-        });
+-
+-        event_dots = new Gee.HashMap<string, Gtk.Widget> ();
+-
+-        model.events_added.connect (add_event_dots);
+-        model.events_removed.connect (remove_event_dots);
+-    }
+-
+-    private void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-        foreach (var component in events) {
+-            if (event_dots.size >= 3) {
+-                return;
+-            }
+-
+-            if (Util.calcomp_is_on_day (component, date)) {
+-                unowned ICal.Component ical = component.get_icalcomponent ();
+-
+-                var event_uid = ical.get_uid ();
+-                if (!event_dots.has_key (event_uid)) {
+-                    var event_dot = new Gtk.Image ();
+-                    event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
+-                    event_dot.pixel_size = 6;
+-
+-                    unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
+-                    style_context.add_class (Granite.STYLE_CLASS_ACCENT);
+-                    style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+-
+-                    var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+-                    Util.set_event_calendar_color (source_calendar, event_dot);
+-
+-                    event_dots[event_uid] = event_dot;
+-
+-                    event_grid.add (event_dot);
+-                }
+-            }
+-        }
+-
+-        event_grid.show_all ();
+-    }
+-
+-    private void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-        foreach (var component in events) {
+-            unowned ICal.Component ical = component.get_icalcomponent ();
+-            var event_uid = ical.get_uid ();
+-            var dot = event_dots[event_uid];
+-            if (dot != null) {
+-                dot.destroy ();
+-                event_dots.remove (event_uid);
+-            }
+-        }
+-    }
+-
+-    public void set_selected (bool selected) {
+-        if (selected) {
+-            set_state_flags (Gtk.StateFlags.SELECTED, true);
+-        } else {
+-            set_state_flags (Gtk.StateFlags.NORMAL, true);
+-        }
+-    }
+-
+-    public void grab_focus_force () {
+-        valid_grab = true;
+-        grab_focus ();
+-    }
+-
+-    public override void grab_focus () {
+-        if (valid_grab) {
+-            base.grab_focus ();
+-            valid_grab = false;
+-        }
+-    }
+-
+-    public void sensitive_container (bool sens) {
+-        label.sensitive = sens;
+-        event_grid.sensitive = sens;
+-    }
+-
+-    private bool on_button_press (Gdk.EventButton event) {
+-        if (event.type == Gdk.EventType.2BUTTON_PRESS && event.button == Gdk.BUTTON_PRIMARY)
+-            on_event_add (date);
+-        valid_grab = true;
+-        grab_focus ();
+-        return false;
+-    }
+-
+-    private bool on_key_press (Gdk.EventKey event) {
+-        if (event.keyval == Gdk.keyval_from_name ("Return") ) {
+-            on_event_add (date);
+-            return true;
+-        }
+-
+-        return false;
+-    }
+-}
+
+From 11f11073d74dac1d831560c3a92687531aaf846e Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Thu, 9 Apr 2020 20:46:31 +0300
+Subject: [PATCH 2/8] Events list moved to a separate file
+
+---
+ meson.build                    |   1 +
+ src/Indicator.vala             | 113 +++------------------------------
+ src/Widgets/EventsListBox.vala | 102 +++++++++++++++++++++++++++++
+ 3 files changed, 113 insertions(+), 103 deletions(-)
+ create mode 100644 src/Widgets/EventsListBox.vala
+
+diff --git a/meson.build b/meson.build
+index b44c5bd..1b52276 100644
+--- a/meson.build
++++ b/meson.build
+@@ -46,6 +46,7 @@ shared_module(
+     'src/Models/CalendarModel.vala',
+     'src/Widgets/CalendarView.vala',
+     'src/Widgets/EventRow.vala',
++    'src/Widgets/EventsListBox.vala',
+     'src/Widgets/Grid.vala',
+     'src/Widgets/GridDay.vala',
+     'src/Widgets/PanelLabel.vala',
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index b712c12..6a8d001 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -22,9 +22,9 @@ namespace DateTimeIndicator {
+         public static GLib.Settings settings;
+ 
+         private Widgets.PanelLabel panel_label;
+-        private Gtk.Grid main_grid;
+         private Widgets.CalendarView calendar;
+-        private Gtk.ListBox event_listbox;
++        private Widgets.EventsListBox event_listbox;
++        private Gtk.Grid main_grid;
+         private uint update_events_idle_source = 0;
+ 
+         public Indicator () {
+@@ -56,24 +56,7 @@ namespace DateTimeIndicator {
+                 calendar = new Widgets.CalendarView ();
+                 calendar.margin_bottom = 6;
+ 
+-                var placeholder_label = new Gtk.Label (_("No Events on This Day"));
+-                placeholder_label.wrap = true;
+-                placeholder_label.wrap_mode = Pango.WrapMode.WORD;
+-                placeholder_label.margin_start = 12;
+-                placeholder_label.margin_end = 12;
+-                placeholder_label.max_width_chars = 20;
+-                placeholder_label.justify = Gtk.Justification.CENTER;
+-                placeholder_label.show_all ();
+-
+-                var placeholder_style_context = placeholder_label.get_style_context ();
+-                placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+-                placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL);
+-
+-                event_listbox = new Gtk.ListBox ();
+-                event_listbox.selection_mode = Gtk.SelectionMode.NONE;
+-                event_listbox.set_header_func (header_update_func);
+-                event_listbox.set_placeholder (placeholder_label);
+-                event_listbox.set_sort_func (sort_function);
++                event_listbox = new Widgets.EventsListBox ();
+ 
+                 var scrolled_window = new Gtk.ScrolledWindow (null, null);
+                 scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
+@@ -84,11 +67,11 @@ namespace DateTimeIndicator {
+ 
+                 main_grid = new Gtk.Grid ();
+                 main_grid.margin_top = 12;
+-                main_grid.attach (calendar, 0, 0);
+-                main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0);
+-                main_grid.attach (scrolled_window, 2, 0);
+-                main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3);
+-                main_grid.attach (settings_button, 0, 3, 3);
++                main_grid.attach (calendar,                                     0, 0);
++                main_grid.attach (new Wingpanel.Widgets.Separator (),           0, 1);
++                main_grid.attach (settings_button,                              0, 2);
++                main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 3);
++                main_grid.attach (scrolled_window,                              2, 0, 1, 3);
+ 
+                 var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
+                 size_group.add_widget (calendar);
+@@ -119,52 +102,6 @@ namespace DateTimeIndicator {
+             return main_grid;
+         }
+ 
+-        private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) {
+-            var row = (EventRow) lbrow;
+-            if (lbbefore != null) {
+-                var before = (EventRow) lbbefore;
+-                if (row.is_allday == before.is_allday) {
+-                    row.set_header (null);
+-                    return;
+-                }
+-
+-                if (row.is_allday != before.is_allday) {
+-                    var header_label = new Granite.HeaderLabel (_("During the Day"));
+-                    header_label.margin_start = header_label.margin_end = 6;
+-
+-                    row.set_header (header_label);
+-                    return;
+-                }
+-            } else {
+-                if (row.is_allday) {
+-                    var allday_header = new Granite.HeaderLabel (_("All Day"));
+-                    allday_header.margin_start = allday_header.margin_end = 6;
+-
+-                    row.set_header (allday_header);
+-                }
+-                return;
+-            }
+-        }
+-
+-        [CCode (instance_pos = -1)]
+-        private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) {
+-            var e1 = (EventRow) child1;
+-            var e2 = (EventRow) child2;
+-
+-            if (e1.start_time.compare (e2.start_time) != 0) {
+-                return e1.start_time.compare (e2.start_time);
+-            }
+-
+-            // If they have the same date, sort them wholeday first
+-            if (e1.is_allday) {
+-                return -1;
+-            } else if (e2.is_allday) {
+-                return 1;
+-            }
+-
+-            return 0;
+-        }
+-
+         private void update_events_model (E.Source source, Gee.Collection<ECal.Component> events) {
+             idle_update_events ();
+         }
+@@ -174,42 +111,12 @@ namespace DateTimeIndicator {
+                 GLib.Source.remove (update_events_idle_source);
+             }
+ 
+-            update_events_idle_source = GLib.Idle.add (update_events);
+-        }
+-
+-        private bool update_events () {
+-            foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) {
+-                widget.destroy ();
+-            }
++            update_events_idle_source = GLib.Idle.add (() => {
++                event_listbox.update_events (calendar.selected_date);
+ 
+-            if (calendar.selected_date == null) {
+                 update_events_idle_source = 0;
+                 return GLib.Source.REMOVE;
+-            }
+-
+-            var date = calendar.selected_date;
+-
+-            var model = Models.CalendarModel.get_default ();
+-
+-            var events_on_day = new Gee.TreeMap<string, EventRow> ();
+-
+-            model.source_events.@foreach ((source, component_map) => {
+-                foreach (var comp in component_map.get_values ()) {
+-                    if (Util.calcomp_is_on_day (comp, date)) {
+-                        unowned ICal.Component ical = comp.get_icalcomponent ();
+-                        var event_uid = ical.get_uid ();
+-                        if (!events_on_day.has_key (event_uid)) {
+-                            events_on_day[event_uid] = new EventRow (date, ical, source);
+-
+-                            event_listbox.add (events_on_day[event_uid]);
+-                        }
+-                    }
+-                }
+             });
+-
+-            event_listbox.show_all ();
+-            update_events_idle_source = 0;
+-            return GLib.Source.REMOVE;
+         }
+ 
+         public override void opened () {
+diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala
+new file mode 100644
+index 0000000..547e4c5
+--- /dev/null
++++ b/src/Widgets/EventsListBox.vala
+@@ -0,0 +1,102 @@
++namespace DateTimeIndicator {
++    public class Widgets.EventsListBox : Gtk.ListBox {
++
++        public EventsListBox () {
++            selection_mode = Gtk.SelectionMode.NONE;
++
++            var placeholder_label = new Gtk.Label (_("No Events on This Day"));
++            placeholder_label.wrap = true;
++            placeholder_label.wrap_mode = Pango.WrapMode.WORD;
++            placeholder_label.margin_start = 12;
++            placeholder_label.margin_end = 12;
++            placeholder_label.max_width_chars = 20;
++            placeholder_label.justify = Gtk.Justification.CENTER;
++            placeholder_label.show_all ();
++
++            var placeholder_style_context = placeholder_label.get_style_context ();
++            placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL);
++            placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL);
++
++            set_header_func (header_update_func);
++            set_placeholder (placeholder_label);
++            set_sort_func (sort_function);
++        }
++
++        public void update_events (GLib.DateTime? selected_date) {
++            foreach (unowned Gtk.Widget widget in get_children ()) {
++                widget.destroy ();
++            }
++
++            if (selected_date == null) {
++                return;
++            }
++
++            var model = Models.CalendarModel.get_default ();
++
++            var events_on_day = new Gee.TreeMap<string, EventRow> ();
++
++            model.source_events.@foreach ((source, component_map) => {
++                foreach (var comp in component_map.get_values ()) {
++                    if (Util.calcomp_is_on_day (comp, selected_date)) {
++                        unowned ICal.Component ical = comp.get_icalcomponent ();
++                        var event_uid = ical.get_uid ();
++                        if (!events_on_day.has_key (event_uid)) {
++                            events_on_day[event_uid] = new EventRow (selected_date, ical, source);
++
++                            add (events_on_day[event_uid]);
++                        }
++                    }
++                }
++            });
++
++            show_all ();
++            return;
++        }
++
++        private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) {
++            var row = (EventRow) lbrow;
++            if (lbbefore != null) {
++                var before = (EventRow) lbbefore;
++                if (row.is_allday == before.is_allday) {
++                    row.set_header (null);
++                    return;
++                }
++
++                if (row.is_allday != before.is_allday) {
++                    var header_label = new Granite.HeaderLabel (_("During the Day"));
++                    header_label.margin_start = header_label.margin_end = 6;
++
++                    row.set_header (header_label);
++                    return;
++                }
++            } else {
++                if (row.is_allday) {
++                    var allday_header = new Granite.HeaderLabel (_("All Day"));
++                    allday_header.margin_start = allday_header.margin_end = 6;
++
++                    row.set_header (allday_header);
++                }
++                return;
++            }
++        }
++
++        [CCode (instance_pos = -1)]
++        private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) {
++            var e1 = (EventRow) child1;
++            var e2 = (EventRow) child2;
++
++            if (e1.start_time.compare (e2.start_time) != 0) {
++                return e1.start_time.compare (e2.start_time);
++            }
++
++            // If they have the same date, sort them wholeday first
++            if (e1.is_allday) {
++                return -1;
++            } else if (e2.is_allday) {
++                return 1;
++            }
++
++            return 0;
++        }
++    }
++}
+
+From 262d91676f78f031bcfbff637344e52c63ab89bd Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Sat, 11 Apr 2020 21:56:33 +0300
+Subject: [PATCH 3/8] added event manager
+
+---
+ meson.build                     |   1 +
+ src/Indicator.vala              |  38 ++++--
+ src/Models/CalendarModel.vala   | 224 +------------------------------
+ src/Services/EventsManager.vala | 226 ++++++++++++++++++++++++++++++++
+ src/Util/Util.vala              |  57 ++------
+ src/Widgets/CalendarView.vala   |   9 ++
+ src/Widgets/EventsListBox.vala  |   7 +-
+ src/Widgets/Grid.vala           |  31 +++++
+ src/Widgets/GridDay.vala        | 111 +++++++++++-----
+ 9 files changed, 385 insertions(+), 319 deletions(-)
+ create mode 100644 src/Services/EventsManager.vala
+
+diff --git a/meson.build b/meson.build
+index 1b52276..e348e3d 100644
+--- a/meson.build
++++ b/meson.build
+@@ -50,6 +50,7 @@ shared_module(
+     'src/Widgets/Grid.vala',
+     'src/Widgets/GridDay.vala',
+     'src/Widgets/PanelLabel.vala',
++    'src/Services/EventsManager.vala',
+     'src/Services/TimeManager.vala',
+     dependencies: [
+         dependency('glib-2.0'),
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index 6a8d001..bf4358f 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -24,9 +24,14 @@ namespace DateTimeIndicator {
+         private Widgets.PanelLabel panel_label;
+         private Widgets.CalendarView calendar;
+         private Widgets.EventsListBox event_listbox;
++
++        private Services.EventsManager event_manager;
++
+         private Gtk.Grid main_grid;
+         private uint update_events_idle_source = 0;
+ 
++        private bool opened_widget = false;
++
+         public Indicator () {
+             Object (
+                 code_name: Wingpanel.Indicator.DATETIME,
+@@ -56,10 +61,22 @@ namespace DateTimeIndicator {
+                 calendar = new Widgets.CalendarView ();
+                 calendar.margin_bottom = 6;
+ 
++                event_manager = new Services.EventsManager ();
++                event_manager.events_updated.connect (update_events_model);
++                event_manager.events_added.connect ((source, events) => {
++                    calendar.add_event_dots (source, events);
++                    update_events_model (source, events);
++                });
++                event_manager.events_removed.connect ((source, events) => {
++                    calendar.remove_event_dots (source, events);
++                    update_events_model (source, events);
++                });
++
+                 event_listbox = new Widgets.EventsListBox ();
+ 
+                 var scrolled_window = new Gtk.ScrolledWindow (null, null);
+                 scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
++                scrolled_window.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
+                 scrolled_window.add (event_listbox);
+ 
+                 var settings_button = new Gtk.ModelButton ();
+@@ -90,6 +107,12 @@ namespace DateTimeIndicator {
+                     close ();
+                 });
+ 
++                var model = Models.CalendarModel.get_default ();
++                model.notify["month-start"].connect (() => {
++                    model.compute_ranges ();
++                    event_manager.load_all_sources ();
++                });
++
+                 settings_button.clicked.connect (() => {
+                     try {
+                         AppInfo.launch_default_for_uri ("settings://time", null);
+@@ -103,7 +126,9 @@ namespace DateTimeIndicator {
+         }
+ 
+         private void update_events_model (E.Source source, Gee.Collection<ECal.Component> events) {
+-            idle_update_events ();
++            if (opened_widget) {
++                idle_update_events ();
++            }
+         }
+ 
+         private void idle_update_events () {
+@@ -112,7 +137,7 @@ namespace DateTimeIndicator {
+             }
+ 
+             update_events_idle_source = GLib.Idle.add (() => {
+-                event_listbox.update_events (calendar.selected_date);
++                event_listbox.update_events (calendar.selected_date, event_manager.source_events);
+ 
+                 update_events_idle_source = 0;
+                 return GLib.Source.REMOVE;
+@@ -122,18 +147,15 @@ namespace DateTimeIndicator {
+         public override void opened () {
+             calendar.show_today ();
+ 
+-            Models.CalendarModel.get_default ().events_added.connect (update_events_model);
+-            Models.CalendarModel.get_default ().events_updated.connect (update_events_model);
+-            Models.CalendarModel.get_default ().events_removed.connect (update_events_model);
++            opened_widget = true;
+         }
+ 
+         public override void closed () {
+-            Models.CalendarModel.get_default ().events_added.disconnect (update_events_model);
+-            Models.CalendarModel.get_default ().events_updated.disconnect (update_events_model);
+-            Models.CalendarModel.get_default ().events_removed.disconnect (update_events_model);
++            opened_widget = false;
+         }
+     }
+ }
++
+ public Wingpanel.Indicator get_indicator (Module module) {
+     debug ("Activating DateTime Indicator");
+     var indicator = new DateTimeIndicator.Indicator ();
+diff --git a/src/Models/CalendarModel.vala b/src/Models/CalendarModel.vala
+index 965b93e..d60a9ac 100644
+--- a/src/Models/CalendarModel.vala
++++ b/src/Models/CalendarModel.vala
+@@ -35,17 +35,6 @@ namespace DateTimeIndicator {
+         /* The start of week, ie. Monday=1 or Sunday=7 */
+         public GLib.DateWeekday week_starts_on { get; set; }
+ 
+-        public HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> source_events { get; private set; }
+-
+-        /* Notifies when events are added, updated, or removed */
+-        public signal void events_added (E.Source source, Gee.Collection<ECal.Component> events);
+-        public signal void events_updated (E.Source source, Gee.Collection<ECal.Component> events);
+-        public signal void events_removed (E.Source source, Gee.Collection<ECal.Component> events);
+-
+-        private E.SourceRegistry registry { get; private set; }
+-        private HashTable<string, ECal.Client> source_client;
+-        private HashTable<string, ECal.ClientView> source_view;
+-
+         private static CalendarModel? calendar_model = null;
+ 
+         public static CalendarModel get_default () {
+@@ -59,12 +48,6 @@ namespace DateTimeIndicator {
+         }
+ 
+         construct {
+-            open.begin ();
+-
+-            source_client = new HashTable<string, ECal.Client> (str_hash, str_equal);
+-            source_events = new HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component> > (Util.source_hash_func, Util.source_equal_func);
+-            source_view = new HashTable<string, ECal.ClientView> (str_hash, str_equal);
+-
+             int week_start = Posix.NLTime.FIRST_WEEKDAY.to_string ().data[0];
+             if (week_start >= 1 && week_start <= 7) {
+                 week_starts_on = (GLib.DateWeekday) (week_start - 1);
+@@ -72,66 +55,6 @@ namespace DateTimeIndicator {
+ 
+             month_start = Util.get_start_of_month ();
+             compute_ranges ();
+-            notify["month-start"].connect (on_parameter_changed);
+-        }
+-
+-        private async void open () {
+-            try {
+-                registry = yield new E.SourceRegistry (null);
+-                registry.source_removed.connect (remove_source);
+-                registry.source_added.connect ((source) => add_source_async.begin (source));
+-
+-                // Add sources
+-                registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => {
+-                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+-                    if (cal.selected == true && source.enabled == true) {
+-                        add_source_async.begin (source);
+-                    }
+-                });
+-
+-                load_all_sources ();
+-            } catch (GLib.Error error) {
+-                critical (error.message);
+-            }
+-        }
+-
+-        private void load_all_sources () {
+-            lock (source_client) {
+-                foreach (var id in source_client.get_keys ()) {
+-                    var source = registry.ref_source (id);
+-                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+-
+-                    if (cal.selected == true && source.enabled == true) {
+-                        load_source (source);
+-                    }
+-                }
+-            }
+-        }
+-
+-        private void remove_source (E.Source source) {
+-            debug ("Removing source '%s'", source.dup_display_name ());
+-            /* Already out of the model, so do nothing */
+-            unowned string uid = source.get_uid ();
+-
+-            if (!source_view.contains (uid)) {
+-                return;
+-            }
+-
+-            var current_view = source_view.get (uid);
+-            try {
+-                current_view.stop ();
+-            } catch (Error e) {
+-                warning (e.message);
+-            }
+-
+-            source_view.remove (uid);
+-            lock (source_client) {
+-                source_client.remove (uid);
+-            }
+-
+-            var events = source_events.get (source).get_values ().read_only_view;
+-            events_removed (source, events);
+-            source_events.remove (source);
+         }
+ 
+         public void change_month (int relative) {
+@@ -144,7 +67,7 @@ namespace DateTimeIndicator {
+ 
+         /* --- Helper Methods ---// */
+ 
+-        private void compute_ranges () {
++        public void compute_ranges () {
+             var month_end = month_start.add_full (0, 1, -1);
+ 
+             int dow = month_start.get_day_of_week ();
+@@ -182,150 +105,5 @@ namespace DateTimeIndicator {
+ 
+             debug (@"Date ranges: ($data_range_first <= $month_start < $month_end <= $data_range_last)");
+         }
+-
+-        private void load_source (E.Source source) {
+-            /* create empty source-event map */
+-            var events = new Gee.TreeMultiMap<string, ECal.Component> (
+-                (GLib.CompareDataFunc<ECal.Component>?) GLib.strcmp,
+-                (GLib.CompareDataFunc<ECal.Component>?) Util.calcomponent_compare_func
+-            );
+-            source_events.set (source, events);
+-            /* query client view */
+-            var iso_first = ECal.isodate_from_time_t ((time_t)data_range.first_dt.to_unix ());
+-            var iso_last = ECal.isodate_from_time_t ((time_t)data_range.last_dt.add_days (1).to_unix ());
+-            var query = @"(occur-in-time-range? (make-time \"$iso_first\") (make-time \"$iso_last\"))";
+-
+-            ECal.Client client;
+-            lock (source_client) {
+-                client = source_client.get (source.dup_uid ());
+-            }
+-
+-            if (client == null) {
+-                return;
+-            }
+-
+-            debug ("Getting client-view for source '%s'", source.dup_display_name ());
+-            client.get_view.begin (query, null, (obj, results) => {
+-                var view = on_client_view_received (results, source, client);
+-                view.objects_added.connect ((objects) => on_objects_added (source, client, objects));
+-                view.objects_removed.connect ((objects) => on_objects_removed (source, client, objects));
+-                view.objects_modified.connect ((objects) => on_objects_modified (source, client, objects));
+-                try {
+-                    view.start ();
+-                } catch (Error e) {
+-                    critical (e.message);
+-                }
+-
+-                source_view.set (source.dup_uid (), view);
+-            });
+-        }
+-
+-        private async void add_source_async (E.Source source) {
+-            debug ("Adding source '%s'", source.dup_display_name ());
+-            try {
+-                var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null);
+-                source_client.insert (source.dup_uid (), client);
+-            } catch (Error e) {
+-                critical (e.message);
+-            }
+-
+-            Idle.add (() => {
+-                load_source (source);
+-
+-                return false;
+-            });
+-        }
+-
+-        private void debug_event (E.Source source, ECal.Component event) {
+-            unowned ICal.Component comp = event.get_icalcomponent ();
+-            debug (@"Event ['$(comp.get_summary())', $(source.dup_display_name()), $(comp.get_uid()))]");
+-        }
+-
+-        /* --- Signal Handlers ---// */
+-        private void on_parameter_changed () {
+-            compute_ranges ();
+-            load_all_sources ();
+-        }
+-
+-        private ECal.ClientView on_client_view_received (AsyncResult results, E.Source source, ECal.Client client) {
+-            ECal.ClientView view;
+-            try {
+-                debug ("Received client-view for source '%s'", source.dup_display_name ());
+-                bool status = client.get_view.end (results, out view);
+-                assert (status == true);
+-            } catch (Error e) {
+-                critical ("Error loading client-view from source '%s': %s", source.dup_display_name (), e.message);
+-            }
+-
+-            return view;
+-        }
+-
+-#if E_CAL_2_0
+-        private void on_objects_added (E.Source source, ECal.Client client, SList<ICal.Component> objects) {
+-#else
+-        private void on_objects_added (E.Source source, ECal.Client client, SList<weak ICal.Component> objects) {
+-#endif
+-            debug (@"Received $(objects.length()) added event(s) for source '%s'", source.dup_display_name ());
+-            var events = source_events.get (source);
+-            var added_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
+-            objects.foreach ((comp) => {
+-                unowned string uid = comp.get_uid ();
+-#if E_CAL_2_0
+-                client.generate_instances_for_object_sync (comp, (time_t) data_range.first_dt.to_unix (), (time_t) data_range.last_dt.to_unix (), null, (comp, start, end) => {
+-                    var event = new ECal.Component.from_icalcomponent (comp);
+-#else
+-                client.generate_instances_for_object_sync (comp, (time_t) data_range.first_dt.to_unix (), (time_t) data_range.last_dt.to_unix (), (event, start, end) => {
+-#endif
+-                    debug_event (source, event);
+-                    events.set (uid, event);
+-                    added_events.add (event);
+-                    return true;
+-                });
+-            });
+-        }
+-
+-#if E_CAL_2_0
+-        private void on_objects_modified (E.Source source, ECal.Client client, SList<ICal.Component> objects) {
+-#else
+-        private void on_objects_modified (E.Source source, ECal.Client client, SList<weak ICal.Component> objects) {
+-#endif
+-            debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ());
+-            var updated_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
+-
+-            objects.foreach ((comp) => {
+-                unowned string uid = comp.get_uid ();
+-                var events = source_events.get (source).get (uid);
+-                updated_events.add_all (events);
+-                foreach (var event in events) {
+-                    debug_event (source, event);
+-                }
+-            });
+-
+-            events_updated (source, updated_events.read_only_view);
+-        }
+-
+-#if E_CAL_2_0
+-        private void on_objects_removed (E.Source source, ECal.Client client, SList<ECal.ComponentId?> cids) {
+-#else
+-        private void on_objects_removed (E.Source source, ECal.Client client, SList<weak ECal.ComponentId?> cids) {
+-#endif
+-            debug (@"Received $(cids.length()) removed event(s) for source '%s'", source.dup_display_name ());
+-            var events = source_events.get (source);
+-            var removed_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
+-
+-            cids.foreach ((cid) => {
+-                if (cid == null) {
+-                    return;
+-                }
+-
+-                var comps = events.get (cid.get_uid ());
+-                foreach (ECal.Component event in comps) {
+-                    removed_events.add (event);
+-                    debug_event (source, event);
+-                }
+-            });
+-
+-            events_removed (source, removed_events.read_only_view);
+-        }
+     }
+ }
+diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala
+new file mode 100644
+index 0000000..d939777
+--- /dev/null
++++ b/src/Services/EventsManager.vala
+@@ -0,0 +1,226 @@
++namespace DateTimeIndicator {
++    public class Services.EventsManager : GLib.Object {
++        public signal void events_added (E.Source source, Gee.Collection<ECal.Component> events);
++        public signal void events_updated (E.Source source, Gee.Collection<ECal.Component> events);
++        public signal void events_removed (E.Source source, Gee.Collection<ECal.Component> events);
++
++        public HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> source_events { get; private set; }
++
++        private E.SourceRegistry registry { get; private set; }
++        private HashTable<string, ECal.Client> source_client;
++        private HashTable<string, ECal.ClientView> source_view;
++
++        public EventsManager () {
++
++        }
++
++        construct {
++            source_client = new HashTable<string, ECal.Client> (str_hash, str_equal);
++            source_events = new HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component> > (Util.source_hash_func, Util.source_equal_func);
++            source_view = new HashTable<string, ECal.ClientView> (str_hash, str_equal);
++
++            open.begin ();
++        }
++
++        private async void open () {
++            try {
++                registry = yield new E.SourceRegistry (null);
++                registry.source_removed.connect (remove_source);
++                registry.source_added.connect ((source) => add_source_async.begin (source));
++
++                // Add sources
++                registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => {
++                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++                    if (cal.selected == true && source.enabled == true) {
++                        add_source_async.begin (source);
++                    }
++                });
++
++                load_all_sources ();
++            } catch (GLib.Error error) {
++                critical (error.message);
++            }
++        }
++
++        public void load_all_sources () {
++            lock (source_client) {
++                foreach (var id in source_client.get_keys ()) {
++                    var source = registry.ref_source (id);
++                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++
++                    if (cal.selected == true && source.enabled == true) {
++                        load_source (source);
++                    }
++                }
++            }
++        }
++
++        private void remove_source (E.Source source) {
++            debug ("Removing source '%s'", source.dup_display_name ());
++            /* Already out of the model, so do nothing */
++            unowned string uid = source.get_uid ();
++
++            if (!source_view.contains (uid)) {
++                return;
++            }
++
++            var current_view = source_view.get (uid);
++            try {
++                current_view.stop ();
++            } catch (Error e) {
++                warning (e.message);
++            }
++
++            source_view.remove (uid);
++            lock (source_client) {
++                source_client.remove (uid);
++            }
++
++            var events = source_events.get (source).get_values ().read_only_view;
++            events_removed (source, events);
++            source_events.remove (source);
++        }
++
++        private void load_source (E.Source source) {
++            var model = Models.CalendarModel.get_default ();
++
++            /* create empty source-event map */
++            var events = new Gee.TreeMultiMap<string, ECal.Component> (
++                (GLib.CompareDataFunc<ECal.Component>?) GLib.strcmp,
++                (GLib.CompareDataFunc<ECal.Component>?) Util.calcomponent_compare_func
++            );
++            source_events.set (source, events);
++            /* query client view */
++            var iso_first = ECal.isodate_from_time_t ((time_t) model.data_range.first_dt.to_unix ());
++            var iso_last = ECal.isodate_from_time_t ((time_t) model.data_range.last_dt.add_days (1).to_unix ());
++            var query = @"(occur-in-time-range? (make-time \"$iso_first\") (make-time \"$iso_last\"))";
++
++            ECal.Client client;
++            lock (source_client) {
++                client = source_client.get (source.dup_uid ());
++            }
++
++            if (client == null) {
++                return;
++            }
++
++            debug ("Getting client-view for source '%s'", source.dup_display_name ());
++            client.get_view.begin (query, null, (obj, results) => {
++                var view = on_client_view_received (results, source, client);
++                view.objects_added.connect ((objects) => on_objects_added (source, client, objects));
++                view.objects_removed.connect ((objects) => on_objects_removed (source, client, objects));
++                view.objects_modified.connect ((objects) => on_objects_modified (source, client, objects));
++                try {
++                    view.start ();
++                } catch (Error e) {
++                    critical (e.message);
++                }
++
++                source_view.set (source.dup_uid (), view);
++            });
++        }
++
++        private async void add_source_async (E.Source source) {
++            debug ("Adding source '%s'", source.dup_display_name ());
++            try {
++                var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null);
++                source_client.insert (source.dup_uid (), client);
++            } catch (Error e) {
++                critical (e.message);
++            }
++
++            Idle.add (() => {
++                load_source (source);
++
++                return false;
++            });
++        }
++
++        private void debug_event (E.Source source, ECal.Component event) {
++            unowned ICal.Component comp = event.get_icalcomponent ();
++            debug (@"Event ['$(comp.get_summary())', $(source.dup_display_name()), $(comp.get_uid()))]");
++        }
++
++        private ECal.ClientView on_client_view_received (AsyncResult results, E.Source source, ECal.Client client) {
++            ECal.ClientView view;
++            try {
++                debug ("Received client-view for source '%s'", source.dup_display_name ());
++                bool status = client.get_view.end (results, out view);
++                assert (status == true);
++            } catch (Error e) {
++                critical ("Error loading client-view from source '%s': %s", source.dup_display_name (), e.message);
++            }
++
++            return view;
++        }
++
++#if E_CAL_2_0
++        private void on_objects_added (E.Source source, ECal.Client client, SList<ICal.Component> objects) {
++#else
++        private void on_objects_added (E.Source source, ECal.Client client, SList<weak ICal.Component> objects) {
++#endif
++            debug (@"Received $(objects.length()) added event(s) for source '%s'", source.dup_display_name ());
++            var events = source_events.get (source);
++            var added_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
++            var model = Models.CalendarModel.get_default ();
++            objects.foreach ((comp) => {
++                unowned string uid = comp.get_uid ();
++#if E_CAL_2_0
++                client.generate_instances_for_object_sync (comp, (time_t) model.data_range.first_dt.to_unix (), (time_t) model.data_range.last_dt.to_unix (), null, (comp, start, end) => {
++                    var event = new ECal.Component.from_icalcomponent (comp);
++#else
++                client.generate_instances_for_object_sync (comp, (time_t) model.data_range.first_dt.to_unix (), (time_t) model.data_range.last_dt.to_unix (), (event, start, end) => {
++#endif
++                    debug_event (source, event);
++                    events.set (uid, event);
++                    added_events.add (event);
++                    return true;
++                });
++            });
++        }
++
++#if E_CAL_2_0
++        private void on_objects_modified (E.Source source, ECal.Client client, SList<ICal.Component> objects) {
++#else
++        private void on_objects_modified (E.Source source, ECal.Client client, SList<weak ICal.Component> objects) {
++#endif
++            debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ());
++            var updated_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
++
++            objects.foreach ((comp) => {
++                unowned string uid = comp.get_uid ();
++                var events = source_events.get (source).get (uid);
++                updated_events.add_all (events);
++                foreach (var event in events) {
++                    debug_event (source, event);
++                }
++            });
++
++            events_updated (source, updated_events.read_only_view);
++        }
++
++#if E_CAL_2_0
++        private void on_objects_removed (E.Source source, ECal.Client client, SList<ECal.ComponentId?> cids) {
++#else
++        private void on_objects_removed (E.Source source, ECal.Client client, SList<weak ECal.ComponentId?> cids) {
++#endif
++            debug (@"Received $(cids.length()) removed event(s) for source '%s'", source.dup_display_name ());
++            var events = source_events.get (source);
++            var removed_events = new Gee.ArrayList<ECal.Component> ((Gee.EqualDataFunc<ECal.Component>?) Util.calcomponent_equal_func);
++
++            cids.foreach ((cid) => {
++                if (cid == null) {
++                    return;
++                }
++
++                var comps = events.get (cid.get_uid ());
++                foreach (ECal.Component event in comps) {
++                    removed_events.add (event);
++                    debug_event (source, event);
++                }
++            });
++
++            events_removed (source, removed_events.read_only_view);
++        }
++    }
++}
+diff --git a/src/Util/Util.vala b/src/Util/Util.vala
+index c261f4b..b0bdf98 100644
+--- a/src/Util/Util.vala
++++ b/src/Util/Util.vala
+@@ -20,47 +20,6 @@
+  */
+ 
+ namespace DateTimeIndicator.Util {
+-    static bool has_scrolled = false;
+-
+-    public bool on_scroll_event (Gdk.EventScroll event) {
+-        double delta_x;
+-        double delta_y;
+-        event.get_scroll_deltas (out delta_x, out delta_y);
+-
+-        double choice = delta_x;
+-
+-        if (((int)delta_x).abs () < ((int)delta_y).abs ()) {
+-            choice = delta_y;
+-        }
+-
+-        /* It's mouse scroll ! */
+-        if (choice == 1 || choice == -1) {
+-            Models.CalendarModel.get_default ().change_month ((int)choice);
+-
+-            return true;
+-        }
+-
+-        if (has_scrolled == true) {
+-            return true;
+-        }
+-
+-        if (choice > 0.3) {
+-            reset_timer.begin ();
+-            Models.CalendarModel.get_default ().change_month (1);
+-
+-            return true;
+-        }
+-
+-        if (choice < -0.3) {
+-            reset_timer.begin ();
+-            Models.CalendarModel.get_default ().change_month (-1);
+-
+-            return true;
+-        }
+-
+-        return false;
+-    }
+-
+     public GLib.DateTime get_start_of_month (owned GLib.DateTime? date = null) {
+         if (date == null) {
+             date = new GLib.DateTime.now_local ();
+@@ -225,12 +184,12 @@ namespace DateTimeIndicator.Util {
+         return a.dup_uid () == b.dup_uid ();
+     }
+ 
+-    public async void reset_timer () {
+-        has_scrolled = true;
+-        Timeout.add (500, () => {
+-            has_scrolled = false;
+-
+-            return false;
+-        });
+-    }
++    // public async void reset_timer () {
++    //     has_scrolled = true;
++    //     Timeout.add (500, () => {
++    //         has_scrolled = false;
++    //
++    //         return false;
++    //     });
++    // }
+ }
+diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala
+index 65cee28..070580f 100644
+--- a/src/Widgets/CalendarView.vala
++++ b/src/Widgets/CalendarView.vala
+@@ -181,5 +181,14 @@ namespace DateTimeIndicator {
+ 
+             stack.set_visible_child (big_grid);
+         }
++
++        public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            grid.add_event_dots (source, events);
++        }
++
++
++        public void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            grid.remove_event_dots (source, events);
++        }
+     }
+ }
+diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala
+index 547e4c5..c25af2e 100644
+--- a/src/Widgets/EventsListBox.vala
++++ b/src/Widgets/EventsListBox.vala
+@@ -1,6 +1,5 @@
+ namespace DateTimeIndicator {
+     public class Widgets.EventsListBox : Gtk.ListBox {
+-
+         public EventsListBox () {
+             selection_mode = Gtk.SelectionMode.NONE;
+ 
+@@ -22,7 +21,7 @@ namespace DateTimeIndicator {
+             set_sort_func (sort_function);
+         }
+ 
+-        public void update_events (GLib.DateTime? selected_date) {
++        public void update_events (GLib.DateTime? selected_date, HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> source_events) {
+             foreach (unowned Gtk.Widget widget in get_children ()) {
+                 widget.destroy ();
+             }
+@@ -31,11 +30,9 @@ namespace DateTimeIndicator {
+                 return;
+             }
+ 
+-            var model = Models.CalendarModel.get_default ();
+-
+             var events_on_day = new Gee.TreeMap<string, EventRow> ();
+ 
+-            model.source_events.@foreach ((source, component_map) => {
++            source_events.@foreach ((source, component_map) => {
+                 foreach (var comp in component_map.get_values ()) {
+                     if (Util.calcomp_is_on_day (comp, selected_date)) {
+                         unowned ICal.Component ical = comp.get_icalcomponent ();
+diff --git a/src/Widgets/Grid.vala b/src/Widgets/Grid.vala
+index 165d11d..660f212 100644
+--- a/src/Widgets/Grid.vala
++++ b/src/Widgets/Grid.vala
+@@ -261,5 +261,36 @@ namespace DateTimeIndicator {
+             return date.get_year () * 10000 + date.get_month () * 100 + date.get_day_of_month ();
+         }
+ 
++        public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            data.foreach ((entry) => {
++
++                foreach (var component in events) {
++                    if (entry.value.skip_day ()) {
++                        return true;
++                    }
++
++                    if (Util.calcomp_is_on_day (component, entry.value.date)) {
++                        entry.value.add_dots (source, component.get_icalcomponent ());
++                    }
++                }
++
++                entry.value.show_event_grid ();
++
++                return true;
++            });
++        }
++
++        public void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
++            foreach (var component in events) {
++                unowned ICal.Component ical = component.get_icalcomponent ();
++                var event_uid = ical.get_uid ();
++                data.foreach ((entry) => {
++                    if (entry.value.exist_event (event_uid)) {
++                        entry.value.remove_dots (event_uid);
++                    }
++                    return true;
++                });
++            }
++        }
+     }
+ }
+diff --git a/src/Widgets/GridDay.vala b/src/Widgets/GridDay.vala
+index 8c44443..00f82ea 100644
+--- a/src/Widgets/GridDay.vala
++++ b/src/Widgets/GridDay.vala
+@@ -31,6 +31,8 @@ namespace DateTimeIndicator {
+ 
+         public GLib.DateTime date { get; construct set; }
+ 
++        private bool has_scrolled = false;
++
+         private static Gtk.CssProvider provider;
+         private static Models.CalendarModel model;
+ 
+@@ -79,59 +81,100 @@ namespace DateTimeIndicator {
+             // Signals and handlers
+             button_press_event.connect (on_button_press);
+             key_press_event.connect (on_key_press);
+-            scroll_event.connect ((event) => {return Util.on_scroll_event (event);});
++            scroll_event.connect (on_scroll_event);
+ 
+             notify["date"].connect (() => {
+                 label.label = date.get_day_of_month ().to_string ();
+             });
+ 
+             event_dots = new Gee.HashMap<string, Gtk.Widget> ();
+-
+-            model.events_added.connect (add_event_dots);
+-            model.events_removed.connect (remove_event_dots);
+         }
+ 
+-        private void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-            foreach (var component in events) {
+-                if (event_dots.size >= 3) {
+-                    return;
+-                }
++        public bool on_scroll_event (Gdk.EventScroll event) {
++            double delta_x;
++            double delta_y;
++            event.get_scroll_deltas (out delta_x, out delta_y);
++
++            double choice = delta_x;
++
++            if (((int)delta_x).abs () < ((int)delta_y).abs ()) {
++                choice = delta_y;
++            }
++
++            /* It's mouse scroll ! */
++            if (choice == 1 || choice == -1) {
++                Models.CalendarModel.get_default ().change_month ((int)choice);
+ 
+-                if (Util.calcomp_is_on_day (component, date)) {
+-                    unowned ICal.Component ical = component.get_icalcomponent ();
++                return true;
++            }
+ 
+-                    var event_uid = ical.get_uid ();
+-                    if (!event_dots.has_key (event_uid)) {
+-                        var event_dot = new Gtk.Image ();
+-                        event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
+-                        event_dot.pixel_size = 6;
++            if (has_scrolled == true) {
++                return true;
++            }
+ 
+-                        unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
+-                        style_context.add_class (Granite.STYLE_CLASS_ACCENT);
+-                        style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++            if (choice > 0.3) {
++                reset_timer.begin ();
++                Models.CalendarModel.get_default ().change_month (1);
+ 
+-                        var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+-                        Util.set_event_calendar_color (source_calendar, event_dot);
++                return true;
++            }
+ 
+-                        event_dots[event_uid] = event_dot;
++            if (choice < -0.3) {
++                reset_timer.begin ();
++                Models.CalendarModel.get_default ().change_month (-1);
+ 
+-                        event_grid.add (event_dot);
+-                    }
+-                }
++                return true;
+             }
+ 
++            return false;
++        }
++
++        public async void reset_timer () {
++            has_scrolled = true;
++            Timeout.add (500, () => {
++                has_scrolled = false;
++
++                return false;
++            });
++        }
++
++        public bool skip_day () {
++            return event_dots.size >= 3 ? true : false;
++        }
++
++        public void show_event_grid () {
+             event_grid.show_all ();
+         }
+ 
+-        private void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-            foreach (var component in events) {
+-                unowned ICal.Component ical = component.get_icalcomponent ();
+-                var event_uid = ical.get_uid ();
+-                var dot = event_dots[event_uid];
+-                if (dot != null) {
+-                    dot.destroy ();
+-                    event_dots.remove (event_uid);
+-                }
++        public void add_dots (E.Source source, ICal.Component ical) {
++            var event_uid = ical.get_uid ();
++            if (!event_dots.has_key (event_uid)) {
++                var event_dot = new Gtk. Image ();
++                event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
++                event_dot.pixel_size = 6;
++
++                unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
++                style_context.add_class (Granite.STYLE_CLASS_ACCENT);
++                style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++
++                var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++                Util.set_event_calendar_color (source_calendar, event_dot);
++
++                event_dots[event_uid] = event_dot;
++
++                event_grid.add (event_dot);
++            }
++        }
++
++        public bool exist_event (string ical_uid) {
++            return event_dots.has_key (ical_uid);
++        }
++
++        public void remove_dots (string event_uid) {
++            var dot = event_dots[event_uid];
++            if (dot != null) {
++                dot.destroy ();
++                event_dots.unset (event_uid);
+             }
+         }
+ 
+
+From c99db5e63b9c48aa1d069b97b98b0c07481de27d Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Sat, 11 Apr 2020 23:44:14 +0300
+Subject: [PATCH 4/8] rename calendar elements
+
+---
+ meson.build                                   |  4 +--
+ .../{GridDay.vala => CalendarDay.vala}        |  4 +--
+ src/Widgets/{Grid.vala => CalendarGrid.vala}  | 26 +++++++--------
+ src/Widgets/CalendarView.vala                 | 33 +++++++++----------
+ 4 files changed, 33 insertions(+), 34 deletions(-)
+ rename src/Widgets/{GridDay.vala => CalendarDay.vala} (98%)
+ rename src/Widgets/{Grid.vala => CalendarGrid.vala} (91%)
+
+diff --git a/meson.build b/meson.build
+index e348e3d..dcdd9b2 100644
+--- a/meson.build
++++ b/meson.build
+@@ -44,11 +44,11 @@ shared_module(
+     'src/Util/DateRange.vala',
+     'src/Util/Util.vala',
+     'src/Models/CalendarModel.vala',
++    'src/Widgets/CalendarDay.vala',
++    'src/Widgets/CalendarGrid.vala',
+     'src/Widgets/CalendarView.vala',
+     'src/Widgets/EventRow.vala',
+     'src/Widgets/EventsListBox.vala',
+-    'src/Widgets/Grid.vala',
+-    'src/Widgets/GridDay.vala',
+     'src/Widgets/PanelLabel.vala',
+     'src/Services/EventsManager.vala',
+     'src/Services/TimeManager.vala',
+diff --git a/src/Widgets/GridDay.vala b/src/Widgets/CalendarDay.vala
+similarity index 98%
+rename from src/Widgets/GridDay.vala
+rename to src/Widgets/CalendarDay.vala
+index 00f82ea..a5ca920 100644
+--- a/src/Widgets/GridDay.vala
++++ b/src/Widgets/CalendarDay.vala
+@@ -23,7 +23,7 @@ namespace DateTimeIndicator {
+ /**
+  * Represents a single day on the grid.
+  */
+-    public class Widgets.GridDay : Gtk.EventBox {
++    public class Widgets.CalendarDay : Gtk.EventBox {
+         /*
+          * Event emitted when the day is double clicked or the ENTER key is pressed.
+          */
+@@ -41,7 +41,7 @@ namespace DateTimeIndicator {
+         private Gtk.Label label;
+         private bool valid_grab = false;
+ 
+-        public GridDay (GLib.DateTime date) {
++        public CalendarDay (GLib.DateTime date) {
+             Object (date: date);
+         }
+ 
+diff --git a/src/Widgets/Grid.vala b/src/Widgets/CalendarGrid.vala
+similarity index 91%
+rename from src/Widgets/Grid.vala
+rename to src/Widgets/CalendarGrid.vala
+index 660f212..66e2757 100644
+--- a/src/Widgets/Grid.vala
++++ b/src/Widgets/CalendarGrid.vala
+@@ -24,7 +24,7 @@ namespace DateTimeIndicator {
+ /**
+  * Represents the entire date grid as a table.
+  */
+-    public class Widgets.Grid : Gtk.Grid {
++    public class Widgets.CalendarGrid : Gtk.Grid {
+         public Util.DateRange grid_range { get; private set; }
+ 
+         /*
+@@ -34,8 +34,8 @@ namespace DateTimeIndicator {
+ 
+         public signal void selection_changed (GLib.DateTime new_date);
+ 
+-        private Gee.HashMap<uint, GridDay> data;
+-        private GridDay selected_gridday;
++        private Gee.HashMap<uint, Widgets.CalendarDay> data;
++        private Widgets.CalendarDay selected_gridday;
+         private Gtk.Label[] header_labels;
+         private Gtk.Revealer[] week_labels;
+ 
+@@ -61,12 +61,12 @@ namespace DateTimeIndicator {
+ 
+             Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT);
+ 
+-            data = new Gee.HashMap<uint, GridDay> ();
++            data = new Gee.HashMap<uint, Widgets.CalendarDay> ();
+             events |= Gdk.EventMask.SCROLL_MASK;
+             events |= Gdk.EventMask.SMOOTH_SCROLL_MASK;
+         }
+ 
+-        private void on_day_focus_in (GridDay day) {
++        private void on_day_focus_in (Widgets.CalendarDay day) {
+             debug ("on_day_focus_in %s", day.date.to_string ());
+             if (selected_gridday != null) {
+                 selected_gridday.set_selected (false);
+@@ -94,7 +94,7 @@ namespace DateTimeIndicator {
+             Gee.List<GLib.DateTime> dates = grid_range.to_list ();
+             for (int i = 0; i < dates.size; i++) {
+                 var date = dates[i];
+-                GridDay? day = data[day_hash (date)];
++                Widgets.CalendarDay? day = data[day_hash (date)];
+                 if (day != null && day.name == "today") {
+                     day.grab_focus_force ();
+                     return;
+@@ -119,7 +119,7 @@ namespace DateTimeIndicator {
+ 
+             var new_dates = new_range.to_list ();
+ 
+-            var data_new = new Gee.HashMap<uint, GridDay> ();
++            var data_new = new Gee.HashMap<uint, Widgets.CalendarDay> ();
+ 
+             /* Assert that a valid number of weeks should be displayed */
+             assert (new_dates.size % 7 == 0);
+@@ -138,7 +138,7 @@ namespace DateTimeIndicator {
+ 
+             for (i = 0; i < new_dates.size; i++) {
+                 var new_date = new_dates[i];
+-                GridDay day;
++                Widgets.CalendarDay day;
+ 
+                 if (i < old_dates.size) {
+                     /* A widget already exists for this date, just change it */
+@@ -147,7 +147,7 @@ namespace DateTimeIndicator {
+                     day = update_day (data[day_hash (old_date)], new_date, today, month_start);
+                 } else {
+                     /* Still update_day to get the color of etc. right */
+-                    day = update_day (new GridDay (new_date), new_date, today, month_start);
++                    day = update_day (new Widgets.CalendarDay (new_date), new_date, today, month_start);
+                     day.on_event_add.connect ((date) => on_event_add (date));
+                     day.scroll_event.connect ((event) => { scroll_event (event); return false; });
+                     day.focus_in_event.connect ((event) => {
+@@ -182,9 +182,9 @@ namespace DateTimeIndicator {
+         }
+ 
+         /**
+-         * Updates the given GridDay so that it shows the given date. Changes to its style etc.
++         * Updates the given CalendarDay so that it shows the given date. Changes to its style etc.
+          */
+-        private GridDay update_day (GridDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) {
++        private Widgets.CalendarDay update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) {
+             update_today_style (day, new_date, today);
+             if (new_date.get_month () == month_start.get_month ()) {
+                 day.sensitive_container (true);
+@@ -237,13 +237,13 @@ namespace DateTimeIndicator {
+             int i = 0;
+             for (i = 0; i < dates.size; i++) {
+                 var date = dates[i];
+-                GridDay? day = data[day_hash (date)];
++                Widgets.CalendarDay? day = data[day_hash (date)];
+                 if (day == null) return;
+                 update_today_style (day, date, today);
+             }
+         }
+ 
+-        private void update_today_style (GridDay day, GLib.DateTime date, GLib.DateTime today) {
++        private void update_today_style (Widgets.CalendarDay day, GLib.DateTime date, GLib.DateTime today) {
+             if (date.get_day_of_year () == today.get_day_of_year () && date.get_year () == today.get_year ()) {
+                 day.name = "today";
+                 day.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT);
+diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala
+index 070580f..db2139c 100644
+--- a/src/Widgets/CalendarView.vala
++++ b/src/Widgets/CalendarView.vala
+@@ -26,7 +26,7 @@ namespace DateTimeIndicator {
+ 
+         public GLib.DateTime? selected_date { get; private set; }
+ 
+-        private Widgets.Grid grid;
++        private Widgets.CalendarGrid calendar_grid;
+         private Gtk.Stack stack;
+         private Gtk.Grid big_grid;
+ 
+@@ -105,20 +105,20 @@ namespace DateTimeIndicator {
+         }
+ 
+         private Gtk.Grid create_big_grid () {
+-            grid = new Widgets.Grid ();
+-            grid.show_all ();
++            calendar_grid = new Widgets.CalendarGrid ();
++            calendar_grid.show_all ();
+ 
+-            grid.on_event_add.connect ((date) => {
++            calendar_grid.on_event_add.connect ((date) => {
+                 show_date_in_maya (date);
+                 day_double_click ();
+             });
+ 
+-            grid.selection_changed.connect ((date) => {
++            calendar_grid.selection_changed.connect ((date) => {
+                 selected_date = date;
+                 selection_changed (date);
+             });
+ 
+-            return grid;
++            return calendar_grid;
+         }
+ 
+         public void show_today () {
+@@ -131,7 +131,7 @@ namespace DateTimeIndicator {
+             }
+             sync_with_model ();
+ 
+-            grid.set_focus_to_today ();
++            calendar_grid.set_focus_to_today ();
+         }
+ 
+         // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app.
+@@ -156,23 +156,23 @@ namespace DateTimeIndicator {
+         /* Sets the calendar widgets to the date range of the model */
+         private void sync_with_model () {
+             var model = Models.CalendarModel.get_default ();
+-            if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
+-                grid.update_today ();
++            if (calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
++                calendar_grid.update_today ();
+                 return; // nothing else to do
+             }
+ 
+             GLib.DateTime previous_first = null;
+-            if (grid.grid_range != null)
+-                previous_first = grid.grid_range.first_dt;
++            if (calendar_grid.grid_range != null)
++                previous_first = calendar_grid.grid_range.first_dt;
+ 
+             big_grid = create_big_grid ();
+             stack.add (big_grid);
+ 
+-            grid.set_range (model.data_range, model.month_start);
+-            grid.update_weeks (model.data_range.first_dt, model.num_weeks);
++            calendar_grid.set_range (model.data_range, model.month_start);
++            calendar_grid.update_weeks (model.data_range.first_dt, model.num_weeks);
+ 
+             if (previous_first != null) {
+-                if (previous_first.compare (grid.grid_range.first_dt) == -1) {
++                if (previous_first.compare (calendar_grid.grid_range.first_dt) == -1) {
+                     stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT;
+                 } else {
+                     stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT;
+@@ -183,12 +183,11 @@ namespace DateTimeIndicator {
+         }
+ 
+         public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-            grid.add_event_dots (source, events);
++            calendar_grid.add_event_dots (source, events);
+         }
+ 
+-
+         public void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-            grid.remove_event_dots (source, events);
++            calendar_grid.remove_event_dots (source, events);
+         }
+     }
+ }
+
+From 6b1b15305a9c90ff8b7e7244727a225984d34a14 Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Sun, 12 Apr 2020 03:10:24 +0300
+Subject: [PATCH 5/8] evolution data server now optional
+
+---
+ meson.build                   | 55 ++++++++++++++---------
+ meson_options.txt             |  1 +
+ src/Indicator.vala            | 43 ++++++++++--------
+ src/Util/Util.vala            | 85 ++++++++++++++++-------------------
+ src/Widgets/CalendarDay.vala  |  2 +
+ src/Widgets/CalendarGrid.vala |  2 +
+ src/Widgets/CalendarView.vala |  2 +
+ 7 files changed, 104 insertions(+), 86 deletions(-)
+ create mode 100644 meson_options.txt
+
+diff --git a/meson.build b/meson.build
+index dcdd9b2..5fee9ab 100644
+--- a/meson.build
++++ b/meson.build
+@@ -24,18 +24,40 @@ gresource = gnome.compile_resources(
+ wingpanel_dep = dependency('wingpanel-2.0')
+ wingpanel_indicatorsdir = wingpanel_dep.get_pkgconfig_variable('indicatorsdir', define_variable: ['libdir', libdir])
+ 
++deps = [
++    dependency('glib-2.0'),
++    dependency('gobject-2.0'),
++    dependency('granite'),
++    dependency('gtk+-3.0'),
++    wingpanel_dep,
++    meson.get_compiler('vala').find_library('posix')
++]
+ 
+-libecal_dep = dependency('libecal-2.0', required: false)
+-if libecal_dep.found()
+-    libical_dep = dependency('libical-glib')
+-    add_project_arguments('--define=E_CAL_2_0', language: 'vala')
+-    add_project_arguments('-DLIBICAL_GLIB_UNSTABLE_API=1', language: 'c')
+-else
+-    libecal_dep = dependency('libecal-1.2', version: '>=3.8.0')
+-    libical_dep = dependency('libical')
+-    add_project_arguments('--vapidir', join_paths(meson.current_source_dir(), 'vapi'), language: 'vala')
++opt_files = []
++
++if get_option('evo')
++    libecal_dep = dependency ('libecal-2.0', required: false)
++    if libecal_dep.found()
++        deps += dependency('libical-glib')
++        deps += libecal_dep
++        add_project_arguments('--define=E_CAL_2_0', language: 'vala')
++        add_project_arguments('-DLIBICAL_GLIB_UNSTABLE_API=1', language: 'c')
++    else
++        deps += dependency('libecal-1.2', version: '>=3.8.0')
++        deps += dependency('libical')
++        add_project_arguments('--vapidir', join_paths(meson.current_source_dir(), 'vapi'), language: 'vala')
++    endif
++
++    deps += dependency ('libedataserver-1.2')
++    opt_files += files (
++        'src/Widgets/EventRow.vala',
++        'src/Widgets/EventsListBox.vala',
++        'src/Services/EventsManager.vala',
++    )
++    add_project_arguments('--define=USE_EVO', language: 'vala')
+ endif
+ 
++
+ shared_module(
+     meson.project_name(),
+     gresource,
+@@ -47,21 +69,10 @@ shared_module(
+     'src/Widgets/CalendarDay.vala',
+     'src/Widgets/CalendarGrid.vala',
+     'src/Widgets/CalendarView.vala',
+-    'src/Widgets/EventRow.vala',
+-    'src/Widgets/EventsListBox.vala',
+     'src/Widgets/PanelLabel.vala',
+-    'src/Services/EventsManager.vala',
+     'src/Services/TimeManager.vala',
+-    dependencies: [
+-        dependency('glib-2.0'),
+-        dependency('gobject-2.0'),
+-        dependency('granite'),
+-        dependency('gtk+-3.0'),
+-        libecal_dep,
+-        dependency('libedataserver-1.2'),
+-        libical_dep,
+-        wingpanel_dep,
+-    ],
++    opt_files,
++    dependencies: deps,
+     install: true,
+     install_dir : wingpanel_indicatorsdir,
+ )
+diff --git a/meson_options.txt b/meson_options.txt
+new file mode 100644
+index 0000000..a1c9f0e
+--- /dev/null
++++ b/meson_options.txt
+@@ -0,0 +1 @@
++option ('evo', type : 'boolean', value : true)
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index bf4358f..31c7af5 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -23,9 +23,11 @@ namespace DateTimeIndicator {
+ 
+         private Widgets.PanelLabel panel_label;
+         private Widgets.CalendarView calendar;
+-        private Widgets.EventsListBox event_listbox;
+ 
++#if USE_EVO
++        private Widgets.EventsListBox event_listbox;
+         private Services.EventsManager event_manager;
++#endif
+ 
+         private Gtk.Grid main_grid;
+         private uint update_events_idle_source = 0;
+@@ -60,7 +62,20 @@ namespace DateTimeIndicator {
+             if (main_grid == null) {
+                 calendar = new Widgets.CalendarView ();
+                 calendar.margin_bottom = 6;
++                calendar.day_double_click.connect (() => {
++                    close ();
++                });
++
++                var settings_button = new Gtk.ModelButton ();
++                settings_button.text = _("Date & Time Settings…");
+ 
++                main_grid = new Gtk.Grid ();
++                main_grid.margin_top = 12;
++                main_grid.attach (calendar,                           0, 0);
++                main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 1);
++                main_grid.attach (settings_button,                    0, 2);
++
++#if USE_EVO
+                 event_manager = new Services.EventsManager ();
+                 event_manager.events_updated.connect (update_events_model);
+                 event_manager.events_added.connect ((source, events) => {
+@@ -73,20 +88,16 @@ namespace DateTimeIndicator {
+                 });
+ 
+                 event_listbox = new Widgets.EventsListBox ();
++                event_listbox.row_activated.connect ((row) => {
++                    calendar.show_date_in_maya (((EventRow) row).date);
++                    close ();
++                });
+ 
+                 var scrolled_window = new Gtk.ScrolledWindow (null, null);
+                 scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
+                 scrolled_window.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
+                 scrolled_window.add (event_listbox);
+ 
+-                var settings_button = new Gtk.ModelButton ();
+-                settings_button.text = _("Date & Time Settings…");
+-
+-                main_grid = new Gtk.Grid ();
+-                main_grid.margin_top = 12;
+-                main_grid.attach (calendar,                                     0, 0);
+-                main_grid.attach (new Wingpanel.Widgets.Separator (),           0, 1);
+-                main_grid.attach (settings_button,                              0, 2);
+                 main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 3);
+                 main_grid.attach (scrolled_window,                              2, 0, 1, 3);
+ 
+@@ -94,23 +105,17 @@ namespace DateTimeIndicator {
+                 size_group.add_widget (calendar);
+                 size_group.add_widget (event_listbox);
+ 
+-                calendar.day_double_click.connect (() => {
+-                    close ();
+-                });
+-
+                 calendar.selection_changed.connect ((date) => {
+                     idle_update_events ();
+                 });
+-
+-                event_listbox.row_activated.connect ((row) => {
+-                    calendar.show_date_in_maya (((EventRow) row).date);
+-                    close ();
+-                });
++#endif
+ 
+                 var model = Models.CalendarModel.get_default ();
+                 model.notify["month-start"].connect (() => {
+                     model.compute_ranges ();
++#if USE_EVO
+                     event_manager.load_all_sources ();
++#endif
+                 });
+ 
+                 settings_button.clicked.connect (() => {
+@@ -125,6 +130,7 @@ namespace DateTimeIndicator {
+             return main_grid;
+         }
+ 
++#if USE_EVO
+         private void update_events_model (E.Source source, Gee.Collection<ECal.Component> events) {
+             if (opened_widget) {
+                 idle_update_events ();
+@@ -143,6 +149,7 @@ namespace DateTimeIndicator {
+                 return GLib.Source.REMOVE;
+             });
+         }
++#endif
+ 
+         public override void opened () {
+             calendar.show_today ();
+diff --git a/src/Util/Util.vala b/src/Util/Util.vala
+index b0bdf98..26b343a 100644
+--- a/src/Util/Util.vala
++++ b/src/Util/Util.vala
+@@ -32,38 +32,6 @@ namespace DateTimeIndicator.Util {
+         return datetime.add_full (0, 0, 0, -datetime.get_hour (), -datetime.get_minute (), -datetime.get_second ());
+     }
+ 
+-    /**
+-     * Converts the given ICal.Time to a DateTime.
+-     */
+-    public TimeZone timezone_from_ical (ICal.Time date) {
+-        int is_daylight;
+-        var interval = date.get_timezone ().get_utc_offset (null, out is_daylight);
+-        bool is_positive = interval >= 0;
+-        interval = interval.abs ();
+-        var hours = (interval / 3600);
+-        var minutes = (interval % 3600) / 60;
+-        var hour_string = "%s%02d:%02d".printf (is_positive ? "+" : "-", hours, minutes);
+-
+-        return new TimeZone (hour_string);
+-    }
+-
+-    /**
+-     * Converts the given ICal.Time to a DateTime.
+-     * XXX : Track next versions of evolution in order to convert ICal.Timezone to GLib.TimeZone with a dedicated function…
+-     */
+-    public GLib.DateTime ical_to_date_time (ICal.Time date) {
+-#if E_CAL_2_0
+-        int year, month, day, hour, minute, second;
+-        date.get_date (out year, out month, out day);
+-        date.get_time (out hour, out minute, out second);
+-        return new GLib.DateTime (timezone_from_ical (date), year, month,
+-            day, hour, minute, second);
+-#else
+-        return new GLib.DateTime (timezone_from_ical (date), date.year, date.month,
+-            date.day, date.hour, date.minute, date.second);
+-#endif
+-    }
+-
+     /**
+      * Say if an event lasts all day.
+      */
+@@ -78,6 +46,7 @@ namespace DateTimeIndicator.Util {
+         }
+     }
+ 
++#if USE_EVO
+     private Gee.HashMap<string, Gtk.CssProvider>? providers;
+     public void set_event_calendar_color (E.SourceCalendar cal, Gtk.Widget widget) {
+         if (providers == null) {
+@@ -104,6 +73,38 @@ namespace DateTimeIndicator.Util {
+         style_context.add_provider (providers[color], Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+     }
+ 
++    /**
++     * Converts the given ICal.Time to a DateTime.
++     */
++    public TimeZone timezone_from_ical (ICal.Time date) {
++        int is_daylight;
++        var interval = date.get_timezone ().get_utc_offset (null, out is_daylight);
++        bool is_positive = interval >= 0;
++        interval = interval.abs ();
++        var hours = (interval / 3600);
++        var minutes = (interval % 3600) / 60;
++        var hour_string = "%s%02d:%02d".printf (is_positive ? "+" : "-", hours, minutes);
++
++        return new TimeZone (hour_string);
++    }
++
++    /**
++     * Converts the given ICal.Time to a DateTime.
++     * XXX : Track next versions of evolution in order to convert ICal.Timezone to GLib.TimeZone with a dedicated function…
++     */
++    public GLib.DateTime ical_to_date_time (ICal.Time date) {
++#if E_CAL_2_0
++        int year, month, day, hour, minute, second;
++        date.get_date (out year, out month, out day);
++        date.get_time (out hour, out minute, out second);
++        return new GLib.DateTime (timezone_from_ical (date), year, month,
++            day, hour, minute, second);
++#else
++        return new GLib.DateTime (timezone_from_ical (date), date.year, date.month,
++            date.day, date.hour, date.minute, date.second);
++#endif
++    }
++
+     /*
+      * Gee Utility Functions
+      */
+@@ -113,6 +114,11 @@ namespace DateTimeIndicator.Util {
+         return key.dup_uid (). hash ();
+     }
+ 
++    /* Returns true if 'a' and 'b' are the same E.Source */
++    public bool source_equal_func (E.Source a, E.Source b) {
++        return a.dup_uid () == b.dup_uid ();
++    }
++
+     /* Returns true if 'a' and 'b' are the same ECal.Component */
+     public bool calcomponent_equal_func (ECal.Component a, ECal.Component b) {
+         return a.get_id ().equal (b.get_id ());
+@@ -178,18 +184,5 @@ namespace DateTimeIndicator.Util {
+ 
+         return false;
+     }
+-
+-    /* Returns true if 'a' and 'b' are the same E.Source */
+-    public bool source_equal_func (E.Source a, E.Source b) {
+-        return a.dup_uid () == b.dup_uid ();
+-    }
+-
+-    // public async void reset_timer () {
+-    //     has_scrolled = true;
+-    //     Timeout.add (500, () => {
+-    //         has_scrolled = false;
+-    //
+-    //         return false;
+-    //     });
+-    // }
++#endif
+ }
+diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala
+index a5ca920..f9c742a 100644
+--- a/src/Widgets/CalendarDay.vala
++++ b/src/Widgets/CalendarDay.vala
+@@ -146,6 +146,7 @@ namespace DateTimeIndicator {
+             event_grid.show_all ();
+         }
+ 
++#if USE_EVO
+         public void add_dots (E.Source source, ICal.Component ical) {
+             var event_uid = ical.get_uid ();
+             if (!event_dots.has_key (event_uid)) {
+@@ -177,6 +178,7 @@ namespace DateTimeIndicator {
+                 event_dots.unset (event_uid);
+             }
+         }
++#endif
+ 
+         public void set_selected (bool selected) {
+             if (selected) {
+diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala
+index 66e2757..1d1e06c 100644
+--- a/src/Widgets/CalendarGrid.vala
++++ b/src/Widgets/CalendarGrid.vala
+@@ -261,6 +261,7 @@ namespace DateTimeIndicator {
+             return date.get_year () * 10000 + date.get_month () * 100 + date.get_day_of_month ();
+         }
+ 
++#if USE_EVO
+         public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+             data.foreach ((entry) => {
+ 
+@@ -292,5 +293,6 @@ namespace DateTimeIndicator {
+                 });
+             }
+         }
++#endif
+     }
+ }
+diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala
+index db2139c..77c233c 100644
+--- a/src/Widgets/CalendarView.vala
++++ b/src/Widgets/CalendarView.vala
+@@ -182,6 +182,7 @@ namespace DateTimeIndicator {
+             stack.set_visible_child (big_grid);
+         }
+ 
++#if USE_EVO
+         public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+             calendar_grid.add_event_dots (source, events);
+         }
+@@ -189,5 +190,6 @@ namespace DateTimeIndicator {
+         public void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+             calendar_grid.remove_event_dots (source, events);
+         }
++#endif
+     }
+ }
+
+From 16715f5114c0597d6961880bf877f04414400334 Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Mon, 13 Apr 2020 22:21:07 +0300
+Subject: [PATCH 6/8] returned dots in the calendar
+
+---
+ src/Indicator.vala              |  6 ++--
+ src/Services/EventsManager.vala | 28 +++++----------
+ src/Widgets/CalendarDay.vala    | 62 ++++++++++++++++++---------------
+ src/Widgets/CalendarGrid.vala   | 29 ++++++---------
+ 4 files changed, 57 insertions(+), 68 deletions(-)
+
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index 31c7af5..c7550aa 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -105,8 +105,10 @@ namespace DateTimeIndicator {
+                 size_group.add_widget (calendar);
+                 size_group.add_widget (event_listbox);
+ 
+-                calendar.selection_changed.connect ((date) => {
+-                    idle_update_events ();
++                event_manager.open.begin ((obj, res) => {
++                    calendar.selection_changed.connect ((date) => {
++                        idle_update_events ();
++                    });
+                 });
+ #endif
+ 
+diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala
+index d939777..ad0397d 100644
+--- a/src/Services/EventsManager.vala
++++ b/src/Services/EventsManager.vala
+@@ -10,33 +10,25 @@ namespace DateTimeIndicator {
+         private HashTable<string, ECal.Client> source_client;
+         private HashTable<string, ECal.ClientView> source_view;
+ 
+-        public EventsManager () {
+-
+-        }
+-
+         construct {
+             source_client = new HashTable<string, ECal.Client> (str_hash, str_equal);
+             source_events = new HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component> > (Util.source_hash_func, Util.source_equal_func);
+             source_view = new HashTable<string, ECal.ClientView> (str_hash, str_equal);
+-
+-            open.begin ();
+         }
+ 
+-        private async void open () {
++        public async void open () {
+             try {
+                 registry = yield new E.SourceRegistry (null);
+                 registry.source_removed.connect (remove_source);
+-                registry.source_added.connect ((source) => add_source_async.begin (source));
++                registry.source_added.connect (add_source);
+ 
+                 // Add sources
+                 registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => {
+-                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++                    E.SourceCalendar cal = (E.SourceCalendar) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+                     if (cal.selected == true && source.enabled == true) {
+-                        add_source_async.begin (source);
++                        add_source (source);
+                     }
+                 });
+-
+-                load_all_sources ();
+             } catch (GLib.Error error) {
+                 critical (error.message);
+             }
+@@ -46,7 +38,7 @@ namespace DateTimeIndicator {
+             lock (source_client) {
+                 foreach (var id in source_client.get_keys ()) {
+                     var source = registry.ref_source (id);
+-                    E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++                    E.SourceCalendar cal = (E.SourceCalendar) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+ 
+                     if (cal.selected == true && source.enabled == true) {
+                         load_source (source);
+@@ -120,7 +112,7 @@ namespace DateTimeIndicator {
+             });
+         }
+ 
+-        private async void add_source_async (E.Source source) {
++        private void add_source (E.Source source) {
+             debug ("Adding source '%s'", source.dup_display_name ());
+             try {
+                 var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null);
+@@ -129,11 +121,7 @@ namespace DateTimeIndicator {
+                 critical (e.message);
+             }
+ 
+-            Idle.add (() => {
+-                load_source (source);
+-
+-                return false;
+-            });
++            load_source (source);
+         }
+ 
+         private void debug_event (E.Source source, ECal.Component event) {
+@@ -177,6 +165,8 @@ namespace DateTimeIndicator {
+                     return true;
+                 });
+             });
++
++            events_added (source, added_events.read_only_view);
+         }
+ 
+ #if E_CAL_2_0
+diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala
+index f9c742a..a2c4922 100644
+--- a/src/Widgets/CalendarDay.vala
++++ b/src/Widgets/CalendarDay.vala
+@@ -36,7 +36,8 @@ namespace DateTimeIndicator {
+         private static Gtk.CssProvider provider;
+         private static Models.CalendarModel model;
+ 
+-        private Gee.HashMap<string, Gtk.Widget> event_dots;
++        // private Gee.HashMap<string, Gtk.Widget> event_dots;
++        private Gee.ArrayList<string> event_dots;
+         private Gtk.Grid event_grid;
+         private Gtk.Label label;
+         private bool valid_grab = false;
+@@ -87,7 +88,8 @@ namespace DateTimeIndicator {
+                 label.label = date.get_day_of_month ().to_string ();
+             });
+ 
+-            event_dots = new Gee.HashMap<string, Gtk.Widget> ();
++            // event_dots = new Gee.HashMap<string, Gtk.Widget> ();
++            event_dots = new Gee.ArrayList<string> ();
+         }
+ 
+         public bool on_scroll_event (Gdk.EventScroll event) {
+@@ -138,44 +140,46 @@ namespace DateTimeIndicator {
+             });
+         }
+ 
+-        public bool skip_day () {
+-            return event_dots.size >= 3 ? true : false;
+-        }
+-
+-        public void show_event_grid () {
+-            event_grid.show_all ();
+-        }
+-
+ #if USE_EVO
+         public void add_dots (E.Source source, ICal.Component ical) {
+             var event_uid = ical.get_uid ();
+-            if (!event_dots.has_key (event_uid)) {
+-                var event_dot = new Gtk. Image ();
+-                event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
+-                event_dot.pixel_size = 6;
++            if (event_dots.contains (event_uid)) {
++                return;
++            }
+ 
+-                unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
+-                style_context.add_class (Granite.STYLE_CLASS_ACCENT);
+-                style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
++            event_dots.add (event_uid);
++            if (event_dots.size > 3) {
++                return;
++            }
+ 
+-                var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
+-                Util.set_event_calendar_color (source_calendar, event_dot);
++            var event_dot = new Gtk.Image ();
++            event_dot.gicon = new ThemedIcon ("pager-checked-symbolic");
++            event_dot.pixel_size = 6;
+ 
+-                event_dots[event_uid] = event_dot;
++            unowned Gtk.StyleContext style_context = event_dot.get_style_context ();
++            style_context.add_class (Granite.STYLE_CLASS_ACCENT);
++            style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ 
+-                event_grid.add (event_dot);
+-            }
+-        }
++            var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR);
++            Util.set_event_calendar_color (source_calendar, event_dot);
+ 
+-        public bool exist_event (string ical_uid) {
+-            return event_dots.has_key (ical_uid);
++            event_grid.add (event_dot);
++            event_dot.show ();
+         }
+ 
+         public void remove_dots (string event_uid) {
+-            var dot = event_dots[event_uid];
+-            if (dot != null) {
+-                dot.destroy ();
+-                event_dots.unset (event_uid);
++            if (event_dots.contains (event_uid)) {
++                return;
++            }
++
++            event_dots.remove (event_uid);
++            if (event_dots.size >= 3) {
++                return;
++            }
++
++            var w = event_grid.get_children ();
++            if (w.length () > 0) {
++                w.nth_data (0).destroy ();
+             }
+         }
+ #endif
+diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala
+index 1d1e06c..c544404 100644
+--- a/src/Widgets/CalendarGrid.vala
++++ b/src/Widgets/CalendarGrid.vala
+@@ -263,22 +263,16 @@ namespace DateTimeIndicator {
+ 
+ #if USE_EVO
+         public void add_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+-            data.foreach ((entry) => {
+-
+-                foreach (var component in events) {
+-                    if (entry.value.skip_day ()) {
+-                        return true;
+-                    }
+-
+-                    if (Util.calcomp_is_on_day (component, entry.value.date)) {
+-                        entry.value.add_dots (source, component.get_icalcomponent ());
+-                    }
++            foreach (var component in events) {
++                unowned ICal.Component? icomp = component.get_icalcomponent ();
++                ICal.Time? start_time = icomp.get_dtstart ();
++                time_t start_unix = start_time.as_timet ();
++                var t = new DateTime.from_unix_utc (start_unix);
++                var d_hash = day_hash (t);
++                if (data.has_key (d_hash)) {
++                    data[d_hash].add_dots (source, component.get_icalcomponent ());
+                 }
+-
+-                entry.value.show_event_grid ();
+-
+-                return true;
+-            });
++            }
+         }
+ 
+         public void remove_event_dots (E.Source source, Gee.Collection<ECal.Component> events) {
+@@ -286,9 +280,8 @@ namespace DateTimeIndicator {
+                 unowned ICal.Component ical = component.get_icalcomponent ();
+                 var event_uid = ical.get_uid ();
+                 data.foreach ((entry) => {
+-                    if (entry.value.exist_event (event_uid)) {
+-                        entry.value.remove_dots (event_uid);
+-                    }
++                    entry.value.remove_dots (event_uid);
++
+                     return true;
+                 });
+             }
+
+From 149da28659883b01ceb0773b35c018d31aa1d912 Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Tue, 14 Apr 2020 00:16:01 +0300
+Subject: [PATCH 7/8] issue #55
+
+---
+ src/Services/EventsManager.vala |  2 ++
+ src/Widgets/CalendarDay.vala    |  2 +-
+ src/Widgets/CalendarGrid.vala   | 11 +++++++----
+ 3 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala
+index ad0397d..959762f 100644
+--- a/src/Services/EventsManager.vala
++++ b/src/Services/EventsManager.vala
+@@ -208,6 +208,8 @@ namespace DateTimeIndicator {
+                     removed_events.add (event);
+                     debug_event (source, event);
+                 }
++
++                events.remove_all (cid.get_uid ());
+             });
+ 
+             events_removed (source, removed_events.read_only_view);
+diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala
+index a2c4922..10d088c 100644
+--- a/src/Widgets/CalendarDay.vala
++++ b/src/Widgets/CalendarDay.vala
+@@ -168,7 +168,7 @@ namespace DateTimeIndicator {
+         }
+ 
+         public void remove_dots (string event_uid) {
+-            if (event_dots.contains (event_uid)) {
++            if (!event_dots.contains (event_uid)) {
+                 return;
+             }
+ 
+diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala
+index c544404..6e6cbdb 100644
+--- a/src/Widgets/CalendarGrid.vala
++++ b/src/Widgets/CalendarGrid.vala
+@@ -279,11 +279,14 @@ namespace DateTimeIndicator {
+             foreach (var component in events) {
+                 unowned ICal.Component ical = component.get_icalcomponent ();
+                 var event_uid = ical.get_uid ();
+-                data.foreach ((entry) => {
+-                    entry.value.remove_dots (event_uid);
+ 
+-                    return true;
+-                });
++                ICal.Time? start_time = ical.get_dtstart ();
++                time_t start_unix = start_time.as_timet ();
++                var t = new DateTime.from_unix_utc (start_unix);
++                var d_hash = day_hash (t);
++                if (data.has_key (d_hash)) {
++                    data[d_hash].remove_dots (event_uid);
++                }
+             }
+         }
+ #endif
+
+From a3910e2b8242b8c4837cc764da7f268a02d05d6e Mon Sep 17 00:00:00 2001
+From: Dirli <litandrej85@gmail.com>
+Date: Fri, 17 Apr 2020 00:52:53 +0300
+Subject: [PATCH 8/8] issue #127
+
+---
+ src/Indicator.vala              |  1 +
+ src/Models/CalendarModel.vala   | 17 ++++++---
+ src/Services/EventsManager.vala | 17 +++++++++
+ src/Widgets/CalendarDay.vala    |  3 +-
+ src/Widgets/CalendarGrid.vala   | 66 ++++++++++++++++++++++-----------
+ src/Widgets/CalendarView.vala   | 17 ++++-----
+ src/Widgets/EventsListBox.vala  |  6 ++-
+ 7 files changed, 87 insertions(+), 40 deletions(-)
+
+diff --git a/src/Indicator.vala b/src/Indicator.vala
+index c7550aa..63614e0 100644
+--- a/src/Indicator.vala
++++ b/src/Indicator.vala
+@@ -116,6 +116,7 @@ namespace DateTimeIndicator {
+                 model.notify["month-start"].connect (() => {
+                     model.compute_ranges ();
+ #if USE_EVO
++                    event_listbox.clear_list ();
+                     event_manager.load_all_sources ();
+ #endif
+                 });
+diff --git a/src/Models/CalendarModel.vala b/src/Models/CalendarModel.vala
+index d60a9ac..48b6e78 100644
+--- a/src/Models/CalendarModel.vala
++++ b/src/Models/CalendarModel.vala
+@@ -57,12 +57,17 @@ namespace DateTimeIndicator {
+             compute_ranges ();
+         }
+ 
+-        public void change_month (int relative) {
+-            month_start = month_start.add_months (relative);
+-        }
+-
+-        public void change_year (int relative) {
+-            month_start = month_start.add_years (relative);
++        public void change_month (int m_relative, int y_relative = 0) {
++            if (y_relative == 0) {
++                month_start = month_start.add_months (m_relative);
++            } else {
++                if (m_relative == 0) {
++                    month_start = month_start.add_years (y_relative);
++                } else {
++                    GLib.DateTime tmp_date = month_start.add_months (m_relative);
++                    month_start = tmp_date.add_years (y_relative);
++                }
++            }
+         }
+ 
+         /* --- Helper Methods ---// */
+diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala
+index 959762f..6ece557 100644
+--- a/src/Services/EventsManager.vala
++++ b/src/Services/EventsManager.vala
+@@ -1,3 +1,20 @@
++/*
++ * Copyright (c) 2011-2020 elementary, Inc. (https://elementary.io)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation; either
++ * version 3 of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
+ namespace DateTimeIndicator {
+     public class Services.EventsManager : GLib.Object {
+         public signal void events_added (E.Source source, Gee.Collection<ECal.Component> events);
+diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala
+index 10d088c..735fdc1 100644
+--- a/src/Widgets/CalendarDay.vala
++++ b/src/Widgets/CalendarDay.vala
+@@ -36,7 +36,6 @@ namespace DateTimeIndicator {
+         private static Gtk.CssProvider provider;
+         private static Models.CalendarModel model;
+ 
+-        // private Gee.HashMap<string, Gtk.Widget> event_dots;
+         private Gee.ArrayList<string> event_dots;
+         private Gtk.Grid event_grid;
+         private Gtk.Label label;
+@@ -105,7 +104,7 @@ namespace DateTimeIndicator {
+ 
+             /* It's mouse scroll ! */
+             if (choice == 1 || choice == -1) {
+-                Models.CalendarModel.get_default ().change_month ((int)choice);
++                Models.CalendarModel.get_default ().change_month ((int) choice);
+ 
+                 return true;
+             }
+diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala
+index 6e6cbdb..ef8edb6 100644
+--- a/src/Widgets/CalendarGrid.vala
++++ b/src/Widgets/CalendarGrid.vala
+@@ -32,7 +32,7 @@ namespace DateTimeIndicator {
+          */
+         public signal void on_event_add (GLib.DateTime date);
+ 
+-        public signal void selection_changed (GLib.DateTime new_date);
++        public signal void selection_changed (GLib.DateTime new_date, bool up);
+ 
+         private Gee.HashMap<uint, Widgets.CalendarDay> data;
+         private Widgets.CalendarDay selected_gridday;
+@@ -66,25 +66,32 @@ namespace DateTimeIndicator {
+             events |= Gdk.EventMask.SMOOTH_SCROLL_MASK;
+         }
+ 
+-        private void on_day_focus_in (Widgets.CalendarDay day) {
+-            debug ("on_day_focus_in %s", day.date.to_string ());
++        private bool on_day_focus_in (Gdk.EventFocus event) {
++            var day = get_focus_child ();
++            if (day == null) {
++                return false;
++            }
++
+             if (selected_gridday != null) {
+                 selected_gridday.set_selected (false);
+             }
+ 
+-            var selected_date = day.date;
+-            selected_gridday = day;
+-            day.set_selected (true);
++            var selected_date = (day as Widgets.CalendarDay).date;
++            selected_gridday = day as Widgets.CalendarDay;
++            (day as Widgets.CalendarDay).set_selected (true);
+             day.set_state_flags (Gtk.StateFlags.FOCUSED, false);
+-            selection_changed (selected_date);
+             var calmodel = Models.CalendarModel.get_default ();
+             var date_month = selected_date.get_month () - calmodel.month_start.get_month ();
+             var date_year = selected_date.get_year () - calmodel.month_start.get_year ();
+ 
+             if (date_month != 0 || date_year != 0) {
+-                calmodel.change_month (date_month);
+-                calmodel.change_year (date_year);
++                selection_changed (selected_date, false);
++                calmodel.change_month (date_month, date_year);
++            } else {
++                selection_changed (selected_date, true);
+             }
++
++            return false;
+         }
+ 
+         public void set_focus_to_today () {
+@@ -106,7 +113,7 @@ namespace DateTimeIndicator {
+          * Sets the given range to be displayed in the grid. Note that the number of days
+          * must remain the same.
+          */
+-        public void set_range (Util.DateRange new_range, GLib.DateTime month_start) {
++        public void set_range (Util.DateRange new_range, GLib.DateTime month_start, GLib.DateTime? selected_date) {
+             var today = new GLib.DateTime.now_local ();
+ 
+             Gee.List<GLib.DateTime> old_dates;
+@@ -138,28 +145,46 @@ namespace DateTimeIndicator {
+ 
+             for (i = 0; i < new_dates.size; i++) {
+                 var new_date = new_dates[i];
+-                Widgets.CalendarDay day;
++                Widgets.CalendarDay? day = null;
+ 
+                 if (i < old_dates.size) {
+                     /* A widget already exists for this date, just change it */
+ 
+                     var old_date = old_dates[i];
+-                    day = update_day (data[day_hash (old_date)], new_date, today, month_start);
+-                } else {
++                    var d_hash = day_hash (old_date);
++                    if (data.has_key (d_hash)) {
++                        day = data[d_hash];
++                    }
++                }
++
++                if (day == null) {
+                     /* Still update_day to get the color of etc. right */
+-                    day = update_day (new Widgets.CalendarDay (new_date), new_date, today, month_start);
++                    day = new Widgets.CalendarDay (new_date);
+                     day.on_event_add.connect ((date) => on_event_add (date));
+-                    day.scroll_event.connect ((event) => { scroll_event (event); return false; });
+-                    day.focus_in_event.connect ((event) => {
+-                        on_day_focus_in (day);
+-
++                    day.scroll_event.connect ((event) => {
++                        scroll_event (event);
+                         return false;
+                     });
++                    day.focus_in_event.connect (on_day_focus_in);
+ 
+                     attach (day, col + 2, row);
+                     day.show_all ();
+                 }
+ 
++                update_day (day, new_date, month_start);
++                update_today_style (day, new_date, today);
++                if (selected_date != null && day.date.equal (selected_date)) {
++                    /* disabled the signal to avoid unnecessary signals and selected
++                    * the specified day from the new period */
++                    debug (@"focus selected day $selected_date");
++                    day.focus_in_event.disconnect (on_day_focus_in);
++                    day.grab_focus_force ();
++                    day.set_selected (true);
++                    day.set_state_flags (Gtk.StateFlags.FOCUSED, false);
++                    selected_gridday = day;
++                    day.focus_in_event.connect (on_day_focus_in);
++                }
++
+                 col = (col + 1) % 7;
+                 row = (col == 0) ? row + 1 : row;
+                 data_new.set (day_hash (new_date), day);
+@@ -184,8 +209,7 @@ namespace DateTimeIndicator {
+         /**
+          * Updates the given CalendarDay so that it shows the given date. Changes to its style etc.
+          */
+-        private Widgets.CalendarDay update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) {
+-            update_today_style (day, new_date, today);
++        private void update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime month_start) {
+             if (new_date.get_month () == month_start.get_month ()) {
+                 day.sensitive_container (true);
+             } else {
+@@ -193,8 +217,6 @@ namespace DateTimeIndicator {
+             }
+ 
+             day.date = new_date;
+-
+-            return day;
+         }
+ 
+         public void update_weeks (GLib.DateTime date, int nr_of_weeks) {
+diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala
+index 77c233c..fe957ab 100644
+--- a/src/Widgets/CalendarView.vala
++++ b/src/Widgets/CalendarView.vala
+@@ -85,10 +85,7 @@ namespace DateTimeIndicator {
+             model.notify["data-range"].connect (() => {
+                 label.label = model.month_start.format (_("%OB, %Y"));
+ 
+-                sync_with_model ();
+-
+-                selected_date = null;
+-                selection_changed (selected_date);
++                sync_with_model (selected_date != null);
+             });
+ 
+             left_button.clicked.connect (() => {
+@@ -113,9 +110,11 @@ namespace DateTimeIndicator {
+                 day_double_click ();
+             });
+ 
+-            calendar_grid.selection_changed.connect ((date) => {
++            calendar_grid.selection_changed.connect ((date, up) => {
+                 selected_date = date;
+-                selection_changed (date);
++                if (up) {
++                    selection_changed (date);
++                }
+             });
+ 
+             return calendar_grid;
+@@ -154,9 +153,9 @@ namespace DateTimeIndicator {
+         }
+ 
+         /* Sets the calendar widgets to the date range of the model */
+-        private void sync_with_model () {
++        private void sync_with_model (bool show_selected = false) {
+             var model = Models.CalendarModel.get_default ();
+-            if (calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
++            if (!show_selected && calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) {
+                 calendar_grid.update_today ();
+                 return; // nothing else to do
+             }
+@@ -168,7 +167,7 @@ namespace DateTimeIndicator {
+             big_grid = create_big_grid ();
+             stack.add (big_grid);
+ 
+-            calendar_grid.set_range (model.data_range, model.month_start);
++            calendar_grid.set_range (model.data_range, model.month_start, show_selected ? selected_date : null);
+             calendar_grid.update_weeks (model.data_range.first_dt, model.num_weeks);
+ 
+             if (previous_first != null) {
+diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala
+index c25af2e..9022072 100644
+--- a/src/Widgets/EventsListBox.vala
++++ b/src/Widgets/EventsListBox.vala
+@@ -21,10 +21,14 @@ namespace DateTimeIndicator {
+             set_sort_func (sort_function);
+         }
+ 
+-        public void update_events (GLib.DateTime? selected_date, HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> source_events) {
++        public void clear_list () {
+             foreach (unowned Gtk.Widget widget in get_children ()) {
+                 widget.destroy ();
+             }
++        }
++
++        public void update_events (GLib.DateTime? selected_date, HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> source_events) {
++            clear_list ();
+ 
+             if (selected_date == null) {
+                 return;
diff --git a/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
index ed70687e0502..c6a0e2f7779f 100644
--- a/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
+++ b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
@@ -1,5 +1,5 @@
 { stdenv
-, fetchFromGitHub 
+, fetchFromGitHub
 , pantheon
 , pkgconfig
 , meson
@@ -28,6 +28,15 @@ stdenv.mkDerivation rec {
     sha256 = "0a0pqrpmrdd5pch30lizr9righlc7165z7krmnaxrzd0fvfkbr2h";
   };
 
+  patches = [
+    # https://github.com/elementary/wingpanel-indicator-datetime/pull/207
+    # Fixes lots of issues despite being rejected upstream
+    # https://github.com/elementary/wingpanel-indicator-datetime/issues/206
+    # https://github.com/elementary/wingpanel-indicator-datetime/issues/55
+    # https://github.com/elementary/wingpanel-indicator-datetime/issues/127
+    ./207.patch
+  ];
+
   passthru = {
     updateScript = pantheon.updateScript {
       attrPath = "pantheon.${pname}";
diff --git a/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel/default.nix b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
index 64ebee4f13d2..ff9925c53574 100644
--- a/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
+++ b/nixpkgs/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
@@ -65,6 +65,13 @@ stdenv.mkDerivation rec {
     patchShebangs meson/post_install.py
   '';
 
+  preFixup = ''
+    gappsWrapperArgs+=(
+      # this theme is required
+      --prefix XDG_DATA_DIRS : "${elementary-gtk-theme}/share"
+    )
+  '';
+
   meta = with stdenv.lib; {
     description = "The extensible top panel for Pantheon";
     longDescription = ''
diff --git a/nixpkgs/pkgs/desktops/xfce/applications/xfce4-notifyd/default.nix b/nixpkgs/pkgs/desktops/xfce/applications/xfce4-notifyd/default.nix
index 40d9c188fa3d..c9a614888404 100644
--- a/nixpkgs/pkgs/desktops/xfce/applications/xfce4-notifyd/default.nix
+++ b/nixpkgs/pkgs/desktops/xfce/applications/xfce4-notifyd/default.nix
@@ -4,9 +4,9 @@
 mkXfceDerivation {
   category = "apps";
   pname = "xfce4-notifyd";
-  version = "0.6.0";
+  version = "0.6.1";
 
-  sha256 = "03lw7zil6pwvx537ibqrynxjz7d6iq6in7vdskrnnn16kfg6hjg2";
+  sha256 = "18d2q5b54df8j2281lash8gm0826c6apn39q4igfz2zfcyqjh1if";
 
   buildInputs = [ exo gtk3 glib libnotify libxfce4ui libxfce4util xfce4-panel xfconf ];
 
diff --git a/nixpkgs/pkgs/desktops/xfce/art/xfce4-icon-theme.nix b/nixpkgs/pkgs/desktops/xfce/art/xfce4-icon-theme.nix
index e614bb1db921..526b70305917 100644
--- a/nixpkgs/pkgs/desktops/xfce/art/xfce4-icon-theme.nix
+++ b/nixpkgs/pkgs/desktops/xfce/art/xfce4-icon-theme.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, pkgconfig, intltool, gtk3, xfce }:
+{ stdenv, fetchurl, pkgconfig, intltool, gtk3, gnome-icon-theme, tango-icon-theme, hicolor-icon-theme, xfce }:
 
 let
   category = "art";
@@ -19,6 +19,15 @@ stdenv.mkDerivation rec {
     gtk3
   ];
 
+  buildInputs = [
+    gnome-icon-theme
+    tango-icon-theme
+    hicolor-icon-theme
+    # missing parent icon theme Industrial
+  ];
+
+  dontDropIconThemeCache = true;
+
   passthru.updateScript = xfce.updateScript {
     inherit pname version;
     attrPath = "xfce.${pname}";
diff --git a/nixpkgs/pkgs/desktops/xfce/core/xfce4-panel/default.nix b/nixpkgs/pkgs/desktops/xfce/core/xfce4-panel/default.nix
index ffd42e4a2c5b..b7bede9e27bb 100644
--- a/nixpkgs/pkgs/desktops/xfce/core/xfce4-panel/default.nix
+++ b/nixpkgs/pkgs/desktops/xfce/core/xfce4-panel/default.nix
@@ -3,9 +3,9 @@
 mkXfceDerivation {
   category = "xfce";
   pname = "xfce4-panel";
-  version = "4.14.3";
+  version = "4.14.4";
 
-  sha256 = "0h8cqs2bghmyp0jihjm2wc7j14k271j178vllin271xrl7kzmvzv";
+  sha256 = "1srzgb9vsvfrbhym74zkz9hdhxcrvbffxpfgv5vprhlwxw3vk3fq";
 
   nativeBuildInputs = [ gobject-introspection ];
   buildInputs = [ exo garcon gtk2 gtk3 glib glib-networking libxfce4ui libxfce4util libwnck3 xfconf ];
diff --git a/nixpkgs/pkgs/desktops/xfce/core/xfconf/default.nix b/nixpkgs/pkgs/desktops/xfce/core/xfconf/default.nix
index a0923f0fda1b..357f4b234108 100644
--- a/nixpkgs/pkgs/desktops/xfce/core/xfconf/default.nix
+++ b/nixpkgs/pkgs/desktops/xfce/core/xfconf/default.nix
@@ -3,9 +3,9 @@
 mkXfceDerivation {
   category = "xfce";
   pname = "xfconf";
-  version = "4.14.1";
+  version = "4.14.3";
 
-  sha256 = "1mbqc1463xgn7gafbh2fyshshdxin33iwk96y4nw2gl48nhx4sgs";
+  sha256 = "0yxpdcyz81di7w9493jzps09bgrlgianjj5abnzahqmkpmpvb0rh";
 
   buildInputs = [ libxfce4util ];
 
diff --git a/nixpkgs/pkgs/desktops/xfce/core/xfwm4/default.nix b/nixpkgs/pkgs/desktops/xfce/core/xfwm4/default.nix
index ed77699f191e..1d119014cab6 100644
--- a/nixpkgs/pkgs/desktops/xfce/core/xfwm4/default.nix
+++ b/nixpkgs/pkgs/desktops/xfce/core/xfwm4/default.nix
@@ -5,9 +5,9 @@
 mkXfceDerivation {
   category = "xfce";
   pname = "xfwm4";
-  version = "4.14.0"; # TODO: remove xfce4-14 alias when this gets bumped
+  version = "4.14.2";
 
-  sha256 = "1z5aqij2d8n9wnha88b0qzkvss54jvqs8w1w5m3mzjl4c9mn9n8m";
+  sha256 = "1zzc4q1j55hjljksmlyghk58bx7kxyq3scihsr9zgyqc24ww1ks3";
 
   nativeBuildInputs = [ exo librsvg ];
 
diff --git a/nixpkgs/pkgs/desktops/xfce/panel-plugins/xfce4-whiskermenu-plugin/default.nix b/nixpkgs/pkgs/desktops/xfce/panel-plugins/xfce4-whiskermenu-plugin/default.nix
index 262093af69f1..859a580bb70b 100644
--- a/nixpkgs/pkgs/desktops/xfce/panel-plugins/xfce4-whiskermenu-plugin/default.nix
+++ b/nixpkgs/pkgs/desktops/xfce/panel-plugins/xfce4-whiskermenu-plugin/default.nix
@@ -1,15 +1,20 @@
-{ mkXfceDerivation, gtk3, glib, cmake, exo, garcon, libxfce4ui, libxfce4util, xfce4-panel, xfconf }:
+{ mkXfceDerivation, gettext, gtk3, glib, cmake, exo, garcon, libxfce4ui, libxfce4util, xfce4-panel, xfconf }:
 
 mkXfceDerivation {
   category = "panel-plugins";
   pname = "xfce4-whiskermenu-plugin";
-  version = "2.4.3";
+  version = "2.4.4";
   rev-prefix = "v";
-  sha256 = "1cs3fps1bj0dd5az7fwrvw1xl3y621qk4dma3n73p7rr19j7fpsn";
+  sha256 = "08b82j9xp3vzjlc740s9svcjkbsal71ggp23y7dvjqppch7sdxzw";
 
   nativeBuildInputs = [ cmake ];
 
-  buildInputs = [ exo garcon gtk3 glib libxfce4ui libxfce4util xfce4-panel xfconf ];
+  buildInputs = [ gettext exo garcon gtk3 glib libxfce4ui libxfce4util xfce4-panel xfconf ];
+
+  postPatch = ''
+    substituteInPlace panel-plugin/xfce4-popup-whiskermenu.in \
+      --replace gettext ${gettext}/bin/gettext
+  '';
 
   postInstall = ''
     substituteInPlace $out/bin/xfce4-popup-whiskermenu \