From 77bf8928096b08af17ff24fcacc1d84a200edb5c Mon Sep 17 00:00:00 2001 From: alex-z Date: Wed, 24 Nov 2021 16:09:41 +0200 Subject: [PATCH] Use different icon for a sync folder on Windows depending on zoom level. Signed-off-by: alex-z --- .gitignore | 1 + cmake/modules/ECMAddAppIcon.cmake | 24 +- src/common/utility_win.cpp | 10 +- src/gui/CMakeLists.txt | 103 ++++++- src/gui/configgui.h.in | 4 + .../icons/Nextcloud-icon-win-folder.svg | 278 ++++++++++++++++++ 6 files changed, 401 insertions(+), 19 deletions(-) create mode 100644 src/gui/configgui.h.in create mode 100644 theme/colored/icons/Nextcloud-icon-win-folder.svg diff --git a/.gitignore b/.gitignore index 15a7371a0..dcd25d421 100644 --- a/.gitignore +++ b/.gitignore @@ -184,6 +184,7 @@ compile_commands.json convert.exe .dir-locals.el *-icon.png +*-icon-win-folder.png *-sidebar.png *-w10startmenu.png theme.qrc diff --git a/cmake/modules/ECMAddAppIcon.cmake b/cmake/modules/ECMAddAppIcon.cmake index 3934491bd..61dba6c42 100644 --- a/cmake/modules/ECMAddAppIcon.cmake +++ b/cmake/modules/ECMAddAppIcon.cmake @@ -41,7 +41,7 @@ # target does not have the ``WIN32_EXECUTABLE`` property set. # * One of the tools png2ico (See :find-module:`FindPng2Ico`) or # icotool (see :find-module:`FindIcoTool`) is required. -# * Supported sizes: 16, 24, 32, 48, 64, 128, 256, 512 and 1024. +# * Supported sizes: 16, 20, 24, 32, 40, 48, 64, 128, 256, 512 and 1024. # # Mac OS X notes # * The executable target must have the ``MACOSX_BUNDLE`` property set. @@ -102,9 +102,12 @@ include(CMakeParseArguments) function(ecm_add_app_icon appsources) set(options) - set(oneValueArgs OUTFILE_BASENAME) - set(multiValueArgs ICONS SIDEBAR_ICONS) + set(oneValueArgs OUTFILE_BASENAME ICON_INDEX) + set(multiValueArgs ICONS SIDEBAR_ICONS RC_DEPENDENCIES) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (NOT ARG_ICON_INDEX) + set(ARG_ICON_INDEX 1) + endif() if(NOT ARG_ICONS) message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon") @@ -138,8 +141,11 @@ function(ecm_add_app_icon appsources) endforeach() endif() - - _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024") + if (WIN32) + _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;20;24;32;40;48;64;128;256;512;1024") + else() + _ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024") + endif() if(ARG_SIDEBAR_ICONS) _ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256") endif() @@ -168,8 +174,10 @@ function(ecm_add_app_icon appsources) set(windows_icons ${icons_at_16px} + ${icons_at_20px} ${icons_at_24px} ${icons_at_32px} + ${icons_at_40px} ${icons_at_48px} ${icons_at_64px} ${icons_at_128px} @@ -204,12 +212,12 @@ function(ecm_add_app_icon appsources) WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) # this bit's a little hacky to make the dependency stuff work - file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n") + file(WRITE "${_outfilename}.rc.in" "IDI_ICON${ARG_ICON_INDEX} ICON DISCARDABLE \"${_outfilename}.ico\"\n") add_custom_command( OUTPUT "${_outfilename}.rc" COMMAND ${CMAKE_COMMAND} ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc" - DEPENDS "${_outfilename}.ico" + DEPENDS ${ARG_RC_DEPENDENCIES} "${_outfilename}.ico" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) endfunction() @@ -226,7 +234,7 @@ function(ecm_add_app_icon appsources) endif() endforeach() - foreach(size 16 24 32 48 64 128 ${maxSize}) + foreach(size 16 20 24 32 40 48 64 128 ${maxSize}) if(NOT icons_at_${size}px) continue() endif() diff --git a/src/common/utility_win.cpp b/src/common/utility_win.cpp index 5637a023e..80907ea5d 100644 --- a/src/common/utility_win.cpp +++ b/src/common/utility_win.cpp @@ -18,6 +18,7 @@ #include "asserts.h" #include "utility.h" +#include "gui/configgui.h" #include #include @@ -48,7 +49,14 @@ static void setupFavLink_private(const QString &folder) desktopIni.open(QFile::WriteOnly); desktopIni.write("[.ShellClassInfo]\r\nIconResource="); desktopIni.write(QDir::toNativeSeparators(qApp->applicationFilePath()).toUtf8()); - desktopIni.write(",0\r\n"); +#ifdef APPLICATION_FOLDER_ICON_INDEX + const auto iconIndex = APPLICATION_FOLDER_ICON_INDEX; +#else + const auto iconIndex = "0"; +#endif + desktopIni.write(","); + desktopIni.write(iconIndex); + desktopIni.write("\r\n"); desktopIni.close(); // Set the folder as system and Desktop.ini as hidden+system for explorer to pick it. diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 794f44f27..abf2a190a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -258,6 +258,10 @@ if (NOT DEFINED APPLICATION_ICON_NAME) set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME}) endif() +if(NOT DEFINED APPLICATION_FOLDER_ICON_INDEX) + set(APPLICATION_FOLDER_ICON_INDEX 0) +endif() + # Generate png icons from svg find_program(SVG_CONVERTER NAMES inkscape inkscape.exe rsvg-convert @@ -269,9 +273,24 @@ if (NOT SVG_CONVERTER) endif() function(generate_sized_png_from_svg icon_path size) + set(options) + set(oneValueArgs OUTPUT_ICON_NAME OUTPUT_ICON_PATH) + set(multiValueArgs) + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + get_filename_component(icon_name_dir ${icon_path} DIRECTORY) get_filename_component(icon_name_wle ${icon_path} NAME_WLE) + if (ARG_OUTPUT_ICON_NAME) + set(icon_name_wle ${ARG_OUTPUT_ICON_NAME}) + endif () + + if (ARG_OUTPUT_ICON_PATH) + set(icon_name_dir ${ARG_OUTPUT_ICON_PATH}) + endif () + + if (EXISTS "${icon_name_dir}/${size}-${icon_name_wle}.png") return() endif() @@ -317,22 +336,84 @@ if(WIN32) endif() set(APP_ICON_SVG "${theme_dir}/colored/${APPLICATION_ICON_NAME}-icon.svg") -generate_sized_png_from_svg(${APP_ICON_SVG} 16) -generate_sized_png_from_svg(${APP_ICON_SVG} 24) -generate_sized_png_from_svg(${APP_ICON_SVG} 32) -generate_sized_png_from_svg(${APP_ICON_SVG} 48) -generate_sized_png_from_svg(${APP_ICON_SVG} 64) -generate_sized_png_from_svg(${APP_ICON_SVG} 128) -generate_sized_png_from_svg(${APP_ICON_SVG} 256) -generate_sized_png_from_svg(${APP_ICON_SVG} 512) -generate_sized_png_from_svg(${APP_ICON_SVG} 1024) + +# generate secondary icon if available (currently for Windows only)-------------------------------------- +set(APP_SECONDARY_ICONS "${theme_dir}/colored/icons") +set(APP_ICON_WIN_FOLDER_SVG "${APP_SECONDARY_ICONS}/${APPLICATION_ICON_NAME}-icon-win-folder.svg") + +set(RC_DEPENDENCIES "") + +if (EXISTS ${APP_ICON_WIN_FOLDER_SVG}) + get_filename_component(output_icon_name_win ${APP_ICON_WIN_FOLDER_SVG} NAME_WLE) + # Product icon (for smallest size) + foreach(size IN ITEMS 16;20) + generate_sized_png_from_svg(${APP_ICON_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/") + endforeach() + + # Product icon with Windows folder (for sizes larger than 20) + foreach(size IN ITEMS 24;32;40;48;64;128;256;512;1024) + generate_sized_png_from_svg(${APP_ICON_WIN_FOLDER_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/") + endforeach() + + file(GLOB_RECURSE OWNCLOUD_ICONS_WIN_FOLDER "${APP_SECONDARY_ICONS}/*-${APPLICATION_ICON_NAME}-icon*") + set(APP_ICON_WIN_FOLDER_ICO_NAME "${APPLICATION_ICON_NAME}-win-folder") + set(RC_DEPENDENCIES "${RC_DEPENDENCIES} ${APP_ICON_WIN_FOLDER_ICO_NAME}.ico") + ecm_add_app_icon(APP_ICON_WIN_FOLDER ICONS "${OWNCLOUD_ICONS_WIN_FOLDER}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APP_ICON_WIN_FOLDER_ICO_NAME}" ICON_INDEX 2) +endif() +# -------------------------------------- + +if (NOT ${RC_DEPENDENCIES} STREQUAL "") + string(STRIP ${RC_DEPENDENCIES} RC_DEPENDENCIES) +endif() + +# generate primary icon from SVG (due to Win .ico vs .rc dependency issues, primary icon must always be generated last)-------------------------------------- +if(WIN32) + foreach(size IN ITEMS 16;20;24;32;40;48;64;128;256;512;1024) + generate_sized_png_from_svg(${APP_ICON_SVG} ${size}) + endforeach() +else() + foreach(size IN ITEMS 16;24;32;48;64;128;256;512;1024) + generate_sized_png_from_svg(${APP_ICON_SVG} ${size}) + endforeach() +endif() file(GLOB_RECURSE OWNCLOUD_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-icon*") + if(APPLE) file(GLOB_RECURSE OWNCLOUD_SIDEBAR_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-sidebar*") MESSAGE(STATUS "OWNCLOUD_SIDEBAR_ICONS: ${APPLICATION_ICON_NAME}: ${OWNCLOUD_SIDEBAR_ICONS}") endif() -ecm_add_app_icon(APP_ICON ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}") + +ecm_add_app_icon(APP_ICON RC_DEPENDENCIES ${RC_DEPENDENCIES} ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}" ICON_INDEX 1) +# -------------------------------------- + +if(WIN32) +# merge *.rc.in files for Windows (multiple ICON resources must be placed in a single file, otherwise, this won't work de to a bug in Windows compiler https://developercommunity.visualstudio.com/t/visual-studio-2017-prof-1557-cvt1100-duplicate-res/363156) + function(merge_files IN_FILE OUT_FILE) + file(READ ${IN_FILE} CONTENTS) + message("Merging ${IN_FILE} into ${OUT_FILE}") + file(APPEND ${OUT_FILE} "${CONTENTS}") + endfunction() + message("APP_ICON is: ${APP_ICON}") + if(APP_ICON) + get_filename_component(RC_IN_FOLDER ${APP_ICON}} DIRECTORY) + + file(GLOB_RECURSE RC_IN_FILES "${RC_IN_FOLDER}/*rc.in") + + foreach(rc_in_file IN ITEMS ${RC_IN_FILES}) + get_filename_component(rc_in_file_name ${rc_in_file} NAME) + get_filename_component(app_icon_name "${APP_ICON}.in" NAME) + if(NOT "${rc_in_file_name}" STREQUAL "${app_icon_name}") + merge_files(${rc_in_file} "${APP_ICON}.in") + if (DEFINED APPLICATION_FOLDER_ICON_INDEX) + MATH(EXPR APPLICATION_FOLDER_ICON_INDEX "${APPLICATION_FOLDER_ICON_INDEX}+1") + message("APPLICATION_FOLDER_ICON_INDEX is now set to: ${APPLICATION_FOLDER_ICON_INDEX}") + endif() + endif() + endforeach() + endif() +endif() +# -------------------------------------- if(UNIX AND NOT APPLE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") @@ -545,3 +626,5 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32) update_xdg_mimetypes( ${CMAKE_INSTALL_DATADIR}/mime/packages ) endif(SharedMimeInfo_FOUND) endif() + +configure_file(configgui.h.in ${CMAKE_CURRENT_BINARY_DIR}/configgui.h) diff --git a/src/gui/configgui.h.in b/src/gui/configgui.h.in new file mode 100644 index 000000000..36bc6fbfc --- /dev/null +++ b/src/gui/configgui.h.in @@ -0,0 +1,4 @@ +#ifndef CONFIG_GUI_H +#define CONFIG_GUI_H +#cmakedefine APPLICATION_FOLDER_ICON_INDEX "@APPLICATION_FOLDER_ICON_INDEX@" +#endif diff --git a/theme/colored/icons/Nextcloud-icon-win-folder.svg b/theme/colored/icons/Nextcloud-icon-win-folder.svg new file mode 100644 index 000000000..2fbba0bdb --- /dev/null +++ b/theme/colored/icons/Nextcloud-icon-win-folder.svg @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +