diff options
37 files changed, 915 insertions, 1888 deletions
@@ -3,58 +3,50 @@ ########################################################## requires: archlinux: - # Useful URL: https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=ayatana-indicator-session + # Useful URL: https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=ayatana-indicator-printers - clang - gcc - git - make - startup-notification - which -# - cmake -# - cmake-extras - - mate-common + - cmake + - cmake-extras - intltool - - ayatana-indicator3 - - gobject-introspection - glib2 + - libayatana-common + - libcups - systemd + - cups debian: - # Useful URL: https://salsa.debian.org/debian-ayatana-team/ayatana-session - - autopoint + # Useful URL: https://salsa.debian.org/debian-ayatana-team/ayatana-printers - clang - clang-tools - g++ - cppcheck - git -# - cmake -# - cmake-extras - - mate-common + - cmake + - cmake-extras - intltool - libglib2.0-dev - - libgtk-3-dev - - libdbusmenu-glib-dev - - libdbusmenu-gtk3-dev - - libayatana-indicator3-dev - libcups2-dev +# - libayatana-common-dev + - liblomiri-url-dispatcher-dev - dbus ubuntu: - - autopoint - clang - clang-tools - g++ - git -# - cmake -# - cmake-extras - - mate-common + - cmake + - cmake-extras - intltool - libglib2.0-dev - - libgtk-3-dev - - libdbusmenu-glib-dev - - libdbusmenu-gtk3-dev - - libayatana-indicator3-dev - libcups2-dev +# - libayatana-common-dev +# - liblomiri-url-dispatcher-dev variables: - 'CHECKERS=" @@ -74,46 +66,32 @@ variables: -enable-checker alpha.core.FixedAddr -enable-checker security.insecureAPI.strcpy"' -### the printers indicator requires a very old version of libayatana-indicator, so no need to -### build it from source here. Leaving the ruleset here, nonetheless. +before_scripts: + - cd ${START_DIR} + - if [ ! -d libayatana-common-build ]; then + - git clone --depth 1 https://github.com/AyatanaIndicators/libayatana-common.git libayatana-common-build + - fi + - cd libayatana-common-build + - if [ ${DISTRO_NAME} == "debian" ]; then + - cmake . -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LOMIRI_FEATURES=ON + - else + - cmake . -DCMAKE_INSTALL_PREFIX=/usr + - fi + - make + - make install + - cd - + - rm -Rf libayatana-common-build/ -#before_scripts: -# - cd ${START_DIR} -# - if [ ! -d ayatana-ido-build ]; then -# - git clone --depth 1 https://github.com/AyatanaIndicators/ayatana-ido.git ayatana-ido-build -# - fi -# - cd ayatana-ido-build -# - cmake . -DCMAKE_INSTALL_PREFIX=/usr -# - make -# - make install -# - cd - -# - rm -Rf ayatana-ido-build/ -# - -# - cd ${START_DIR} -# - if [ ! -d libayatana-indicator-build ]; then -# - git clone --depth 1 https://github.com/AyatanaIndicators/libayatana-indicator.git libayatana-indicator-build -# - fi -# - cd libayatana-indicator-build -# - cmake . -DCMAKE_INSTALL_PREFIX=/usr -# - make -# - make install -# - cd - -# - rm -Rf libayatana-indicator-build/ -# build_scripts: - if [ ${DISTRO_NAME} == "debian" ];then - - export CFLAGS+=" -Wsign-compare -Wunused-parameter" - cppcheck --enable=warning,style,performance,portability,information,missingInclude . - fi - - - if [ -e ./autogen.sh ]; then - - NOCONFIGURE=1 ./autogen.sh - - scan-build $CHECKERS ./configure --prefix=/usr --enable-gtk-doc --enable-compile-warnings=maximum - - elif [ -e ./CMakeLists.txt ]; then + - if [ -e ./CMakeLists.txt ]; then - if [ ${DISTRO_NAME} == "debian" ] || [ ${DISTRO_NAME} == "ubuntu" ]; then - - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_TESTS=ON + - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_WERROR=ON -DENABLE_TESTS=ON - else - - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON + - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_WERROR=ON - fi - else - exit 1 @@ -132,12 +110,10 @@ build_scripts: - fi - scan-build $CHECKERS --keep-cc -o html-report make - fi -# - -# - XVFB_RUN="$(which xvfb-run || true)" -# - if [ ${DISTRO_NAME} == "debian" ] || [ ${DISTRO_NAME} == "ubuntu" ];then -# - if [ -e ./autogen.sh ]; then -# - ${XVFB_RUN} make check -# - elif [ -e ./CMakeLists.txt ]; then -# - ${XVFB_RUN} env CTEST_OUTPUT_ON_FAILURE=1 make test -# - fi -# - fi + - + - XVFB_RUN="$(which xvfb-run || true)" + - if [ ${DISTRO_NAME} == "debian" ] || [ ${DISTRO_NAME} == "ubuntu" ];then + - if [ -e ./CMakeLists.txt ]; then + - ${XVFB_RUN} env CTEST_OUTPUT_ON_FAILURE=1 make test + - fi + - fi diff --git a/.travis.yml b/.travis.yml index 9556732..73bc55b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ # vim: set ts=2 sts=2 sw=2 expandtab : -dist: bionic +dist: focal language: shell os: linux @@ -11,16 +11,18 @@ Baka Gaijin <lewdwarrior@waifu.club> Bileto Bot <ci-train-bot@canonical.com> Charles Kerr <charles.kerr@canonical.com> CI Train Bot <ci-train-bot@canonical.com> +David Mohammed <fossfreedom@ubuntu.com> +David Mohammed <fossfreedom@users.noreply.github.com> Davit Mayilyan <davit.mayilyan@protonmail.ch> Didier Roche <didier.roche@canonical.com> Didier Roche <didrocks@ubuntu.com> Efstathios Iosifidis <iefstathios@gmail.com> Gabor Kelemen <kelemeng@ubuntu.com> george k <norhorn@gmail.com> +gits0000 <19572405+gits0000@users.noreply.github.com> Heimen Stoffels <vistausss@outlook.com> Hosted Weblate <hosted@weblate.org> iNetRoos <inetroos@gmail.com> -Iván Seoane <ivanrsm1997@gmail.com> Jeannette L <j.lavoie@net-c.ca> Jeremy Bicha <jbicha@ubuntu.com> Joan CiberSheep <cibersheep@gmail.com> @@ -29,6 +31,7 @@ Kentaro Hayashi <kenhys@gmail.com> Kristjan Räts <kristjanrats@gmail.com> Lars Uebernickel <lars.uebernickel@canonical.com> Louies <louies0623@gmail.com> +Luca Weiss <luca@z3ntu.xyz> MarongHappy <daemul72@gmail.com> Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com> Matteo F. Vescovi <mfvescovi+github@gmail.com> @@ -40,6 +43,7 @@ Murilo Venturoso <muriloventuroso@gmail.com> Niara <kitekatkek@gmail.com> OrionJK - <idorionjk@gmail.com> Pavel Borecki <pavel.borecki@gmail.com> +phlostically <phlostically@mailinator.com> Prachi Joshi <josprachi@yahoo.com> Quentin PAGÈS <quentinantonin@free.fr> Reza Almanda <rezaalmanda27@gmail.com> diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..37c1bf6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,71 @@ +project (ayatana-indicator-printers C) +cmake_minimum_required (VERSION 3.13) + +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + SET (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "..." FORCE) +endif (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + +list (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +set (PROJECT_VERSION "22.9.0") +set (PACKAGE ${CMAKE_PROJECT_NAME}) +set (GETTEXT_PACKAGE "ayatana-indicator-printers") + +# Options +option (ENABLE_TESTS "Enable all tests and checks" OFF) +option (ENABLE_COVERAGE "Enable coverage reports (includes enabling all tests and checks)" OFF) +option (ENABLE_WERROR "Treat all build warnings as errors" OFF) + +if (ENABLE_COVERAGE) + set (ENABLE_TESTS ON) + set (CMAKE_BUILD_TYPE "Coverage") +else () + set (CMAKE_BUILD_TYPE "Release") +endif () + +if (ENABLE_WERROR) + add_definitions ("-Werror") +endif () + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + add_definitions ("-Weverything") +else () + add_definitions ("-Wall") +endif () + +# Check for prerequisites +include (GNUInstallDirs) +find_package (PkgConfig REQUIRED) +include (FindPkgConfig) +pkg_check_modules (SERVICE REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 gio-unix-2.0>=2.36 libayatana-common) +find_program (CUPS_CONFIG cups-config REQUIRED) +execute_process (COMMAND ${CUPS_CONFIG} --cflags OUTPUT_VARIABLE CUPS_CFLAGS) +execute_process (COMMAND ${CUPS_CONFIG} --libs OUTPUT_VARIABLE CUPS_LIBS) +list (APPEND SERVICE_CFLAGS ${CUPS_CFLAGS}) +list (APPEND SERVICE_LDFLAGS ${CUPS_LIBS}) +list (APPEND SERVICE_LIBRARIES "cups") + +# Custom targets +set (ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}) +add_custom_target (dist COMMAND bzr export --root=${ARCHIVE_NAME} ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_custom_target (cppcheck COMMAND cppcheck --enable=all -q --error-exitcode=2 --inline-suppr ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/test) + +# Build +add_subdirectory (src) +add_subdirectory (data) +add_subdirectory (po) + +if (ENABLE_TESTS) + include (CTest) + enable_testing () + add_subdirectory (test) + if (ENABLE_COVERAGE) + find_package (CoverageReport) + ENABLE_COVERAGE_REPORT (TARGETS "ayatanaindicatorprintersservice" "ayatana-indicator-printers-service" TESTS "mock-cups-notifier" FILTER /usr/include ${CMAKE_BINARY_DIR}/*) + endif () +endif () + +# Display config info +message (STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") +message (STATUS "Unit tests: ${ENABLE_TESTS}") +message (STATUS "Build with -Werror: ${ENABLE_WERROR}") @@ -1,6 +1,110 @@ +2022-12-15 Mike Gabriel + + * release 22.9.0 (HEAD -> main, tag: 22.9.0) + +2022-09-22 Robert Tari + + * Merge branch 'sunweaver-pr/tooltip-support' (025c06a) + +2022-09-22 Mike Gabriel + + * src/indicator-printers-service.c: Add tooltip support. (bcd0658) + +2022-09-21 Mike Gabriel + + * Merge branch 'tari01-pr/indicator-ng' (ce5fa07) + * CMake: Typo fix in target name. (0c689d5) + +2022-09-06 Robert Tari + + * .build.yml: Update build dependencies (f22f67c) + * debian/control: Update build dependencies (0c644b5) + * Rewrite to indicator-ng: Remove unused source files (3caee4c) + * Rewrite to indicator-ng: Add service configuration file (fdd0455) + * Rewrite to indicator-ng: Code and build changes (d32524e) + +2022-09-05 Mike Gabriel + + * update-po{,t}.sh: White-space changes (use same script as on other + ayatana-indicator-* projects). (4e646da) + * Merge branch 'tari01-pr/move-to-cmake' (e953439) + +2022-08-14 Robert Tari + + * Drop all references to config.h (9e5b57c) + * Drop Automake files (f487079) + * debian/*: Change to using CMake (e03433a) + * .build.yml: Use CMake build (8b90bcc) + * Update translation scripts (de319a7) + * Use CMake variables in configurable files (7d9327a) + * Add CMakeLists.txt files (be468e9) + * config.h: Add dummy file (8963b20) + * Whitespace fix (b0e1be9) + +2022-02-28 Mike Gabriel + + * Merge branch 'tari01-pr/cleanup-compile-flags' (0ef8ce7) + +2022-02-23 Robert Tari + + * .build.yml: Remove extra compilation flags (8173711) + +2022-02-28 Mike Gabriel + + * Merge branch 'gits0000-patch-1' (3929de4) + +2022-02-26 gits0000 + + * Update AUTHORS (7db50cc) + +2022-02-17 Mike Gabriel + + * release 22.2.0 (4c2b65a) (tag: 22.2.0) + +2022-02-08 Mike Gabriel + + * Merge branch 'fossfreedom-main' (0cd3d2c) + +2021-12-23 David Mohammed + + * Check if valid cupsoption before processing - closes #12 (6f54901) + +2022-02-08 Mike Gabriel + + * Merge branch 'fossfreedom-patch-1' (264f7af) + +2021-12-20 David Mohammed + + * Add budgie-desktop support (898307d) + +2022-02-08 Robert Tari + + * .travis.yml: Run CI builds on Travis CI's Ubuntu focal base system + (0c26e5c) + +2021-12-08 Mike Gabriel + + * Merge branch 'z3ntu-bashism' (9ad3ae4) + +2021-12-07 Luca Weiss + + * Remove bash-ism from configure.ac (b4e36f4) + +2021-11-21 phlostically + + * Translated using Weblate (Esperanto) (5af7477) + +2021-11-20 phlostically + + * Translated using Weblate (Esperanto) (193a122) + +2021-11-18 phlostically + + * Translated using Weblate (Esperanto) (31e5e29) + 2021-11-17 Mike Gabriel - * release 0.9.0 (HEAD -> main, tag: 0.9.0) + * release 0.9.0 (5c1756c) (tag: 0.9.0) 2021-10-25 Robert Tari diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 26e7118..0000000 --- a/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -SUBDIRS = src data test po - -include $(top_srcdir)/Makefile.am.coverage - -DISTCLEANFILES = \ - INSTALL \ - Makefile.in \ - aclocal.m4 \ - compile \ - configure \ - config.h.in \ - config.h \ - config.sub \ - config.guess \ - depcomp \ - install-sh \ - ltmain.sh \ - missing \ - m4/intltool.m4 \ - m4/libtool.m4 \ - m4/ltoptions.m4 \ - m4/ltsugar.m4 \ - m4/ltversion.m4 \ - m4/lt~obsolete.m4 \ - po/Makefile.in.in diff --git a/Makefile.am.coverage b/Makefile.am.coverage deleted file mode 100644 index 7d2d43f..0000000 --- a/Makefile.am.coverage +++ /dev/null @@ -1,47 +0,0 @@ -# Coverage targets - -.PHONY: clean-gcno clean-gcda \ - coverage-html generate-coverage-html clean-coverage-html \ - coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr - -clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr - -if HAVE_GCOV - -clean-gcno: - @echo Removing old coverage instrumentation - -find -name '*.gcno' -print | xargs -r rm - -clean-gcda: - @echo Removing old coverage results - -find -name '*.gcda' -print | xargs -r rm - -coverage-html: clean-gcda - -$(MAKE) $(AM_MAKEFLAGS) -k check - $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html - -generate-coverage-html: - @echo Collecting coverage data - $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool - LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info - -clean-coverage-html: clean-gcda - -$(LCOV) --directory $(top_builddir) -z - -rm -rf coverage.info coveragereport - -if HAVE_GCOVR - -coverage-gcovr: clean-gcda - -$(MAKE) $(AM_MAKEFLAGS) -k check - $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr - -generate-coverage-gcovr: - @echo Generating coverage GCOVR report - $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml - -clean-coverage-gcovr: clean-gcda - -rm -rf $(top_builddir)/coverage.xml - -endif # HAVE_GCOVR - -endif # HAVE_GCOV @@ -1,3 +1,20 @@ +Overview of changes in ayatana-indicator-printers 22.9.0 + + - Port to CMake + - Rewrite to indicator-ng. + - Add tooltip support. + +Overview of changes in ayatana-indicator-printers 22.2.0 + + - Upstream version bump to new release versioning scheme: + <year>.<month>.<revision>, where <year>.<month> will be + bumped in Ayatana Indicators bundle releases and <revision> + gets incremented with minor changeset releases. + - Check if cupsoption is valid before processing. + - Add budgie-desktop support. + - Remove bash-ism from configure.ac. + - Translation updates. + Overview of changes in ayatana-indicator-printers 0.9.0 - Add Travis CI configuration. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 0478484..0000000 --- a/autogen.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -which mate-autogen || { - echo "Could not find 'mate-autgen'. Is mate-common installed?" - exit 1 -} - -. mate-autogen - diff --git a/cmake/GdbusCodegen.cmake b/cmake/GdbusCodegen.cmake new file mode 100644 index 0000000..5261ba8 --- /dev/null +++ b/cmake/GdbusCodegen.cmake @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.13) +if(POLICY CMP0011) + cmake_policy(SET CMP0011 NEW) +endif(POLICY CMP0011) + +find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable") +if(NOT GDBUS_CODEGEN) + message(FATAL_ERROR "Excutable gdbus-codegen not found") +endif() + +macro(add_gdbus_codegen outfiles name prefix service_xml) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" + COMMAND "${GDBUS_CODEGEN}" + --interface-prefix "${prefix}" + --generate-c-code "${name}" + "${service_xml}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${ARGN} "${service_xml}" + ) + list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") +endmacro(add_gdbus_codegen) + +macro(add_gdbus_codegen_with_namespace outfiles name prefix namespace service_xml) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" + COMMAND "${GDBUS_CODEGEN}" + --interface-prefix "${prefix}" + --generate-c-code "${name}" + --c-namespace "${namespace}" + "${service_xml}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${ARGN} "${service_xml}" + ) + list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") +endmacro(add_gdbus_codegen_with_namespace) diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 0986f8c..0000000 --- a/configure.ac +++ /dev/null @@ -1,98 +0,0 @@ -AC_INIT(ayatana-indicator-printers, 0.9.0) - -AC_PREREQ(2.53) -AM_INIT_AUTOMAKE([]) - -AC_PROG_CC -AC_PROG_INSTALL -AC_PROG_LIBTOOL -AM_PROG_CC_C_O -AM_SILENT_RULES([yes]) -AC_CONFIG_MACRO_DIR([m4]) - -AC_DEFUN([AC_DEFINE_PATH], [ - test "x$prefix" = xNONE && prefix="$ac_default_prefix" - test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - ac_define_path=`eval echo [$]$2` - ac_define_path=`eval echo [$]ac_define_path` - $1="$ac_define_path" - AC_SUBST($1) - ifelse($3, , - AC_DEFINE_UNQUOTED($1, "$ac_define_path"), - AC_DEFINE_UNQUOTED($1, "$ac_define_path", $3)) -]) - -IT_PROG_INTLTOOL([0.35.0]) -GETTEXT_PACKAGE=ayatana-indicator-printers -AC_SUBST(GETTEXT_PACKAGE) -AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package]) -AC_DEFINE_PATH(LOCALEDIR, "${datadir}/locale", [locale directory]) -AM_GLIB_GNU_GETTEXT - -AC_CONFIG_HEADER(config.h) -AC_CONFIG_FILES([ - Makefile - src/Makefile - data/Makefile - test/Makefile - po/Makefile.in -]) - -PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= 3.0 - ayatana-indicator3-0.4 >= 0.2 - dbusmenu-gtk3-0.4 >= 0.2) -PKG_CHECK_MODULES(SERVICE, gtk+-3.0 >= 3.0 - ayatana-indicator3-0.4 >= 0.2 - dbusmenu-glib-0.4 >= 0.2) - -AC_PATH_PROG(CUPS_CONFIG, cups-config, no) -if test "x$CUPS_CONFIG" = "xno"; then - AC_MSG_ERROR([could not find cups-config]) -fi -AC_CHECK_HEADER(cups/cups.h,,AC_MSG_ERROR([could not find cups.h])) -CUPS_CFLAGS+=`$CUPS_CONFIG --cflags` -CUPS_LIBS+=`$CUPS_CONFIG --libs` -SERVICE_CFLAGS="$SERVICE_CFLAGS $CUPS_CFLAGS" -SERVICE_LIBS="$SERVICE_LIBS $CUPS_LIBS" - -######################### -# Check for systemd -######################### -PKG_CHECK_MODULES(SYSTEMD, systemd, - [has_systemd=yes], - [] -) -if test "x$has_systemd" = "xyes"; then - SYSTEMD_USERDIR=`$PKG_CONFIG --variable=systemduserunitdir systemd` - AC_SUBST(SYSTEMD_USERDIR) - AC_DEFINE(HAVE_SYSTEMD, 1, [create ayatana-indicator-printers.service for systemd]) -fi - -INDICATORDIR=`$PKG_CONFIG --variable=indicatordir ayatana-indicator3-0.4` -INDICATORICONSDIR=`$PKG_CONFIG --variable=iconsdir ayatana-indicator3-0.4` - -AC_SUBST(INDICATORDIR) -AC_SUBST(INDICATORICONSDIR) - -########################### -# DBus Service Info -########################### - -DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1` -AC_SUBST(DBUSSERVICEDIR) - -########################### -# gcov coverage reporting -########################### - -m4_include([m4/gcov.m4]) -AC_TDD_GCOV -AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes]) -AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes]) -AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes]) -AC_SUBST(COVERAGE_CFLAGS) -AC_SUBST(COVERAGE_LDFLAGS) - -AC_SUBST(AM_CFLAGS, "-Wall") - -AC_OUTPUT diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 0000000..ac6a6c6 --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,15 @@ +# ayatana-indicator-printers.service +pkg_check_modules (SYSTEMD systemd) + +if (${SYSTEMD_FOUND}) + pkg_get_variable (SYSTEMD_USER_DIR systemd systemduserunitdir) + configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/ayatana-indicator-printers.service.in" "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator-printers.service" @ONLY) + install (FILES "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator-printers.service" DESTINATION "${SYSTEMD_USER_DIR}") +endif () + +# ayatana-indicator-printers.desktop +configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/ayatana-indicator-printers.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator-printers.desktop" @ONLY) +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator-printers.desktop" DESTINATION "/etc/xdg/autostart") + +# org.ayatana.indicator.printers +install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/org.ayatana.indicator.printers" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/ayatana/indicators") diff --git a/data/Makefile.am b/data/Makefile.am deleted file mode 100644 index 8bf680d..0000000 --- a/data/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -BUILT_SOURCES= -CLEANFILES= -EXTRA_DIST= - -# -# the systemd unit file -# - -#if defined(HAVE_SYSTEMD) -systemddir = $(SYSTEMD_USERDIR) -systemd_DATA = ayatana-indicator-printers.service -systemd_in = $(systemd_DATA:.service=.service.in) -$(systemd_DATA): $(systemd_in) - $(AM_V_GEN) $(SED) -e "s|\@pkglibexecdir\@|$(pkglibexecdir)|" $< > $@ -BUILT_SOURCES += $(systemd_DATA) -EXTRA_DIST += $(systemd_in) -CLEANFILES += $(systemd_DATA) -#endif - -# -# the xdg autostart job file -# - -xdg_autostartdir = /etc/xdg/autostart -xdg_autostart_DATA = ayatana-indicator-printers.desktop -xdg_autostart_in = $(xdg_autostart_DATA:.desktop=.desktop.in) -$(xdg_autostart_DATA): $(xdg_autostart_in) - $(AM_V_GEN) $(SED) -e "s|\@pkglibexecdir\@|$(pkglibexecdir)|" $< > $@ -BUILT_SOURCES += $(xdg_autostart_DATA) -CLEANFILES += $(xdg_autostart_DATA) -EXTRA_DIST += $(xdg_autostart_in) - -DISTCLEANFILES = \ - Makefile.in diff --git a/data/ayatana-indicator-printers.desktop.in b/data/ayatana-indicator-printers.desktop.in index 72e98ec..1027096 100644 --- a/data/ayatana-indicator-printers.desktop.in +++ b/data/ayatana-indicator-printers.desktop.in @@ -1,8 +1,8 @@ [Desktop Entry] Type=Application Name=Ayatana Indicator Printers -Exec=@pkglibexecdir@/ayatana-indicator-printers-service -OnlyShowIn=MATE;XFCE; +Exec=@CMAKE_INSTALL_FULL_LIBEXECDIR@/ayatana-indicator-printers/ayatana-indicator-printers-service +OnlyShowIn=MATE;XFCE;Budgie NoDisplay=true StartupNotify=false Terminal=false diff --git a/data/ayatana-indicator-printers.service.in b/data/ayatana-indicator-printers.service.in index 781f3e6..e482f96 100644 --- a/data/ayatana-indicator-printers.service.in +++ b/data/ayatana-indicator-printers.service.in @@ -4,7 +4,7 @@ PartOf=graphical-session.target PartOf=ayatana-indicators.target [Service] -ExecStart=@pkglibexecdir@/ayatana-indicator-printers-service +ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/ayatana-indicator-printers/ayatana-indicator-printers-service Restart=on-failure [Install] diff --git a/data/org.ayatana.indicator.printers b/data/org.ayatana.indicator.printers new file mode 100644 index 0000000..d9fe355 --- /dev/null +++ b/data/org.ayatana.indicator.printers @@ -0,0 +1,11 @@ +[Indicator Service] +Name=ayatana-indicator-printers +ObjectPath=/org/ayatana/indicator/printers +Position=100 + +[phone] +ObjectPath=/org/ayatana/indicator/printers/phone +Position=25 + +[desktop] +ObjectPath=/org/ayatana/indicator/printers/desktop diff --git a/debian/changelog b/debian/changelog index a595f5a..e3ad93e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +ayatana-indicator-printers (22.9.0-0) unstable; urgency=medium + + * Upstream-provided Debian package for ayatana-indicator-printers. + See upstream ChangeLog for recent changes. + + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Thu, 15 Dec 2022 21:48:08 +0100 + +ayatana-indicator-printers (22.2.0-0) unstable; urgency=medium + + * Upstream-provided Debian package for ayatana-indicator-printers. + See upstream ChangeLog for recent changes. + + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Thu, 17 Feb 2022 22:26:01 +0100 + ayatana-indicator-printers (0.9.0-0) unstable; urgency=medium * Upstream-provided Debian package for ayatana-indicator-printers. diff --git a/debian/control b/debian/control index 3e98b9c..040ff2b 100644 --- a/debian/control +++ b/debian/control @@ -3,17 +3,14 @@ Section: x11 Priority: extra Maintainer: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Build-Depends: debhelper (>= 10), - autotools-dev, - dh-autoreconf | debhelper (>= 9.20160403~), + cmake, + cmake-extras, dh-systemd | debhelper (>= 10.2~), dpkg-dev (>= 1.16.1.1), - mate-common, + intltool, libglib2.0-dev (>= 2.43.2), - libgtk-3-dev, - libdbusmenu-glib-dev (>= 0.5.90), - libdbusmenu-gtk3-dev (>= 0.5.90), - libayatana-indicator3-dev (>= 0.3.91), libcups2-dev, + libayatana-common-dev, systemd [linux-any], Standards-Version: 4.1.1 Homepage: https://github.com/AyatanaIndicators/ayatana-indicator-printers diff --git a/debian/rules b/debian/rules index ba2e36f..fac96d4 100755 --- a/debian/rules +++ b/debian/rules @@ -1,28 +1,32 @@ #!/usr/bin/make -f +export DPKG_GENSYMBOLS_CHECK_LEVEL=4 + export DEB_BUILD_MAINT_OPTIONS = hardening=+all DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk -CFLAGS += -Wno-error=deprecated-declarations -LDFLAGS += -Wl,-z,defs -Wl,--as-needed +DEB_CMAKE_EXTRA_FLAGS = \ + -DENABLE_TESTS=ON \ + -DENABLE_COVERAGE=OFF \ + $(NULL) export DPKG_GENSYMBOLS_CHECK_LEVEL = 4 %: - dh $@ --without autoreconf,systemd + dh $@ --with systemd override_dh_auto_configure: - NOCONFIGURE=1 ./autogen.sh - dh_auto_configure -- \ - --disable-static + dh_auto_configure -- $(DEB_CMAKE_EXTRA_FLAGS) override_dh_install: find debian/ayatana-indicator-printers -name \*.la -delete find debian/ayatana-indicator-printers -name \*.a -delete dh_install --fail-missing -override_dh_auto_clean: - dh_auto_clean - # no clue, why they don't disappear during make distclean... - rm -f config.sub config.guess +# Hack as it seems it's not possible to easy run that under dbus-test-runner +override_dh_auto_test: + env -u LD_PRELOAD dh_auto_test + +get-orig-source: + uscan --noconf --force-download --rename --download-current-version --destdir=.. diff --git a/m4/gcov.m4 b/m4/gcov.m4 deleted file mode 100644 index 3163584..0000000 --- a/m4/gcov.m4 +++ /dev/null @@ -1,86 +0,0 @@ -# Checks for existence of coverage tools: -# * gcov -# * lcov -# * genhtml -# * gcovr -# -# Sets ac_cv_check_gcov to yes if tooling is present -# and reports the executables to the variables LCOV, GCOVR and GENHTML. -AC_DEFUN([AC_TDD_GCOV], -[ - AC_ARG_ENABLE(gcov, - AS_HELP_STRING([--enable-gcov], - [enable coverage testing with gcov]), - [use_gcov=$enableval], [use_gcov=no]) - - if test "x$use_gcov" = "xyes"; then - # we need gcc: - if test "$GCC" != "yes"; then - AC_MSG_ERROR([GCC is required for --enable-gcov]) - fi - - # Check if ccache is being used - AC_CHECK_PROG(SHTOOL, shtool, shtool) - case `$SHTOOL path $CC` in - *ccache*[)] gcc_ccache=yes;; - *[)] gcc_ccache=no;; - esac - - if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then - AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) - fi - - lcov_version_list="1.6 1.7 1.8 1.9" - AC_CHECK_PROG(LCOV, lcov, lcov) - AC_CHECK_PROG(GENHTML, genhtml, genhtml) - - if test "$LCOV"; then - AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [ - glib_cv_lcov_version=invalid - lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` - for lcov_check_version in $lcov_version_list; do - if test "$lcov_version" = "$lcov_check_version"; then - glib_cv_lcov_version="$lcov_check_version (ok)" - fi - done - ]) - else - lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" - AC_MSG_ERROR([$lcov_msg]) - fi - - case $glib_cv_lcov_version in - ""|invalid[)] - lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." - AC_MSG_ERROR([$lcov_msg]) - LCOV="exit 0;" - ;; - esac - - if test -z "$GENHTML"; then - AC_MSG_ERROR([Could not find genhtml from the lcov package]) - fi - - ac_cv_check_gcov=yes - ac_cv_check_lcov=yes - - # Remove all optimization flags from CFLAGS - changequote({,}) - CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` - changequote([,]) - - # Add the special gcc flags - COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" - COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage" - COVERAGE_LDFLAGS="-lgcov" - - # Check availability of gcovr - AC_CHECK_PROG(GCOVR, gcovr, gcovr) - if test -z "$GCOVR"; then - ac_cv_check_gcovr=no - else - ac_cv_check_gcovr=yes - fi - -fi -]) # AC_TDD_GCOV diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt new file mode 100644 index 0000000..fce8216 --- /dev/null +++ b/po/CMakeLists.txt @@ -0,0 +1,2 @@ +find_package (Intltool REQUIRED) +intltool_install_translations (ALL GETTEXT_PACKAGE ${GETTEXT_PACKAGE}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..d0fdbd1 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# cups-notifier.h +# cups-notifier.c +include (GdbusCodegen) +add_gdbus_codegen_with_namespace (CUPS_NOTIFIER cups-notifier org.cups.cupsd Cups "${CMAKE_CURRENT_SOURCE_DIR}/org.cups.cupsd.Notifier.xml") + +# libayatanaindicatorprintersservice.a +add_library (ayatanaindicatorprintersservice STATIC + indicator-printers-service.h + indicator-printers-service.c + indicator-printer-state-notifier.c + indicator-printer-state-notifier.h + spawn-printer-settings.c + spawn-printer-settings.h + dbus-names.h + ${CUPS_NOTIFIER}) +target_include_directories (ayatanaindicatorprintersservice PUBLIC ${SERVICE_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) +target_compile_definitions (ayatanaindicatorprintersservice PUBLIC GETTEXT_PACKAGE="${GETTEXT_PACKAGE}" LOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") + +# ayatana-indicator-printers-service +add_executable (ayatana-indicator-printers-service main.c) +target_link_libraries (ayatana-indicator-printers-service ayatanaindicatorprintersservice ${SERVICE_LIBRARIES}) +install (TARGETS ayatana-indicator-printers-service RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}) diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 48e81f0..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,53 +0,0 @@ -printersmenulibdir = $(INDICATORDIR) -printersmenulib_LTLIBRARIES = libayatana-printersmenu.la -libayatana_printersmenu_la_SOURCES = \ - indicator-printers.c \ - indicator-printers.h \ - indicator-menu-item.c \ - indicator-menu-item.h \ - dbus-names.h - -libayatana_printersmenu_la_CPPFLAGS = $(APPLET_CFLAGS) -libayatana_printersmenu_la_CFLAGS = $(COVERAGE_CFLAGS) -libayatana_printersmenu_la_LIBADD = $(APPLET_LIBS) -lm -libayatana_printersmenu_la_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - -module -avoid-version - - -cups_notifier_sources = \ - cups-notifier.c \ - cups-notifier.h - -$(cups_notifier_sources): org.cups.cupsd.Notifier.xml - gdbus-codegen \ - --interface-prefix org.cups.cupsd \ - --c-namespace Cups \ - --generate-c-code cups-notifier \ - $^ - - -pkglibexec_PROGRAMS = ayatana-indicator-printers-service -ayatana_indicator_printers_service_SOURCES = \ - indicator-printers-service.c \ - indicator-printers-menu.c \ - indicator-printers-menu.h \ - indicator-printer-state-notifier.c \ - indicator-printer-state-notifier.h \ - spawn-printer-settings.c \ - spawn-printer-settings.h \ - dbus-names.h - -nodist_ayatana_indicator_printers_service_SOURCES = $(cups_notifier_sources) - -ayatana_indicator_printers_service_CPPFLAGS = $(SERVICE_CFLAGS) -ayatana_indicator_printers_service_CFLAGS = $(COVERAGE_CFLAGS) -ayatana_indicator_printers_service_LDADD = $(SERVICE_LIBS) -ayatana_indicator_printers_service_LDFLAGS = $(COVERAGE_LDFLAGS) - -BUILT_SOURCES = $(cups_notifier_sources) -CLEANFILES= $(BUILT_SOURCES) -EXTRA_DIST = org.cups.cupsd.Notifier.xml - -DISTCLEANFILES = \ - Makefile.in
\ No newline at end of file diff --git a/src/indicator-menu-item.c b/src/indicator-menu-item.c deleted file mode 100644 index ed89a0f..0000000 --- a/src/indicator-menu-item.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "indicator-menu-item.h" - -#include <math.h> - -struct _IndicatorMenuItemPrivate -{ - GtkImage *image; - GtkWidget *label; - GtkWidget *right_label; - gboolean right_is_lozenge; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(IndicatorMenuItem, indicator_menu_item, GTK_TYPE_MENU_ITEM) - -enum { - PROP_0, - PROP_ICON, - PROP_ICON_NAME, - PROP_LABEL, - PROP_RIGHT, - PROP_RIGHT_IS_LOZENGE, - N_PROPERTIES -}; - -static GParamSpec *properties[N_PROPERTIES]; - - -static gint -gtk_widget_get_font_size (GtkWidget *widget) -{ - const PangoFontDescription *font; - - gtk_style_context_get(gtk_widget_get_style_context(widget), gtk_widget_get_state_flags(widget), "font", &font, NULL); - - return pango_font_description_get_size (font) / PANGO_SCALE; -} - -static void -cairo_lozenge (cairo_t *cr, double x, double y, double w, double h) -{ - double radius = MIN (w / 2.0, h / 2.0); - double x1 = x + w - radius; - double x2 = x + radius; - double y1 = y + radius; - double y2 = y + h - radius; - - cairo_move_to (cr, x+radius, y); - cairo_arc (cr, x1, y1, radius, M_PI * 1.5, M_PI * 2); - cairo_arc (cr, x1, y2, radius, 0, M_PI * 0.5); - cairo_arc (cr, x2, y2, radius, M_PI * 0.5, M_PI); - cairo_arc (cr, x2, y1, radius, M_PI, M_PI * 1.5); -} - -static gboolean -detail_label_draw (GtkWidget *widget, - cairo_t *cr, - gpointer data) -{ - GtkAllocation allocation; - double x, y, w, h; - GdkRGBA color; - PangoLayout *layout; - PangoRectangle layout_extents; - gboolean is_lozenge = *(gboolean *)data; - gint font_size = gtk_widget_get_font_size (widget); - - /* let the label handle the drawing if it's not a lozenge */ - if (!is_lozenge) - return FALSE; - - layout = gtk_label_get_layout (GTK_LABEL(widget)); - pango_layout_get_extents (layout, NULL, &layout_extents); - pango_extents_to_pixels (&layout_extents, NULL); - - gtk_widget_get_allocation (widget, &allocation); - x = -font_size / 2.0; - y = 1; - w = allocation.width; - h = MIN (allocation.height, layout_extents.height + 4); - - if (layout_extents.width == 0) - return TRUE; - - gtk_style_context_get_color (gtk_widget_get_style_context (widget), - gtk_widget_get_state_flags (widget), - &color); - gdk_cairo_set_source_rgba (cr, &color); - - cairo_set_line_width (cr, 1.0); - cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); - cairo_lozenge (cr, x - font_size / 2.0, y, w + font_size, h); - - x += (w - layout_extents.width) / 2.0; - y += (h - layout_extents.height) / 2.0; - cairo_move_to (cr, floor (x), floor (y)); - pango_cairo_layout_path (cr, layout); - cairo_fill (cr); - - return TRUE; -} - - -static void -indicator_menu_item_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - IndicatorMenuItem *self = INDICATOR_MENU_ITEM (object); - - switch (property_id) - { - case PROP_ICON: - g_value_set_object (value, indicator_menu_item_get_icon (self)); - break; - - case PROP_ICON_NAME: - g_value_set_string (value, indicator_menu_item_get_icon_name (self)); - break; - - case PROP_LABEL: - g_value_set_string (value, gtk_label_get_label (GTK_LABEL (self->priv->label))); - break; - - case PROP_RIGHT: - g_value_set_string (value, gtk_label_get_label (GTK_LABEL (self->priv->right_label))); - break; - - case PROP_RIGHT_IS_LOZENGE: - g_value_set_boolean (value, self->priv->right_is_lozenge); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - - -static void -indicator_menu_item_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) - { - case PROP_ICON: - indicator_menu_item_set_icon (INDICATOR_MENU_ITEM (object), - g_value_get_object (value)); - break; - - case PROP_ICON_NAME: - indicator_menu_item_set_icon_name (INDICATOR_MENU_ITEM (object), - g_value_get_string (value)); - break; - - case PROP_LABEL: - indicator_menu_item_set_label (INDICATOR_MENU_ITEM (object), - g_value_get_string (value)); - break; - - case PROP_RIGHT: - indicator_menu_item_set_right (INDICATOR_MENU_ITEM (object), - g_value_get_string (value)); - break; - - case PROP_RIGHT_IS_LOZENGE: - indicator_menu_item_set_right_is_lozenge (INDICATOR_MENU_ITEM (object), - g_value_get_boolean (value)); - break; - - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - - -static void -indicator_menu_item_dispose (GObject *object) -{ - IndicatorMenuItem *self = INDICATOR_MENU_ITEM (object); - - g_clear_object (&self->priv->image); - g_clear_object (&self->priv->label); - g_clear_object (&self->priv->right_label); - - G_OBJECT_CLASS (indicator_menu_item_parent_class)->dispose (object); -} - - -static void -indicator_menu_item_class_init (IndicatorMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = indicator_menu_item_get_property; - object_class->set_property = indicator_menu_item_set_property; - object_class->dispose = indicator_menu_item_dispose; - - properties[PROP_ICON] = g_param_spec_object ("icon", - "Icon", - "Icon for this menu item", - GDK_TYPE_PIXBUF, - G_PARAM_READWRITE); - - properties[PROP_ICON_NAME] = g_param_spec_string ("icon-name", - "Icon name", - "Name of the themed icon", - "", - G_PARAM_READWRITE); - - properties[PROP_LABEL] = g_param_spec_string ("label", - "Label", - "The text for the main label", - "", - G_PARAM_READWRITE); - - properties[PROP_RIGHT] = g_param_spec_string ("right", - "Right", - "The text on the right side of the menu item", - "", - G_PARAM_READWRITE); - - properties[PROP_RIGHT_IS_LOZENGE] = g_param_spec_boolean ("right-is-lozenge", - "Right is a lozenge", - "Whether the right label is displayed as a lonzenge", - FALSE, - G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); -} - - -static void -indicator_menu_item_init (IndicatorMenuItem *self) -{ - IndicatorMenuItemPrivate *priv; - gint spacing; - GtkWidget *hbox; - - priv = indicator_menu_item_get_instance_private(self); - self->priv = priv; - - gtk_widget_style_get (GTK_WIDGET (self), - "toggle-spacing", &spacing, - NULL); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, spacing); - - priv->image = g_object_new (GTK_TYPE_IMAGE, NULL); - g_object_ref_sink (priv->image); - gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (priv->image), FALSE, FALSE, 0); - - priv->label = g_object_new (GTK_TYPE_LABEL, - "xalign", 0.0, - NULL); - g_object_ref_sink (priv->label); - gtk_box_pack_start (GTK_BOX (hbox), priv->label, TRUE, TRUE, 0); - - priv->right_label = g_object_new (GTK_TYPE_LABEL, - "xalign", 1.0, - "width-chars", 2, - NULL); - gtk_style_context_add_class (gtk_widget_get_style_context (priv->right_label), - "accelerator"); - g_signal_connect (priv->right_label, - "draw", - G_CALLBACK (detail_label_draw), - &priv->right_is_lozenge); - g_object_ref_sink (priv->right_label); - gtk_box_pack_start (GTK_BOX (hbox), - priv->right_label, - FALSE, - FALSE, - gtk_widget_get_font_size (priv->right_label) / 2.0 + 1); - - gtk_container_add (GTK_CONTAINER (self), hbox); - - priv->right_is_lozenge = FALSE; -} - - -IndicatorMenuItem * -indicator_menu_item_new (void) -{ - return g_object_new (INDICATOR_TYPE_MENU_ITEM, NULL); -} - - -const gchar * -indicator_menu_item_get_label (IndicatorMenuItem *self) -{ - return gtk_label_get_label (GTK_LABEL (self->priv->label)); -} - - -void -indicator_menu_item_set_label (IndicatorMenuItem *self, - const gchar *text) -{ - gtk_label_set_label (GTK_LABEL (self->priv->label), text); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LABEL]); -} - - -const gchar * -indicator_menu_item_get_right (IndicatorMenuItem *self) -{ - return gtk_label_get_label (GTK_LABEL (self->priv->right_label)); -} - - -void -indicator_menu_item_set_right (IndicatorMenuItem *self, - const gchar *text) -{ - gtk_label_set_label (GTK_LABEL (self->priv->right_label), text); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RIGHT]); -} - - -gboolean -indicator_menu_item_get_right_is_lozenge (IndicatorMenuItem *self) -{ - return self->priv->right_is_lozenge; -} - - -void -indicator_menu_item_set_right_is_lozenge (IndicatorMenuItem *self, - gboolean is_lozenge) -{ - self->priv->right_is_lozenge = is_lozenge; - gtk_widget_queue_draw (self->priv->right_label); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RIGHT_IS_LOZENGE]); -} - - -GdkPixbuf * -indicator_menu_item_get_icon (IndicatorMenuItem *self) -{ - if (gtk_image_get_storage_type (self->priv->image) == GTK_IMAGE_PIXBUF) - return gtk_image_get_pixbuf (self->priv->image); - else - return NULL; -} - - -void -indicator_menu_item_set_icon (IndicatorMenuItem *self, - GdkPixbuf *icon) -{ - gtk_image_set_from_pixbuf (self->priv->image, icon); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ICON]); -} - - -const gchar * -indicator_menu_item_get_icon_name (IndicatorMenuItem *self) -{ - const gchar *name = NULL; - - if (gtk_image_get_storage_type (self->priv->image) == GTK_IMAGE_ICON_NAME) - gtk_image_get_icon_name (self->priv->image, &name, NULL); - - return name; -} - - -void -indicator_menu_item_set_icon_name (IndicatorMenuItem *self, - const gchar *name) -{ - gtk_image_set_from_icon_name (self->priv->image, name, GTK_ICON_SIZE_MENU); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ICON_NAME]); -} diff --git a/src/indicator-menu-item.h b/src/indicator-menu-item.h deleted file mode 100644 index 84d6b74..0000000 --- a/src/indicator-menu-item.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INDICATOR_MENU_ITEM_H -#define INDICATOR_MENU_ITEM_H - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_MENU_ITEM indicator_menu_item_get_type() - -#define INDICATOR_MENU_ITEM(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - INDICATOR_TYPE_MENU_ITEM, IndicatorMenuItem)) - -#define INDICATOR_MENU_ITEM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - INDICATOR_TYPE_MENU_ITEM, IndicatorMenuItemClass)) - -#define INDICATOR_IS_MENU_ITEM(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - INDICATOR_TYPE_MENU_ITEM)) - -#define INDICATOR_IS_MENU_ITEM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - INDICATOR_TYPE_MENU_ITEM)) - -#define INDICATOR_MENU_ITEM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - INDICATOR_TYPE_MENU_ITEM, IndicatorMenuItemClass)) - -typedef struct _IndicatorMenuItem IndicatorMenuItem; -typedef struct _IndicatorMenuItemClass IndicatorMenuItemClass; -typedef struct _IndicatorMenuItemPrivate IndicatorMenuItemPrivate; - -struct _IndicatorMenuItem -{ - GtkMenuItem parent; - IndicatorMenuItemPrivate *priv; -}; - -struct _IndicatorMenuItemClass -{ - GtkMenuItemClass parent_class; -}; - -GType indicator_menu_item_get_type (void) G_GNUC_CONST; - -IndicatorMenuItem *indicator_menu_item_new (void); - -const gchar * indicator_menu_item_get_label (IndicatorMenuItem *self); -void indicator_menu_item_set_label (IndicatorMenuItem *self, const gchar *text); -const gchar * indicator_menu_item_get_right (IndicatorMenuItem *self); -void indicator_menu_item_set_right (IndicatorMenuItem *self, const gchar *text); - -gboolean indicator_menu_item_get_right_is_lozenge (IndicatorMenuItem *self); -void indicator_menu_item_set_right_is_lozenge (IndicatorMenuItem *self, gboolean is_lozenge); -const gchar * indicator_menu_item_get_icon_name (IndicatorMenuItem *self); -void indicator_menu_item_set_icon (IndicatorMenuItem *self, GdkPixbuf *icon); -GdkPixbuf * indicator_menu_item_get_icon (IndicatorMenuItem *self); -void indicator_menu_item_set_icon_name (IndicatorMenuItem *self, const gchar *name); - -G_END_DECLS - -#endif diff --git a/src/indicator-printer-state-notifier.c b/src/indicator-printer-state-notifier.c index 7a587a0..12f77c6 100644 --- a/src/indicator-printer-state-notifier.c +++ b/src/indicator-printer-state-notifier.c @@ -1,7 +1,9 @@ /* * Copyright 2012 Canonical Ltd. + * Copyright 2022 Robert Tari * * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> + * Robert Tari <robert@tari.in> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -17,9 +19,8 @@ */ #include "indicator-printer-state-notifier.h" - +#include <ayatana/common/utils.h> #include <glib/gi18n.h> -#include <gtk/gtk.h> #include <cups/cups.h> #include <string.h> #include <stdarg.h> @@ -27,9 +28,6 @@ #include "cups-notifier.h" #include "spawn-printer-settings.h" - -#define RESPONSE_SHOW_SYSTEM_SETTINGS 1 - struct _IndicatorPrinterStateNotifierPrivate { CupsNotifier *cups_notifier; @@ -95,12 +93,9 @@ show_alert_box (const gchar *printer, const gchar *reason, int njobs) { - GtkWidget *dialog; - GtkWidget *image; gchar *primary_text; gchar *secondary_text; - image = gtk_image_new_from_icon_name ("printer", GTK_ICON_SIZE_DIALOG); primary_text = g_strdup_printf (reason, printer); secondary_text = g_strdup_printf (ngettext( @@ -108,31 +103,14 @@ show_alert_box (const gchar *printer, "You have %d jobs queued to print on this printer.", njobs), njobs); - dialog = g_object_new (GTK_TYPE_MESSAGE_DIALOG, - "title", _("Printing Problem"), - "icon-name", "printer", - "image", image, - "text", primary_text, - "secondary-text", secondary_text, - "urgency-hint", TRUE, - "focus-on-map", FALSE, - "window-position", GTK_WIN_POS_CENTER, - "skip-taskbar-hint", FALSE, - "deletable", FALSE, - NULL); - + gchar *sText = g_strdup_printf("<b>%s</b>\n\n%s", primary_text, secondary_text); g_free (primary_text); g_free (secondary_text); - gtk_dialog_add_buttons(GTK_DIALOG (dialog), _("_Settings…"), RESPONSE_SHOW_SYSTEM_SETTINGS, _("_OK"), GTK_RESPONSE_OK, NULL); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), - GTK_RESPONSE_OK); - gtk_widget_show_all (dialog); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == RESPONSE_SHOW_SYSTEM_SETTINGS) - spawn_printer_settings (); + ayatana_common_utils_zenity_warning ("printer", _("Printing Problem"), sText); + g_free (sText); - gtk_widget_destroy (dialog); + spawn_printer_settings (); } diff --git a/src/indicator-printers-menu.c b/src/indicator-printers-menu.c deleted file mode 100644 index 54ea281..0000000 --- a/src/indicator-printers-menu.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "indicator-printers-menu.h" - -#include <glib/gi18n.h> - -#include <cups/cups.h> - -#include "spawn-printer-settings.h" - -struct _IndicatorPrintersMenuPrivate -{ - DbusmenuMenuitem *root; - GHashTable *printers; /* printer name -> dbusmenuitem */ - CupsNotifier *cups_notifier; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(IndicatorPrintersMenu, indicator_printers_menu, G_TYPE_OBJECT) - -enum { - PROP_0, - PROP_CUPS_NOTIFIER, - NUM_PROPERTIES -}; - -static GParamSpec *properties[NUM_PROPERTIES]; - - -static void -dispose (GObject *object) -{ - IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (object); - - if (self->priv->printers) { - g_hash_table_unref (self->priv->printers); - self->priv->printers = NULL; - } - - g_clear_object (&self->priv->root); - g_clear_object (&self->priv->cups_notifier); - - G_OBJECT_CLASS (indicator_printers_menu_parent_class)->dispose (object); -} - - -void -set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (object); - - switch (property_id) { - case PROP_CUPS_NOTIFIER: - indicator_printers_menu_set_cups_notifier (self, - g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - - -void -get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (object); - - switch (property_id) { - case PROP_CUPS_NOTIFIER: - g_value_set_object (value, - indicator_printers_menu_get_cups_notifier (self)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - - -static void -indicator_printers_menu_class_init (IndicatorPrintersMenuClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - object_class->get_property = get_property; - object_class->set_property = set_property; - - properties[PROP_CUPS_NOTIFIER] = g_param_spec_object ("cups-notifier", - "Cups Notifier", - "A cups notifier object", - CUPS_TYPE_NOTIFIER, - G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); -} - - -static void -on_printer_item_activated (DbusmenuMenuitem *menuitem, - guint timestamp, - gpointer user_data) -{ - const gchar *printer = user_data; - spawn_printer_settings_with_args ("--show-jobs %s", printer); -} - - -static void -update_indicator_visibility (IndicatorPrintersMenu *self) -{ - GList *it; - gboolean is_visible = FALSE; - - for (it = dbusmenu_menuitem_get_children (self->priv->root); - it; - it = g_list_next (it)) - { - DbusmenuMenuitem *child = it->data; - if ((is_visible = dbusmenu_menuitem_property_get_bool (child, "visible"))) - break; - } - - dbusmenu_menuitem_property_set_bool (self->priv->root, "visible", is_visible); -} - - -static void -update_printer_menuitem (IndicatorPrintersMenu *self, - const char *printer, - int state) -{ - DbusmenuMenuitem *item; - int njobs; - cups_job_t *jobs; - - njobs = cupsGetJobs (&jobs, printer, 1, CUPS_WHICHJOBS_ACTIVE); - cupsFreeJobs (njobs, jobs); - - if (njobs < 0) { - g_warning ("printer '%s' does not exist\n", printer); - return; - } - - item = g_hash_table_lookup (self->priv->printers, printer); - - if (!item) { - item = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (item, "type", "indicator-item"); - dbusmenu_menuitem_property_set (item, "indicator-icon-name", "printer"); - dbusmenu_menuitem_property_set (item, "indicator-label", printer); - g_signal_connect_data (item, "item-activated", - G_CALLBACK (on_printer_item_activated), - g_strdup (printer), (GClosureNotify) g_free, 0); - - dbusmenu_menuitem_child_append(self->priv->root, item); - g_hash_table_insert (self->priv->printers, g_strdup (printer), item); - } - - if (njobs == 0) { - dbusmenu_menuitem_property_set_bool (item, "visible", FALSE); - update_indicator_visibility (self); - return; - } - - /* there are jobs for this printer. Make sure the indicator and the menu - * item for that printer are shown */ - dbusmenu_menuitem_property_set_bool (self->priv->root, "visible", TRUE); - dbusmenu_menuitem_property_set_bool (item, "visible", TRUE); - - switch (state) { - case IPP_PRINTER_STOPPED: - dbusmenu_menuitem_property_set (item, "indicator-right", _("Paused")); - dbusmenu_menuitem_property_set_bool (item, "indicator-right-is-lozenge", FALSE); - break; - - case IPP_PRINTER_PROCESSING: { - gchar *jobstr = g_strdup_printf ("%d", njobs); - dbusmenu_menuitem_property_set (item, "indicator-right", jobstr); - dbusmenu_menuitem_property_set_bool (item, "indicator-right-is-lozenge", TRUE); - g_free (jobstr); - break; - } - } -} - - -static void -update_all_printer_menuitems (IndicatorPrintersMenu *self) -{ - int ndests, i; - cups_dest_t *dests; - - ndests = cupsGetDests (&dests); - for (i = 0; i < ndests; i++) { - int state = atoi (cupsGetOption ("printer-state", - dests[i].num_options, - dests[i].options)); - update_printer_menuitem (self, dests[i].name, state); - } - cupsFreeDests (ndests, dests); -} - - -static void -update_job (CupsNotifier *cups_notifier, - const gchar *text, - const gchar *printer_uri, - const gchar *printer_name, - guint printer_state, - const gchar *printer_state_reasons, - gboolean printer_is_accepting_jobs, - guint job_id, - guint job_state, - const gchar *job_state_reasons, - const gchar *job_name, - guint job_impressions_completed, - gpointer user_data) -{ - IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data); - - /* CUPS doesn't send the printer's name for these events. Update all menu - * items as a temporary workaround */ - if (job_state == IPP_JOB_CANCELLED || - job_state == IPP_JOB_ABORTED || - job_state == IPP_JOB_COMPLETED) - update_all_printer_menuitems (self); - else - update_printer_menuitem (self, printer_name, printer_state); -} - - -static void -on_printer_state_changed (CupsNotifier *object, - const gchar *text, - const gchar *printer_uri, - const gchar *printer_name, - guint printer_state, - const gchar *printer_state_reasons, - gboolean printer_is_accepting_jobs, - gpointer user_data) -{ - IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data); - - update_printer_menuitem (self, printer_name, printer_state); -} - - -static void -indicator_printers_menu_init (IndicatorPrintersMenu *self) -{ - self->priv = indicator_printers_menu_get_instance_private(self); - - self->priv->root = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set_bool (self->priv->root, "visible", FALSE); - - self->priv->printers = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); - - /* create initial menu items */ - update_all_printer_menuitems (self); -} - - -IndicatorPrintersMenu * -indicator_printers_menu_new (void) -{ - return g_object_new (INDICATOR_TYPE_PRINTERS_MENU, NULL); -} - - -DbusmenuMenuitem * -indicator_printers_menu_get_root (IndicatorPrintersMenu *self) -{ - return self->priv->root; -} - - -CupsNotifier * -indicator_printers_menu_get_cups_notifier (IndicatorPrintersMenu *self) -{ - return self->priv->cups_notifier; -} - - -void -indicator_printers_menu_set_cups_notifier (IndicatorPrintersMenu *self, - CupsNotifier *cups_notifier) -{ - if (self->priv->cups_notifier) { - g_object_disconnect (self->priv->cups_notifier, - "any-signal", update_job, self, - "any-signal", on_printer_state_changed, self, - NULL); - g_clear_object (&self->priv->cups_notifier); - } - - if (cups_notifier) { - self->priv->cups_notifier = g_object_ref (cups_notifier); - g_object_connect (self->priv->cups_notifier, - "signal::job-created", update_job, self, - "signal::job-state", update_job, self, - "signal::job-completed", update_job, self, - "signal::printer-state-changed", on_printer_state_changed, self, - NULL); - } -} diff --git a/src/indicator-printers-menu.h b/src/indicator-printers-menu.h deleted file mode 100644 index c10f221..0000000 --- a/src/indicator-printers-menu.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INDICATOR_PRINTERS_MENU_H -#define INDICATOR_PRINTERS_MENU_H - -#include <glib-object.h> -#include <libdbusmenu-glib/dbusmenu-glib.h> - -#include "cups-notifier.h" - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_PRINTERS_MENU indicator_printers_menu_get_type() - -#define INDICATOR_PRINTERS_MENU(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - INDICATOR_TYPE_PRINTERS_MENU, IndicatorPrintersMenu)) - -#define INDICATOR_PRINTERS_MENU_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - INDICATOR_TYPE_PRINTERS_MENU, IndicatorPrintersMenuClass)) - -#define INDICATOR_IS_PRINTERS_MENU(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - INDICATOR_TYPE_PRINTERS_MENU)) - -#define INDICATOR_IS_PRINTERS_MENU_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - INDICATOR_TYPE_PRINTERS_MENU)) - -#define INDICATOR_PRINTERS_MENU_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - INDICATOR_TYPE_PRINTERS_MENU, IndicatorPrintersMenuClass)) - -typedef struct _IndicatorPrintersMenu IndicatorPrintersMenu; -typedef struct _IndicatorPrintersMenuClass IndicatorPrintersMenuClass; -typedef struct _IndicatorPrintersMenuPrivate IndicatorPrintersMenuPrivate; - -struct _IndicatorPrintersMenu -{ - GObject parent; - IndicatorPrintersMenuPrivate *priv; -}; - -struct _IndicatorPrintersMenuClass -{ - GObjectClass parent_class; -}; - -GType indicator_printers_menu_get_type (void) G_GNUC_CONST; - -IndicatorPrintersMenu *indicator_printers_menu_new (void); -DbusmenuMenuitem * indicator_printers_menu_get_root (IndicatorPrintersMenu *menu); -CupsNotifier * indicator_printers_menu_get_cups_notifier (IndicatorPrintersMenu *self); -void indicator_printers_menu_set_cups_notifier (IndicatorPrintersMenu *self, - CupsNotifier *cups_notifier); - -G_END_DECLS - -#endif diff --git a/src/indicator-printers-service.c b/src/indicator-printers-service.c index 8d31360..ed9553c 100644 --- a/src/indicator-printers-service.c +++ b/src/indicator-printers-service.c @@ -1,7 +1,9 @@ /* * Copyright 2012 Canonical Ltd. + * Copyright 2022 Robert Tari * * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> + * Robert Tari <robert@tari.in> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -16,190 +18,491 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <libayatana-indicator/indicator-service.h> -#include <libdbusmenu-glib/dbusmenu-glib.h> -#include <gtk/gtk.h> #include <cups/cups.h> #include "dbus-names.h" -#include "config.h" #include <glib/gi18n-lib.h> +#include <gio/gio.h> +#include "indicator-printers-service.h" #include "cups-notifier.h" -#include "indicator-printers-menu.h" #include "indicator-printer-state-notifier.h" +#include "spawn-printer-settings.h" #define NOTIFY_LEASE_DURATION (24 * 60 * 60) +static guint m_nSignal = 0; -static int -create_subscription () -{ - ipp_t *req; - ipp_t *resp; - ipp_attribute_t *attr; - int id = 0; - - req = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION); - ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, "/"); - ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, - "notify-events", NULL, "all"); - ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, - "notify-recipient-uri", NULL, "dbus://"); - ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, - "notify-lease-duration", NOTIFY_LEASE_DURATION); - - resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); - if (!resp || cupsLastError() != IPP_OK) { - g_warning ("Error subscribing to CUPS notifications: %s\n", - cupsLastErrorString ()); - return 0; +enum +{ + SECTION_HEADER = (1<<0), + SECTION_PRINTERS = (1<<2) +}; + +enum +{ + PROFILE_PHONE, + PROFILE_DESKTOP, + N_PROFILES +}; + +static const char *const lMenuNames[N_PROFILES] = +{ + "phone", + "desktop" +}; + +struct ProfileMenuInfo +{ + GMenu *pMenu; + GMenu *pSubmenu; + guint nExportId; +}; + +struct _IndicatorPrintersServicePrivate +{ + GCancellable *pCancellable; + IndicatorPrinterStateNotifier *pStateNotifier; + CupsNotifier *pCupsNotifier; + guint nOwnId; + guint nActionsId; + GDBusConnection *pConnection; + gboolean bMenusBuilt; + int nSubscriptionId; + struct ProfileMenuInfo lMenus[N_PROFILES]; + GSimpleActionGroup *pActionGroup; + GSimpleAction *pHeaderAction; + GSimpleAction *pPrinterAction; + GMenu *pPrintersSection; + gboolean bVisible; +}; + +typedef IndicatorPrintersServicePrivate priv_t; + +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorPrintersService, indicator_printers_service, G_TYPE_OBJECT) + +static void rebuildNow (IndicatorPrintersService *self, guint nSections); + +static void unexport (IndicatorPrintersService *self) +{ + if (self->pPrivate->nSubscriptionId > 0) + { + ipp_t *pRequest = ippNewRequest (IPP_CANCEL_SUBSCRIPTION); + ippAddString (pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "/"); + ippAddInteger (pRequest, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-id", self->pPrivate->nSubscriptionId); + ipp_t *pResponse = cupsDoRequest (CUPS_HTTP_DEFAULT, pRequest, "/"); + + if (!pResponse || cupsLastError () != IPP_OK) + { + g_warning ("Error subscribing to CUPS notifications: %s\n", cupsLastErrorString ()); + + return; + } + + ippDelete (pResponse); } - attr = ippFindAttribute (resp, "notify-subscription-id", IPP_TAG_INTEGER); - if (attr) - id = ippGetInteger (attr, 0); - else - g_warning ("ipp-create-printer-subscription response doesn't contain " - "subscription id.\n"); + // Unexport the menus + for (int i = 0; i < N_PROFILES; ++i) + { + guint *pId = &self->pPrivate->lMenus[i].nExportId; + + if (*pId) + { + g_dbus_connection_unexport_menu_model (self->pPrivate->pConnection, *pId); + *pId = 0; + } + } + + // Unexport the actions + if (self->pPrivate->nActionsId) + { + g_dbus_connection_unexport_action_group (self->pPrivate->pConnection, self->pPrivate->nActionsId); + self->pPrivate->nActionsId = 0; + } +} - ippDelete (resp); - return id; +static void onPrinterStateChanged (CupsNotifier *pNotifier, const gchar *sText, const gchar *sPrinterUri, const gchar *sPrinterName, guint nPrinterState, const gchar *sPrinterStateReasons, gboolean bPrinterIsAcceptingJobs, IndicatorPrintersService *self) +{ + rebuildNow(self, SECTION_PRINTERS | SECTION_HEADER); } +static void onJobChanged (CupsNotifier *pNotifier, const gchar *sText, const gchar *sPrinterUri, const gchar *sPrinterName, guint nPrinterState, const gchar *sPrinterStateReasons, gboolean bPrinterIsAcceptingJobs, guint nJobId, guint nJobState, const gchar *sJobStateReasons, const gchar *sJobName, guint nJobImpressionsCompleted, IndicatorPrintersService *self) +{ + rebuildNow(self, SECTION_PRINTERS | SECTION_HEADER); +} -static gboolean -renew_subscription (int id) +static void onDispose (GObject *pObject) { - ipp_t *req; - ipp_t *resp; + IndicatorPrintersService *self = INDICATOR_PRINTERS_SERVICE (pObject); - req = ippNewRequest (IPP_RENEW_SUBSCRIPTION); - ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER, - "notify-subscription-id", id); - ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, "/"); - ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, - "notify-recipient-uri", NULL, "dbus://"); - ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, - "notify-lease-duration", NOTIFY_LEASE_DURATION); + unexport (self); - resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); - if (!resp || cupsLastError() != IPP_OK) { - g_warning ("Error renewing CUPS subscription %d: %s\n", - id, cupsLastErrorString ()); - return FALSE; + if (self->pPrivate->pCancellable != NULL) + { + g_cancellable_cancel (self->pPrivate->pCancellable); + g_clear_object (&self->pPrivate->pCancellable); } - ippDelete (resp); - return TRUE; + if (self->pPrivate->pCupsNotifier) + { + g_object_disconnect (self->pPrivate->pCupsNotifier, "any-signal", onJobChanged, self, "any-signal", onPrinterStateChanged, self, NULL); + g_clear_object (&self->pPrivate->pCupsNotifier); + } + + g_object_unref (self->pPrivate->pStateNotifier); + g_clear_object (&self->pPrivate->pPrinterAction); + g_clear_object (&self->pPrivate->pHeaderAction); + g_clear_object (&self->pPrivate->pActionGroup); + g_clear_object (&self->pPrivate->pConnection); + + G_OBJECT_CLASS (indicator_printers_service_parent_class)->dispose (pObject); +} + +static void indicator_printers_service_class_init (IndicatorPrintersServiceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->dispose = onDispose; + m_nSignal = g_signal_new ("name-lost", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IndicatorPrintersServiceClass, pNameLost), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } +static int createSubscription () +{ + int nId = 0; + + ipp_t *pRequest = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION); + ippAddString (pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "/"); + ippAddString (pRequest, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events", NULL, "all"); + ippAddString (pRequest, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-recipient-uri", NULL, "dbus://"); + ippAddInteger (pRequest, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-lease-duration", NOTIFY_LEASE_DURATION); + ipp_t *pResponse = cupsDoRequest (CUPS_HTTP_DEFAULT, pRequest, "/"); + + if (!pResponse || cupsLastError () != IPP_OK) + { + g_warning ("Error subscribing to CUPS notifications: %s\n", cupsLastErrorString ()); + + return 0; + } + + ipp_attribute_t *pAttribute = ippFindAttribute (pResponse, "notify-subscription-id", IPP_TAG_INTEGER); + + if (pAttribute) + { + nId = ippGetInteger (pAttribute, 0); + } + else + { + g_warning ("ipp-create-printer-subscription response doesn't contain subscription id.\n"); + } + + ippDelete (pResponse); -static gboolean -renew_subscription_timeout (gpointer userdata) + return nId; +} + +static gboolean renewSubscriptionTimeout (gpointer pData) { - int *subscription_id = userdata; + int *nSubscriptionId = pData; + gboolean bRenewed = TRUE; + ipp_t *pRequest = ippNewRequest (IPP_RENEW_SUBSCRIPTION); + ippAddInteger (pRequest, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-id", *nSubscriptionId); + ippAddString (pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "/"); + ippAddString (pRequest, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-recipient-uri", NULL, "dbus://"); + ippAddInteger (pRequest, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-lease-duration", NOTIFY_LEASE_DURATION); + ipp_t *pResponse = cupsDoRequest (CUPS_HTTP_DEFAULT, pRequest, "/"); + + if (!pResponse || cupsLastError () != IPP_OK) + { + g_warning ("Error renewing CUPS subscription %d: %s\n", *nSubscriptionId, cupsLastErrorString ()); + bRenewed = FALSE; + } + else + { + ippDelete (pResponse); + } - if (*subscription_id <= 0 || !renew_subscription (*subscription_id)) - *subscription_id = create_subscription (); + if (*nSubscriptionId <= 0 || !bRenewed) + { + *nSubscriptionId = createSubscription (); + } return TRUE; } +static GVariant *createHeaderState (IndicatorPrintersService *self) +{ + GVariantBuilder b; + + g_variant_builder_init (&b, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (_("Printers"))); + g_variant_builder_add (&b, "{sv}", "tooltip", g_variant_new_string (_("Show print jobs and queues"))); + g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); + + if (self->pPrivate->bVisible) + { + GIcon *pIcon = g_themed_icon_new_with_default_fallbacks ("printer-symbolic"); + g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (_("Printers"))); + + if (pIcon) + { + GVariant *pSerialized = g_icon_serialize (pIcon); + + if (pSerialized != NULL) + { + g_variant_builder_add (&b, "{sv}", "icon", pSerialized); + g_variant_unref (pSerialized); + } + + g_object_unref (pIcon); + } + } + + return g_variant_builder_end (&b); +} -void -cancel_subscription (int id) +static void onPrinterItemActivated (GSimpleAction *pAction, GVariant *pVariant, gpointer pData) { - ipp_t *req; - ipp_t *resp; + const gchar *sPrinter = g_variant_get_string(pVariant, NULL); + spawn_printer_settings_with_args ("--show-jobs %s", sPrinter); +} - if (id <= 0) - return; +static void initActions (IndicatorPrintersService *self) +{ + self->pPrivate->pActionGroup = g_simple_action_group_new (); - req = ippNewRequest (IPP_CANCEL_SUBSCRIPTION); - ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, "/"); - ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER, - "notify-subscription-id", id); + GSimpleAction *pAction = g_simple_action_new_stateful ("_header", NULL, createHeaderState (self)); + g_action_map_add_action (G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction)); + self->pPrivate->pHeaderAction = pAction; - resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); - if (!resp || cupsLastError() != IPP_OK) { - g_warning ("Error subscribing to CUPS notifications: %s\n", - cupsLastErrorString ()); - return; + pAction = g_simple_action_new("printer", G_VARIANT_TYPE_STRING); + g_action_map_add_action (G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction)); + self->pPrivate->pPrinterAction = pAction; + g_signal_connect(pAction, "activate", G_CALLBACK(onPrinterItemActivated), self); + + rebuildNow (self, SECTION_HEADER); +} + +static GMenuModel *createPrintersSection (IndicatorPrintersService *self) +{ + self->pPrivate->pPrintersSection = g_menu_new (); + self->pPrivate->bVisible = FALSE; + cups_dest_t *lDests; + gint nDests = cupsGetDests (&lDests); + + for (gint i = 0; i < nDests; i++) + { + const gchar *sOption = cupsGetOption ("printer-state", lDests[i].num_options, lDests[i].options); + + if (sOption != NULL) + { + cups_job_t *lJobs; + gint nJobs = cupsGetJobs (&lJobs, lDests[i].name, 1, CUPS_WHICHJOBS_ACTIVE); + cupsFreeJobs (nJobs, lJobs); + + if (nJobs < 0) + { + g_warning ("printer '%s' does not exist\n", lDests[i].name); + } + else if (nJobs != 0) + { + GMenuItem *pItem = g_menu_item_new (lDests[i].name, NULL); + g_menu_item_set_attribute (pItem, "x-ayatana-type", "s", "org.ayatana.indicator.basic"); + g_menu_item_set_action_and_target_value(pItem, "indicator.printer", g_variant_new_string (lDests[i].name)); + GIcon *pIcon = g_themed_icon_new_with_default_fallbacks ("printer"); + GVariant *pSerialized = g_icon_serialize(pIcon); + + if (pSerialized != NULL) + { + g_menu_item_set_attribute_value(pItem, G_MENU_ATTRIBUTE_ICON, pSerialized); + g_variant_unref(pSerialized); + } + + g_object_unref(pIcon); + + gint nState = atoi (sOption); + + switch (nState) + { + case IPP_PRINTER_STOPPED: + { + g_menu_item_set_attribute (pItem, "x-ayatana-secondary-text", "s", _("Paused")); + + break; + } + case IPP_PRINTER_PROCESSING: + { + g_menu_item_set_attribute (pItem, "x-ayatana-secondary-count", "i", nJobs); + + break; + } + } + + g_menu_append_item(self->pPrivate->pPrintersSection, pItem); + g_object_unref(pItem); + self->pPrivate->bVisible = TRUE; + } + } + } + + cupsFreeDests (nDests, lDests); + + return G_MENU_MODEL (self->pPrivate->pPrintersSection); +} + +static void createMenu (IndicatorPrintersService *self, int nProfile) +{ + g_assert (0 <= nProfile && nProfile < N_PROFILES); + g_assert (self->pPrivate->lMenus[nProfile].pMenu == NULL); + + GMenuModel *lSections[16]; + guint nSection = 0; + + // Build the sections + switch (nProfile) + { + case PROFILE_PHONE: + case PROFILE_DESKTOP: + { + lSections[nSection++] = createPrintersSection (self); + + break; + } + + break; + } + + // Add sections to the submenu + GMenu *pSubmenu = g_menu_new (); + + for (guint i = 0; i < nSection; ++i) + { + g_menu_append_section (pSubmenu, NULL, lSections[i]); + g_object_unref (lSections[i]); } - ippDelete (resp); + // Add submenu to the header + GMenuItem *pHeader = g_menu_item_new (NULL, "indicator._header"); + g_menu_item_set_attribute (pHeader, "x-ayatana-type", "s", "org.ayatana.indicator.root"); + g_menu_item_set_submenu (pHeader, G_MENU_MODEL (pSubmenu)); + g_object_unref (pSubmenu); + + // Add header to the menu + GMenu *pMenu = g_menu_new (); + g_menu_append_item (pMenu, pHeader); + g_object_unref (pHeader); + + self->pPrivate->lMenus[nProfile].pMenu = pMenu; + self->pPrivate->lMenus[nProfile].pSubmenu = pSubmenu; } -static void -name_lost (GDBusConnection *connection, - const gchar *name, - gpointer user_data) +static void onBusAcquired (GDBusConnection *pConnection, const gchar *sName, gpointer pSelf) { - int subscription_id = GPOINTER_TO_INT (user_data); + g_debug ("bus acquired: %s", sName); + + IndicatorPrintersService *self = INDICATOR_PRINTERS_SERVICE (pSelf); + guint nId; + GError *pError = NULL; + GString *pPath = g_string_new (NULL); + self->pPrivate->pConnection = (GDBusConnection*)g_object_ref (G_OBJECT (pConnection)); + + // Export the actions + if ((nId = g_dbus_connection_export_action_group (pConnection, INDICATOR_PRINTERS_DBUS_OBJECT_PATH, G_ACTION_GROUP (self->pPrivate->pActionGroup), &pError))) + { + self->pPrivate->nActionsId = nId; + } + else + { + g_warning ("cannot export action group: %s", pError->message); + g_clear_error (&pError); + } - cancel_subscription (subscription_id); - gtk_main_quit (); + // Export the menus + for (gint nProfile = 0; nProfile < N_PROFILES; ++nProfile) + { + struct ProfileMenuInfo *pInfo = &self->pPrivate->lMenus[nProfile]; + + g_string_printf (pPath, "%s/%s", INDICATOR_PRINTERS_DBUS_OBJECT_PATH, lMenuNames[nProfile]); + + if ((nId = g_dbus_connection_export_menu_model (pConnection, pPath->str, G_MENU_MODEL (pInfo->pMenu), &pError))) + { + pInfo->nExportId = nId; + } + else + { + g_warning ("cannot export %s menu: %s", pPath->str, pError->message); + g_clear_error (&pError); + } + } + + g_string_free (pPath, TRUE); } -int main (int argc, char *argv[]) +static void onNameLost (GDBusConnection *pConnection, const gchar *sName, gpointer pSelf) { - /* Init i18n */ - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); + IndicatorPrintersService *self = INDICATOR_PRINTERS_SERVICE (pSelf); - DbusmenuServer *menuserver; - CupsNotifier *cups_notifier; - IndicatorPrintersMenu *menu; - IndicatorPrinterStateNotifier *state_notifier; - GError *error = NULL; - int subscription_id; + g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, sName); - gtk_init (&argc, &argv); + unexport (self); +} - subscription_id = create_subscription (); - g_timeout_add_seconds (NOTIFY_LEASE_DURATION - 60, - renew_subscription_timeout, - &subscription_id); +static void indicator_printers_service_init (IndicatorPrintersService *self) +{ + self->pPrivate = indicator_printers_service_get_instance_private (self); + self->pPrivate->pCancellable = g_cancellable_new (); + + GError *pError = NULL; + self->pPrivate->nSubscriptionId = createSubscription (); + g_timeout_add_seconds (NOTIFY_LEASE_DURATION - 60, renewSubscriptionTimeout, &self->pPrivate->nSubscriptionId); + self->pPrivate->pCupsNotifier = cups_notifier_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL, CUPS_DBUS_PATH, NULL, &pError); + + if (pError) + { + g_error ("Error creating cups notify handler: %s", pError->message); + g_error_free (pError); + } - g_bus_own_name (G_BUS_TYPE_SESSION, - INDICATOR_PRINTERS_DBUS_NAME, - G_BUS_NAME_OWNER_FLAGS_NONE, - NULL, NULL, name_lost, - GINT_TO_POINTER (subscription_id), NULL); + g_object_connect (self->pPrivate->pCupsNotifier, "signal::job-created", onJobChanged, self, "signal::job-state", onJobChanged, self, "signal::job-completed", onJobChanged, self, "signal::printer-state-changed", onPrinterStateChanged, self, NULL); + self->pPrivate->pStateNotifier = g_object_new (INDICATOR_TYPE_PRINTER_STATE_NOTIFIER, "cups-notifier", self->pPrivate->pCupsNotifier, NULL); + initActions (self); - cups_notifier = cups_notifier_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - 0, - NULL, - CUPS_DBUS_PATH, - NULL, - &error); - if (error) { - g_warning ("Error creating cups notify handler: %s", error->message); - g_error_free (error); - return 1; + for (gint nProfile = 0; nProfile < N_PROFILES; ++nProfile) + { + createMenu (self, nProfile); } - menu = g_object_new (INDICATOR_TYPE_PRINTERS_MENU, - "cups-notifier", cups_notifier, - NULL); + self->pPrivate->bMenusBuilt = TRUE; + self->pPrivate->nOwnId = g_bus_own_name (G_BUS_TYPE_SESSION, INDICATOR_PRINTERS_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, onBusAcquired, NULL, onNameLost, self, NULL); +} + +IndicatorPrintersService *indicator_printers_service_new () +{ + GObject *pObject = g_object_new (INDICATOR_TYPE_PRINTERS_SERVICE, NULL); + + return INDICATOR_PRINTERS_SERVICE (pObject); +} + +static void rebuildSection (GMenu *pMenu, int nPos, GMenuModel *pSection) +{ + g_menu_remove (pMenu, nPos); + g_menu_insert_section (pMenu, nPos, NULL, pSection); + g_object_unref (pSection); +} - menuserver = dbusmenu_server_new (INDICATOR_PRINTERS_DBUS_OBJECT_PATH); - dbusmenu_server_set_root (menuserver, - indicator_printers_menu_get_root (menu)); +static void rebuildNow (IndicatorPrintersService *self, guint nSections) +{ + struct ProfileMenuInfo *pinfo = &self->pPrivate->lMenus[PROFILE_DESKTOP]; - state_notifier = g_object_new (INDICATOR_TYPE_PRINTER_STATE_NOTIFIER, - "cups-notifier", cups_notifier, - NULL); + if (nSections & SECTION_HEADER) + { + g_simple_action_set_state (self->pPrivate->pHeaderAction, createHeaderState (self)); + } - gtk_main (); + if (!self->pPrivate->bMenusBuilt) + { + return; + } - g_object_unref (menu); - g_object_unref (menuserver); - g_object_unref (state_notifier); - g_object_unref (cups_notifier); - return 0; + if (nSections & SECTION_PRINTERS) + { + rebuildSection (pinfo->pSubmenu, 0, createPrintersSection (self)); + } } diff --git a/src/indicator-printers-service.h b/src/indicator-printers-service.h new file mode 100644 index 0000000..0b093c1 --- /dev/null +++ b/src/indicator-printers-service.h @@ -0,0 +1,52 @@ +/* + * Copyright 2022 Robert Tari + * + * Authors: Robert Tari <robert@tari.in> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __INDICATOR_PRINTERS_SERVICE_H__ +#define __INDICATOR_PRINTERS_SERVICE_H__ + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define INDICATOR_PRINTERS_SERVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_PRINTERS_SERVICE, IndicatorPrintersService)) +#define INDICATOR_TYPE_PRINTERS_SERVICE (indicator_printers_service_get_type ()) +#define INDICATOR_IS_PRINTERS_SERVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_PRINTERS_SERVICE)) + +typedef struct _IndicatorPrintersService IndicatorPrintersService; +typedef struct _IndicatorPrintersServiceClass IndicatorPrintersServiceClass; +typedef struct _IndicatorPrintersServicePrivate IndicatorPrintersServicePrivate; + +struct _IndicatorPrintersService +{ + GObject parent; + IndicatorPrintersServicePrivate *pPrivate; +}; + +struct _IndicatorPrintersServiceClass +{ + GObjectClass parent_class; + void (*pNameLost) (IndicatorPrintersService *self); +}; + +GType indicator_printers_service_get_type (void); +IndicatorPrintersService *indicator_printers_service_new (); + +G_END_DECLS + +#endif diff --git a/src/indicator-printers.c b/src/indicator-printers.c deleted file mode 100644 index ba263c9..0000000 --- a/src/indicator-printers.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "config.h" - -#include "indicator-printers.h" -#include "indicator-menu-item.h" -#include "dbus-names.h" - -#include <glib/gi18n-lib.h> -#include <gtk/gtk.h> -#include <gio/gio.h> - -#include <libayatana-indicator/indicator.h> -#include <libayatana-indicator/indicator-image-helper.h> - -#include <libdbusmenu-gtk/menu.h> -#include <libdbusmenu-gtk/menuitem.h> - - -INDICATOR_SET_VERSION -INDICATOR_SET_TYPE(INDICATOR_PRINTERS_TYPE) - -struct _IndicatorPrintersPrivate -{ - IndicatorObjectEntry entry; - guint name_watch; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(IndicatorPrinters, indicator_printers, INDICATOR_OBJECT_TYPE) - -static void -dispose (GObject *object) -{ - IndicatorPrinters *self = INDICATOR_PRINTERS (object); - if (self->priv->name_watch != 0) { - g_bus_unwatch_name(self->priv->name_watch); - self->priv->name_watch = 0; - } - g_clear_object (&self->priv->entry.menu); - g_clear_object (&self->priv->entry.image); - G_OBJECT_CLASS (indicator_printers_parent_class)->dispose (object); -} - - -static GList * -get_entries (IndicatorObject *io) -{ - IndicatorPrinters *self = INDICATOR_PRINTERS (io); - return g_list_append (NULL, &self->priv->entry); -} - - -static void -indicator_printers_class_init (IndicatorPrintersClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - - io_class->get_entries = get_entries; -} - - -static void -name_vanished (GDBusConnection * con, - const gchar * name, - gpointer user_data) -{ - IndicatorPrinters *self = INDICATOR_PRINTERS (user_data); - - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); -} - - -static GdkPixbuf * -gdk_pixbuf_new_from_encoded_data (guchar *data, - gsize length) -{ - GInputStream * input; - GError *err = NULL; - GdkPixbuf *img; - - input = g_memory_input_stream_new_from_data(data, length, NULL); - if (input == NULL) - return NULL; - - img = gdk_pixbuf_new_from_stream(input, NULL, &err); - if (err) { - g_warning("%s", err->message); - g_error_free(err); - } - - g_object_unref(input); - return img; -} - - -static GdkPixbuf * -g_variant_get_image (GVariant *value) -{ - const gchar *strvalue = NULL; - gsize length = 0; - guchar *icondata; - GdkPixbuf *img; - - if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) - strvalue = g_variant_get_string(value, NULL); - - if (!strvalue || !*strvalue) { - g_warning ("%s: value does not contain a base64 encoded image", - __func__); - return NULL; - } - - icondata = g_base64_decode(strvalue, &length); - img = gdk_pixbuf_new_from_encoded_data (icondata, length); - - g_free(icondata); - return img; -} - - -static gboolean -properties_match (const gchar *name, - const gchar *prop, - GVariant *value, - const GVariantType *type) -{ - return !g_strcmp0 (name, prop) && g_variant_is_of_type (value, type); -} - - -static void -indicator_prop_change_cb (DbusmenuMenuitem *mi, - gchar *prop, - GVariant *value, - gpointer user_data) -{ - IndicatorMenuItem *menuitem = user_data; - - if (properties_match (prop, "indicator-label", value, G_VARIANT_TYPE_STRING)) - indicator_menu_item_set_label (menuitem, g_variant_get_string (value, NULL)); - - else if (properties_match (prop, "indicator-right", value, G_VARIANT_TYPE_STRING)) - indicator_menu_item_set_right (menuitem, g_variant_get_string (value, NULL)); - - else if (properties_match (prop, "indicator-icon-name", value, G_VARIANT_TYPE_STRING)) - indicator_menu_item_set_icon_name (menuitem, g_variant_get_string (value, NULL)); - - else if (properties_match (prop, "indicator-icon", value, G_VARIANT_TYPE_STRING)) { - GdkPixbuf *pb = g_variant_get_image (value); - indicator_menu_item_set_icon (menuitem, pb); - g_object_unref (pb); - } - - else if (properties_match (prop, "visible", value, G_VARIANT_TYPE_BOOLEAN)) - gtk_widget_set_visible (GTK_WIDGET (menuitem), g_variant_get_boolean (value)); - - else if (properties_match (prop, "indicator-right-is-lozenge", value, G_VARIANT_TYPE_BOOLEAN)) - indicator_menu_item_set_right_is_lozenge (menuitem, g_variant_get_boolean (value)); -} - - -static void -root_property_changed (DbusmenuMenuitem *mi, - gchar *prop, - GVariant *value, - gpointer user_data) -{ - IndicatorObject *io = user_data; - - if (properties_match (prop, "visible", value, G_VARIANT_TYPE_BOOLEAN)) - indicator_object_set_visible (io, g_variant_get_boolean (value)); -} - - -static gboolean -new_indicator_item (DbusmenuMenuitem *newitem, - DbusmenuMenuitem *parent, - DbusmenuClient *client, - gpointer user_data) -{ - GtkWidget *menuitem; - const gchar *icon_name, *text, *right_text; - GVariant *icon; - gboolean is_lozenge, visible; - - icon_name = dbusmenu_menuitem_property_get (newitem, "indicator-icon-name"); - icon = dbusmenu_menuitem_property_get_variant (newitem, "indicator-icon"); - text = dbusmenu_menuitem_property_get (newitem, "indicator-label"); - right_text = dbusmenu_menuitem_property_get (newitem, "indicator-right"); - is_lozenge = dbusmenu_menuitem_property_get_bool (newitem, "indicator-right-is-lozenge"); - visible = dbusmenu_menuitem_property_get_bool (newitem, "visible"); - - menuitem = g_object_new (INDICATOR_TYPE_MENU_ITEM, - "icon-name", icon_name, - "label", text, - "right", right_text, - "right-is-lozenge", is_lozenge, - "visible", visible, - NULL); - if (icon) { - GdkPixbuf *pb = g_variant_get_image (icon); - indicator_menu_item_set_icon (INDICATOR_MENU_ITEM (menuitem), pb); - g_object_unref (pb); - } - gtk_widget_show_all (menuitem); - - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), - newitem, - GTK_MENU_ITEM (menuitem), - parent); - - g_signal_connect(G_OBJECT(newitem), - "property-changed", - G_CALLBACK(indicator_prop_change_cb), - menuitem); - - return TRUE; -} - - -static void -root_changed (DbusmenuClient *client, - DbusmenuMenuitem *newroot, - gpointer user_data) -{ - IndicatorPrinters *indicator = user_data; - gboolean is_visible; - - if (newroot) { - is_visible = dbusmenu_menuitem_property_get_bool (newroot, "visible"); - g_signal_connect (newroot, "property-changed", - G_CALLBACK (root_property_changed), indicator); - } - else - is_visible = FALSE; - - indicator_object_set_visible (INDICATOR_OBJECT (indicator), is_visible); -} - - -static void -indicator_printers_init (IndicatorPrinters *self) -{ - IndicatorPrintersPrivate *priv; - DbusmenuGtkMenu *menu; - DbusmenuClient *client; - GtkImage *image; - - priv = indicator_printers_get_instance_private(self); - self->priv = priv; - - priv->name_watch = g_bus_watch_name(G_BUS_TYPE_SESSION, - INDICATOR_PRINTERS_DBUS_NAME, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, /* appeared */ - name_vanished, - self, NULL); - - menu = dbusmenu_gtkmenu_new(INDICATOR_PRINTERS_DBUS_NAME, - INDICATOR_PRINTERS_DBUS_OBJECT_PATH); - - client = DBUSMENU_CLIENT (dbusmenu_gtkmenu_get_client (menu)); - dbusmenu_client_add_type_handler(client, - "indicator-item", - new_indicator_item); - g_signal_connect (client, "root-changed", G_CALLBACK (root_changed), self); - - image = indicator_image_helper ("printer-symbolic"); - gtk_widget_show (GTK_WIDGET (image)); - - priv->entry.name_hint = PACKAGE_NAME; - priv->entry.accessible_desc = _("Printers"); - priv->entry.menu = GTK_MENU (g_object_ref_sink (menu)); - priv->entry.image = g_object_ref_sink (image); - - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); -} - - -IndicatorPrinters * -indicator_printers_new (void) -{ - return g_object_new (INDICATOR_PRINTERS_TYPE, NULL); -} diff --git a/src/indicator-printers.h b/src/indicator-printers.h deleted file mode 100644 index 51b790c..0000000 --- a/src/indicator-printers.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2012 Canonical Ltd. - * - * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INDICATOR_PRINTERS_H -#define INDICATOR_PRINTERS_H - -#include <libayatana-indicator/indicator-object.h> - -G_BEGIN_DECLS - -#define INDICATOR_PRINTERS_TYPE indicator_printers_get_type() - -#define INDICATOR_PRINTERS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - INDICATOR_PRINTERS_TYPE, IndicatorPrinters)) - -#define INDICATOR_PRINTERS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - INDICATOR_PRINTERS_TYPE, IndicatorPrintersClass)) - -#define INDICATOR_IS_PRINTERS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - INDICATOR_PRINTERS_TYPE)) - -#define INDICATOR_IS_PRINTERS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - INDICATOR_PRINTERS_TYPE)) - -#define INDICATOR_PRINTERS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - INDICATOR_PRINTERS_TYPE, IndicatorPrintersClass)) - -typedef struct _IndicatorPrinters IndicatorPrinters; -typedef struct _IndicatorPrintersClass IndicatorPrintersClass; -typedef struct _IndicatorPrintersPrivate IndicatorPrintersPrivate; - -struct _IndicatorPrinters -{ - IndicatorObject parent; - IndicatorPrintersPrivate *priv; -}; - -struct _IndicatorPrintersClass -{ - IndicatorObjectClass parent_class; -}; - -GType indicator_printers_get_type (void) G_GNUC_CONST; - -IndicatorPrinters *indicator_printers_new (void); - -G_END_DECLS - -#endif - diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..6cc5103 --- /dev/null +++ b/src/main.c @@ -0,0 +1,47 @@ +/* + * Copyright 2022 Robert Tari + * + * Authors: + * Robert Tari <robert@tari.in> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <locale.h> +#include <glib.h> +#include <glib/gi18n.h> +#include "indicator-printers-service.h" + +static void onNameLost (gpointer pInstance G_GNUC_UNUSED, gpointer pLoop) +{ + g_message("Exiting: service couldn't acquire or lost ownership of busname"); + g_main_loop_quit ((GMainLoop*) pLoop); +} + +int main (int argc G_GNUC_UNUSED, char **argv G_GNUC_UNUSED) +{ + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + IndicatorPrintersService *pService = indicator_printers_service_new (NULL); + GMainLoop *pLoop = g_main_loop_new (NULL, FALSE); + g_signal_connect (pService, "name-lost", G_CALLBACK (onNameLost), pLoop); + g_main_loop_run (pLoop); + + g_main_loop_unref (pLoop); + g_clear_object (&pService); + + return 0; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..78d8965 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,12 @@ +# cups-notifier.h +# cups-notifier.c +include (GdbusCodegen) +add_gdbus_codegen_with_namespace (CUPS_NOTIFIER cups-notifier org.cups.cupsd Cups "${CMAKE_SOURCE_DIR}/src/org.cups.cupsd.Notifier.xml") + +# mock-cups-notifier +add_executable (mock-cups-notifier mock-cups-notifier.c ${CUPS_NOTIFIER}) +target_include_directories (mock-cups-notifier PUBLIC ${SERVICE_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries (mock-cups-notifier ${SERVICE_LIBRARIES}) +add_test (mock-cups-notifier mock-cups-notifier) + + diff --git a/test/Makefile.am b/test/Makefile.am deleted file mode 100644 index 0ecb702..0000000 --- a/test/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -noinst_PROGRAMS = mock-cups-notifier -DISTCLEANFILES = mock-cups-notifier - -cups_notifier_sources = \ - cups-notifier.c \ - cups-notifier.h - -$(cups_notifier_sources): $(top_srcdir)/src/org.cups.cupsd.Notifier.xml - gdbus-codegen \ - --interface-prefix org.cups.cupsd \ - --c-namespace Cups \ - --generate-c-code cups-notifier \ - $^ - -mock_cups_notifier_SOURCES = \ - mock-cups-notifier.c - -nodist_mock_cups_notifier_SOURCES = $(cups_notifier_sources) - -mock_cups_notifier_CPPFLAGS = \ - $(SERVICE_CFLAGS) \ - -I$(top_builddir)/src - -mock_cups_notifier_LDADD = $(SERVICE_LIBS) - -BUILT_SOURCES = $(cups_notifier_sources) -CLEANFILES = $(BUILT_SOURCES) - -DISTCLEANFILES = \ - Makefile.in
\ No newline at end of file diff --git a/update-po.sh b/update-po.sh index 5f9e9fd..2043358 100755 --- a/update-po.sh +++ b/update-po.sh @@ -16,7 +16,7 @@ set -x # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/> -GETTEXT_DOMAIN=$(cat configure.ac | grep -E "^GETTEXT_PACKAGE=" | sed -e 's/GETTEXT_PACKAGE=//') +GETTEXT_DOMAIN=$(cat CMakeLists.txt | grep 'set.*(.*GETTEXT_PACKAGE' | sed -r -e 's/.*\"([^"]+)\"\)/\1/') cp po/${GETTEXT_DOMAIN}.pot po/${GETTEXT_DOMAIN}.pot~ diff --git a/update-pot.sh b/update-pot.sh index b0cb9b5..43a8d06 100755 --- a/update-pot.sh +++ b/update-pot.sh @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/> -GETTEXT_DOMAIN=$(cat configure.ac | grep -E "^GETTEXT_PACKAGE=" | sed -e 's/GETTEXT_PACKAGE=//') +GETTEXT_DOMAIN=$(cat CMakeLists.txt | grep 'set.*(.*GETTEXT_PACKAGE' | sed -r -e 's/.*\"([^"]+)\"\)/\1/') cd po/ && intltool-update --gettext-package ${GETTEXT_DOMAIN} --pot && cd - 1>/dev/null |