diff --git a/doc/using/overlays.xml b/doc/using/overlays.xml index 5f808839dd0..3fa68e32a3c 100644 --- a/doc/using/overlays.xml +++ b/doc/using/overlays.xml @@ -140,8 +140,8 @@ self: super:
Using overlays to configure alternatives - Certain software has different implementations of the same - interface. Other distributions have functionality to switch + Certain software packages have different implementations of the + same interface. Other distributions have functionality to switch between these. For example, Debian provides DebianAlternatives. Nixpkgs has what we call alternatives, which @@ -160,8 +160,9 @@ self: super: The Nixpkgs attribute is openblas for - ILP64 and openblasCompat for LP64. This - is the default. + ILP64 (integer width = 64 bits) and + openblasCompat for LP64 (integer width = + 32 bits). openblasCompat is the default. @@ -190,8 +191,15 @@ self: super: #83888, we are able to override the ‘blas’ and ‘lapack’ packages to use different implementations, through the ‘blasProvider’ and ‘lapackProvider’ argument. This can be used - to select a different provider. For example, an overlay can be - created that looks like: + to select a different provider. BLAS providers will have + symlinks in $out/lib/libblas.so.3 and + $out/lib/libcblas.so.3 to their respective + BLAS libraries. Likewise, LAPACK providers will have symlinks + in $out/lib/liblapack.so.3 and + $out/lib/liblapacke.so.3 to their respective + LAPCK libraries. For example, Intel MKL is both a BLAS and + LAPACK provider. An overlay can be created to use Intel MKL + that looks like: self: super: @@ -208,9 +216,12 @@ self: super: This overlay uses Intel’s MKL library for both BLAS and LAPACK interfaces. Note that the same can be accomplished at runtime - using LD_PRELOAD of libblas.so.3 and - liblapack.so.3. + using LD_LIBRARY_PATH of libblas.so.3 and + liblapack.so.3. For instance: + +$ LD_LIBRARY_PATH=$(nix-build -A mkl)/lib:$LD_LIBRARY_PATH nix-shell -p octave --run octave + Intel MKL requires an openmp implementation when running with multiple processors. By default, @@ -221,8 +232,8 @@ self: super: set it with LD_PRELOAD. Note that mkl is only available on x86_64-linux and - x86_64-darwin. Moreover, Hydra is not build - and distributing pre-compiled binaries using it. + x86_64-darwin. Moreover, Hydra is not + building and distributing pre-compiled binaries using it. For BLAS/LAPACK switching to work correctly, all packages must diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index dcf96307c3b..a12f5443c6d 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -6738,6 +6738,12 @@ githubId = 2347889; name = "Sauyon Lee"; }; + savannidgerinel = { + email = "savanni@luminescent-dreams.com"; + github = "savannidgerinel"; + githubId = 8534888; + name = "Savanni D'Gerinel"; + }; sb0 = { email = "sb@m-labs.hk"; github = "sbourdeauducq"; diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index 4f5be91939d..016d68ea301 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -442,7 +442,7 @@ in Whether this NixOS machine is a lightweight container running in another NixOS system. If set to true, support for nested containers is disabled by default, but can be reenabled by - setting boot.enableContainers to true. + setting to true. ''; }; diff --git a/nixos/tests/systemd-confinement.nix b/nixos/tests/systemd-confinement.nix index f22836e227b..ebf6d218fd6 100644 --- a/nixos/tests/systemd-confinement.nix +++ b/nixos/tests/systemd-confinement.nix @@ -1,4 +1,4 @@ -import ./make-test.nix { +import ./make-test-python.nix { name = "systemd-confinement"; machine = { pkgs, lib, ... }: let @@ -17,7 +17,7 @@ import ./make-test.nix { exit "''${ret:-1}" ''; - mkTestStep = num: { description, config ? {}, testScript }: { + mkTestStep = num: { config ? {}, testScript }: { systemd.sockets."test${toString num}" = { description = "Socket for Test Service ${toString num}"; wantedBy = [ "sockets.target" ]; @@ -34,52 +34,48 @@ import ./make-test.nix { }; } // removeAttrs config [ "confinement" "serviceConfig" ]; - __testSteps = lib.mkOrder num '' - subtest '${lib.escape ["\\" "'"] description}', sub { - $machine->succeed('echo ${toString num} > /teststep'); - ${testScript} - }; - ''; + __testSteps = lib.mkOrder num ('' + machine.succeed("echo ${toString num} > /teststep") + '' + testScript); }; in { imports = lib.imap1 mkTestStep [ - { description = "chroot-only confinement"; - config.confinement.mode = "chroot-only"; + { config.confinement.mode = "chroot-only"; testScript = '' - $machine->succeed( - 'test "$(chroot-exec ls -1 / | paste -sd,)" = bin,nix', - 'test "$(chroot-exec id -u)" = 0', - 'chroot-exec chown 65534 /bin', - ); + with subtest("chroot-only confinement"): + machine.succeed( + 'test "$(chroot-exec ls -1 / | paste -sd,)" = bin,nix', + 'test "$(chroot-exec id -u)" = 0', + "chroot-exec chown 65534 /bin", + ) ''; } - { description = "full confinement with APIVFS"; - testScript = '' - $machine->fail( - 'chroot-exec ls -l /etc', - 'chroot-exec ls -l /run', - 'chroot-exec chown 65534 /bin', - ); - $machine->succeed( - 'test "$(chroot-exec id -u)" = 0', - 'chroot-exec chown 0 /bin', - ); + { testScript = '' + with subtest("full confinement with APIVFS"): + machine.fail( + "chroot-exec ls -l /etc", + "chroot-exec ls -l /run", + "chroot-exec chown 65534 /bin", + ) + machine.succeed( + 'test "$(chroot-exec id -u)" = 0', "chroot-exec chown 0 /bin", + ) ''; } - { description = "check existence of bind-mounted /etc"; - config.serviceConfig.BindReadOnlyPaths = [ "/etc" ]; + { config.serviceConfig.BindReadOnlyPaths = [ "/etc" ]; testScript = '' - $machine->succeed('test -n "$(chroot-exec cat /etc/passwd)"'); + with subtest("check existence of bind-mounted /etc"): + machine.succeed('test -n "$(chroot-exec cat /etc/passwd)"') ''; } - { description = "check if User/Group really runs as non-root"; - config.serviceConfig.User = "chroot-testuser"; + { config.serviceConfig.User = "chroot-testuser"; config.serviceConfig.Group = "chroot-testgroup"; testScript = '' - $machine->succeed('chroot-exec ls -l /dev'); - $machine->succeed('test "$(chroot-exec id -u)" != 0'); - $machine->fail('chroot-exec touch /bin/test'); + with subtest("check if User/Group really runs as non-root"): + machine.succeed("chroot-exec ls -l /dev") + machine.succeed('test "$(chroot-exec id -u)" != 0') + machine.fail("chroot-exec touch /bin/test") ''; } (let @@ -87,62 +83,60 @@ import ./make-test.nix { target = pkgs.writeText "symlink-target" "got me\n"; } "ln -s \"$target\" \"$out\""; in { - description = "check if symlinks are properly bind-mounted"; config.confinement.packages = lib.singleton symlink; testScript = '' - $machine->fail('chroot-exec test -e /etc'); - $machine->succeed('chroot-exec cat ${symlink} >&2'); - $machine->succeed('test "$(chroot-exec cat ${symlink})" = "got me"'); + with subtest("check if symlinks are properly bind-mounted"): + machine.fail("chroot-exec test -e /etc") + machine.succeed( + "chroot-exec cat ${symlink} >&2", + 'test "$(chroot-exec cat ${symlink})" = "got me"', + ) ''; }) - { description = "check if StateDirectory works"; - config.serviceConfig.User = "chroot-testuser"; + { config.serviceConfig.User = "chroot-testuser"; config.serviceConfig.Group = "chroot-testgroup"; config.serviceConfig.StateDirectory = "testme"; testScript = '' - $machine->succeed('chroot-exec touch /tmp/canary'); - $machine->succeed('chroot-exec "echo works > /var/lib/testme/foo"'); - $machine->succeed('test "$(< /var/lib/testme/foo)" = works'); - $machine->succeed('test ! -e /tmp/canary'); + with subtest("check if StateDirectory works"): + machine.succeed("chroot-exec touch /tmp/canary") + machine.succeed('chroot-exec "echo works > /var/lib/testme/foo"') + machine.succeed('test "$(< /var/lib/testme/foo)" = works') + machine.succeed("test ! -e /tmp/canary") ''; } - { description = "check if /bin/sh works"; + { testScript = '' + with subtest("check if /bin/sh works"): + machine.succeed( + "chroot-exec test -e /bin/sh", + 'test "$(chroot-exec \'/bin/sh -c "echo bar"\')" = bar', + ) + ''; + } + { config.confinement.binSh = null; testScript = '' - $machine->succeed( - 'chroot-exec test -e /bin/sh', - 'test "$(chroot-exec \'/bin/sh -c "echo bar"\')" = bar', - ); + with subtest("check if suppressing /bin/sh works"): + machine.succeed("chroot-exec test ! -e /bin/sh") + machine.succeed('test "$(chroot-exec \'/bin/sh -c "echo foo"\')" != foo') ''; } - { description = "check if suppressing /bin/sh works"; - config.confinement.binSh = null; + { config.confinement.binSh = "${pkgs.hello}/bin/hello"; testScript = '' - $machine->succeed( - 'chroot-exec test ! -e /bin/sh', - 'test "$(chroot-exec \'/bin/sh -c "echo foo"\')" != foo', - ); + with subtest("check if we can set /bin/sh to something different"): + machine.succeed("chroot-exec test -e /bin/sh") + machine.succeed('test "$(chroot-exec /bin/sh -g foo)" = foo') ''; } - { description = "check if we can set /bin/sh to something different"; - config.confinement.binSh = "${pkgs.hello}/bin/hello"; + { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n"; testScript = '' - $machine->succeed( - 'chroot-exec test -e /bin/sh', - 'test "$(chroot-exec /bin/sh -g foo)" = foo', - ); + with subtest("check if only Exec* dependencies are included"): + machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" != eek') ''; } - { description = "check if only Exec* dependencies are included"; - config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n"; - testScript = '' - $machine->succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" != eek'); - ''; - } - { description = "check if all unit dependencies are included"; - config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n"; + { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n"; config.confinement.fullUnit = true; testScript = '' - $machine->succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" = eek'); + with subtest("check if all unit dependencies are included"): + machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" = eek') ''; } ]; @@ -162,7 +156,6 @@ import ./make-test.nix { }; testScript = { nodes, ... }: '' - $machine->waitForUnit('multi-user.target'); - ${nodes.machine.config.__testSteps} - ''; + machine.wait_for_unit("multi-user.target") + '' + nodes.machine.config.__testSteps; } diff --git a/pkgs/applications/audio/dfasma/default.nix b/pkgs/applications/audio/dfasma/default.nix index 7965cbd83fd..6df4679d1d5 100644 --- a/pkgs/applications/audio/dfasma/default.nix +++ b/pkgs/applications/audio/dfasma/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchFromGitHub, fftw, libsndfile, qtbase, qtmultimedia, qmake }: +{ mkDerivation, stdenv, fetchFromGitHub, fftw, libsndfile, qtbase, qtmultimedia, qmake }: let @@ -26,7 +26,7 @@ let }; }; -in stdenv.mkDerivation rec { +in mkDerivation rec { pname = "dfasma"; version = "1.4.5"; diff --git a/pkgs/applications/audio/iannix/default.nix b/pkgs/applications/audio/iannix/default.nix index 2d4a2e9265a..fa779a7f0f4 100644 --- a/pkgs/applications/audio/iannix/default.nix +++ b/pkgs/applications/audio/iannix/default.nix @@ -1,7 +1,7 @@ -{ stdenv, fetchFromGitHub, alsaLib, pkgconfig, qtbase, qtscript, qmake +{ mkDerivation, stdenv, fetchFromGitHub, alsaLib, pkgconfig, qtbase, qtscript, qmake }: -stdenv.mkDerivation { +mkDerivation { pname = "iannix"; version = "2016-01-31"; src = fetchFromGitHub { diff --git a/pkgs/applications/audio/traverso/default.nix b/pkgs/applications/audio/traverso/default.nix index 504e6ae9644..63ba44bec35 100644 --- a/pkgs/applications/audio/traverso/default.nix +++ b/pkgs/applications/audio/traverso/default.nix @@ -1,8 +1,8 @@ -{ stdenv, fetchurl, cmake, pkgconfig +{ mkDerivation, stdenv, fetchurl, cmake, pkgconfig , alsaLib, fftw, flac, lame, libjack2, libmad, libpulseaudio , libsamplerate, libsndfile, libvorbis, portaudio, qtbase, wavpack }: -stdenv.mkDerivation { +mkDerivation { pname = "traverso"; version = "0.49.6"; diff --git a/pkgs/applications/editors/mindforger/default.nix b/pkgs/applications/editors/mindforger/default.nix index 1397ea2d586..82aa38c1449 100644 --- a/pkgs/applications/editors/mindforger/default.nix +++ b/pkgs/applications/editors/mindforger/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchurl, qmake, qtbase, qtwebkit }: +{ mkDerivation, stdenv, fetchurl, qmake, qtbase, qtwebkit }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "mindforger"; version = "1.48.2"; diff --git a/pkgs/applications/editors/okteta/default.nix b/pkgs/applications/editors/okteta/default.nix index fa63ee90adc..b9d92409198 100644 --- a/pkgs/applications/editors/okteta/default.nix +++ b/pkgs/applications/editors/okteta/default.nix @@ -1,8 +1,8 @@ -{ stdenv, fetchurl, extra-cmake-modules, kdoctools, qtscript, kconfig +{ mkDerivation, stdenv, fetchurl, extra-cmake-modules, kdoctools, qtscript, kconfig , kinit, karchive, kcrash, kcmutils, kconfigwidgets, knewstuff, kparts , qca-qt5, shared-mime-info }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "okteta"; version = "0.26.3"; diff --git a/pkgs/applications/graphics/awesomebump/default.nix b/pkgs/applications/graphics/awesomebump/default.nix index c02140e1905..4d79f10a9e1 100644 --- a/pkgs/applications/graphics/awesomebump/default.nix +++ b/pkgs/applications/graphics/awesomebump/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, fetchgit, qtbase, qmake, makeWrapper, qtscript, flex, bison, qtdeclarative }: +{ mkDerivation, lib, fetchgit, qtbase, qmake, qtscript, flex, bison, qtdeclarative }: let @@ -11,7 +11,7 @@ let fetchSubmodules = true; }; - qtnproperty = stdenv.mkDerivation { + qtnproperty = mkDerivation { name = "qtnproperty"; inherit src; sourceRoot = "AwesomeBump/Sources/utils/QtnProperty"; @@ -22,7 +22,7 @@ let install -D bin-linux/QtnPEG $out/bin/QtnPEG ''; }; -in stdenv.mkDerivation { +in mkDerivation { pname = "awesomebump"; inherit version; @@ -30,12 +30,13 @@ in stdenv.mkDerivation { buildInputs = [ qtbase qtscript qtdeclarative ]; - nativeBuildInputs = [ qmake makeWrapper ]; + nativeBuildInputs = [ qmake ]; preBuild = '' ln -sf ${qtnproperty}/bin/QtnPEG Sources/utils/QtnProperty/bin-linux/QtnPEG ''; + dontWrapQtApps = true; postInstall = '' d=$out/libexec/AwesomeBump @@ -44,7 +45,7 @@ in stdenv.mkDerivation { cp -prd Bin/Configs Bin/Core $d/ # AwesomeBump expects to find Core and Configs in its current directory. - makeWrapper $d/AwesomeBump $out/bin/AwesomeBump \ + makeQtWrapper $d/AwesomeBump $out/bin/AwesomeBump \ --run "cd $d" ''; diff --git a/pkgs/applications/graphics/phototonic/default.nix b/pkgs/applications/graphics/phototonic/default.nix index 1c6c1b43354..7020bf6c83e 100644 --- a/pkgs/applications/graphics/phototonic/default.nix +++ b/pkgs/applications/graphics/phototonic/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qtbase, qmake, exiv2 }: +{ mkDerivation, stdenv, fetchFromGitHub, qtbase, qmake, exiv2 }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "phototonic"; version = "2.1"; diff --git a/pkgs/applications/graphics/qcomicbook/default.nix b/pkgs/applications/graphics/qcomicbook/default.nix index 4f7e5b931f4..f9dc494b4b3 100644 --- a/pkgs/applications/graphics/qcomicbook/default.nix +++ b/pkgs/applications/graphics/qcomicbook/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, pkgconfig, cmake, qtbase, qttools, qtx11extras, poppler }: +{ mkDerivation, stdenv, fetchFromGitHub, pkgconfig, cmake, qtbase, qttools, qtx11extras, poppler }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "qcomicbook"; version = "0.9.1"; diff --git a/pkgs/applications/graphics/write_stylus/default.nix b/pkgs/applications/graphics/write_stylus/default.nix index b1bfbe3c4cf..31fc4045026 100644 --- a/pkgs/applications/graphics/write_stylus/default.nix +++ b/pkgs/applications/graphics/write_stylus/default.nix @@ -1,4 +1,4 @@ -{ stdenv, lib, qtbase, qtsvg, libglvnd, fetchurl, makeDesktopItem }: +{ mkDerivation, stdenv, lib, qtbase, qtsvg, libglvnd, fetchurl, makeDesktopItem }: let # taken from: https://www.iconfinder.com/icons/50835/edit_pencil_write_icon # license: Free for commercial use @@ -7,7 +7,7 @@ let sha256 = "0abdya42yf9alxbsmc2nf8jwld50zfria6z3d4ncvp1zw2a9jhb8"; }; in -stdenv.mkDerivation rec { +mkDerivation rec { pname = "write_stylus"; version = "209"; diff --git a/pkgs/applications/misc/bibletime/default.nix b/pkgs/applications/misc/bibletime/default.nix index 9489bfa0016..cfac79bef4b 100644 --- a/pkgs/applications/misc/bibletime/default.nix +++ b/pkgs/applications/misc/bibletime/default.nix @@ -1,8 +1,8 @@ -{ stdenv, fetchurl, cmake, pkgconfig, sword, boost, clucene_core +{ mkDerivation, stdenv, fetchurl, cmake, pkgconfig, sword, boost, clucene_core , qtbase, qttools, qtsvg, qtwebkit }: -stdenv.mkDerivation rec { +mkDerivation rec { version = "2.11.2"; diff --git a/pkgs/applications/misc/candle/default.nix b/pkgs/applications/misc/candle/default.nix index a951046ce01..842ef2262d9 100644 --- a/pkgs/applications/misc/candle/default.nix +++ b/pkgs/applications/misc/candle/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qtbase, qtserialport, qmake }: +{ mkDerivation, stdenv, fetchFromGitHub, qtbase, qtserialport, qmake }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "candle"; version = "1.1"; diff --git a/pkgs/applications/misc/fitnesstrax/default.nix b/pkgs/applications/misc/fitnesstrax/default.nix new file mode 100644 index 00000000000..f0081c39102 --- /dev/null +++ b/pkgs/applications/misc/fitnesstrax/default.nix @@ -0,0 +1,43 @@ +{ fetchFromGitHub +, glib +, gtk3 +, lib +, rustPlatform +, wrapGAppsHook +}: + +rustPlatform.buildRustPackage rec { + pname = "fitnesstrax"; + version = "0.1.0"; + + src = fetchFromGitHub { + owner = "luminescent-dreams"; + repo = "fitnesstrax"; + rev = "${pname}-${version}"; + sha256 = "1k6zhnbs0ggx7q0ig2abcnzprsgrychlpvsh6d36dw6mr8zpfkp7"; + }; + + nativeBuildInputs = [ + wrapGAppsHook + ]; + + buildInputs = [ + glib + gtk3 + ]; + + cargoSha256 = "1xgyyxd2kz21xan0pk7rbxiym90s7m2qrzg2ddilcszva60bxdd9"; + + postInstall = '' + mkdir -p $out/share/glib-2.0/schemas + cp -r $src/share/* $out/share/ + glib-compile-schemas $out/share/glib-2.0/schemas + ''; + + meta = with lib; { + description = "Privacy-first fitness tracking"; + homepage = "https://github.com/luminescent-dreams/fitnesstrax"; + license = licenses.bsd3; + maintainers = with maintainers; [ savannidgerinel ]; + }; +} diff --git a/pkgs/applications/misc/openbrf/default.nix b/pkgs/applications/misc/openbrf/default.nix index 6140343fae7..8e990b6dffb 100644 --- a/pkgs/applications/misc/openbrf/default.nix +++ b/pkgs/applications/misc/openbrf/default.nix @@ -1,7 +1,7 @@ -{ stdenv, fetchFromGitHub, qtbase, vcg, glew, qmake, libGLU, libGL }: +{ mkDerivation, stdenv, fetchFromGitHub, qtbase, vcg, glew, qmake, libGLU, libGL }: -stdenv.mkDerivation { +mkDerivation { name = "openbrf-unstable-2016-01-09"; src = fetchFromGitHub { diff --git a/pkgs/applications/misc/qt-box-editor/default.nix b/pkgs/applications/misc/qt-box-editor/default.nix index c65e5377eb3..852f0d30f9a 100644 --- a/pkgs/applications/misc/qt-box-editor/default.nix +++ b/pkgs/applications/misc/qt-box-editor/default.nix @@ -1,4 +1,5 @@ -{ stdenv +{ mkDerivation +, stdenv , fetchFromGitHub , qtbase , qtsvg @@ -7,7 +8,7 @@ , tesseract }: -stdenv.mkDerivation { +mkDerivation { pname = "qt-box-editor"; version = "unstable-2019-07-12"; diff --git a/pkgs/applications/misc/valentina/default.nix b/pkgs/applications/misc/valentina/default.nix index 6a1dd06de32..e9e8cfed796 100644 --- a/pkgs/applications/misc/valentina/default.nix +++ b/pkgs/applications/misc/valentina/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchhg +{ mkDerivation, stdenv, fetchhg , qmake, qttools , qtbase, qtsvg, qtxmlpatterns , poppler_utils @@ -6,7 +6,7 @@ with stdenv.lib; -stdenv.mkDerivation rec { +mkDerivation rec { pname = "valentina"; version = "0.6.1"; diff --git a/pkgs/applications/networking/instant-messengers/ricochet/default.nix b/pkgs/applications/networking/instant-messengers/ricochet/default.nix index 01295697ad3..de46c891d1f 100644 --- a/pkgs/applications/networking/instant-messengers/ricochet/default.nix +++ b/pkgs/applications/networking/instant-messengers/ricochet/default.nix @@ -1,9 +1,9 @@ -{ stdenv, fetchurl, pkgconfig, makeDesktopItem +{ mkDerivation, stdenv, fetchurl, pkgconfig, makeDesktopItem , qtbase, qttools, qtmultimedia, qtquick1, qtquickcontrols , openssl, protobuf, qmake }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "ricochet"; version = "1.1.4"; diff --git a/pkgs/applications/networking/instant-messengers/swift-im/default.nix b/pkgs/applications/networking/instant-messengers/swift-im/default.nix index ce59d574619..953ce2809c4 100644 --- a/pkgs/applications/networking/instant-messengers/swift-im/default.nix +++ b/pkgs/applications/networking/instant-messengers/swift-im/default.nix @@ -1,9 +1,9 @@ -{ stdenv, fetchurl, pkgconfig, qttools, scons +{ mkDerivation, stdenv, fetchurl, pkgconfig, qttools, scons , GConf, avahi, boost, hunspell, libXScrnSaver, libedit, libidn, libnatpmp, libxml2 , lua, miniupnpc, openssl, qtbase, qtmultimedia, qtsvg, qtwebkit, qtx11extras, zlib }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "swift-im"; version = "4.0.2"; diff --git a/pkgs/applications/networking/instant-messengers/tensor/default.nix b/pkgs/applications/networking/instant-messengers/tensor/default.nix index dcb2c720bc6..1ea249a8b51 100644 --- a/pkgs/applications/networking/instant-messengers/tensor/default.nix +++ b/pkgs/applications/networking/instant-messengers/tensor/default.nix @@ -1,9 +1,9 @@ -{ stdenv, fetchgit, qtbase, qtquickcontrols, qmake, makeDesktopItem }: +{ mkDerivation, stdenv, fetchgit, qtbase, qtquickcontrols, qmake, makeDesktopItem }: # we now have libqmatrixclient so a future version of tensor that supports it # should use that -stdenv.mkDerivation rec { +mkDerivation rec { pname = "tensor-git"; version = "2017-02-21"; diff --git a/pkgs/applications/networking/p2p/tixati/default.nix b/pkgs/applications/networking/p2p/tixati/default.nix index 8691335d129..151d652de52 100644 --- a/pkgs/applications/networking/p2p/tixati/default.nix +++ b/pkgs/applications/networking/p2p/tixati/default.nix @@ -2,11 +2,11 @@ stdenv.mkDerivation rec { pname = "tixati"; - version = "2.67"; + version = "2.72"; src = fetchurl { url = "https://download2.tixati.com/download/tixati-${version}-1.x86_64.manualinstall.tar.gz"; - sha256 = "0510wkwmwrlv61958zd5nsc4lr0l0lka3jf4pq3dyiyfsf4k20rq"; + sha256 = "04si7xwbpvljdbngmzlfvkn51wih3aqcb5g6r76wdh3pfpppskhr"; }; installPhase = '' diff --git a/pkgs/applications/office/elementary-planner/default.nix b/pkgs/applications/office/elementary-planner/default.nix index b01c34d5a0e..0f5ec6137d6 100644 --- a/pkgs/applications/office/elementary-planner/default.nix +++ b/pkgs/applications/office/elementary-planner/default.nix @@ -1,6 +1,12 @@ -{ stdenv, fetchFromGitHub, fetchpatch -, meson, ninja, pkgconfig, desktop-file-utils -, python3, vala, wrapGAppsHook +{ stdenv +, fetchFromGitHub +, meson +, ninja +, pkgconfig +, desktop-file-utils +, python3 +, vala +, wrapGAppsHook , evolution-data-server , libical , libgee @@ -63,8 +69,15 @@ stdenv.mkDerivation rec { patchShebangs build-aux/meson/post_install.py ''; + preFixup = '' + gappsWrapperArgs+=( + # the theme is hardcoded + --prefix XDG_DATA_DIRS : "${pantheon.elementary-gtk-theme}/share" + ) + ''; + meta = with stdenv.lib; { - description = "Task and project manager designed to elementary OS"; + description = "Task manager with Todoist support designed for GNU/Linux 🚀️"; homepage = "https://planner-todo.web.app"; license = licenses.gpl3; maintainers = with maintainers; [ dtzWill ] ++ pantheon.maintainers; diff --git a/pkgs/applications/science/electronics/caneda/default.nix b/pkgs/applications/science/electronics/caneda/default.nix index 6f832013e8c..c90ceac6788 100644 --- a/pkgs/applications/science/electronics/caneda/default.nix +++ b/pkgs/applications/science/electronics/caneda/default.nix @@ -1,6 +1,6 @@ -{stdenv, fetchFromGitHub, cmake, qtbase, qttools, qtsvg, qwt }: +{ mkDerivation, stdenv, fetchFromGitHub, cmake, qtbase, qttools, qtsvg, qwt }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "caneda"; version = "0.3.1"; diff --git a/pkgs/applications/version-management/git-and-tools/gh/default.nix b/pkgs/applications/version-management/git-and-tools/gh/default.nix index acd09f0d0c0..597e0672073 100644 --- a/pkgs/applications/version-management/git-and-tools/gh/default.nix +++ b/pkgs/applications/version-management/git-and-tools/gh/default.nix @@ -2,19 +2,19 @@ buildGoModule rec { pname = "gh"; - version = "0.6.4"; + version = "0.7.0"; src = fetchFromGitHub { owner = "cli"; repo = "cli"; rev = "v${version}"; - sha256 = "0na8zfvcmdy968i47x6qd1jwfaphy5h18ff7ym5sxyia9a27yhf8"; + sha256 = "054mag8jgxkvx2f95ha10n45v4xv5lms69w76g95z18m62qhjcyl"; }; - modSha256 = "102v30wr9wmd6n20qdvgs5mp2s639pwbqqd71r8q52f42p694bi1"; + modSha256 = "0v33x9bnwjfg4425vralnsb4i22c0g1rcmaga9911v0i7d51k0fn"; buildFlagsArray = [ - "-ldflags=-X github.com/cli/cli/command.Version=${version}" + "-ldflags=-s -w -X github.com/cli/cli/command.Version=${version}" ]; subPackages = [ "cmd/gh" ]; diff --git a/pkgs/applications/version-management/git-and-tools/git-gone/default.nix b/pkgs/applications/version-management/git-and-tools/git-gone/default.nix index aaf22c940cb..32350fa538d 100644 --- a/pkgs/applications/version-management/git-and-tools/git-gone/default.nix +++ b/pkgs/applications/version-management/git-and-tools/git-gone/default.nix @@ -1,23 +1,27 @@ -{ stdenv, fetchFromGitHub, rustPlatform, pkgconfig, makeWrapper, openssl, git, libiconv, Security }: +{ stdenv, fetchFromGitHub, rustPlatform, pkgconfig, makeWrapper, openssl, git, libiconv, Security, installShellFiles }: rustPlatform.buildRustPackage rec { pname = "git-gone"; - version = "0.3.0"; + version = "0.3.2"; src = fetchFromGitHub { owner = "lunaryorn"; repo = pname; rev = "v${version}"; - sha256 = "05wlng563p9iy0ky3z23a4jakcix887fb45r7j2mk0fp5ykdjmzh"; + sha256 = "0zc4cb1dg30np5yc4ymkr894qs2bk0r123i302md00niayk4njyd"; }; - cargoSha256 = "1scp9rzn59akxsf9p48j1zq6clbwdyasnyi4j28nj03ghvdv2i33"; + cargoSha256 = "1d892889ml7sqyxzmjipq5fvizb4abqhmmn450qm7yam9fn5q5wf"; - nativeBuildInputs = [ pkgconfig makeWrapper ]; + nativeBuildInputs = [ pkgconfig makeWrapper installShellFiles ]; buildInputs = [ openssl ] ++ stdenv.lib.optionals stdenv.isDarwin [ libiconv Security ]; + postInstall = '' + installManPage git-gone.1 + ''; + postFixup = '' wrapProgram $out/bin/git-gone --prefix PATH : "${stdenv.lib.makeBinPath [ git ]}" ''; diff --git a/pkgs/applications/video/bomi/default.nix b/pkgs/applications/video/bomi/default.nix index 7ba37936c68..d812ac48874 100644 --- a/pkgs/applications/video/bomi/default.nix +++ b/pkgs/applications/video/bomi/default.nix @@ -1,7 +1,7 @@ -{ config, stdenv, fetchFromGitHub +{ mkDerivation, config, stdenv, fetchFromGitHub , fetchpatch, pkgconfig, perl, python, which , libX11, libxcb, libGLU, libGL -, qtbase, qtdeclarative, qtquickcontrols, qttools, qtx11extras, qmake, makeWrapper +, qtbase, qtdeclarative, qtquickcontrols, qttools, qtx11extras, qmake , libchardet , ffmpeg @@ -29,7 +29,7 @@ assert pulseSupport -> libpulseaudio != null; assert cddaSupport -> libcdda != null; assert youtubeSupport -> youtube-dl != null; -stdenv.mkDerivation rec { +mkDerivation rec { pname = "bomi"; version = "0.9.11"; @@ -90,8 +90,9 @@ stdenv.mkDerivation rec { patchShebangs build-mpv ''; + dontWrapQtApps = true; postInstall = '' - wrapProgram $out/bin/bomi \ + wrapQtApp $out/bin/bomi \ ${optionalString youtubeSupport "--prefix PATH ':' '${youtube-dl}/bin'"} ''; @@ -105,7 +106,7 @@ stdenv.mkDerivation rec { ++ optional cddaSupport "--enable-cdda" ; - nativeBuildInputs = [ makeWrapper pkgconfig perl python which qttools qmake ]; + nativeBuildInputs = [ pkgconfig perl python which qttools qmake ]; meta = with stdenv.lib; { description = "Powerful and easy-to-use multimedia player"; diff --git a/pkgs/applications/video/qmediathekview/default.nix b/pkgs/applications/video/qmediathekview/default.nix index 16006668846..7556727a80d 100644 --- a/pkgs/applications/video/qmediathekview/default.nix +++ b/pkgs/applications/video/qmediathekview/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qtbase, qttools, xz, boost, qmake, pkgconfig }: +{ mkDerivation, stdenv, fetchFromGitHub, qtbase, qttools, xz, boost, qmake, pkgconfig }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "QMediathekView"; version = "2019-01-06"; diff --git a/pkgs/applications/video/qstopmotion/default.nix b/pkgs/applications/video/qstopmotion/default.nix index e2243797a3b..4a6d2a05a67 100644 --- a/pkgs/applications/video/qstopmotion/default.nix +++ b/pkgs/applications/video/qstopmotion/default.nix @@ -1,8 +1,8 @@ -{ stdenv, fetchurl, qt5, ffmpeg, guvcview, cmake, ninja, libxml2 +{ mkDerivation, stdenv, fetchurl, qt5, ffmpeg, guvcview, cmake, ninja, libxml2 , gettext, pkgconfig, libgphoto2, gphoto2, v4l-utils, libv4l, pcre , qwt, extra-cmake-modules }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "qstopmotion"; version = "2.4.1"; diff --git a/pkgs/applications/virtualization/aqemu/default.nix b/pkgs/applications/virtualization/aqemu/default.nix index f98b8eefd78..9177f264502 100644 --- a/pkgs/applications/virtualization/aqemu/default.nix +++ b/pkgs/applications/virtualization/aqemu/default.nix @@ -1,7 +1,7 @@ -{ cmake, fetchFromGitHub, libvncserver, qemu, qtbase, stdenv +{ mkDerivation, cmake, fetchFromGitHub, libvncserver, qemu, qtbase, stdenv }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "aqemu"; version = "0.9.2"; diff --git a/pkgs/build-support/alternatives/blas/default.nix b/pkgs/build-support/alternatives/blas/default.nix index 8bba49b4550..bdee6688a74 100644 --- a/pkgs/build-support/alternatives/blas/default.nix +++ b/pkgs/build-support/alternatives/blas/default.nix @@ -63,7 +63,7 @@ stdenv.mkDerivation { installPhase = ('' mkdir -p $out/lib $dev/include $dev/lib/pkgconfig - libblas="${lib.getLib blasProvider}/lib/libblas${stdenv.hostPlatform.extensions.sharedLibrary}" + libblas="${lib.getLib blasProvider}/lib/libblas${canonicalExtension}" if ! [ -e "$libblas" ]; then echo "$libblas does not exist, ${blasProvider.name} does not provide libblas." @@ -100,7 +100,7 @@ Libs: -L$out/lib -lblas Cflags: -I$dev/include EOF - libcblas="${lib.getLib blasProvider}/lib/libcblas${stdenv.hostPlatform.extensions.sharedLibrary}" + libcblas="${lib.getLib blasProvider}/lib/libcblas${canonicalExtension}" if ! [ -e "$libcblas" ]; then echo "$libcblas does not exist, ${blasProvider.name} does not provide libcblas." diff --git a/pkgs/build-support/alternatives/lapack/default.nix b/pkgs/build-support/alternatives/lapack/default.nix index e260ad1bd93..5a19916f83e 100644 --- a/pkgs/build-support/alternatives/lapack/default.nix +++ b/pkgs/build-support/alternatives/lapack/default.nix @@ -41,7 +41,7 @@ stdenv.mkDerivation { installPhase = ('' mkdir -p $out/lib $dev/include $dev/lib/pkgconfig - liblapack="${lib.getLib lapackProvider}/lib/liblapack${stdenv.hostPlatform.extensions.sharedLibrary}" + liblapack="${lib.getLib lapackProvider}/lib/liblapack${canonicalExtension}" if ! [ -e "$liblapack" ]; then echo "$liblapack does not exist, ${lapackProvider.name} does not provide liblapack." @@ -74,7 +74,7 @@ Cflags: -I$dev/include Libs: -L$out/lib -llapack EOF - liblapacke="${lib.getLib lapackProvider}/lib/liblapacke${stdenv.hostPlatform.extensions.sharedLibrary}" + liblapacke="${lib.getLib lapackProvider}/lib/liblapacke${canonicalExtension}" if ! [ -e "$liblapacke" ]; then echo "$liblapacke does not exist, ${lapackProvider.name} does not provide liblapacke." diff --git a/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix b/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix index 432f7c3ac5f..64c4509280a 100644 --- a/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix +++ b/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/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch new file mode 100644 index 00000000000..c4d6d8574a5 --- /dev/null +++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/207.patch @@ -0,0 +1,4726 @@ +From 20228e34bf97f67b1dd542a22e92cd90f0db5c72 Mon Sep 17 00:00:00 2001 +From: Dirli +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 +- */ +- +-public class Util.DateIterator : Object, Gee.Traversable, Gee.Iterator { +- 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 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 +- */ +- +-/* Represents date range from 'first' to 'last' inclusive */ +-public class Util.DateRange : Object, Gee.Traversable, Gee.Iterable { +- public GLib.DateTime first_dt { get; construct; } +- public GLib.DateTime last_dt { get; construct; } +- +- public bool @foreach (Gee.ForallFunc 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 iterator () { +- return new DateIterator (this); +- } +- +- public Gee.List to_list () { +- var list = new Gee.ArrayList ((Gee.EqualDataFunc? )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 events) { ++ idle_update_events (); + } + +- return 0; +- } +- +- private void update_events_model (E.Source source, Gee.Collection 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 (); ++ var events_on_day = new Gee.TreeMap (); + +- 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 . + */ + +-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 (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 (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 (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 (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 ++ */ ++ ++namespace DateTimeIndicator { ++ public class Util.DateIterator : Object, Gee.Traversable, Gee.Iterator { ++ 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 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 ++ */ ++ ++namespace DateTimeIndicator { ++/* Represents date range from 'first' to 'last' inclusive */ ++ public class Util.DateRange : Object, Gee.Traversable, Gee.Iterable { ++ public GLib.DateTime first_dt { get; construct; } ++ public GLib.DateTime last_dt { get; construct; } ++ ++ public bool @foreach (Gee.ForallFunc 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 iterator () { ++ return new DateIterator (this); ++ } ++ ++ public Gee.List to_list () { ++ var list = new Gee.ArrayList ((Gee.EqualDataFunc? )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 + */ + +-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 . ++ * ++ * Authored by: Maxwell Barvian ++ * Corentin Noël ++ */ ++ ++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 = "%s – %s".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 = "%s – %s".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 + */ + +-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 (); + 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 . ++ * ++ * Authored by: Maxwell Barvian ++ * Corentin Noël ++ */ ++ ++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 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 (); ++ ++ model.events_added.connect (add_event_dots); ++ model.events_removed.connect (remove_event_dots); ++ } ++ ++ private void add_event_dots (E.Source source, Gee.Collection 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 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 . +- * +- * Authored by: Maxwell Barvian +- * Corentin Noël +- */ +- +-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 . +- * +- * Authored by: Maxwell Barvian +- * Corentin Noël +- */ +- +-/** +- * 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 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 (); +- +- model.events_added.connect (add_event_dots); +- model.events_removed.connect (remove_event_dots); +- } +- +- private void add_event_dots (E.Source source, Gee.Collection 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 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 +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 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 (); +- +- 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 (); ++ ++ 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 +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 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> source_events { get; private set; } +- +- /* Notifies when events are added, updated, or removed */ +- public signal void events_added (E.Source source, Gee.Collection events); +- public signal void events_updated (E.Source source, Gee.Collection events); +- public signal void events_removed (E.Source source, Gee.Collection events); +- +- private E.SourceRegistry registry { get; private set; } +- private HashTable source_client; +- private HashTable 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 (str_hash, str_equal); +- source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); +- source_view = new HashTable (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 ( +- (GLib.CompareDataFunc?) GLib.strcmp, +- (GLib.CompareDataFunc?) 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 objects) { +-#else +- private void on_objects_added (E.Source source, ECal.Client client, SList 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 ((Gee.EqualDataFunc?) 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 objects) { +-#else +- private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { +-#endif +- debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ()); +- var updated_events = new Gee.ArrayList ((Gee.EqualDataFunc?) 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 cids) { +-#else +- private void on_objects_removed (E.Source source, ECal.Client client, SList 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 ((Gee.EqualDataFunc?) 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 events); ++ public signal void events_updated (E.Source source, Gee.Collection events); ++ public signal void events_removed (E.Source source, Gee.Collection events); ++ ++ public HashTable> source_events { get; private set; } ++ ++ private E.SourceRegistry registry { get; private set; } ++ private HashTable source_client; ++ private HashTable source_view; ++ ++ public EventsManager () { ++ ++ } ++ ++ construct { ++ source_client = new HashTable (str_hash, str_equal); ++ source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); ++ source_view = new HashTable (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 ( ++ (GLib.CompareDataFunc?) GLib.strcmp, ++ (GLib.CompareDataFunc?) 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 objects) { ++#else ++ private void on_objects_added (E.Source source, ECal.Client client, SList 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 ((Gee.EqualDataFunc?) 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 objects) { ++#else ++ private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { ++#endif ++ debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ()); ++ var updated_events = new Gee.ArrayList ((Gee.EqualDataFunc?) 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 cids) { ++#else ++ private void on_objects_removed (E.Source source, ECal.Client client, SList 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 ((Gee.EqualDataFunc?) 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 events) { ++ grid.add_event_dots (source, events); ++ } ++ ++ ++ public void remove_event_dots (E.Source source, Gee.Collection 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> 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 (); + +- 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 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 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 (); +- +- model.events_added.connect (add_event_dots); +- model.events_removed.connect (remove_event_dots); + } + +- private void add_event_dots (E.Source source, Gee.Collection 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 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 +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 data; +- private GridDay selected_gridday; ++ private Gee.HashMap 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 (); ++ data = new Gee.HashMap (); + 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 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 (); ++ var data_new = new Gee.HashMap (); + + /* 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 events) { +- grid.add_event_dots (source, events); ++ calendar_grid.add_event_dots (source, events); + } + +- + public void remove_event_dots (E.Source source, Gee.Collection 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 +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 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? 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 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 events) { + calendar_grid.add_event_dots (source, events); + } +@@ -189,5 +190,6 @@ namespace DateTimeIndicator { + public void remove_event_dots (E.Source source, Gee.Collection events) { + calendar_grid.remove_event_dots (source, events); + } ++#endif + } + } + +From 16715f5114c0597d6961880bf877f04414400334 Mon Sep 17 00:00:00 2001 +From: Dirli +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 source_client; + private HashTable source_view; + +- public EventsManager () { +- +- } +- + construct { + source_client = new HashTable (str_hash, str_equal); + source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); + source_view = new HashTable (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 event_dots; ++ // private Gee.HashMap event_dots; ++ private Gee.ArrayList 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 (); ++ // event_dots = new Gee.HashMap (); ++ event_dots = new Gee.ArrayList (); + } + + 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 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 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 +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 +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 . ++ */ ++ + namespace DateTimeIndicator { + public class Services.EventsManager : GLib.Object { + public signal void events_added (E.Source source, Gee.Collection 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 event_dots; + private Gee.ArrayList 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 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 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> 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> source_events) { ++ clear_list (); + + if (selected_date == null) { + return; diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix index ed70687e050..c6a0e2f7779 100644 --- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix +++ b/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/pkgs/desktops/pantheon/desktop/wingpanel/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel/default.nix index 64ebee4f13d..ff9925c5357 100644 --- a/pkgs/desktops/pantheon/desktop/wingpanel/default.nix +++ b/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/pkgs/development/libraries/gegl/4.0.nix b/pkgs/development/libraries/gegl/4.0.nix index 858596597b1..4810390ac1b 100644 --- a/pkgs/development/libraries/gegl/4.0.nix +++ b/pkgs/development/libraries/gegl/4.0.nix @@ -46,8 +46,13 @@ stdenv.mkDerivation rec { }; patches = [ - # Remove gegl:simple / backend-file test that times out frequently - ./patches/no-simple-backend-file-test.patch + # Prevent deadlock making tests time-out + # https://gitlab.gnome.org/GNOME/gegl/issues/226 + # https://gitlab.gnome.org/GNOME/glib/issues/1941 + (fetchpatch { + url = "https://gitlab.gnome.org/GNOME/gegl/commit/1d530816266b52c8788bbe1504c5b2d6eceba036.patch"; + sha256 = "8PlUcLQkuskjDGCA2obUPDW3jE++A6B5YWVgvn+GFrU="; + }) ]; nativeBuildInputs = [ diff --git a/pkgs/development/libraries/gegl/patches/no-simple-backend-file-test.patch b/pkgs/development/libraries/gegl/patches/no-simple-backend-file-test.patch deleted file mode 100644 index bf07572182b..00000000000 --- a/pkgs/development/libraries/gegl/patches/no-simple-backend-file-test.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/tests/simple/meson.build b/tests/simple/meson.build -index 2c735d80a..ae4d50f2a 100644 ---- a/tests/simple/meson.build -+++ b/tests/simple/meson.build -@@ -1,5 +1,4 @@ - testnames = [ -- 'backend-file', - 'buffer-cast', - 'buffer-changes', - 'buffer-extract', diff --git a/pkgs/development/libraries/science/math/mkl/default.nix b/pkgs/development/libraries/science/math/mkl/default.nix index f9026ec7b99..ee861c14ab4 100644 --- a/pkgs/development/libraries/science/math/mkl/default.nix +++ b/pkgs/development/libraries/science/math/mkl/default.nix @@ -114,10 +114,10 @@ in stdenvNoCC.mkDerivation { '') + '' # Setup symlinks for blas / lapack - ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/libblas${stdenvNoCC.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/libcblas${stdenvNoCC.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/liblapack${stdenvNoCC.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/liblapacke${stdenvNoCC.hostPlatform.extensions.sharedLibrary} + ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/libblas${stdenvNoCC.hostPlatform.extensions.sharedLibrary}${stdenvNoCC.lib.optionalString stdenvNoCC.hostPlatform.isLinux ".3"} + ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/libcblas${stdenvNoCC.hostPlatform.extensions.sharedLibrary}${stdenvNoCC.lib.optionalString stdenvNoCC.hostPlatform.isLinux ".3"} + ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/liblapack${stdenvNoCC.hostPlatform.extensions.sharedLibrary}${stdenvNoCC.lib.optionalString stdenvNoCC.hostPlatform.isLinux ".3"} + ln -s $out/lib/libmkl_rt${stdenvNoCC.hostPlatform.extensions.sharedLibrary} $out/lib/liblapacke${stdenvNoCC.hostPlatform.extensions.sharedLibrary}${stdenvNoCC.lib.optionalString stdenvNoCC.hostPlatform.isLinux ".3"} ''; # fixDarwinDylibName fails for libmkl_cdft_core.dylib because the diff --git a/pkgs/development/libraries/science/math/openblas/default.nix b/pkgs/development/libraries/science/math/openblas/default.nix index c55a5cb7878..f6a40204587 100644 --- a/pkgs/development/libraries/science/math/openblas/default.nix +++ b/pkgs/development/libraries/science/math/openblas/default.nix @@ -178,10 +178,10 @@ EOF done # Setup symlinks for blas / lapack - ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libblas${stdenv.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libcblas${stdenv.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/liblapack${stdenv.hostPlatform.extensions.sharedLibrary} - ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/liblapacke${stdenv.hostPlatform.extensions.sharedLibrary} + ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libblas${stdenv.hostPlatform.extensions.sharedLibrary}${stdenv.lib.optionalString stdenv.hostPlatform.isLinux ".3"} + ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libcblas${stdenv.hostPlatform.extensions.sharedLibrary}${stdenv.lib.optionalString stdenv.hostPlatform.isLinux ".3"} + ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/liblapack${stdenv.hostPlatform.extensions.sharedLibrary}${stdenv.lib.optionalString stdenv.hostPlatform.isLinux ".3"} + ln -s $out/lib/libopenblas${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/liblapacke${stdenv.hostPlatform.extensions.sharedLibrary}${stdenv.lib.optionalString stdenv.hostPlatform.isLinux ".3"} ''; meta = with stdenv.lib; { diff --git a/pkgs/development/python-modules/arrow/default.nix b/pkgs/development/python-modules/arrow/default.nix index 04295dce261..141ce20fdcb 100644 --- a/pkgs/development/python-modules/arrow/default.nix +++ b/pkgs/development/python-modules/arrow/default.nix @@ -25,7 +25,7 @@ buildPythonPackage rec { meta = with stdenv.lib; { description = "Python library for date manipulation"; - license = "apache"; + license = licenses.asl20; maintainers = with maintainers; [ thoughtpolice ]; }; } diff --git a/pkgs/development/python-modules/caldav/default.nix b/pkgs/development/python-modules/caldav/default.nix index 895775eb87f..7a7a175362a 100644 --- a/pkgs/development/python-modules/caldav/default.nix +++ b/pkgs/development/python-modules/caldav/default.nix @@ -1,5 +1,12 @@ -{ lib, buildPythonPackage, fetchPypi -, tzlocal, requests, vobject, lxml, nose }: +{ lib +, buildPythonPackage +, fetchPypi +, tzlocal +, requests +, vobject +, lxml +, nose +}: buildPythonPackage rec { pname = "caldav"; @@ -12,11 +19,16 @@ buildPythonPackage rec { sha256 = "80c33b143539da3a471148ac89512f67d9df3a5286fae5a023e2ad3923246c0d"; }; + # xandikos is only a optional test dependency, not available for python3 + postPatch = '' + substituteInPlace setup.py \ + --replace ", 'xandikos'" "" + ''; + meta = with lib; { description = "This project is a CalDAV (RFC4791) client library for Python."; homepage = "https://pythonhosted.org/caldav/"; license = licenses.asl20; maintainers = with maintainers; [ marenz ]; - broken = true; # missing xandikos package }; } diff --git a/pkgs/development/python-modules/scipy/default.nix b/pkgs/development/python-modules/scipy/default.nix index a9947e7e689..ace6c248ab2 100644 --- a/pkgs/development/python-modules/scipy/default.nix +++ b/pkgs/development/python-modules/scipy/default.nix @@ -53,6 +53,8 @@ in buildPythonPackage rec { setupPyBuildFlags = [ "--fcompiler='gnu95'" ]; + SCIPY_USE_G77_ABI_WRAPPER = 1; + meta = { description = "SciPy (pronounced 'Sigh Pie') is open-source software for mathematics, science, and engineering. "; homepage = "https://www.scipy.org/"; diff --git a/pkgs/development/tools/misc/texlab/default.nix b/pkgs/development/tools/misc/texlab/default.nix index 1edc86017ba..5cc67cb5e17 100644 --- a/pkgs/development/tools/misc/texlab/default.nix +++ b/pkgs/development/tools/misc/texlab/default.nix @@ -6,16 +6,16 @@ rustPlatform.buildRustPackage rec { pname = "texlab"; - version = "1.10.0"; + version = "2.0.0"; src = fetchFromGitHub { owner = "latex-lsp"; repo = pname; rev = "v${version}"; - sha256 = "12zfcvbihirh38xxzc8fbx293m4vsrhq6kh0qnhnhlrx75m09l9i"; + sha256 = "0y8cv8y92a4nqwrvqk2cxgs6nspqjk8jm4spr8rgkwlpfbrg74xn"; }; - cargoSha256 = "08fi0c4s0d1p2rqxvj1y82zg6xl3n0ikgyhgrjwh6xay8f0121f0"; + cargoSha256 = "1qi1c4v5d5a4xcf1bjbdicrv35w6chl5swlm96c1h3pr9s09lqy7"; buildInputs = stdenv.lib.optionals stdenv.isDarwin [ Security ]; diff --git a/pkgs/games/enyo-doom/default.nix b/pkgs/games/enyo-doom/default.nix index af002a690e4..ba07b50a1e7 100644 --- a/pkgs/games/enyo-doom/default.nix +++ b/pkgs/games/enyo-doom/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitLab, cmake, qtbase }: +{ mkDerivation, stdenv, fetchFromGitLab, cmake, qtbase }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "enyo-doom"; version = "1.06.9"; diff --git a/pkgs/games/pro-office-calculator/default.nix b/pkgs/games/pro-office-calculator/default.nix index bbdcd3f5850..7a0e3bec78d 100644 --- a/pkgs/games/pro-office-calculator/default.nix +++ b/pkgs/games/pro-office-calculator/default.nix @@ -1,5 +1,5 @@ -{ stdenv, fetchFromGitHub, tinyxml-2, cmake, qtbase, qtmultimedia }: -stdenv.mkDerivation rec { +{ mkDerivation, stdenv, fetchFromGitHub, tinyxml-2, cmake, qtbase, qtmultimedia }: +mkDerivation rec { version = "1.0.13"; pname = "pro-office-calculator"; diff --git a/pkgs/misc/calaos/installer/default.nix b/pkgs/misc/calaos/installer/default.nix index 81f00d59f69..6254c9c24f4 100644 --- a/pkgs/misc/calaos/installer/default.nix +++ b/pkgs/misc/calaos/installer/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qmake, qttools, qtbase }: +{ mkDerivation, stdenv, fetchFromGitHub, qmake, qttools, qtbase }: -stdenv.mkDerivation rec { +mkDerivation rec { name = "calaos_installer-3.1"; version = "3.1"; diff --git a/pkgs/misc/emulators/firebird-emu/default.nix b/pkgs/misc/emulators/firebird-emu/default.nix index 583e692e133..888cfea0204 100644 --- a/pkgs/misc/emulators/firebird-emu/default.nix +++ b/pkgs/misc/emulators/firebird-emu/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qmake, qtbase, qtdeclarative }: +{ mkDerivation, stdenv, fetchFromGitHub, qmake, qtbase, qtdeclarative }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "firebird-emu"; version = "1.4"; diff --git a/pkgs/misc/emulators/yabause/default.nix b/pkgs/misc/emulators/yabause/default.nix index d29d7b1e7b8..584a7b47dc7 100644 --- a/pkgs/misc/emulators/yabause/default.nix +++ b/pkgs/misc/emulators/yabause/default.nix @@ -1,7 +1,7 @@ -{ stdenv, fetchurl, cmake, pkgconfig, qtbase, qt5, libGLU, libGL +{ mkDerivation, stdenv, fetchurl, cmake, pkgconfig, qtbase, qt5, libGLU, libGL , freeglut ? null, openal ? null, SDL2 ? null }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "yabause"; version = "0.9.15"; diff --git a/pkgs/misc/vim-plugins/overrides.nix b/pkgs/misc/vim-plugins/overrides.nix index 7333b61deae..ef27712b568 100644 --- a/pkgs/misc/vim-plugins/overrides.nix +++ b/pkgs/misc/vim-plugins/overrides.nix @@ -57,16 +57,16 @@ self: super: { }; LanguageClient-neovim = let - version = "0.1.156"; + version = "0.1.157"; LanguageClient-neovim-src = fetchurl { url = "https://github.com/autozimu/LanguageClient-neovim/archive/${version}.tar.gz"; - sha256 = "0bf2va6lpgw7wqpwpfidijbzphhvw48hyc2b529qv12vwgnd1shq"; + sha256 = "1ccq5akkm8n612ni5g7w7v5gv73g7p1d9i92k0bnsy33fvi3pmnh"; }; LanguageClient-neovim-bin = rustPlatform.buildRustPackage { name = "LanguageClient-neovim-bin"; src = LanguageClient-neovim-src; - cargoSha256 = "0w66fcrlaxf6zgkrfpgfybfbm759fzimnr3pjq6sm14frar7lhr6"; + cargoSha256 = "0r3f7sixkvgfrw0j81bxj1jpam5si9dnivrw63s29cvjxrdbnmqz"; buildInputs = stdenv.lib.optionals stdenv.isDarwin [ CoreServices ]; # FIXME: Use impure version of CoreFoundation because of missing symbols. diff --git a/pkgs/os-specific/linux/kernel/hardened-patches.json b/pkgs/os-specific/linux/kernel/hardened-patches.json index 97fbbb405e3..6eb83ee8bb1 100644 --- a/pkgs/os-specific/linux/kernel/hardened-patches.json +++ b/pkgs/os-specific/linux/kernel/hardened-patches.json @@ -4,24 +4,24 @@ "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.176.a/linux-hardened-4.14.176.a.patch", "version_suffix": "a" }, - "4.19.116": { - "sha256": "00y4i905gzs9w9kckrn1frh2vw32fsndz03g2psl1gk17snc3q7c", - "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.116.a/linux-hardened-4.19.116.a.patch", + "4.19.117": { + "sha256": "0c8dvh49nzypxwvsls10i896smvpdrk40x8ybljb3qk3r8j7niaw", + "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.117.a/linux-hardened-4.19.117.a.patch", "version_suffix": "a" }, - "5.4.33": { - "sha256": "1hjfvhyvz5kyvx25809brhsvfv9mjv9q1mw6ydb71gfwhw6q8d8b", - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.33.a/linux-hardened-5.4.33.a.patch", + "5.4.34": { + "sha256": "1xwpqr9nzpjg837b3wnzb8fmrl2g9rz8gz5yb55vnnllbzbz36v6", + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.34.a/linux-hardened-5.4.34.a.patch", "version_suffix": "a" }, - "5.5.18": { - "sha256": "0v7vla784sf1fk6d8qa5x8hkyhjb1jkw4lxxcgvvlqbmxl8md8ld", - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.5.18.a/linux-hardened-5.5.18.a.patch", + "5.5.19": { + "sha256": "1ya5nsfhr3nwz6qiz4pdhvm6k9mx1kr0prhdvhx3p40f1vk281sc", + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.5.19.a/linux-hardened-5.5.19.a.patch", "version_suffix": "a" }, - "5.6.5": { - "sha256": "19cdpygm5zx3szxl456lfjg5sffqcmn18470wv7prm8rf6liqdj3", - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.6.5.a/linux-hardened-5.6.5.a.patch", + "5.6.6": { + "sha256": "0jiqh0frxirjbccgfdk007fca6r6n36n0pkqq4jszkckn59ayl7r", + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.6.6.a/linux-hardened-5.6.6.a.patch", "version_suffix": "a" } } diff --git a/pkgs/os-specific/linux/kernel/linux-4.19.nix b/pkgs/os-specific/linux/kernel/linux-4.19.nix index cdb19fd54ab..6ff9919e192 100644 --- a/pkgs/os-specific/linux/kernel/linux-4.19.nix +++ b/pkgs/os-specific/linux/kernel/linux-4.19.nix @@ -3,7 +3,7 @@ with stdenv.lib; buildLinux (args // rec { - version = "4.19.116"; + version = "4.19.117"; # modDirVersion needs to be x.y.z, will automatically add .0 if needed modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg; @@ -13,6 +13,6 @@ buildLinux (args // rec { src = fetchurl { url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz"; - sha256 = "0r3vdc3npl1bn06w9v6wsq7d5mm7bnhm9wsz36pb9ar3xhimvrlf"; + sha256 = "12xc1pwhwq4vp67hmn7hdynl4ik76cni79356hpzf1lbiqlrya6n"; }; } // (args.argsOverride or {})) diff --git a/pkgs/os-specific/linux/kernel/linux-5.4.nix b/pkgs/os-specific/linux/kernel/linux-5.4.nix index b2de6ea8689..69519a156fe 100644 --- a/pkgs/os-specific/linux/kernel/linux-5.4.nix +++ b/pkgs/os-specific/linux/kernel/linux-5.4.nix @@ -3,7 +3,7 @@ with stdenv.lib; buildLinux (args // rec { - version = "5.4.33"; + version = "5.4.34"; # modDirVersion needs to be x.y.z, will automatically add .0 if needed modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg; @@ -13,6 +13,6 @@ buildLinux (args // rec { src = fetchurl { url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz"; - sha256 = "0q9q48ij6vppfcrdf7fr24pvpwsd13pxjkdni6rnjq9a60hrcmxm"; + sha256 = "1ljcsrw9jknw2d9hb0yfr1pwy85l8z4rqycgd0kad9mb9lrw2glh"; }; } // (args.argsOverride or {})) diff --git a/pkgs/os-specific/linux/kernel/linux-5.5.nix b/pkgs/os-specific/linux/kernel/linux-5.5.nix index ecb92b5bfe7..96a349d985c 100644 --- a/pkgs/os-specific/linux/kernel/linux-5.5.nix +++ b/pkgs/os-specific/linux/kernel/linux-5.5.nix @@ -3,7 +3,7 @@ with stdenv.lib; buildLinux (args // rec { - version = "5.5.18"; + version = "5.5.19"; # modDirVersion needs to be x.y.z, will automatically add .0 if needed modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg; @@ -13,6 +13,6 @@ buildLinux (args // rec { src = fetchurl { url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz"; - sha256 = "01iiiq4dsyyc5y6b52wax9as6dzhdi172vd1423sc1yp4rrk8178"; + sha256 = "1sqiw9d25sqqzdh04dd722i7ff6kchj869jp4l8zalpvf51k6j0l"; }; } // (args.argsOverride or {})) diff --git a/pkgs/os-specific/linux/kernel/linux-5.6.nix b/pkgs/os-specific/linux/kernel/linux-5.6.nix index d3334293dc1..4ed77c98301 100644 --- a/pkgs/os-specific/linux/kernel/linux-5.6.nix +++ b/pkgs/os-specific/linux/kernel/linux-5.6.nix @@ -3,7 +3,7 @@ with stdenv.lib; buildLinux (args // rec { - version = "5.6.5"; + version = "5.6.6"; # modDirVersion needs to be x.y.z, will automatically add .0 if needed modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg; @@ -13,6 +13,6 @@ buildLinux (args // rec { src = fetchurl { url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz"; - sha256 = "1rjjkcmzsj9azggh960qnk2x44ns475b8nbd4nxazrz1rgdx76zp"; + sha256 = "1m3blvkma08v5y11jh0vhf4sr7jbcylkh15bssb5dgp40p8cx134"; }; } // (args.argsOverride or {})) diff --git a/pkgs/os-specific/linux/kernel/linux-libre.nix b/pkgs/os-specific/linux/kernel/linux-libre.nix index d167a89ea83..b13791ccb99 100644 --- a/pkgs/os-specific/linux/kernel/linux-libre.nix +++ b/pkgs/os-specific/linux/kernel/linux-libre.nix @@ -1,8 +1,8 @@ { stdenv, lib, fetchsvn, linux , scripts ? fetchsvn { url = "https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/branches/"; - rev = "17402"; - sha256 = "1g151h6hdiwpvpip1r2rhbma8j13xghcyxddh0ppg9h548wwwack"; + rev = "17445"; + sha256 = "0d2gd2w4pbb728a7mw9dnq3aicwpjzg8zahg80ismvc9l1sym50a"; } , ... }: diff --git a/pkgs/tools/admin/lxd/default.nix b/pkgs/tools/admin/lxd/default.nix index f85a61be4a8..19fbff747fc 100644 --- a/pkgs/tools/admin/lxd/default.nix +++ b/pkgs/tools/admin/lxd/default.nix @@ -9,13 +9,13 @@ buildGoPackage rec { pname = "lxd"; - version = "4.0.0"; + version = "4.0.1"; goPackagePath = "github.com/lxc/lxd"; src = fetchurl { url = "https://github.com/lxc/lxd/releases/download/${pname}-${version}/${pname}-${version}.tar.gz"; - sha256 = "00kydp6aysggng9a7m0q3zj3591yk6jgcibbqxx4ki20pd4vmqnb"; + sha256 = "0sxkyjayn7yyiy9kvbdlpkl58lwsl2rhlxnncg628f2kad2zgkdx"; }; preBuild = '' diff --git a/pkgs/tools/admin/pulumi/default.nix b/pkgs/tools/admin/pulumi/default.nix index 07ad2d95f14..c0547f0c0c8 100644 --- a/pkgs/tools/admin/pulumi/default.nix +++ b/pkgs/tools/admin/pulumi/default.nix @@ -17,10 +17,11 @@ in stdenv.mkDerivation { installPhase = '' mkdir -p $out/bin cp * $out/bin/ + '' + optionalString stdenv.isLinux '' wrapProgram $out/bin/pulumi --set LD_LIBRARY_PATH "${stdenv.cc.cc.lib}/lib" ''; - buildInputs = optionals stdenv.isLinux [ autoPatchelfHook makeWrapper ]; + nativeBuildInputs = optionals stdenv.isLinux [ autoPatchelfHook makeWrapper ]; meta = { homepage = "https://pulumi.io/"; diff --git a/pkgs/tools/archivers/p7zip/default.nix b/pkgs/tools/archivers/p7zip/default.nix index e41d9a2eb2d..3f0c2487c91 100644 --- a/pkgs/tools/archivers/p7zip/default.nix +++ b/pkgs/tools/archivers/p7zip/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchurl }: +{ stdenv, fetchurl, lib, enableUnfree ? false }: stdenv.mkDerivation rec { pname = "p7zip"; @@ -24,7 +24,7 @@ stdenv.mkDerivation rec { substituteInPlace makefile.machine \ --replace 'CC=gcc' 'CC=${stdenv.cc.targetPrefix}gcc' \ --replace 'CXX=g++' 'CXX=${stdenv.cc.targetPrefix}g++' - '' + '' + '' + lib.optionalString (!enableUnfree) '' # Remove non-free RAR source code # (see DOC/License.txt, https://fedoraproject.org/wiki/Licensing:Unrar) rm -r CPP/7zip/Compress/Rar* @@ -50,6 +50,6 @@ stdenv.mkDerivation rec { platforms = stdenv.lib.platforms.unix; maintainers = [ stdenv.lib.maintainers.raskin ]; # RAR code is under non-free UnRAR license, but we remove it - license = stdenv.lib.licenses.lgpl2Plus; + license = if enableUnfree then lib.licenses.unfree else lib.licenses.lgpl2Plus; }; } diff --git a/pkgs/tools/backup/httrack/qt.nix b/pkgs/tools/backup/httrack/qt.nix index fe5b965e570..6ee7f6e6a21 100644 --- a/pkgs/tools/backup/httrack/qt.nix +++ b/pkgs/tools/backup/httrack/qt.nix @@ -1,7 +1,7 @@ -{ stdenv, fetchurl, cmake, pkgconfig, makeWrapper +{ mkDerivation, stdenv, fetchurl, cmake, pkgconfig, makeWrapper , httrack, qtbase, qtmultimedia }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "httraqt"; version = "1.4.9"; diff --git a/pkgs/tools/backup/luckybackup/default.nix b/pkgs/tools/backup/luckybackup/default.nix index 3e89be15391..7203ba480e6 100644 --- a/pkgs/tools/backup/luckybackup/default.nix +++ b/pkgs/tools/backup/luckybackup/default.nix @@ -1,10 +1,10 @@ -{ stdenv, fetchurl +{ mkDerivation, stdenv, fetchurl , pkgconfig, libtool, qmake , rsync, ssh }: with stdenv.lib; -stdenv.mkDerivation rec { +mkDerivation rec { pname = "luckybackup"; version = "0.5.0"; diff --git a/pkgs/tools/graphics/rocket/default.nix b/pkgs/tools/graphics/rocket/default.nix index 97c400fbc9e..683a2c73f45 100644 --- a/pkgs/tools/graphics/rocket/default.nix +++ b/pkgs/tools/graphics/rocket/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchFromGitHub, qmake, qtbase }: +{ mkDerivation, stdenv, fetchFromGitHub, qmake, qtbase }: -stdenv.mkDerivation { +mkDerivation { pname = "rocket"; version = "2018-06-09"; diff --git a/pkgs/tools/misc/bat/default.nix b/pkgs/tools/misc/bat/default.nix index bf84502af2b..201ad5ed03f 100644 --- a/pkgs/tools/misc/bat/default.nix +++ b/pkgs/tools/misc/bat/default.nix @@ -4,17 +4,17 @@ rustPlatform.buildRustPackage rec { pname = "bat"; - version = "0.13.0"; + version = "0.14.0"; src = fetchFromGitHub { owner = "sharkdp"; repo = pname; rev = "v${version}"; - sha256 = "1kaa6ps6v1wk9qs63h116k4pbz7y9mfbfxfbq7g89yjhzkjmh6xc"; + sha256 = "0wxmn3ifrgpfq44xs747qqik2p2vazdw5zi4imxqap2krha4k2ms"; fetchSubmodules = true; }; - cargoSha256 = "01l1y124gjh6gf9z1jkbpfzh0w92hrgwvsmqkqdw3a9pa4w5f6yg"; + cargoSha256 = "0bs6pqrg0vdam2h2ddikmgmksqlfjljqacc52rh6p546is6jcp2s"; nativeBuildInputs = [ pkgconfig llvmPackages.libclang installShellFiles makeWrapper ]; diff --git a/pkgs/tools/misc/colord-kde/default.nix b/pkgs/tools/misc/colord-kde/default.nix index 8897514783a..33686498112 100644 --- a/pkgs/tools/misc/colord-kde/default.nix +++ b/pkgs/tools/misc/colord-kde/default.nix @@ -1,11 +1,11 @@ -{ stdenv, lib, fetchurl +{ mkDerivation, lib, fetchurl , extra-cmake-modules, ki18n , kconfig, kconfigwidgets, kcoreaddons, kdbusaddons, kiconthemes, kcmutils , kio, knotifications, plasma-framework, kwidgetsaddons, kwindowsystem , kitemviews, lcms2, libXrandr, qtx11extras }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "colord-kde"; version = "0.5.0"; diff --git a/pkgs/tools/misc/vdirsyncer/default.nix b/pkgs/tools/misc/vdirsyncer/default.nix index ecf87b7c0a5..eee4e5648e9 100644 --- a/pkgs/tools/misc/vdirsyncer/default.nix +++ b/pkgs/tools/misc/vdirsyncer/default.nix @@ -53,6 +53,9 @@ python3Packages.buildPythonApplication rec { echo 'Version: ${version}' >PKG-INFO sed -i 's/spec.add_external_build(cmd=cmd/spec.add_external_build(cmd="true"/g' setup.py + + # fixing test + sed -i "s/invalid value for \"--verbosity\"/invalid value for \\\'--verbosity\\\'/" tests/system/cli/test_sync.py ''; preBuild = '' diff --git a/pkgs/tools/networking/babeld/default.nix b/pkgs/tools/networking/babeld/default.nix index a2f486717da..debd918eb39 100644 --- a/pkgs/tools/networking/babeld/default.nix +++ b/pkgs/tools/networking/babeld/default.nix @@ -2,11 +2,11 @@ stdenv.mkDerivation rec { pname = "babeld"; - version = "1.9.1"; + version = "1.9.2"; src = fetchurl { url = "http://www.pps.univ-paris-diderot.fr/~jch/software/files/${pname}-${version}.tar.gz"; - sha256 = "1d503igqv9s5pgrhvxp1czjy2xfsjhagyyh2iny7g4cjvl0kq6qy"; + sha256 = "01vzhrspnm4sy9ggaz9n3bfl5hy3qlynr218j3mdcddzm3h00kqm"; }; preBuild = '' diff --git a/pkgs/tools/package-management/nixpkgs-review/default.nix b/pkgs/tools/package-management/nixpkgs-review/default.nix index d8811b2a7e2..b6455cc1705 100644 --- a/pkgs/tools/package-management/nixpkgs-review/default.nix +++ b/pkgs/tools/package-management/nixpkgs-review/default.nix @@ -8,13 +8,13 @@ python3.pkgs.buildPythonApplication rec { pname = "nixpkgs-review"; - version = "2.2.0"; + version = "2.3.0"; src = fetchFromGitHub { owner = "Mic92"; repo = "nixpkgs-review"; rev = version; - sha256 = "0qsvrcxl97nih1yprydzlqc6n1ppg726664d6harx5kjzp5776mr"; + sha256 = "0qkvjl4f8a1905yj3ml32rfdr5q76igz21gn3dcya0pfqhrnb28i"; }; makeWrapperArgs = [ diff --git a/pkgs/tools/security/jwt-cli/default.nix b/pkgs/tools/security/jwt-cli/default.nix index f2314d7a0e8..2161aa5f1cd 100644 --- a/pkgs/tools/security/jwt-cli/default.nix +++ b/pkgs/tools/security/jwt-cli/default.nix @@ -2,16 +2,16 @@ rustPlatform.buildRustPackage rec { pname = "jwt-cli"; - version = "3.0.1"; + version = "3.1.0"; src = fetchFromGitHub { owner = "mike-engel"; repo = pname; rev = version; - sha256 = "108pwk0h6zcbfmp0k8rhjxaa9yk8rhb78aaql22x48n11fnjl27i"; + sha256 = "0pmxis3m3madwnmswz9hn0i8fz6a9bg11slgrrwql7mx23ijqf6y"; }; - cargoSha256 = "1xh2ylx5fqblhlrs8yhl3zf8kvgrqnwdwmix6yzch9bi5mv5c11w"; + cargoSha256 = "165g1v0c8jxs8ddm8ld0hh7k8mvk3566ig43pf99hnw009fg1yc2"; buildInputs = stdenv.lib.optional stdenv.isDarwin Security; diff --git a/pkgs/tools/security/pcsc-cyberjack/default.nix b/pkgs/tools/security/pcsc-cyberjack/default.nix index cb651ff7ce1..7ae062547aa 100644 --- a/pkgs/tools/security/pcsc-cyberjack/default.nix +++ b/pkgs/tools/security/pcsc-cyberjack/default.nix @@ -1,25 +1,28 @@ { stdenv, fetchurl, autoreconfHook, pkgconfig, libusb1, pcsclite }: -stdenv.mkDerivation rec { - pname = "pcsc-cyberjack"; - version = "3.99.5_SP13"; +let + version = "3.99.5"; + suffix = "SP13"; + tarBall = "${version}final.${suffix}"; - src = with stdenv.lib; let - splittedVer = splitString "_" version; - mainVer = if length splittedVer >= 1 then head splittedVer else version; - spVer = optionalString (length splittedVer >= 1) ("." + last splittedVer); - tarballVersion = "${mainVer}final${spVer}"; - in fetchurl { - url = "http://support.reiner-sct.de/downloads/LINUX/V${version}" - + "/pcsc-cyberjack_${tarballVersion}.tar.gz"; +in stdenv.mkDerivation rec { + pname = "pcsc-cyberjack"; + inherit version; + + src = fetchurl { + url = + "http://support.reiner-sct.de/downloads/LINUX/V${version}_${suffix}/${pname}_${tarBall}.tar.gz"; sha256 = "1lx4bfz4riz7j77sl65akyxzww0ygm63w0c1b75knr1pijlv8d3b"; }; outputs = [ "out" "tools" ]; nativeBuildInputs = [ autoreconfHook pkgconfig ]; + buildInputs = [ libusb1 pcsclite ]; + enableParallelBuilding = true; + configureFlags = [ "--with-usbdropdir=${placeholder "out"}/pcsc/drivers" "--bindir=${placeholder "tools"}/bin" @@ -31,7 +34,7 @@ stdenv.mkDerivation rec { description = "REINER SCT cyberJack USB chipcard reader user space driver"; homepage = "https://www.reiner-sct.com/"; license = licenses.gpl2Plus; - platforms = platforms.linux; maintainers = with maintainers; [ aszlig ]; + platforms = platforms.linux; }; } diff --git a/pkgs/tools/text/glogg/default.nix b/pkgs/tools/text/glogg/default.nix index 9dec057dfe9..90c1419ef30 100644 --- a/pkgs/tools/text/glogg/default.nix +++ b/pkgs/tools/text/glogg/default.nix @@ -1,6 +1,6 @@ -{ stdenv, fetchurl, qmake, boost }: +{ mkDerivation, stdenv, fetchurl, qmake, boost }: -stdenv.mkDerivation rec { +mkDerivation rec { pname = "glogg"; version = "1.1.4"; diff --git a/pkgs/tools/typesetting/tex/texlive/bin.nix b/pkgs/tools/typesetting/tex/texlive/bin.nix index 5800cedf7f1..c0ae6b8e187 100644 --- a/pkgs/tools/typesetting/tex/texlive/bin.nix +++ b/pkgs/tools/typesetting/tex/texlive/bin.nix @@ -76,6 +76,14 @@ let url = "https://git.archlinux.org/svntogit/packages.git/plain/trunk/texlive-poppler-0.86.patch?h=packages/texlive-bin&id=60244e41bb6f1501e8ed1fc9e6b7ba8d3f283398"; sha256 = "0pdvhaqc3zgz7hp0x3a4qs0nh26fkvgmr6w1cjljqhp1nyiw2f1l"; }) + + # Needed for ghostscript>=9.50 + (fetchpatch { + name = "xdvipdfm-fix.patch"; + url = "https://www.tug.org/svn/texlive/trunk/Build/source/texk/dvipdfm-x/spc_dvips.c?view=patch&r1=52765&r2=52764&pathrev=52765"; + sha256 = "0qvrc7yxhbl5f4g340z8aql388bwib0m2gxd473skbmviy5bjr3f"; + stripLen = 2; + }) ]; # remove when removing synctex-missing-header.patch diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index e09819318aa..e4c3019ff37 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -920,6 +920,8 @@ in libfx2 = with python3Packages; toPythonApplication fx2; + fitnesstrax = callPackage ../applications/misc/fitnesstrax/default.nix { }; + fxlinuxprintutil = callPackage ../tools/misc/fxlinuxprintutil { }; genymotion = callPackage ../development/mobile/genymotion { };